diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/ModeledUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/ModeledUser.java index 6c6eb844c..8ea650ae3 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/ModeledUser.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/ModeledUser.java @@ -48,6 +48,7 @@ import org.glyptodon.guacamole.form.BooleanField; import org.glyptodon.guacamole.form.Field; import org.glyptodon.guacamole.form.Form; import org.glyptodon.guacamole.form.TextField; +import org.glyptodon.guacamole.form.TimeZoneField; import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet; import org.glyptodon.guacamole.net.auth.permission.SystemPermission; @@ -131,7 +132,7 @@ public class ModeledUser extends ModeledDirectoryObject implements Us new TextField(ACCESS_WINDOW_END_ATTRIBUTE_NAME), new TextField(VALID_FROM_ATTRIBUTE_NAME), new TextField(VALID_UNTIL_ATTRIBUTE_NAME), - new TextField(TIMEZONE_ATTRIBUTE_NAME) + new TimeZoneField(TIMEZONE_ATTRIBUTE_NAME) )); /** diff --git a/guacamole-ext/src/main/java/org/glyptodon/guacamole/form/Field.java b/guacamole-ext/src/main/java/org/glyptodon/guacamole/form/Field.java index c463c47b3..6e8b48058 100644 --- a/guacamole-ext/src/main/java/org/glyptodon/guacamole/form/Field.java +++ b/guacamole-ext/src/main/java/org/glyptodon/guacamole/form/Field.java @@ -84,6 +84,12 @@ public class Field { */ public static String MULTILINE = "MULTILINE"; + /** + * A time zone field whose legal values are only valid time zone IDs, + * as dictated by Java within TimeZone.getAvailableIDs(). + */ + public static String TIMEZONE = "TIMEZONE"; + } /** diff --git a/guacamole-ext/src/main/java/org/glyptodon/guacamole/form/TimeZoneField.java b/guacamole-ext/src/main/java/org/glyptodon/guacamole/form/TimeZoneField.java new file mode 100644 index 000000000..5d07e918e --- /dev/null +++ b/guacamole-ext/src/main/java/org/glyptodon/guacamole/form/TimeZoneField.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.glyptodon.guacamole.form; + +/** + * Represents a time zone field. The field may contain only valid time zone IDs, + * as dictated by TimeZone.getAvailableIDs(). + * + * @author Michael Jumper + */ +public class TimeZoneField extends Field { + + /** + * Creates a new TimeZoneField with the given name. + * + * @param name + * The unique name to associate with this field. + */ + public TimeZoneField(String name) { + super(name, Field.Type.TIMEZONE); + } + +} diff --git a/guacamole/src/main/webapp/app/form/controllers/timeZoneFieldController.js b/guacamole/src/main/webapp/app/form/controllers/timeZoneFieldController.js new file mode 100644 index 000000000..85483b195 --- /dev/null +++ b/guacamole/src/main/webapp/app/form/controllers/timeZoneFieldController.js @@ -0,0 +1,711 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +/** + * Controller for time zone fields. Time zone fields use Java IDs as the + * standard representation for each supported time zone. + */ +angular.module('form').controller('timeZoneFieldController', ['$scope', '$injector', + function timeZoneFieldController($scope, $injector) { + + /** + * Map of time zone regions to the map of all time zone name/ID pairs + * within those regions. + * + * @type Object.> + */ + $scope.timeZones = { + + "Africa" : { + "Abidjan" : "Africa/Abidjan", + "Accra" : "Africa/Accra", + "Addis Ababa" : "Africa/Addis_Ababa", + "Algiers" : "Africa/Algiers", + "Asmara" : "Africa/Asmara", + "Asmera" : "Africa/Asmera", + "Bamako" : "Africa/Bamako", + "Bangui" : "Africa/Bangui", + "Banjul" : "Africa/Banjul", + "Bissau" : "Africa/Bissau", + "Blantyre" : "Africa/Blantyre", + "Brazzaville" : "Africa/Brazzaville", + "Bujumbura" : "Africa/Bujumbura", + "Cairo" : "Africa/Cairo", + "Casablanca" : "Africa/Casablanca", + "Ceuta" : "Africa/Ceuta", + "Conakry" : "Africa/Conakry", + "Dakar" : "Africa/Dakar", + "Dar es Salaam" : "Africa/Dar_es_Salaam", + "Djibouti" : "Africa/Djibouti", + "Douala" : "Africa/Douala", + "El Aaiun" : "Africa/El_Aaiun", + "Freetown" : "Africa/Freetown", + "Gaborone" : "Africa/Gaborone", + "Harare" : "Africa/Harare", + "Johannesburg" : "Africa/Johannesburg", + "Juba" : "Africa/Juba", + "Kampala" : "Africa/Kampala", + "Khartoum" : "Africa/Khartoum", + "Kigali" : "Africa/Kigali", + "Kinshasa" : "Africa/Kinshasa", + "Lagos" : "Africa/Lagos", + "Libreville" : "Africa/Libreville", + "Lome" : "Africa/Lome", + "Luanda" : "Africa/Luanda", + "Lubumbashi" : "Africa/Lubumbashi", + "Lusaka" : "Africa/Lusaka", + "Malabo" : "Africa/Malabo", + "Maputo" : "Africa/Maputo", + "Maseru" : "Africa/Maseru", + "Mbabane" : "Africa/Mbabane", + "Mogadishu" : "Africa/Mogadishu", + "Monrovia" : "Africa/Monrovia", + "Nairobi" : "Africa/Nairobi", + "Ndjamena" : "Africa/Ndjamena", + "Niamey" : "Africa/Niamey", + "Nouakchott" : "Africa/Nouakchott", + "Ouagadougou" : "Africa/Ouagadougou", + "Porto-Novo" : "Africa/Porto-Novo", + "Sao Tome" : "Africa/Sao_Tome", + "Timbuktu" : "Africa/Timbuktu", + "Tripoli" : "Africa/Tripoli", + "Tunis" : "Africa/Tunis", + "Windhoek" : "Africa/Windhoek" + }, + + "America" : { + "Adak" : "America/Adak", + "Anchorage" : "America/Anchorage", + "Anguilla" : "America/Anguilla", + "Antigua" : "America/Antigua", + "Araguaina" : "America/Araguaina", + "Argentina / Buenos Aires" : "America/Argentina/Buenos_Aires", + "Argentina / Catamarca" : "America/Argentina/Catamarca", + "Argentina / Comodoro Rivadavia" : "America/Argentina/ComodRivadavia", + "Argentina / Cordoba" : "America/Argentina/Cordoba", + "Argentina / Jujuy" : "America/Argentina/Jujuy", + "Argentina / La Rioja" : "America/Argentina/La_Rioja", + "Argentina / Mendoza" : "America/Argentina/Mendoza", + "Argentina / Rio Gallegos" : "America/Argentina/Rio_Gallegos", + "Argentina / Salta" : "America/Argentina/Salta", + "Argentina / San Juan" : "America/Argentina/San_Juan", + "Argentina / San Luis" : "America/Argentina/San_Luis", + "Argentina / Tucuman" : "America/Argentina/Tucuman", + "Argentina / Ushuaia" : "America/Argentina/Ushuaia", + "Aruba" : "America/Aruba", + "Asuncion" : "America/Asuncion", + "Atikokan" : "America/Atikokan", + "Atka" : "America/Atka", + "Bahia" : "America/Bahia", + "Bahia Banderas" : "America/Bahia_Banderas", + "Barbados" : "America/Barbados", + "Belem" : "America/Belem", + "Belize" : "America/Belize", + "Blanc-Sablon" : "America/Blanc-Sablon", + "Boa Vista" : "America/Boa_Vista", + "Bogota" : "America/Bogota", + "Boise" : "America/Boise", + "Buenos Aires" : "America/Buenos_Aires", + "Cambridge Bay" : "America/Cambridge_Bay", + "Campo Grande" : "America/Campo_Grande", + "Cancun" : "America/Cancun", + "Caracas" : "America/Caracas", + "Catamarca" : "America/Catamarca", + "Cayenne" : "America/Cayenne", + "Cayman" : "America/Cayman", + "Chicago" : "America/Chicago", + "Chihuahua" : "America/Chihuahua", + "Coral Harbour" : "America/Coral_Harbour", + "Cordoba" : "America/Cordoba", + "Costa Rica" : "America/Costa_Rica", + "Creston" : "America/Creston", + "Cuiaba" : "America/Cuiaba", + "Curacao" : "America/Curacao", + "Danmarkshavn" : "America/Danmarkshavn", + "Dawson" : "America/Dawson", + "Dawson Creek" : "America/Dawson_Creek", + "Denver" : "America/Denver", + "Detroit" : "America/Detroit", + "Dominica" : "America/Dominica", + "Edmonton" : "America/Edmonton", + "Eirunepe" : "America/Eirunepe", + "El Salvador" : "America/El_Salvador", + "Ensenada" : "America/Ensenada", + "Fort Wayne" : "America/Fort_Wayne", + "Fortaleza" : "America/Fortaleza", + "Glace Bay" : "America/Glace_Bay", + "Godthab" : "America/Godthab", + "Goose Bay" : "America/Goose_Bay", + "Grand Turk" : "America/Grand_Turk", + "Grenada" : "America/Grenada", + "Guadeloupe" : "America/Guadeloupe", + "Guatemala" : "America/Guatemala", + "Guayaquil" : "America/Guayaquil", + "Guyana" : "America/Guyana", + "Halifax" : "America/Halifax", + "Havana" : "America/Havana", + "Hermosillo" : "America/Hermosillo", + "Indiana / Indianapolis" : "America/Indiana/Indianapolis", + "Indiana / Knox" : "America/Indiana/Knox", + "Indiana / Marengo" : "America/Indiana/Marengo", + "Indiana / Petersburg" : "America/Indiana/Petersburg", + "Indiana / Tell City" : "America/Indiana/Tell_City", + "Indiana / Vevay" : "America/Indiana/Vevay", + "Indiana / Vincennes" : "America/Indiana/Vincennes", + "Indiana / Winamac" : "America/Indiana/Winamac", + "Indianapolis" : "America/Indianapolis", + "Inuvik" : "America/Inuvik", + "Iqaluit" : "America/Iqaluit", + "Jamaica" : "America/Jamaica", + "Jujuy" : "America/Jujuy", + "Juneau" : "America/Juneau", + "Kentucky / Louisville" : "America/Kentucky/Louisville", + "Kentucky / Monticello" : "America/Kentucky/Monticello", + "Kralendijk" : "America/Kralendijk", + "La Paz" : "America/La_Paz", + "Lima" : "America/Lima", + "Los Angeles" : "America/Los_Angeles", + "Louisville" : "America/Louisville", + "Lower Princes" : "America/Lower_Princes", + "Maceio" : "America/Maceio", + "Managua" : "America/Managua", + "Manaus" : "America/Manaus", + "Marigot" : "America/Marigot", + "Martinique" : "America/Martinique", + "Matamoros" : "America/Matamoros", + "Mazatlan" : "America/Mazatlan", + "Mendoza" : "America/Mendoza", + "Menominee" : "America/Menominee", + "Merida" : "America/Merida", + "Metlakatla" : "America/Metlakatla", + "Mexico City" : "America/Mexico_City", + "Miquelon" : "America/Miquelon", + "Moncton" : "America/Moncton", + "Monterrey" : "America/Monterrey", + "Montevideo" : "America/Montevideo", + "Montreal" : "America/Montreal", + "Montserrat" : "America/Montserrat", + "Nassau" : "America/Nassau", + "New York" : "America/New_York", + "Nipigon" : "America/Nipigon", + "Nome" : "America/Nome", + "Noronha" : "America/Noronha", + "North Dakota / Beulah" : "America/North_Dakota/Beulah", + "North Dakota / Center" : "America/North_Dakota/Center", + "North Dakota / New Salem" : "America/North_Dakota/New_Salem", + "Ojinaga" : "America/Ojinaga", + "Panama" : "America/Panama", + "Pangnirtung" : "America/Pangnirtung", + "Paramaribo" : "America/Paramaribo", + "Phoenix" : "America/Phoenix", + "Port-au-Prince" : "America/Port-au-Prince", + "Port of Spain" : "America/Port_of_Spain", + "Porto Acre" : "America/Porto_Acre", + "Porto Velho" : "America/Porto_Velho", + "Puerto Rico" : "America/Puerto_Rico", + "Rainy River" : "America/Rainy_River", + "Rankin Inlet" : "America/Rankin_Inlet", + "Recife" : "America/Recife", + "Regina" : "America/Regina", + "Resolute" : "America/Resolute", + "Rio Branco" : "America/Rio_Branco", + "Rosario" : "America/Rosario", + "Santa Isabel" : "America/Santa_Isabel", + "Santarem" : "America/Santarem", + "Santiago" : "America/Santiago", + "Santo Domingo" : "America/Santo_Domingo", + "Sao Paulo" : "America/Sao_Paulo", + "Scoresbysund" : "America/Scoresbysund", + "Shiprock" : "America/Shiprock", + "Sitka" : "America/Sitka", + "St. Barthelemy" : "America/St_Barthelemy", + "St. Johns" : "America/St_Johns", + "St. Kitts" : "America/St_Kitts", + "St. Lucia" : "America/St_Lucia", + "St. Thomas" : "America/St_Thomas", + "St. Vincent" : "America/St_Vincent", + "Swift Current" : "America/Swift_Current", + "Tegucigalpa" : "America/Tegucigalpa", + "Thule" : "America/Thule", + "Thunder Bay" : "America/Thunder_Bay", + "Tijuana" : "America/Tijuana", + "Toronto" : "America/Toronto", + "Tortola" : "America/Tortola", + "Vancouver" : "America/Vancouver", + "Virgin" : "America/Virgin", + "Whitehorse" : "America/Whitehorse", + "Winnipeg" : "America/Winnipeg", + "Yakutat" : "America/Yakutat", + "Yellowknife" : "America/Yellowknife" + }, + + "Antarctica" : { + "Casey" : "Antarctica/Casey", + "Davis" : "Antarctica/Davis", + "Dumont d'Urville" : "Antarctica/DumontDUrville", + "Macquarie" : "Antarctica/Macquarie", + "Mawson" : "Antarctica/Mawson", + "McMurdo" : "Antarctica/McMurdo", + "Palmer" : "Antarctica/Palmer", + "Rothera" : "Antarctica/Rothera", + "South Pole" : "Antarctica/South_Pole", + "Syowa" : "Antarctica/Syowa", + "Troll" : "Antarctica/Troll", + "Vostok" : "Antarctica/Vostok" + }, + + "Arctic" : { + "Longyearbyen" : "Arctic/Longyearbyen" + }, + + "Asia" : { + "Aden" : "Asia/Aden", + "Almaty" : "Asia/Almaty", + "Amman" : "Asia/Amman", + "Anadyr" : "Asia/Anadyr", + "Aqtau" : "Asia/Aqtau", + "Aqtobe" : "Asia/Aqtobe", + "Ashgabat" : "Asia/Ashgabat", + "Ashkhabad" : "Asia/Ashkhabad", + "Baghdad" : "Asia/Baghdad", + "Bahrain" : "Asia/Bahrain", + "Baku" : "Asia/Baku", + "Bangkok" : "Asia/Bangkok", + "Beirut" : "Asia/Beirut", + "Bishkek" : "Asia/Bishkek", + "Brunei" : "Asia/Brunei", + "Calcutta" : "Asia/Calcutta", + "Chita" : "Asia/Chita", + "Choibalsan" : "Asia/Choibalsan", + "Chongqing" : "Asia/Chongqing", + "Colombo" : "Asia/Colombo", + "Dacca" : "Asia/Dacca", + "Damascus" : "Asia/Damascus", + "Dhaka" : "Asia/Dhaka", + "Dili" : "Asia/Dili", + "Dubai" : "Asia/Dubai", + "Dushanbe" : "Asia/Dushanbe", + "Gaza" : "Asia/Gaza", + "Harbin" : "Asia/Harbin", + "Hebron" : "Asia/Hebron", + "Ho Chi Minh" : "Asia/Ho_Chi_Minh", + "Hong Kong" : "Asia/Hong_Kong", + "Hovd" : "Asia/Hovd", + "Irkutsk" : "Asia/Irkutsk", + "Istanbul" : "Asia/Istanbul", + "Jakarta" : "Asia/Jakarta", + "Jayapura" : "Asia/Jayapura", + "Jerusalem" : "Asia/Jerusalem", + "Kabul" : "Asia/Kabul", + "Kamchatka" : "Asia/Kamchatka", + "Karachi" : "Asia/Karachi", + "Kashgar" : "Asia/Kashgar", + "Kathmandu" : "Asia/Kathmandu", + "Katmandu" : "Asia/Katmandu", + "Khandyga" : "Asia/Khandyga", + "Kolkata" : "Asia/Kolkata", + "Krasnoyarsk" : "Asia/Krasnoyarsk", + "Kuala Lumpur" : "Asia/Kuala_Lumpur", + "Kuching" : "Asia/Kuching", + "Kuwait" : "Asia/Kuwait", + "Macao" : "Asia/Macao", + "Macau" : "Asia/Macau", + "Magadan" : "Asia/Magadan", + "Makassar" : "Asia/Makassar", + "Manila" : "Asia/Manila", + "Muscat" : "Asia/Muscat", + "Nicosia" : "Asia/Nicosia", + "Novokuznetsk" : "Asia/Novokuznetsk", + "Novosibirsk" : "Asia/Novosibirsk", + "Omsk" : "Asia/Omsk", + "Oral" : "Asia/Oral", + "Phnom Penh" : "Asia/Phnom_Penh", + "Pontianak" : "Asia/Pontianak", + "Pyongyang" : "Asia/Pyongyang", + "Qatar" : "Asia/Qatar", + "Qyzylorda" : "Asia/Qyzylorda", + "Rangoon" : "Asia/Rangoon", + "Riyadh" : "Asia/Riyadh", + "Saigon" : "Asia/Saigon", + "Sakhalin" : "Asia/Sakhalin", + "Samarkand" : "Asia/Samarkand", + "Seoul" : "Asia/Seoul", + "Shanghai" : "Asia/Shanghai", + "Singapore" : "Asia/Singapore", + "Srednekolymsk" : "Asia/Srednekolymsk", + "Taipei" : "Asia/Taipei", + "Tashkent" : "Asia/Tashkent", + "Tbilisi" : "Asia/Tbilisi", + "Tehran" : "Asia/Tehran", + "Tel Aviv" : "Asia/Tel_Aviv", + "Thimbu" : "Asia/Thimbu", + "Thimphu" : "Asia/Thimphu", + "Tokyo" : "Asia/Tokyo", + "Ujung Pandang" : "Asia/Ujung_Pandang", + "Ulaanbaatar" : "Asia/Ulaanbaatar", + "Ulan Bator" : "Asia/Ulan_Bator", + "Urumqi" : "Asia/Urumqi", + "Ust-Nera" : "Asia/Ust-Nera", + "Vientiane" : "Asia/Vientiane", + "Vladivostok" : "Asia/Vladivostok", + "Yakutsk" : "Asia/Yakutsk", + "Yekaterinburg" : "Asia/Yekaterinburg", + "Yerevan" : "Asia/Yerevan" + }, + + "Atlantic" : { + "Azores" : "Atlantic/Azores", + "Bermuda" : "Atlantic/Bermuda", + "Canary" : "Atlantic/Canary", + "Cape Verde" : "Atlantic/Cape_Verde", + "Faeroe" : "Atlantic/Faeroe", + "Faroe" : "Atlantic/Faroe", + "Jan Mayen" : "Atlantic/Jan_Mayen", + "Madeira" : "Atlantic/Madeira", + "Reykjavik" : "Atlantic/Reykjavik", + "South Georgia" : "Atlantic/South_Georgia", + "St. Helena" : "Atlantic/St_Helena", + "Stanley" : "Atlantic/Stanley" + }, + + "Australia" : { + "Adelaide" : "Australia/Adelaide", + "Brisbane" : "Australia/Brisbane", + "Broken Hill" : "Australia/Broken_Hill", + "Canberra" : "Australia/Canberra", + "Currie" : "Australia/Currie", + "Darwin" : "Australia/Darwin", + "Eucla" : "Australia/Eucla", + "Hobart" : "Australia/Hobart", + "Lindeman" : "Australia/Lindeman", + "Lord Howe" : "Australia/Lord_Howe", + "Melbourne" : "Australia/Melbourne", + "North" : "Australia/North", + "Perth" : "Australia/Perth", + "Queensland" : "Australia/Queensland", + "South" : "Australia/South", + "Sydney" : "Australia/Sydney", + "Tasmania" : "Australia/Tasmania", + "Victoria" : "Australia/Victoria", + "West" : "Australia/West", + "Yancowinna" : "Australia/Yancowinna" + }, + + "Brazil" : { + "Acre" : "Brazil/Acre", + "Fernando de Noronha" : "Brazil/DeNoronha", + "East" : "Brazil/East", + "West" : "Brazil/West" + }, + + "Canada" : { + "Atlantic" : "Canada/Atlantic", + "Central" : "Canada/Central", + "East-Saskatchewan" : "Canada/East-Saskatchewan", + "Eastern" : "Canada/Eastern", + "Mountain" : "Canada/Mountain", + "Newfoundland" : "Canada/Newfoundland", + "Pacific" : "Canada/Pacific", + "Saskatchewan" : "Canada/Saskatchewan", + "Yukon" : "Canada/Yukon" + }, + + "Chile" : { + "Continental" : "Chile/Continental", + "Easter Island" : "Chile/EasterIsland" + }, + + "Europe" : { + "Amsterdam" : "Europe/Amsterdam", + "Andorra" : "Europe/Andorra", + "Athens" : "Europe/Athens", + "Belfast" : "Europe/Belfast", + "Belgrade" : "Europe/Belgrade", + "Berlin" : "Europe/Berlin", + "Bratislava" : "Europe/Bratislava", + "Brussels" : "Europe/Brussels", + "Bucharest" : "Europe/Bucharest", + "Budapest" : "Europe/Budapest", + "Busingen" : "Europe/Busingen", + "Chisinau" : "Europe/Chisinau", + "Copenhagen" : "Europe/Copenhagen", + "Dublin" : "Europe/Dublin", + "Gibraltar" : "Europe/Gibraltar", + "Guernsey" : "Europe/Guernsey", + "Helsinki" : "Europe/Helsinki", + "Isle of Man" : "Europe/Isle_of_Man", + "Istanbul" : "Europe/Istanbul", + "Jersey" : "Europe/Jersey", + "Kaliningrad" : "Europe/Kaliningrad", + "Kiev" : "Europe/Kiev", + "Lisbon" : "Europe/Lisbon", + "Ljubljana" : "Europe/Ljubljana", + "London" : "Europe/London", + "Luxembourg" : "Europe/Luxembourg", + "Madrid" : "Europe/Madrid", + "Malta" : "Europe/Malta", + "Mariehamn" : "Europe/Mariehamn", + "Minsk" : "Europe/Minsk", + "Monaco" : "Europe/Monaco", + "Moscow" : "Europe/Moscow", + "Nicosia" : "Europe/Nicosia", + "Oslo" : "Europe/Oslo", + "Paris" : "Europe/Paris", + "Podgorica" : "Europe/Podgorica", + "Prague" : "Europe/Prague", + "Riga" : "Europe/Riga", + "Rome" : "Europe/Rome", + "Samara" : "Europe/Samara", + "San Marino" : "Europe/San_Marino", + "Sarajevo" : "Europe/Sarajevo", + "Simferopol" : "Europe/Simferopol", + "Skopje" : "Europe/Skopje", + "Sofia" : "Europe/Sofia", + "Stockholm" : "Europe/Stockholm", + "Tallinn" : "Europe/Tallinn", + "Tirane" : "Europe/Tirane", + "Tiraspol" : "Europe/Tiraspol", + "Uzhgorod" : "Europe/Uzhgorod", + "Vaduz" : "Europe/Vaduz", + "Vatican" : "Europe/Vatican", + "Vienna" : "Europe/Vienna", + "Vilnius" : "Europe/Vilnius", + "Volgograd" : "Europe/Volgograd", + "Warsaw" : "Europe/Warsaw", + "Zagreb" : "Europe/Zagreb", + "Zaporozhye" : "Europe/Zaporozhye", + "Zurich" : "Europe/Zurich" + }, + + "GMT" : { + "GMT-14" : "Etc/GMT-14", + "GMT-13" : "Etc/GMT-13", + "GMT-12" : "Etc/GMT-12", + "GMT-11" : "Etc/GMT-11", + "GMT-10" : "Etc/GMT-10", + "GMT-9" : "Etc/GMT-9", + "GMT-8" : "Etc/GMT-8", + "GMT-7" : "Etc/GMT-7", + "GMT-6" : "Etc/GMT-6", + "GMT-5" : "Etc/GMT-5", + "GMT-4" : "Etc/GMT-4", + "GMT-3" : "Etc/GMT-3", + "GMT-2" : "Etc/GMT-2", + "GMT-1" : "Etc/GMT-1", + "GMT+0" : "Etc/GMT+0", + "GMT+1" : "Etc/GMT+1", + "GMT+2" : "Etc/GMT+2", + "GMT+3" : "Etc/GMT+3", + "GMT+4" : "Etc/GMT+4", + "GMT+5" : "Etc/GMT+5", + "GMT+6" : "Etc/GMT+6", + "GMT+7" : "Etc/GMT+7", + "GMT+8" : "Etc/GMT+8", + "GMT+9" : "Etc/GMT+9", + "GMT+10" : "Etc/GMT+10", + "GMT+11" : "Etc/GMT+11", + "GMT+12" : "Etc/GMT+12" + }, + + "Indian" : { + "Antananarivo" : "Indian/Antananarivo", + "Chagos" : "Indian/Chagos", + "Christmas" : "Indian/Christmas", + "Cocos" : "Indian/Cocos", + "Comoro" : "Indian/Comoro", + "Kerguelen" : "Indian/Kerguelen", + "Mahe" : "Indian/Mahe", + "Maldives" : "Indian/Maldives", + "Mauritius" : "Indian/Mauritius", + "Mayotte" : "Indian/Mayotte", + "Reunion" : "Indian/Reunion" + }, + + "Mexico" : { + "Baja Norte" : "Mexico/BajaNorte", + "Baja Sur" : "Mexico/BajaSur", + "General" : "Mexico/General" + }, + + "Pacific" : { + "Apia" : "Pacific/Apia", + "Auckland" : "Pacific/Auckland", + "Bougainville" : "Pacific/Bougainville", + "Chatham" : "Pacific/Chatham", + "Chuuk" : "Pacific/Chuuk", + "Easter" : "Pacific/Easter", + "Efate" : "Pacific/Efate", + "Enderbury" : "Pacific/Enderbury", + "Fakaofo" : "Pacific/Fakaofo", + "Fiji" : "Pacific/Fiji", + "Funafuti" : "Pacific/Funafuti", + "Galapagos" : "Pacific/Galapagos", + "Gambier" : "Pacific/Gambier", + "Guadalcanal" : "Pacific/Guadalcanal", + "Guam" : "Pacific/Guam", + "Honolulu" : "Pacific/Honolulu", + "Johnston" : "Pacific/Johnston", + "Kiritimati" : "Pacific/Kiritimati", + "Kosrae" : "Pacific/Kosrae", + "Kwajalein" : "Pacific/Kwajalein", + "Majuro" : "Pacific/Majuro", + "Marquesas" : "Pacific/Marquesas", + "Midway" : "Pacific/Midway", + "Nauru" : "Pacific/Nauru", + "Niue" : "Pacific/Niue", + "Norfolk" : "Pacific/Norfolk", + "Noumea" : "Pacific/Noumea", + "Pago Pago" : "Pacific/Pago_Pago", + "Palau" : "Pacific/Palau", + "Pitcairn" : "Pacific/Pitcairn", + "Pohnpei" : "Pacific/Pohnpei", + "Ponape" : "Pacific/Ponape", + "Port Moresby" : "Pacific/Port_Moresby", + "Rarotonga" : "Pacific/Rarotonga", + "Saipan" : "Pacific/Saipan", + "Samoa" : "Pacific/Samoa", + "Tahiti" : "Pacific/Tahiti", + "Tarawa" : "Pacific/Tarawa", + "Tongatapu" : "Pacific/Tongatapu", + "Truk" : "Pacific/Truk", + "Wake" : "Pacific/Wake", + "Wallis" : "Pacific/Wallis", + "Yap" : "Pacific/Yap" + } + + }; + + /** + * All selectable regions. + * + * @type String[] + */ + $scope.regions = (function collectRegions() { + + // Start with blank entry + var regions = [ '' ]; + + // Add each available region + for (var region in $scope.timeZones) + regions.push(region); + + return regions; + + })(); + + /** + * Direct mapping of all time zone IDs to the region containing that ID. + * + * @type Object. + */ + var timeZoneRegions = (function mapRegions() { + + var regions = {}; + + // For each available region + for (var region in $scope.timeZones) { + + // Get time zones within that region + var timeZonesInRegion = $scope.timeZones[region]; + + // For each of those time zones + for (var timeZoneName in timeZonesInRegion) { + + // Get corresponding ID + var timeZoneID = timeZonesInRegion[timeZoneName]; + + // Store region in map + regions[timeZoneID] = region; + + } + + } + + return regions; + + })(); + + /** + * Map of regions to the currently selected time zone for that region. + * Initially, all regions will be set to default selections (the first + * time zone, sorted lexicographically). + * + * @type Object. + */ + var selectedTimeZone = (function produceDefaultTimeZones() { + + var defaultTimeZone = {}; + + // For each available region + for (var region in $scope.timeZones) { + + // Get time zones within that region + var timeZonesInRegion = $scope.timeZones[region]; + + // No default initially + var defaultZoneName = null; + var defaultZoneID = null; + + // For each of those time zones + for (var timeZoneName in timeZonesInRegion) { + + // Get corresponding ID + var timeZoneID = timeZonesInRegion[timeZoneName]; + + // Set as default if earlier than existing default + if (!defaultZoneName || timeZoneName < defaultZoneName) { + defaultZoneName = timeZoneName; + defaultZoneID = timeZoneID; + } + + } + + // Store default zone + defaultTimeZone[region] = defaultZoneID; + + } + + return defaultTimeZone; + + })(); + + /** + * The name of the region currently selected. The selected region narrows + * which time zones are selectable. + * + * @type String + */ + $scope.region = ''; + + // Restore time zone selection when region changes + $scope.$watch('region', function restoreSelection(region) { + $scope.model = selectedTimeZone[region] || null; + }); + + // Ensure corresponding region is selected + $scope.$watch('model', function setModel(model) { + $scope.region = timeZoneRegions[model] || ''; + selectedTimeZone[$scope.region] = model; + }); + +}]); diff --git a/guacamole/src/main/webapp/app/form/services/formService.js b/guacamole/src/main/webapp/app/form/services/formService.js index b598347ab..ef42f864c 100644 --- a/guacamole/src/main/webapp/app/form/services/formService.js +++ b/guacamole/src/main/webapp/app/form/services/formService.js @@ -119,6 +119,18 @@ angular.module('form').provider('formService', function formServiceProvider() { */ 'MULTILINE' : { templateUrl : 'app/form/templates/textAreaField.html' + }, + + /** + * Field type which allows selection of time zones. + * + * @see {@link Field.Type.TIMEZONE} + * @type FieldType + */ + 'TIMEZONE' : { + module : 'form', + controller : 'timeZoneFieldController', + templateUrl : 'app/form/templates/timeZoneField.html' } }; diff --git a/guacamole/src/main/webapp/app/form/templates/timeZoneField.html b/guacamole/src/main/webapp/app/form/templates/timeZoneField.html new file mode 100644 index 000000000..e5db1b8a6 --- /dev/null +++ b/guacamole/src/main/webapp/app/form/templates/timeZoneField.html @@ -0,0 +1,14 @@ +
+ + + + + + + +
diff --git a/guacamole/src/main/webapp/app/rest/types/Field.js b/guacamole/src/main/webapp/app/rest/types/Field.js index 77dd8fff7..c5b913408 100644 --- a/guacamole/src/main/webapp/app/rest/types/Field.js +++ b/guacamole/src/main/webapp/app/rest/types/Field.js @@ -129,7 +129,16 @@ angular.module('rest').factory('Field', [function defineField() { * * @type String */ - MULTILINE : "MULTILINE" + MULTILINE : "MULTILINE", + + /** + * The type string associated with parameters that may contain timezone + * IDs. Valid timezone IDs are dictated by Java: + * http://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html#getAvailableIDs%28%29 + * + * @type String + */ + TIMEZONE : "TIMEZONE" };