From f079563daf486e0be4ef25998540dcb02f2be092 Mon Sep 17 00:00:00 2001 From: Philip Magyar Date: Thu, 22 Feb 2024 18:10:06 +0100 Subject: [PATCH 1/3] UI: sync country list & add flags to tb-contact country selector --- .../app/modules/home/models/contact.models.ts | 252 ------------------ .../shared/components/contact.component.html | 7 +- .../shared/components/contact.component.ts | 11 +- .../src/app/shared/models/country.models.ts | 15 ++ 4 files changed, 26 insertions(+), 259 deletions(-) diff --git a/ui-ngx/src/app/modules/home/models/contact.models.ts b/ui-ngx/src/app/modules/home/models/contact.models.ts index 41ebecc865..f1b23a0839 100644 --- a/ui-ngx/src/app/modules/home/models/contact.models.ts +++ b/ui-ngx/src/app/modules/home/models/contact.models.ts @@ -14,258 +14,6 @@ /// limitations under the License. /// -export const COUNTRIES = [ - 'Afghanistan', - 'ร…land Islands', - 'Albania', - 'Algeria', - 'American Samoa', - 'Andorra', - 'Angola', - 'Anguilla', - 'Antarctica', - 'Antigua and Barbuda', - 'Argentina', - 'Armenia', - 'Aruba', - 'Australia', - 'Austria', - 'Azerbaijan', - 'Bahamas', - 'Bahrain', - 'Bangladesh', - 'Barbados', - 'Belarus', - 'Belgium', - 'Belize', - 'Benin', - 'Bermuda', - 'Bhutan', - 'Bolivia', - 'Bonaire, Sint Eustatius and Saba', - 'Bosnia and Herzegovina', - 'Botswana', - 'Bouvet Island', - 'Brazil', - 'British Indian Ocean Territory', - 'Brunei Darussalam', - 'Bulgaria', - 'Burkina Faso', - 'Burundi', - 'Cambodia', - 'Cameroon', - 'Canada', - 'Cape Verde', - 'Cayman Islands', - 'Central African Republic', - 'Chad', - 'Chile', - 'China', - 'Christmas Island', - 'Cocos (Keeling) Islands', - 'Colombia', - 'Comoros', - 'Congo', - 'Congo, The Democratic Republic of the', - 'Cook Islands', - 'Costa Rica', - 'Cรดte d\'Ivoire', - 'Croatia', - 'Cuba', - 'Curaรงao', - 'Cyprus', - 'Czech Republic', - 'Denmark', - 'Djibouti', - 'Dominica', - 'Dominican Republic', - 'Ecuador', - 'Egypt', - 'El Salvador', - 'Equatorial Guinea', - 'Eritrea', - 'Estonia', - 'Ethiopia', - 'Falkland Islands (Malvinas)', - 'Faroe Islands', - 'Fiji', - 'Finland', - 'France', - 'French Guiana', - 'French Polynesia', - 'French Southern Territories', - 'Gabon', - 'Gambia', - 'Georgia', - 'Germany', - 'Ghana', - 'Gibraltar', - 'Greece', - 'Greenland', - 'Grenada', - 'Guadeloupe', - 'Guam', - 'Guatemala', - 'Guernsey', - 'Guinea', - 'Guinea-Bissau', - 'Guyana', - 'Haiti', - 'Heard Island and McDonald Islands', - 'Holy See (Vatican City State)', - 'Honduras', - 'Hong Kong', - 'Hungary', - 'Iceland', - 'India', - 'Indonesia', - 'Iran, Islamic Republic of', - 'Iraq', - 'Ireland', - 'Isle of Man', - 'Israel', - 'Italy', - 'Jamaica', - 'Japan', - 'Jersey', - 'Jordan', - 'Kazakhstan', - 'Kenya', - 'Kiribati', - 'Korea, Democratic People\'s Republic of', - 'Korea, Republic of', - 'Kuwait', - 'Kyrgyzstan', - 'Lao People\'s Democratic Republic', - 'Latvia', - 'Lebanon', - 'Lesotho', - 'Liberia', - 'Libya', - 'Liechtenstein', - 'Lithuania', - 'Luxembourg', - 'Macao', - 'Macedonia, Republic Of', - 'Madagascar', - 'Malawi', - 'Malaysia', - 'Maldives', - 'Mali', - 'Malta', - 'Marshall Islands', - 'Martinique', - 'Mauritania', - 'Mauritius', - 'Mayotte', - 'Mexico', - 'Micronesia, Federated States of', - 'Moldova, Republic of', - 'Monaco', - 'Mongolia', - 'Montenegro', - 'Montserrat', - 'Morocco', - 'Mozambique', - 'Myanmar', - 'Namibia', - 'Nauru', - 'Nepal', - 'Netherlands', - 'New Caledonia', - 'New Zealand', - 'Nicaragua', - 'Niger', - 'Nigeria', - 'Niue', - 'Norfolk Island', - 'Northern Mariana Islands', - 'Norway', - 'Oman', - 'Pakistan', - 'Palau', - 'Palestinian Territory, Occupied', - 'Panama', - 'Papua New Guinea', - 'Paraguay', - 'Peru', - 'Philippines', - 'Pitcairn', - 'Poland', - 'Portugal', - 'Puerto Rico', - 'Qatar', - 'Reunion', - 'Romania', - 'Russian Federation', - 'Rwanda', - 'Saint Barthรฉlemy', - 'Saint Helena, Ascension and Tristan da Cunha', - 'Saint Kitts and Nevis', - 'Saint Lucia', - 'Saint Martin (French Part)', - 'Saint Pierre and Miquelon', - 'Saint Vincent and the Grenadines', - 'Samoa', - 'San Marino', - 'Sao Tome and Principe', - 'Saudi Arabia', - 'Senegal', - 'Serbia', - 'Seychelles', - 'Sierra Leone', - 'Singapore', - 'Sint Maarten (Dutch Part)', - 'Slovakia', - 'Slovenia', - 'Solomon Islands', - 'Somalia', - 'South Africa', - 'South Georgia and the South Sandwich Islands', - 'South Sudan', - 'Spain', - 'Sri Lanka', - 'Sudan', - 'Suriname', - 'Svalbard and Jan Mayen', - 'Swaziland', - 'Sweden', - 'Switzerland', - 'Syrian Arab Republic', - 'Taiwan', - 'Tajikistan', - 'Tanzania, United Republic of', - 'Thailand', - 'Timor-Leste', - 'Togo', - 'Tokelau', - 'Tonga', - 'Trinidad and Tobago', - 'Tunisia', - 'Turkey', - 'Turkmenistan', - 'Turks and Caicos Islands', - 'Tuvalu', - 'Uganda', - 'Ukraine', - 'United Arab Emirates', - 'United Kingdom', - 'United States', - 'United States Minor Outlying Islands', - 'Uruguay', - 'Uzbekistan', - 'Vanuatu', - 'Venezuela', - 'Viet Nam', - 'Virgin Islands, British', - 'Virgin Islands, U.S.', - 'Wallis and Futuna', - 'Western Sahara', - 'Yemen', - 'Zambia', - 'Zimbabwe' -]; - /* eslint-disable */ export const POSTAL_CODE_PATTERNS = { 'United States': '(\\d{5}([\\-]\\d{4})?)', diff --git a/ui-ngx/src/app/shared/components/contact.component.html b/ui-ngx/src/app/shared/components/contact.component.html index 059fd09c80..c0688be71a 100644 --- a/ui-ngx/src/app/shared/components/contact.component.html +++ b/ui-ngx/src/app/shared/components/contact.component.html @@ -18,9 +18,10 @@
contact.country - - - {{ country }} + + + {{country.flag}} + {{country.name }} diff --git a/ui-ngx/src/app/shared/components/contact.component.ts b/ui-ngx/src/app/shared/components/contact.component.ts index c5a3daecf8..dae5f2ac0d 100644 --- a/ui-ngx/src/app/shared/components/contact.component.ts +++ b/ui-ngx/src/app/shared/components/contact.component.ts @@ -16,11 +16,13 @@ import { Component, Input } from '@angular/core'; import { UntypedFormGroup } from '@angular/forms'; -import { COUNTRIES } from '@home/models/contact.models'; - +import { CountryData } from '../models/country.models'; @Component({ selector: 'tb-contact', - templateUrl: './contact.component.html' + templateUrl: './contact.component.html', + providers: [ + CountryData + ] }) export class ContactComponent { @@ -29,6 +31,7 @@ export class ContactComponent { @Input() isEdit: boolean; - countries = COUNTRIES; + countries = this.countryData.allCountries; + constructor(private countryData: CountryData) {} } diff --git a/ui-ngx/src/app/shared/models/country.models.ts b/ui-ngx/src/app/shared/models/country.models.ts index 814cb81147..919d362067 100644 --- a/ui-ngx/src/app/shared/models/country.models.ts +++ b/ui-ngx/src/app/shared/models/country.models.ts @@ -32,6 +32,7 @@ export enum CountryISO { Andorra = 'AD', Angola = 'AO', Anguilla = 'AI', + Antarctica = 'AQ', AntiguaAndBarbuda = 'AG', Argentina = 'AR', Armenia = 'AM', @@ -50,6 +51,8 @@ export enum CountryISO { Bermuda = 'BM', Bhutan = 'BT', Bolivia = 'BO', + BonaireAndSintEustatiusAndSaba = 'BQ', + BouvetIsland = 'BV', BosniaAndHerzegovina = 'BA', Botswana = 'BW', Brazil = 'BR', @@ -101,6 +104,7 @@ export enum CountryISO { France = 'FR', FrenchGuiana = 'GF', FrenchPolynesia = 'PF', + FrenchSouthernTerritories = 'TF', Gabon = 'GA', Gambia = 'GM', Georgia = 'GE', @@ -118,6 +122,7 @@ export enum CountryISO { GuineaBissau = 'GW', Guyana = 'GY', Haiti = 'HT', + HeardIslandandMcDonaldIslands = 'HM', Honduras = 'HN', HongKong = 'HK', Hungary = 'HU', @@ -195,6 +200,7 @@ export enum CountryISO { Paraguay = 'PY', Peru = 'PE', Philippines = 'PH', + PitcairnIslands = 'PN', Poland = 'PL', Portugal = 'PT', PuertoRico = 'PR', @@ -225,6 +231,7 @@ export enum CountryISO { SolomonIslands = 'SB', Somalia = 'SO', SouthAfrica = 'ZA', + SouthGeorgiaAndTheSouthSandwichIslands = 'GS', SouthKorea = 'KR', SouthSudan = 'SS', Spain = 'ES', @@ -280,6 +287,7 @@ export class CountryData { {name: 'Andorra', iso2: CountryISO.Andorra, dialCode: '376', flag: '๐Ÿ‡ฆ๐Ÿ‡ฉ'}, {name: 'Angola', iso2: CountryISO.Angola, dialCode: '244', flag: '๐Ÿ‡ฆ๐Ÿ‡ด'}, {name: 'Anguilla', iso2: CountryISO.Anguilla, dialCode: '1', flag: '๐Ÿ‡ฆ๐Ÿ‡ฎ'}, + {name: 'Antarctica', iso2: CountryISO.Antarctica, dialCode: '672', flag: '๐Ÿ‡ฆ๐Ÿ‡ถ'}, {name: 'Antigua and Barbuda', iso2: CountryISO.AntiguaAndBarbuda, dialCode: '1', flag: '๐Ÿ‡ฆ๐Ÿ‡ฌ'}, {name: 'Argentina', iso2: CountryISO.Argentina, dialCode: '54', flag: '๐Ÿ‡ฆ๐Ÿ‡ท'}, {name: 'Armenia', iso2: CountryISO.Armenia, dialCode: '374', flag: '๐Ÿ‡ฆ๐Ÿ‡ฒ'}, @@ -298,6 +306,8 @@ export class CountryData { {name: 'Bermuda', iso2: CountryISO.Bermuda, dialCode: '1', flag: '๐Ÿ‡ง๐Ÿ‡ฒ'}, {name: 'Bhutan', iso2: CountryISO.Bhutan, dialCode: '975', flag: '๐Ÿ‡ง๐Ÿ‡น'}, {name: 'Bolivia', iso2: CountryISO.Bolivia, dialCode: '591', flag: '๐Ÿ‡ง๐Ÿ‡ด'}, + {name: 'Bonaire, Sint Eustatius and Saba', iso2: CountryISO.BonaireAndSintEustatiusAndSaba, dialCode: '599', flag: '๐Ÿ‡ง๐Ÿ‡ถ'}, + {name: 'Bouvet Island', iso2: CountryISO.BouvetIsland, dialCode: '47', flag: '๐Ÿ‡ง๐Ÿ‡ป'}, {name: 'Bosnia and Herzegovina', iso2: CountryISO.BosniaAndHerzegovina, dialCode: '387', flag: '๐Ÿ‡ง๐Ÿ‡ฆ'}, {name: 'Botswana', iso2: CountryISO.Botswana, dialCode: '267', flag: '๐Ÿ‡ง๐Ÿ‡ผ'}, {name: 'Brazil', iso2: CountryISO.Brazil, dialCode: '55', flag: '๐Ÿ‡ง๐Ÿ‡ท'}, @@ -349,6 +359,7 @@ export class CountryData { {name: 'France', iso2: CountryISO.France, dialCode: '33', flag: '๐Ÿ‡ซ๐Ÿ‡ท'}, {name: 'French Guiana', iso2: CountryISO.FrenchGuiana, dialCode: '594', flag: '๐Ÿ‡ฌ๐Ÿ‡ซ'}, {name: 'French Polynesia', iso2: CountryISO.FrenchPolynesia, dialCode: '689', flag: '๐Ÿ‡ต๐Ÿ‡ซ'}, + {name: 'French Southern Territories', iso2: CountryISO.FrenchSouthernTerritories, dialCode: '262', flag: '๐Ÿ‡น๐Ÿ‡ซ'}, {name: 'Gabon', iso2: CountryISO.Gabon, dialCode: '241', flag: '๐Ÿ‡ฌ๐Ÿ‡ฆ'}, {name: 'Gambia', iso2: CountryISO.Gambia, dialCode: '220', flag: '๐Ÿ‡ฌ๐Ÿ‡ฒ'}, {name: 'Georgia', iso2: CountryISO.Georgia, dialCode: '995', flag: '๐Ÿ‡ฌ๐Ÿ‡ช'}, @@ -366,6 +377,7 @@ export class CountryData { {name: 'Guinea-Bissau', iso2: CountryISO.GuineaBissau, dialCode: '245', flag: '๐Ÿ‡ฌ๐Ÿ‡ผ'}, {name: 'Guyana', iso2: CountryISO.Guyana, dialCode: '592', flag: '๐Ÿ‡ฌ๐Ÿ‡พ'}, {name: 'Haiti', iso2: CountryISO.Haiti, dialCode: '509', flag: '๐Ÿ‡ญ๐Ÿ‡น'}, + {name: 'Heard Island and McDonald Islands', iso2: CountryISO.HeardIslandandMcDonaldIslands, dialCode: '672', flag: '๐Ÿ‡ญ๐Ÿ‡ฒ'}, {name: 'Honduras', iso2: CountryISO.Honduras, dialCode: '504', flag: '๐Ÿ‡ญ๐Ÿ‡ณ'}, {name: 'Hong Kong', iso2: CountryISO.HongKong, dialCode: '852', flag: '๐Ÿ‡ญ๐Ÿ‡ฐ'}, {name: 'Hungary', iso2: CountryISO.Hungary, dialCode: '36', flag: '๐Ÿ‡ญ๐Ÿ‡บ'}, @@ -443,6 +455,7 @@ export class CountryData { {name: 'Paraguay', iso2: CountryISO.Paraguay, dialCode: '595', flag: '๐Ÿ‡ต๐Ÿ‡พ'}, {name: 'Peru', iso2: CountryISO.Peru, dialCode: '51', flag: '๐Ÿ‡ต๐Ÿ‡ช'}, {name: 'Philippines', iso2: CountryISO.Philippines, dialCode: '63', flag: '๐Ÿ‡ต๐Ÿ‡ญ'}, + {name: 'Pitcairn Islands', iso2: CountryISO.PitcairnIslands, dialCode: '649', flag: '๐Ÿ‡ต๐Ÿ‡ณ'}, {name: 'Poland', iso2: CountryISO.Poland, dialCode: '48', flag: '๐Ÿ‡ต๐Ÿ‡ฑ'}, {name: 'Portugal', iso2: CountryISO.Portugal, dialCode: '351', flag: '๐Ÿ‡ต๐Ÿ‡น'}, {name: 'Puerto Rico', iso2: CountryISO.PuertoRico, dialCode: '1', flag: '๐Ÿ‡ต๐Ÿ‡ท'}, @@ -473,6 +486,8 @@ export class CountryData { {name: 'Solomon Islands', iso2: CountryISO.SolomonIslands, dialCode: '677', flag: '๐Ÿ‡ธ๐Ÿ‡ง'}, {name: 'Somalia', iso2: CountryISO.Somalia, dialCode: '252', flag: '๐Ÿ‡ธ๐Ÿ‡ด'}, {name: 'South Africa', iso2: CountryISO.SouthAfrica, dialCode: '27', flag: '๐Ÿ‡ฟ๐Ÿ‡ฆ'}, + {name: 'South Georgia and the South Sandwich Islands', + iso2: CountryISO.SouthGeorgiaAndTheSouthSandwichIslands, dialCode: '500', flag: '๐Ÿ‡ฌ๐Ÿ‡ธ'}, {name: 'South Korea', iso2: CountryISO.SouthKorea, dialCode: '82', flag: '๐Ÿ‡ฐ๐Ÿ‡ท'}, {name: 'South Sudan', iso2: CountryISO.SouthSudan, dialCode: '211', flag: '๐Ÿ‡ธ๐Ÿ‡ธ'}, {name: 'Spain', iso2: CountryISO.Spain, dialCode: '34', flag: '๐Ÿ‡ช๐Ÿ‡ธ'}, From 4096a60612a7c3329830620764230e5fa27fb62a Mon Sep 17 00:00:00 2001 From: Philip Magyar Date: Thu, 29 Feb 2024 16:15:26 +0100 Subject: [PATCH 2/3] searchable countries --- .../shared/components/contact.component.html | 11 ++-- .../shared/components/contact.component.ts | 50 +++++++++++++++++-- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/ui-ngx/src/app/shared/components/contact.component.html b/ui-ngx/src/app/shared/components/contact.component.html index c0688be71a..6b997da07c 100644 --- a/ui-ngx/src/app/shared/components/contact.component.html +++ b/ui-ngx/src/app/shared/components/contact.component.html @@ -18,12 +18,13 @@
contact.country - - + + + {{country.flag}} {{country.name }} - +
@@ -56,7 +57,9 @@ contact.address2 - diff --git a/ui-ngx/src/app/shared/components/contact.component.ts b/ui-ngx/src/app/shared/components/contact.component.ts index dae5f2ac0d..410944f36a 100644 --- a/ui-ngx/src/app/shared/components/contact.component.ts +++ b/ui-ngx/src/app/shared/components/contact.component.ts @@ -14,9 +14,12 @@ /// limitations under the License. /// -import { Component, Input } from '@angular/core'; +import { Component, Input, OnInit, ViewChild } from '@angular/core'; import { UntypedFormGroup } from '@angular/forms'; -import { CountryData } from '../models/country.models'; +import { Country, CountryData } from '../models/country.models'; +import { Observable, map, startWith } from 'rxjs'; +import { PhoneInputComponent } from './phone-input.component'; +import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; @Component({ selector: 'tb-contact', templateUrl: './contact.component.html', @@ -24,14 +27,53 @@ import { CountryData } from '../models/country.models'; CountryData ] }) -export class ContactComponent { +export class ContactComponent implements OnInit { @Input() parentForm: UntypedFormGroup; @Input() isEdit: boolean; + @Input() phoneInputDefaultCountry = 'US'; + + @ViewChild('phoneInput') phoneInput: PhoneInputComponent | undefined; countries = this.countryData.allCountries; + countriesFiltered: Observable; + + constructor(private countryData: CountryData) { + this.displayCountryWithFlag = this.displayCountryWithFlag.bind(this); + } + + ngOnInit() { + this.countriesFiltered = this.parentForm.get('country').valueChanges + .pipe( + startWith(''), + map((countryName: string) => this._filterCountries(countryName)) + ); + } + + private _filterCountries(countryName: string): Country[] { + const filterValue = countryName.toLowerCase(); + return this.countries.filter(country => this.displayCountryWithFlag(country.name).toLowerCase().includes(filterValue)); + } + + displayCountryWithFlag(countryName: string): string { + const country = this.countries.find(c => c.name === countryName); + if (!country) { + return ''; + } + return country ? `${country.flag} ${country.name}` : ''; + } - constructor(private countryData: CountryData) {} + onCountryChange(select: MatAutocompleteSelectedEvent) { + // Get the selected country and check if the phone number is empty + // If it is, set the country code to the selected country + const countryName = select.option.value; + const country = this.countries.find(c => c.name === countryName); + if (country && this.phoneInput) { + if (!this.phoneInput.phoneFormGroup.get('phoneNumber').value) { + this.phoneInput.phoneFormGroup.get('country').setValue(country.iso2); + } + } + } } From 41b5fefd24ba622e95a1a13670209bb8f3a17c0c Mon Sep 17 00:00:00 2001 From: Vladyslav Prykhodko Date: Sun, 1 Sep 2024 17:28:22 +0300 Subject: [PATCH 3/3] UI: Add country autocomplete and refactoring code --- .../entity/contact-based.component.ts | 13 +- .../app/modules/home/models/contact.models.ts | 39 ---- .../home/pages/customer/customer.component.ts | 6 +- .../home/pages/tenant/tenant.component.ts | 6 +- .../shared/components/contact.component.html | 17 +- .../shared/components/contact.component.ts | 59 +---- .../country-autocomplete.component.html | 58 +++++ .../country-autocomplete.component.ts | 209 ++++++++++++++++++ .../src/app/shared/models/country.models.ts | 103 ++++----- ui-ngx/src/app/shared/shared.module.ts | 3 + .../assets/locale/locale.constant-en_US.json | 3 + 11 files changed, 358 insertions(+), 158 deletions(-) delete mode 100644 ui-ngx/src/app/modules/home/models/contact.models.ts create mode 100644 ui-ngx/src/app/shared/components/country-autocomplete.component.html create mode 100644 ui-ngx/src/app/shared/components/country-autocomplete.component.ts diff --git a/ui-ngx/src/app/modules/home/components/entity/contact-based.component.ts b/ui-ngx/src/app/modules/home/components/entity/contact-based.component.ts index 063de82ad2..2d08fd9f50 100644 --- a/ui-ngx/src/app/modules/home/components/entity/contact-based.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/contact-based.component.ts @@ -19,10 +19,10 @@ import { AppState } from '@core/core.state'; import { UntypedFormBuilder, UntypedFormGroup, ValidatorFn, Validators } from '@angular/forms'; import { ContactBased } from '@shared/models/contact-based.model'; import { AfterViewInit, ChangeDetectorRef, Directive } from '@angular/core'; -import { POSTAL_CODE_PATTERNS } from '@home/models/contact.models'; import { HasId } from '@shared/models/base-data'; import { EntityComponent } from './entity.component'; import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; +import { CountryData } from '@shared/models/country.models'; @Directive() export abstract class ContactBasedComponent> extends EntityComponent implements AfterViewInit { @@ -31,7 +31,8 @@ export abstract class ContactBasedComponent> exten protected fb: UntypedFormBuilder, protected entityValue: T, protected entitiesTableConfigValue: EntityTableConfig, - protected cd: ChangeDetectorRef) { + protected cd: ChangeDetectorRef, + protected countryData: CountryData) { super(store, fb, entityValue, entitiesTableConfigValue, cd); } @@ -75,9 +76,11 @@ export abstract class ContactBasedComponent> exten zipValidators(country: string): ValidatorFn[] { const zipValidators = []; - if (country && POSTAL_CODE_PATTERNS[country]) { - const postalCodePattern = POSTAL_CODE_PATTERNS[country]; - zipValidators.push(Validators.pattern(postalCodePattern)); + if (country) { + const postCodePattern = this.countryData.allCountries.find(item => item.name === country)?.postCodePattern; + if (postCodePattern) { + zipValidators.push(Validators.pattern(postCodePattern)); + } } return zipValidators; } diff --git a/ui-ngx/src/app/modules/home/models/contact.models.ts b/ui-ngx/src/app/modules/home/models/contact.models.ts deleted file mode 100644 index f1b23a0839..0000000000 --- a/ui-ngx/src/app/modules/home/models/contact.models.ts +++ /dev/null @@ -1,39 +0,0 @@ -/// -/// Copyright ยฉ 2016-2024 The Thingsboard Authors -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// - -/* eslint-disable */ -export const POSTAL_CODE_PATTERNS = { - 'United States': '(\\d{5}([\\-]\\d{4})?)', - 'Australia': '[0-9]{4}', - 'Austria': '[0-9]{4}', - 'Belgium': '[0-9]{4}', - 'Brazil': '[0-9]{5}[\\-]?[0-9]{3}', - 'Canada': '^(?!.*[DFIOQU])[A-VXY][0-9][A-Z][ -]?[0-9][A-Z][0-9]$', - 'Denmark': '[0-9]{3,4}', - 'Faroe Islands': '[0-9]{3,4}', - 'Netherlands': '[1-9][0-9]{3}\\s?[a-zA-Z]{2}', - 'Germany': '[0-9]{5}', - 'Hungary': '[0-9]{4}', - 'Italy': '[0-9]{5}', - 'Japan': '\\d{3}-\\d{4}', - 'Luxembourg': '(L\\s*(-|โ€”|โ€“))\\s*?[\\d]{4}', - 'Poland': '[0-9]{2}\\-[0-9]{3}', - 'Spain': '((0[1-9]|5[0-2])|[1-4][0-9])[0-9]{3}', - 'Sweden': '\\d{3}\\s?\\d{2}', - 'United Kingdom': '[A-Za-z]{1,2}[0-9Rr][0-9A-Za-z]? [0-9][ABD-HJLNP-UW-Zabd-hjlnp-uw-z]{2}' -}; -/* eslint-enable */ - diff --git a/ui-ngx/src/app/modules/home/pages/customer/customer.component.ts b/ui-ngx/src/app/modules/home/pages/customer/customer.component.ts index 8d04eb34c7..29ed565b6f 100644 --- a/ui-ngx/src/app/modules/home/pages/customer/customer.component.ts +++ b/ui-ngx/src/app/modules/home/pages/customer/customer.component.ts @@ -26,6 +26,7 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod import { isDefinedAndNotNull } from '@core/utils'; import { getCurrentAuthState } from '@core/auth/auth.selectors'; import { AuthState } from '@core/auth/auth.models'; +import { CountryData } from '@shared/models/country.models'; @Component({ selector: 'tb-customer', @@ -43,8 +44,9 @@ export class CustomerComponent extends ContactBasedComponent { @Inject('entity') protected entityValue: Customer, @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig, protected fb: UntypedFormBuilder, - protected cd: ChangeDetectorRef) { - super(store, fb, entityValue, entitiesTableConfigValue, cd); + protected cd: ChangeDetectorRef, + protected countryData: CountryData) { + super(store, fb, entityValue, entitiesTableConfigValue, cd, countryData); } hideDelete() { diff --git a/ui-ngx/src/app/modules/home/pages/tenant/tenant.component.ts b/ui-ngx/src/app/modules/home/pages/tenant/tenant.component.ts index e35d990ecb..9858850437 100644 --- a/ui-ngx/src/app/modules/home/pages/tenant/tenant.component.ts +++ b/ui-ngx/src/app/modules/home/pages/tenant/tenant.component.ts @@ -24,6 +24,7 @@ import { TranslateService } from '@ngx-translate/core'; import { ContactBasedComponent } from '../../components/entity/contact-based.component'; import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; import { isDefinedAndNotNull } from '@core/utils'; +import { CountryData } from '@shared/models/country.models'; @Component({ selector: 'tb-tenant', @@ -37,8 +38,9 @@ export class TenantComponent extends ContactBasedComponent { @Inject('entity') protected entityValue: TenantInfo, @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig, protected fb: UntypedFormBuilder, - protected cd: ChangeDetectorRef) { - super(store, fb, entityValue, entitiesTableConfigValue, cd); + protected cd: ChangeDetectorRef, + protected countryData: CountryData) { + super(store, fb, entityValue, entitiesTableConfigValue, cd, countryData); } hideDelete() { diff --git a/ui-ngx/src/app/shared/components/contact.component.html b/ui-ngx/src/app/shared/components/contact.component.html index 6b997da07c..0f4038abe9 100644 --- a/ui-ngx/src/app/shared/components/contact.component.html +++ b/ui-ngx/src/app/shared/components/contact.component.html @@ -16,16 +16,10 @@ -->
- - contact.country - - - - {{country.flag}} - {{country.name }} - - - + +
contact.city @@ -57,8 +51,7 @@ contact.address2 - ; - - constructor(private countryData: CountryData) { - this.displayCountryWithFlag = this.displayCountryWithFlag.bind(this); - } - - ngOnInit() { - this.countriesFiltered = this.parentForm.get('country').valueChanges - .pipe( - startWith(''), - map((countryName: string) => this._filterCountries(countryName)) - ); - } - private _filterCountries(countryName: string): Country[] { - const filterValue = countryName.toLowerCase(); - return this.countries.filter(country => this.displayCountryWithFlag(country.name).toLowerCase().includes(filterValue)); - } + phoneInputDefaultCountry = 'US'; - displayCountryWithFlag(countryName: string): string { - const country = this.countries.find(c => c.name === countryName); - if (!country) { - return ''; - } - return country ? `${country.flag} ${country.name}` : ''; + constructor() { } - onCountryChange(select: MatAutocompleteSelectedEvent) { - // Get the selected country and check if the phone number is empty - // If it is, set the country code to the selected country - const countryName = select.option.value; - const country = this.countries.find(c => c.name === countryName); - if (country && this.phoneInput) { - if (!this.phoneInput.phoneFormGroup.get('phoneNumber').value) { - this.phoneInput.phoneFormGroup.get('country').setValue(country.iso2); - } - } + changeCountry(countryCode: string) { + this.phoneInputDefaultCountry = countryCode ?? 'US'; + setTimeout(() => { + this.parentForm.get('phone').setValue(this.parentForm.get('phone').value); + }); } } diff --git a/ui-ngx/src/app/shared/components/country-autocomplete.component.html b/ui-ngx/src/app/shared/components/country-autocomplete.component.html new file mode 100644 index 0000000000..eadf630dcd --- /dev/null +++ b/ui-ngx/src/app/shared/components/country-autocomplete.component.html @@ -0,0 +1,58 @@ + + + {{ labelText }} + + + + + {{country.flag}} + + + +
+
+ contact.no-country-found +
+ + + {{ 'contact.no-country-matching' | translate: + {country: (searchText | truncate: true: 6: '...')} }} + + +
+
+
+ {{ autocompleteHint }} + + {{ requiredText }} + +
diff --git a/ui-ngx/src/app/shared/components/country-autocomplete.component.ts b/ui-ngx/src/app/shared/components/country-autocomplete.component.ts new file mode 100644 index 0000000000..7fc3a10bca --- /dev/null +++ b/ui-ngx/src/app/shared/components/country-autocomplete.component.ts @@ -0,0 +1,209 @@ +/// +/// Copyright ยฉ 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Component, ElementRef, EventEmitter, forwardRef, Input, OnInit, Output, ViewChild } from '@angular/core'; +import { Country, CountryData } from '@shared/models/country.models'; +import { + ControlValueAccessor, + FormBuilder, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + ValidationErrors, + Validator +} from '@angular/forms'; +import { isNotEmptyStr } from '@core/utils'; +import { Observable, of } from 'rxjs'; +import { debounceTime, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; +import { SubscriptSizing } from '@angular/material/form-field'; +import { coerceBoolean } from '@shared/decorators/coercion'; +import { TranslateService } from '@ngx-translate/core'; + +interface CountrySearchData extends Country { + searchText?: string; +} + +@Component({ + selector: 'tb-country-autocomplete', + templateUrl: 'country-autocomplete.component.html', + providers: [ + CountryData, + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CountryAutocompleteComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => CountryAutocompleteComponent), + multi: true + } + ] +}) +export class CountryAutocompleteComponent implements OnInit, ControlValueAccessor, Validator { + + @Input() + labelText = this.translate.instant('contact.country'); + + @Input() + requiredText = this.translate.instant('contact.country-required'); + + @Input() + autocompleteHint: string; + + @Input() + disabled: boolean; + + @Input() + @coerceBoolean() + required = false; + + @Input() + subscriptSizing: SubscriptSizing = 'fixed'; + + @ViewChild('countryInput', {static: true}) countryInput: ElementRef; + + @Output() + selectCountryCode = new EventEmitter(); + + countryFormGroup: FormGroup; + + searchText = ''; + + filteredCountries: Observable>; + + onTouched = () => { + }; + private propagateChange: (value: any) => void = () => { + }; + + private modelValue: Country; + + private allCountries: CountrySearchData[] = this.countryData.allCountries; + private initSearchData = false; + private dirty = false; + + constructor(private fb: FormBuilder, + private countryData: CountryData, + private translate: TranslateService) { + this.countryFormGroup = this.fb.group({ + country: [''] + }); + } + + ngOnInit(): void { + this.filteredCountries = this.countryFormGroup.get('country').valueChanges.pipe( + debounceTime(150), + tap(value => { + let modelValue: Country; + if (typeof value === 'string' || !value) { + modelValue = null; + } else { + modelValue = value; + } + this.updateView(modelValue); + if (value === null) { + this.clear(); + } + }), + map(value => value ? (typeof value === 'string' ? value : value.name) : ''), + distinctUntilChanged(), + switchMap(name => of(this.fetchCountries(name))), + share() + ); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + this.onTouched = fn; + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.countryFormGroup.disable({emitEvent: false}); + } else { + this.countryFormGroup.enable({emitEvent: false}); + } + } + + validate(): ValidationErrors | null { + return this.countryFormGroup.valid ? null : { + countryFormGroup: false + }; + } + + writeValue(country: string) { + this.dirty = true; + + const findCountry = isNotEmptyStr(country) ? this.allCountries.find(item => item.name === country) : null; + + this.modelValue = findCountry || null; + this.countryFormGroup.get('country').patchValue(this.modelValue || '', { emitEvent: false }); + this.selectCountryCode.emit(this.modelValue ? this.modelValue.iso2 : null); + } + + displayCountryFn(country?: Country): string | undefined { + return country ? `${country.flag} ${country.name}` : undefined; + } + + onFocus() { + if (this.dirty) { + this.countryFormGroup.get('country').updateValueAndValidity({onlySelf: true}); + this.dirty = false; + } + } + + textIsNotEmpty(text: string): boolean { + return (text && text.length > 0); + } + + clear() { + this.countryFormGroup.get('country').patchValue('', {emitEvent: true}); + setTimeout(() => { + this.countryInput.nativeElement.blur(); + this.countryInput.nativeElement.focus(); + }, 0); + } + + private fetchCountries(searchText: string): Country[] { + this.searchText = searchText; + if (!this.initSearchData) { + this.allCountries.forEach(country => { + country.searchText = `${country.name} ${country.iso2}`.toLowerCase(); + }); + this.initSearchData = true; + } + if (isNotEmptyStr(searchText)) { + const filterValue = searchText.toLowerCase(); + return this.allCountries.filter(country => country.searchText.includes(filterValue)); + } + return this.allCountries; + } + + private updateView(value: Country | null) { + if (this.modelValue?.name !== value?.name) { + this.modelValue = value; + this.propagateChange(this.modelValue); + if (value) { + this.selectCountryCode.emit(value.iso2); + } + } + } +} diff --git a/ui-ngx/src/app/shared/models/country.models.ts b/ui-ngx/src/app/shared/models/country.models.ts index 919d362067..d8563e2449 100644 --- a/ui-ngx/src/app/shared/models/country.models.ts +++ b/ui-ngx/src/app/shared/models/country.models.ts @@ -22,6 +22,7 @@ export interface Country { dialCode: string; areaCodes?: string[]; flag: string; + postCodePattern?: RegExp; } export enum CountryISO { @@ -80,10 +81,10 @@ export enum CountryISO { CongoRepublicCongoBrazzaville = 'CG', CookIslands = 'CK', CostaRica = 'CR', - CรดteDIvoire = 'CI', + CoteDivoire = 'CI', Croatia = 'HR', Cuba = 'CU', - Curaรงao = 'CW', + Curacao = 'CW', Cyprus = 'CY', CzechRepublic = 'CZ', Denmark = 'DK', @@ -155,7 +156,6 @@ export enum CountryISO { Lithuania = 'LT', Luxembourg = 'LU', Macau = 'MO', - Macedonia = 'MK', Madagascar = 'MG', Malawi = 'MW', Malaysia = 'MY', @@ -189,6 +189,7 @@ export enum CountryISO { Niue = 'NU', NorfolkIsland = 'NF', NorthKorea = 'KP', + NorthMacedonia = 'MK', NorthernMarianaIslands = 'MP', Norway = 'NO', Oman = 'OM', @@ -205,11 +206,11 @@ export enum CountryISO { Portugal = 'PT', PuertoRico = 'PR', Qatar = 'QA', - Rรฉunion = 'RE', + Reunion = 'RE', Romania = 'RO', Russia = 'RU', Rwanda = 'RW', - SaintBarthรฉlemy = 'BL', + SaintBarthelemy = 'BL', SaintHelena = 'SH', SaintKittsAndNevis = 'KN', SaintLucia = 'LC', @@ -218,7 +219,7 @@ export enum CountryISO { SaintVincentAndTheGrenadines = 'VC', Samoa = 'WS', SanMarino = 'SM', - SรฃoTomรฉAndPrรญncipe = 'ST', + SaoTomeAndPrincipe = 'ST', SaudiArabia = 'SA', Senegal = 'SN', Serbia = 'RS', @@ -274,9 +275,10 @@ export enum CountryISO { Yemen = 'YE', Zambia = 'ZM', Zimbabwe = 'ZW', - ร…landIslands = 'AX', + AlandIslands = 'AX', } +/* eslint-disable max-len */ @Injectable() export class CountryData { public allCountries: Array = [ @@ -292,15 +294,15 @@ export class CountryData { {name: 'Argentina', iso2: CountryISO.Argentina, dialCode: '54', flag: '๐Ÿ‡ฆ๐Ÿ‡ท'}, {name: 'Armenia', iso2: CountryISO.Armenia, dialCode: '374', flag: '๐Ÿ‡ฆ๐Ÿ‡ฒ'}, {name: 'Aruba', iso2: CountryISO.Aruba, dialCode: '297', flag: '๐Ÿ‡ฆ๐Ÿ‡ผ'}, - {name: 'Australia', iso2: CountryISO.Australia, dialCode: '61', flag: '๐Ÿ‡ฆ๐Ÿ‡บ'}, - {name: 'Austria', iso2: CountryISO.Austria, dialCode: '43', flag: '๐Ÿ‡ฆ๐Ÿ‡น'}, + {name: 'Australia', iso2: CountryISO.Australia, dialCode: '61', flag: '๐Ÿ‡ฆ๐Ÿ‡บ', postCodePattern: /[0-9]{4}/}, + {name: 'Austria', iso2: CountryISO.Austria, dialCode: '43', flag: '๐Ÿ‡ฆ๐Ÿ‡น', postCodePattern: /[0-9]{4}/}, {name: 'Azerbaijan', iso2: CountryISO.Azerbaijan, dialCode: '994', flag: '๐Ÿ‡ฆ๐Ÿ‡ฟ'}, {name: 'Bahamas', iso2: CountryISO.Bahamas, dialCode: '1', flag: '๐Ÿ‡ง๐Ÿ‡ธ'}, {name: 'Bahrain', iso2: CountryISO.Bahrain, dialCode: '973', flag: '๐Ÿ‡ง๐Ÿ‡ญ'}, {name: 'Bangladesh', iso2: CountryISO.Bangladesh, dialCode: '880', flag: '๐Ÿ‡ง๐Ÿ‡ฉ'}, {name: 'Barbados', iso2: CountryISO.Barbados, dialCode: '1', flag: '๐Ÿ‡ง๐Ÿ‡ง'}, {name: 'Belarus', iso2: CountryISO.Belarus, dialCode: '375', flag: '๐Ÿ‡ง๐Ÿ‡พ'}, - {name: 'Belgium', iso2: CountryISO.Belgium, dialCode: '32', flag: '๐Ÿ‡ง๐Ÿ‡ช'}, + {name: 'Belgium', iso2: CountryISO.Belgium, dialCode: '32', flag: '๐Ÿ‡ง๐Ÿ‡ช', postCodePattern: /[0-9]{4}/}, {name: 'Belize', iso2: CountryISO.Belize, dialCode: '501', flag: '๐Ÿ‡ง๐Ÿ‡ฟ'}, {name: 'Benin', iso2: CountryISO.Benin, dialCode: '229', flag: '๐Ÿ‡ง๐Ÿ‡ฏ'}, {name: 'Bermuda', iso2: CountryISO.Bermuda, dialCode: '1', flag: '๐Ÿ‡ง๐Ÿ‡ฒ'}, @@ -310,16 +312,16 @@ export class CountryData { {name: 'Bouvet Island', iso2: CountryISO.BouvetIsland, dialCode: '47', flag: '๐Ÿ‡ง๐Ÿ‡ป'}, {name: 'Bosnia and Herzegovina', iso2: CountryISO.BosniaAndHerzegovina, dialCode: '387', flag: '๐Ÿ‡ง๐Ÿ‡ฆ'}, {name: 'Botswana', iso2: CountryISO.Botswana, dialCode: '267', flag: '๐Ÿ‡ง๐Ÿ‡ผ'}, - {name: 'Brazil', iso2: CountryISO.Brazil, dialCode: '55', flag: '๐Ÿ‡ง๐Ÿ‡ท'}, + {name: 'Brazil', iso2: CountryISO.Brazil, dialCode: '55', flag: '๐Ÿ‡ง๐Ÿ‡ท', postCodePattern: /[0-9]{5}-?[0-9]{3}/}, {name: 'British Indian Ocean Territory', iso2: CountryISO.BritishIndianOceanTerritory, dialCode: '246', flag: '๐Ÿ‡ฎ๐Ÿ‡ด'}, {name: 'British Virgin Islands', iso2: CountryISO.BritishVirginIslands, dialCode: '1', flag: '๐Ÿ‡ป๐Ÿ‡ฌ'}, - {name: 'Brunei', iso2: CountryISO.Brunei, dialCode: '673', flag: '๐Ÿ‡ง๐Ÿ‡ณ'}, + {name: 'Brunei Darussalam', iso2: CountryISO.Brunei, dialCode: '673', flag: '๐Ÿ‡ง๐Ÿ‡ณ'}, {name: 'Bulgaria', iso2: CountryISO.Bulgaria, dialCode: '359', flag: '๐Ÿ‡ง๐Ÿ‡ฌ'}, {name: 'Burkina Faso', iso2: CountryISO.BurkinaFaso, dialCode: '226', flag: '๐Ÿ‡ง๐Ÿ‡ซ'}, {name: 'Burundi', iso2: CountryISO.Burundi, dialCode: '257', flag: '๐Ÿ‡ง๐Ÿ‡ฎ'}, {name: 'Cambodia', iso2: CountryISO.Cambodia, dialCode: '855', flag: '๐Ÿ‡ฐ๐Ÿ‡ญ'}, {name: 'Cameroon', iso2: CountryISO.Cameroon, dialCode: '237', flag: '๐Ÿ‡จ๐Ÿ‡ฒ'}, - {name: 'Canada', iso2: CountryISO.Canada, dialCode: '1', flag: '๐Ÿ‡จ๐Ÿ‡ฆ'}, + {name: 'Canada', iso2: CountryISO.Canada, dialCode: '1', flag: '๐Ÿ‡จ๐Ÿ‡ฆ', postCodePattern: /^(?!.*[DFIOQU])[A-VXY][0-9][A-Z][ -]?[0-9][A-Z][0-9]$/}, {name: 'Cape Verde', iso2: CountryISO.CapeVerde, dialCode: '238', flag: '๐Ÿ‡จ๐Ÿ‡ป'}, {name: 'Caribbean Netherlands', iso2: CountryISO.CaribbeanNetherlands, dialCode: '599', flag: '๐Ÿ‡ง๐Ÿ‡ถ'}, {name: 'Cayman Islands', iso2: CountryISO.CaymanIslands, dialCode: '1', flag: '๐Ÿ‡ฐ๐Ÿ‡พ'}, @@ -328,20 +330,20 @@ export class CountryData { {name: 'Chile', iso2: CountryISO.Chile, dialCode: '56', flag: '๐Ÿ‡จ๐Ÿ‡ฑ'}, {name: 'China', iso2: CountryISO.China, dialCode: '86', flag: '๐Ÿ‡จ๐Ÿ‡ณ'}, {name: 'Christmas Island', iso2: CountryISO.ChristmasIsland, dialCode: '61', flag: '๐Ÿ‡จ๐Ÿ‡ฝ'}, - {name: 'Cocos Islands', iso2: CountryISO.Cocos, dialCode: '61', flag: '๐Ÿ‡จ๐Ÿ‡จ'}, + {name: 'Cocos (Keeling) Islands', iso2: CountryISO.Cocos, dialCode: '61', flag: '๐Ÿ‡จ๐Ÿ‡จ'}, {name: 'Colombia', iso2: CountryISO.Colombia, dialCode: '57', flag: '๐Ÿ‡จ๐Ÿ‡จ'}, {name: 'Comoros', iso2: CountryISO.Comoros, dialCode: '269', flag: '๐Ÿ‡ฐ๐Ÿ‡ฒ'}, - {name: 'Congo-Kinshasa', iso2: CountryISO.CongoDRCJamhuriYaKidemokrasiaYaKongo, dialCode: '243', flag: '๐Ÿ‡จ๐Ÿ‡ฉ'}, - {name: 'Congo-Brazzaville', iso2: CountryISO.CongoRepublicCongoBrazzaville, dialCode: '242', flag: '๐Ÿ‡จ๐Ÿ‡ฌ'}, + {name: 'Congo', iso2: CountryISO.CongoDRCJamhuriYaKidemokrasiaYaKongo, dialCode: '243', flag: '๐Ÿ‡จ๐Ÿ‡ฉ'}, + {name: 'Congo, Democratic Republic of the', iso2: CountryISO.CongoRepublicCongoBrazzaville, dialCode: '242', flag: '๐Ÿ‡จ๐Ÿ‡ฌ'}, {name: 'Cook Islands', iso2: CountryISO.CookIslands, dialCode: '682', flag: '๐Ÿ‡จ๐Ÿ‡ฐ'}, {name: 'Costa Rica', iso2: CountryISO.CostaRica, dialCode: '506', flag: '๐Ÿ‡จ๐Ÿ‡ท'}, - {name: 'Cรดte dโ€™Ivoire', iso2: CountryISO.CรดteDIvoire, dialCode: '225', flag: '๐Ÿ‡จ๐Ÿ‡ฎ'}, + {name: 'Cรดte d\'Ivoire', iso2: CountryISO.CoteDivoire, dialCode: '225', flag: '๐Ÿ‡จ๐Ÿ‡ฎ'}, {name: 'Croatia', iso2: CountryISO.Croatia, dialCode: '385', flag: '๐Ÿ‡ญ๐Ÿ‡ท'}, {name: 'Cuba', iso2: CountryISO.Cuba, dialCode: '53', flag: '๐Ÿ‡จ๐Ÿ‡บ'}, - {name: 'Curaรงao', iso2: CountryISO.Curaรงao, dialCode: '599', flag: '๐Ÿ‡จ๐Ÿ‡ผ'}, + {name: 'Curaรงao', iso2: CountryISO.Curacao, dialCode: '599', flag: '๐Ÿ‡จ๐Ÿ‡ผ'}, {name: 'Cyprus', iso2: CountryISO.Cyprus, dialCode: '357', flag: '๐Ÿ‡จ๐Ÿ‡พ'}, {name: 'Czech Republic', iso2: CountryISO.CzechRepublic, dialCode: '420', flag: '๐Ÿ‡จ๐Ÿ‡ฟ'}, - {name: 'Denmark', iso2: CountryISO.Denmark, dialCode: '45', flag: '๐Ÿ‡ฉ๐Ÿ‡ฐ'}, + {name: 'Denmark', iso2: CountryISO.Denmark, dialCode: '45', flag: '๐Ÿ‡ฉ๐Ÿ‡ฐ', postCodePattern: /[0-9]{3,4}/}, {name: 'Djibouti', iso2: CountryISO.Djibouti, dialCode: '253', flag: '๐Ÿ‡ฉ๐Ÿ‡ฏ'}, {name: 'Dominica', iso2: CountryISO.Dominica, dialCode: '1767', flag: '๐Ÿ‡ฉ๐Ÿ‡ฒ'}, {name: 'Dominican Republic', iso2: CountryISO.DominicanRepublic, dialCode: '1', flag: '๐Ÿ‡ฉ๐Ÿ‡ด'}, @@ -352,8 +354,8 @@ export class CountryData { {name: 'Eritrea', iso2: CountryISO.Eritrea, dialCode: '291', flag: '๐Ÿ‡ช๐Ÿ‡ท'}, {name: 'Estonia', iso2: CountryISO.Estonia, dialCode: '372', flag: '๐Ÿ‡ช๐Ÿ‡ช'}, {name: 'Ethiopia', iso2: CountryISO.Ethiopia, dialCode: '251', flag: '๐Ÿ‡ช๐Ÿ‡น'}, - {name: 'Falkland Islands', iso2: CountryISO.FalklandIslands, dialCode: '500', flag: '๐Ÿ‡ซ๐Ÿ‡ฐ'}, - {name: 'Faroe Islands', iso2: CountryISO.FaroeIslands, dialCode: '298', flag: '๐Ÿ‡ซ๐Ÿ‡ด'}, + {name: 'Falkland Islands (Malvinas)', iso2: CountryISO.FalklandIslands, dialCode: '500', flag: '๐Ÿ‡ซ๐Ÿ‡ฐ'}, + {name: 'Faroe Islands', iso2: CountryISO.FaroeIslands, dialCode: '298', flag: '๐Ÿ‡ซ๐Ÿ‡ด', postCodePattern: /[0-9]{3,4}/}, {name: 'Fiji', iso2: CountryISO.Fiji, dialCode: '679', flag: '๐Ÿ‡ซ๐Ÿ‡ฏ'}, {name: 'Finland', iso2: CountryISO.Finland, dialCode: '358', flag: '๐Ÿ‡ซ๐Ÿ‡ฎ'}, {name: 'France', iso2: CountryISO.France, dialCode: '33', flag: '๐Ÿ‡ซ๐Ÿ‡ท'}, @@ -363,7 +365,7 @@ export class CountryData { {name: 'Gabon', iso2: CountryISO.Gabon, dialCode: '241', flag: '๐Ÿ‡ฌ๐Ÿ‡ฆ'}, {name: 'Gambia', iso2: CountryISO.Gambia, dialCode: '220', flag: '๐Ÿ‡ฌ๐Ÿ‡ฒ'}, {name: 'Georgia', iso2: CountryISO.Georgia, dialCode: '995', flag: '๐Ÿ‡ฌ๐Ÿ‡ช'}, - {name: 'Germany', iso2: CountryISO.Germany, dialCode: '49', flag: '๐Ÿ‡ฉ๐Ÿ‡ช'}, + {name: 'Germany', iso2: CountryISO.Germany, dialCode: '49', flag: '๐Ÿ‡ฉ๐Ÿ‡ช', postCodePattern: /[0-9]{5}/}, {name: 'Ghana', iso2: CountryISO.Ghana, dialCode: '233', flag: '๐Ÿ‡ฌ๐Ÿ‡ญ'}, {name: 'Gibraltar', iso2: CountryISO.Gibraltar, dialCode: '350', flag: '๐Ÿ‡ฌ๐Ÿ‡ฎ'}, {name: 'Greece', iso2: CountryISO.Greece, dialCode: '30', flag: '๐Ÿ‡ฌ๐Ÿ‡ท'}, @@ -380,18 +382,18 @@ export class CountryData { {name: 'Heard Island and McDonald Islands', iso2: CountryISO.HeardIslandandMcDonaldIslands, dialCode: '672', flag: '๐Ÿ‡ญ๐Ÿ‡ฒ'}, {name: 'Honduras', iso2: CountryISO.Honduras, dialCode: '504', flag: '๐Ÿ‡ญ๐Ÿ‡ณ'}, {name: 'Hong Kong', iso2: CountryISO.HongKong, dialCode: '852', flag: '๐Ÿ‡ญ๐Ÿ‡ฐ'}, - {name: 'Hungary', iso2: CountryISO.Hungary, dialCode: '36', flag: '๐Ÿ‡ญ๐Ÿ‡บ'}, + {name: 'Hungary', iso2: CountryISO.Hungary, dialCode: '36', flag: '๐Ÿ‡ญ๐Ÿ‡บ', postCodePattern: /[0-9]{4}/}, {name: 'Iceland', iso2: CountryISO.Iceland, dialCode: '354', flag: '๐Ÿ‡ฎ๐Ÿ‡ธ'}, {name: 'India', iso2: CountryISO.India, dialCode: '91', flag: '๐Ÿ‡ฎ๐Ÿ‡ณ'}, {name: 'Indonesia', iso2: CountryISO.Indonesia, dialCode: '62', flag: '๐Ÿ‡ฎ๐Ÿ‡ฉ'}, - {name: 'Iran', iso2: CountryISO.Iran, dialCode: '98', flag: '๐Ÿ‡ฎ๐Ÿ‡ท'}, + {name: 'Islamic Republic of Iran', iso2: CountryISO.Iran, dialCode: '98', flag: '๐Ÿ‡ฎ๐Ÿ‡ท'}, {name: 'Iraq', iso2: CountryISO.Iraq, dialCode: '964', flag: '๐Ÿ‡ฎ๐Ÿ‡ถ'}, {name: 'Ireland', iso2: CountryISO.Ireland, dialCode: '353', flag: '๐Ÿ‡ฎ๐Ÿ‡ช'}, {name: 'Isle of Man', iso2: CountryISO.IsleOfMan, dialCode: '44', flag: '๐Ÿ‡ฎ๐Ÿ‡ฒ'}, {name: 'Israel', iso2: CountryISO.Israel, dialCode: '972', flag: '๐Ÿ‡ฎ๐Ÿ‡ฑ'}, - {name: 'Italy', iso2: CountryISO.Italy, dialCode: '39', flag: '๐Ÿ‡ฎ๐Ÿ‡น'}, + {name: 'Italy', iso2: CountryISO.Italy, dialCode: '39', flag: '๐Ÿ‡ฎ๐Ÿ‡น', postCodePattern: /[0-9]{5}/}, {name: 'Jamaica', iso2: CountryISO.Jamaica, dialCode: '1', flag: '๐Ÿ‡ฏ๐Ÿ‡ฒ'}, - {name: 'Japan', iso2: CountryISO.Japan, dialCode: '81', flag: '๐Ÿ‡ฏ๐Ÿ‡ต'}, + {name: 'Japan', iso2: CountryISO.Japan, dialCode: '81', flag: '๐Ÿ‡ฏ๐Ÿ‡ต', postCodePattern: /\d{3}-\d{4}/}, {name: 'Jersey', iso2: CountryISO.Jersey, dialCode: '44', flag: '๐Ÿ‡ฏ๐Ÿ‡ช'}, {name: 'Jordan', iso2: CountryISO.Jordan, dialCode: '962', flag: '๐Ÿ‡ฏ๐Ÿ‡ด'}, {name: 'Kazakhstan', iso2: CountryISO.Kazakhstan, dialCode: '7', flag: '๐Ÿ‡ฐ๐Ÿ‡ฟ'}, @@ -400,7 +402,7 @@ export class CountryData { {name: 'Kosovo', iso2: CountryISO.Kosovo, dialCode: '383', flag: '๐Ÿ‡ฝ๐Ÿ‡ฐ'}, {name: 'Kuwait', iso2: CountryISO.Kuwait, dialCode: '965', flag: '๐Ÿ‡ฐ๐Ÿ‡ผ'}, {name: 'Kyrgyzstan', iso2: CountryISO.Kyrgyzstan, dialCode: '996', flag: '๐Ÿ‡ฐ๐Ÿ‡ฌ'}, - {name: 'Laos', iso2: CountryISO.Laos, dialCode: '856', flag: '๐Ÿ‡ฑ๐Ÿ‡ฆ'}, + {name: 'Lao People\'s Democratic Republic', iso2: CountryISO.Laos, dialCode: '856', flag: '๐Ÿ‡ฑ๐Ÿ‡ฆ'}, {name: 'Latvia', iso2: CountryISO.Latvia, dialCode: '371', flag: '๐Ÿ‡ฑ๐Ÿ‡ป'}, {name: 'Lebanon', iso2: CountryISO.Lebanon, dialCode: '961', flag: '๐Ÿ‡ฑ๐Ÿ‡ง'}, {name: 'Lesotho', iso2: CountryISO.Lesotho, dialCode: '266', flag: '๐Ÿ‡ฑ๐Ÿ‡ธ'}, @@ -408,9 +410,8 @@ export class CountryData { {name: 'Libya', iso2: CountryISO.Libya, dialCode: '218', flag: '๐Ÿ‡ฑ๐Ÿ‡พ'}, {name: 'Liechtenstein', iso2: CountryISO.Liechtenstein, dialCode: '423', flag: '๐Ÿ‡ฑ๐Ÿ‡ฎ'}, {name: 'Lithuania', iso2: CountryISO.Lithuania, dialCode: '370', flag: '๐Ÿ‡ฑ๐Ÿ‡น'}, - {name: 'Luxembourg', iso2: CountryISO.Luxembourg, dialCode: '352', flag: '๐Ÿ‡ฑ๐Ÿ‡บ'}, - {name: 'Macau', iso2: CountryISO.Macau, dialCode: '853', flag: '๐Ÿ‡ฒ๐Ÿ‡ด'}, - {name: 'Macedonia', iso2: CountryISO.Macedonia, dialCode: '389', flag: '๐Ÿ‡ฒ๐Ÿ‡ฐ'}, + {name: 'Luxembourg', iso2: CountryISO.Luxembourg, dialCode: '352', flag: '๐Ÿ‡ฑ๐Ÿ‡บ', postCodePattern: /(L\s*([-โ€”โ€“]))\s*?\d{4}/}, + {name: 'Macao', iso2: CountryISO.Macau, dialCode: '853', flag: '๐Ÿ‡ฒ๐Ÿ‡ด'}, {name: 'Madagascar', iso2: CountryISO.Madagascar, dialCode: '261', flag: '๐Ÿ‡ฒ๐Ÿ‡ฌ'}, {name: 'Malawi', iso2: CountryISO.Malawi, dialCode: '265', flag: '๐Ÿ‡ฒ๐Ÿ‡ผ'}, {name: 'Malaysia', iso2: CountryISO.Malaysia, dialCode: '60', flag: '๐Ÿ‡ฒ๐Ÿ‡พ'}, @@ -423,8 +424,8 @@ export class CountryData { {name: 'Mauritius', iso2: CountryISO.Mauritius, dialCode: '230', flag: '๐Ÿ‡ฒ๐Ÿ‡บ'}, {name: 'Mayotte', iso2: CountryISO.Mayotte, dialCode: '262', flag: '๐Ÿ‡พ๐Ÿ‡น'}, {name: 'Mexico', iso2: CountryISO.Mexico, dialCode: '52', flag: '๐Ÿ‡ฒ๐Ÿ‡ฝ'}, - {name: 'Micronesia', iso2: CountryISO.Micronesia, dialCode: '691', flag: '๐Ÿ‡ซ๐Ÿ‡ฒ'}, - {name: 'Moldova', iso2: CountryISO.Moldova, dialCode: '373', flag: '๐Ÿ‡ฒ๐Ÿ‡ฉ'}, + {name: 'Micronesia, Federated States of', iso2: CountryISO.Micronesia, dialCode: '691', flag: '๐Ÿ‡ซ๐Ÿ‡ฒ'}, + {name: 'Moldova, Republic of', iso2: CountryISO.Moldova, dialCode: '373', flag: '๐Ÿ‡ฒ๐Ÿ‡ฉ'}, {name: 'Monaco', iso2: CountryISO.Monaco, dialCode: '377', flag: '๐Ÿ‡ฒ๐Ÿ‡จ'}, {name: 'Mongolia', iso2: CountryISO.Mongolia, dialCode: '976', flag: '๐Ÿ‡ฒ๐Ÿ‡ณ'}, {name: 'Montenegro', iso2: CountryISO.Montenegro, dialCode: '382', flag: '๐Ÿ‡ฒ๐Ÿ‡ช'}, @@ -435,7 +436,7 @@ export class CountryData { {name: 'Namibia', iso2: CountryISO.Namibia, dialCode: '264', flag: '๐Ÿ‡ณ๐Ÿ‡ฆ'}, {name: 'Nauru', iso2: CountryISO.Nauru, dialCode: '674', flag: '๐Ÿ‡ณ๐Ÿ‡ท'}, {name: 'Nepal', iso2: CountryISO.Nepal, dialCode: '977', flag: '๐Ÿ‡ณ๐Ÿ‡ต'}, - {name: 'Netherlands', iso2: CountryISO.Netherlands, dialCode: '31', flag: '๐Ÿ‡ณ๐Ÿ‡ฑ'}, + {name: 'Netherlands', iso2: CountryISO.Netherlands, dialCode: '31', flag: '๐Ÿ‡ณ๐Ÿ‡ฑ', postCodePattern: /[1-9][0-9]{3}\s?[a-zA-Z]{2}/}, {name: 'New Caledonia', iso2: CountryISO.NewCaledonia, dialCode: '687', flag: '๐Ÿ‡ณ๐Ÿ‡จ'}, {name: 'New Zealand', iso2: CountryISO.NewZealand, dialCode: '64', flag: '๐Ÿ‡ณ๐Ÿ‡ฟ'}, {name: 'Nicaragua', iso2: CountryISO.Nicaragua, dialCode: '505', flag: '๐Ÿ‡ณ๐Ÿ‡ฎ'}, @@ -444,43 +445,44 @@ export class CountryData { {name: 'Niue', iso2: CountryISO.Niue, dialCode: '683', flag: '๐Ÿ‡ณ๐Ÿ‡บ'}, {name: 'Norfolk Island', iso2: CountryISO.NorfolkIsland, dialCode: '672', flag: '๐Ÿ‡ณ๐Ÿ‡ซ'}, {name: 'North Korea', iso2: CountryISO.NorthKorea, dialCode: '850', flag: '๐Ÿ‡ฐ๐Ÿ‡ต'}, + {name: 'North Macedonia', iso2: CountryISO.NorthMacedonia, dialCode: '389', flag: '๐Ÿ‡ฒ๐Ÿ‡ฐ'}, {name: 'Northern Mariana Islands', iso2: CountryISO.NorthernMarianaIslands, dialCode: '1', flag: '๐Ÿ‡ฒ๐Ÿ‡ต'}, {name: 'Norway', iso2: CountryISO.Norway, dialCode: '47', flag: '๐Ÿ‡ณ๐Ÿ‡ด'}, {name: 'Oman', iso2: CountryISO.Oman, dialCode: '968', flag: '๐Ÿ‡ด๐Ÿ‡ฒ'}, {name: 'Pakistan', iso2: CountryISO.Pakistan, dialCode: '92', flag: '๐Ÿ‡ต๐Ÿ‡ฐ'}, {name: 'Palau', iso2: CountryISO.Palau, dialCode: '680', flag: '๐Ÿ‡ต๐Ÿ‡ผ'}, - {name: 'Palestine', iso2: CountryISO.Palestine, dialCode: '970', flag: '๐Ÿ‡ต๐Ÿ‡ธ'}, + {name: 'Palestine, State of', iso2: CountryISO.Palestine, dialCode: '970', flag: '๐Ÿ‡ต๐Ÿ‡ธ'}, {name: 'Panama', iso2: CountryISO.Panama, dialCode: '507', flag: '๐Ÿ‡ต๐Ÿ‡ฆ'}, {name: 'Papua New Guinea', iso2: CountryISO.PapuaNewGuinea, dialCode: '675', flag: '๐Ÿ‡ต๐Ÿ‡ฌ'}, {name: 'Paraguay', iso2: CountryISO.Paraguay, dialCode: '595', flag: '๐Ÿ‡ต๐Ÿ‡พ'}, {name: 'Peru', iso2: CountryISO.Peru, dialCode: '51', flag: '๐Ÿ‡ต๐Ÿ‡ช'}, {name: 'Philippines', iso2: CountryISO.Philippines, dialCode: '63', flag: '๐Ÿ‡ต๐Ÿ‡ญ'}, {name: 'Pitcairn Islands', iso2: CountryISO.PitcairnIslands, dialCode: '649', flag: '๐Ÿ‡ต๐Ÿ‡ณ'}, - {name: 'Poland', iso2: CountryISO.Poland, dialCode: '48', flag: '๐Ÿ‡ต๐Ÿ‡ฑ'}, + {name: 'Poland', iso2: CountryISO.Poland, dialCode: '48', flag: '๐Ÿ‡ต๐Ÿ‡ฑ', postCodePattern: /[0-9]{2}-[0-9]{3}/}, {name: 'Portugal', iso2: CountryISO.Portugal, dialCode: '351', flag: '๐Ÿ‡ต๐Ÿ‡น'}, {name: 'Puerto Rico', iso2: CountryISO.PuertoRico, dialCode: '1', flag: '๐Ÿ‡ต๐Ÿ‡ท'}, {name: 'Qatar', iso2: CountryISO.Qatar, dialCode: '974', flag: '๐Ÿ‡ถ๐Ÿ‡ฆ'}, - {name: 'Rรฉunion', iso2: CountryISO.Rรฉunion, dialCode: '262', flag: '๐Ÿ‡ท๐Ÿ‡ช'}, + {name: 'Rรฉunion', iso2: CountryISO.Reunion, dialCode: '262', flag: '๐Ÿ‡ท๐Ÿ‡ช'}, {name: 'Romania', iso2: CountryISO.Romania, dialCode: '40', flag: '๐Ÿ‡ท๐Ÿ‡ด'}, - {name: 'Russia', iso2: CountryISO.Russia, dialCode: '7', flag: '๐Ÿ‡ท๐Ÿ‡บ'}, + {name: 'Russian Federation', iso2: CountryISO.Russia, dialCode: '7', flag: '๐Ÿ‡ท๐Ÿ‡บ'}, {name: 'Rwanda', iso2: CountryISO.Rwanda, dialCode: '250', flag: '๐Ÿ‡ท๐Ÿ‡ผ'}, - {name: 'Saint Barthรฉlemy', iso2: CountryISO.SaintBarthรฉlemy, dialCode: '590', flag: '๐Ÿ‡ง๐Ÿ‡ฑ'}, - {name: 'Saint Helena', iso2: CountryISO.SaintHelena, dialCode: '290', flag: '๐Ÿ‡ธ๐Ÿ‡ญ'}, + {name: 'Saint Barthรฉlemy', iso2: CountryISO.SaintBarthelemy, dialCode: '590', flag: '๐Ÿ‡ง๐Ÿ‡ฑ'}, + {name: 'Saint Helena, Ascension and Tristan da Cunha', iso2: CountryISO.SaintHelena, dialCode: '290', flag: '๐Ÿ‡ธ๐Ÿ‡ญ'}, {name: 'Saint Kitts and Nevis', iso2: CountryISO.SaintKittsAndNevis, dialCode: '1', flag: '๐Ÿ‡ฐ๐Ÿ‡ณ'}, {name: 'Saint Lucia', iso2: CountryISO.SaintLucia, dialCode: '1', flag: '๐Ÿ‡ฑ๐Ÿ‡จ'}, - {name: 'Saint Martin', iso2: CountryISO.SaintMartin, dialCode: '590', flag: '๐Ÿ‡ฒ๐Ÿ‡ซ'}, + {name: 'Saint Martin (French part)', iso2: CountryISO.SaintMartin, dialCode: '590', flag: '๐Ÿ‡ฒ๐Ÿ‡ซ'}, {name: 'Saint Pierre and Miquelon', iso2: CountryISO.SaintPierreAndMiquelon, dialCode: '508', flag: '๐Ÿ‡ต๐Ÿ‡ฒ'}, {name: 'Saint Vincent and the Grenadines', iso2: CountryISO.SaintVincentAndTheGrenadines, dialCode: '1', flag: '๐Ÿ‡ป๐Ÿ‡จ'}, {name: 'Samoa', iso2: CountryISO.Samoa, dialCode: '685', flag: '๐Ÿ‡ผ๐Ÿ‡ธ'}, {name: 'San Marino', iso2: CountryISO.SanMarino, dialCode: '378', flag: '๐Ÿ‡ธ๐Ÿ‡ฒ'}, - {name: 'Sรฃo Tomรฉ and Prรญncipe', iso2: CountryISO.SรฃoTomรฉAndPrรญncipe, dialCode: '239', flag: '๐Ÿ‡ธ๐Ÿ‡น'}, + {name: 'Sao Tome and Principe', iso2: CountryISO.SaoTomeAndPrincipe, dialCode: '239', flag: '๐Ÿ‡ธ๐Ÿ‡น'}, {name: 'Saudi Arabia', iso2: CountryISO.SaudiArabia, dialCode: '966', flag: '๐Ÿ‡ธ๐Ÿ‡ฆ'}, {name: 'Senegal', iso2: CountryISO.Senegal, dialCode: '221', flag: '๐Ÿ‡ธ๐Ÿ‡ณ'}, {name: 'Serbia', iso2: CountryISO.Serbia, dialCode: '381', flag: '๐Ÿ‡ท๐Ÿ‡ธ'}, {name: 'Seychelles', iso2: CountryISO.Seychelles, dialCode: '248', flag: '๐Ÿ‡ธ๐Ÿ‡จ'}, {name: 'Sierra Leone', iso2: CountryISO.SierraLeone, dialCode: '232', flag: '๐Ÿ‡ธ๐Ÿ‡ฑ'}, {name: 'Singapore', iso2: CountryISO.Singapore, dialCode: '65', flag: '๐Ÿ‡ธ๐Ÿ‡ฌ'}, - {name: 'Sint Maarten', iso2: CountryISO.SintMaarten, dialCode: '1', flag: '๐Ÿ‡ธ๐Ÿ‡ฝ'}, + {name: 'Sint Maarten (Dutch Part)', iso2: CountryISO.SintMaarten, dialCode: '1', flag: '๐Ÿ‡ธ๐Ÿ‡ฝ'}, {name: 'Slovakia', iso2: CountryISO.Slovakia, dialCode: '421', flag: '๐Ÿ‡ธ๐Ÿ‡ฐ'}, {name: 'Slovenia', iso2: CountryISO.Slovenia, dialCode: '386', flag: '๐Ÿ‡ธ๐Ÿ‡ฎ'}, {name: 'Solomon Islands', iso2: CountryISO.SolomonIslands, dialCode: '677', flag: '๐Ÿ‡ธ๐Ÿ‡ง'}, @@ -490,18 +492,18 @@ export class CountryData { iso2: CountryISO.SouthGeorgiaAndTheSouthSandwichIslands, dialCode: '500', flag: '๐Ÿ‡ฌ๐Ÿ‡ธ'}, {name: 'South Korea', iso2: CountryISO.SouthKorea, dialCode: '82', flag: '๐Ÿ‡ฐ๐Ÿ‡ท'}, {name: 'South Sudan', iso2: CountryISO.SouthSudan, dialCode: '211', flag: '๐Ÿ‡ธ๐Ÿ‡ธ'}, - {name: 'Spain', iso2: CountryISO.Spain, dialCode: '34', flag: '๐Ÿ‡ช๐Ÿ‡ธ'}, + {name: 'Spain', iso2: CountryISO.Spain, dialCode: '34', flag: '๐Ÿ‡ช๐Ÿ‡ธ', postCodePattern: /((0[1-9]|5[0-2])|[1-4][0-9])[0-9]{3}/}, {name: 'Sri Lanka', iso2: CountryISO.SriLanka, dialCode: '94', flag: '๐Ÿ‡ฑ๐Ÿ‡ฐ'}, {name: 'Sudan', iso2: CountryISO.Sudan, dialCode: '249', flag: '๐Ÿ‡ธ๐Ÿ‡ฉ'}, - {name: 'Suriname: ', iso2: CountryISO.Suriname, dialCode: '597', flag: '๐Ÿ‡ธ๐Ÿ‡ท'}, + {name: 'Suriname', iso2: CountryISO.Suriname, dialCode: '597', flag: '๐Ÿ‡ธ๐Ÿ‡ท'}, {name: 'Svalbard and Jan Mayen', iso2: CountryISO.SvalbardAndJanMayen, dialCode: '47', flag: '๐Ÿ‡ธ๐Ÿ‡ฏ'}, {name: 'Swaziland', iso2: CountryISO.Swaziland, dialCode: '268', flag: '๐Ÿ‡ธ๐Ÿ‡ฟ'}, - {name: 'Sweden', iso2: CountryISO.Sweden, dialCode: '46', flag: '๐Ÿ‡ธ๐Ÿ‡ช'}, + {name: 'Sweden', iso2: CountryISO.Sweden, dialCode: '46', flag: '๐Ÿ‡ธ๐Ÿ‡ช', postCodePattern: /\d{3}\s?\d{2}/}, {name: 'Switzerland', iso2: CountryISO.Switzerland, dialCode: '41', flag: '๐Ÿ‡จ๐Ÿ‡ญ'}, - {name: 'Syria', iso2: CountryISO.Syria, dialCode: '963', flag: '๐Ÿ‡ธ๐Ÿ‡พ'}, + {name: 'Syrian Arab Republic', iso2: CountryISO.Syria, dialCode: '963', flag: '๐Ÿ‡ธ๐Ÿ‡พ'}, {name: 'Taiwan', iso2: CountryISO.Taiwan, dialCode: '886', flag: '๐Ÿ‡น๐Ÿ‡ผ'}, {name: 'Tajikistan', iso2: CountryISO.Tajikistan, dialCode: '992', flag: '๐Ÿ‡น๐Ÿ‡ฏ'}, - {name: 'Tanzania', iso2: CountryISO.Tanzania, dialCode: '255', flag: '๐Ÿ‡น๐Ÿ‡ฟ'}, + {name: 'Tanzania, United Republic of', iso2: CountryISO.Tanzania, dialCode: '255', flag: '๐Ÿ‡น๐Ÿ‡ฟ'}, {name: 'Thailand', iso2: CountryISO.Thailand, dialCode: '66', flag: '๐Ÿ‡น๐Ÿ‡ญ'}, {name: 'Timor-Leste', iso2: CountryISO.TimorLeste, dialCode: '670', flag: '๐Ÿ‡น๐Ÿ‡ฑ'}, {name: 'Togo', iso2: CountryISO.Togo, dialCode: '228', flag: '๐Ÿ‡น๐Ÿ‡ฌ'}, @@ -517,8 +519,8 @@ export class CountryData { {name: 'Uganda', iso2: CountryISO.Uganda, dialCode: '256', flag: '๐Ÿ‡บ๐Ÿ‡ฌ'}, {name: 'Ukraine', iso2: CountryISO.Ukraine, dialCode: '380', flag: '๐Ÿ‡บ๐Ÿ‡ฆ'}, {name: 'United Arab Emirates', iso2: CountryISO.UnitedArabEmirates, dialCode: '971', flag: '๐Ÿ‡ฆ๐Ÿ‡ช'}, - {name: 'United Kingdom', iso2: CountryISO.UnitedKingdom, dialCode: '44', flag: '๐Ÿ‡ฌ๐Ÿ‡ง'}, - {name: 'United States', iso2: CountryISO.UnitedStates, dialCode: '1', flag: '๐Ÿ‡บ๐Ÿ‡ธ'}, + {name: 'United Kingdom', iso2: CountryISO.UnitedKingdom, dialCode: '44', flag: '๐Ÿ‡ฌ๐Ÿ‡ง', postCodePattern: /[A-Za-z]{1,2}[0-9Rr][0-9A-Za-z]? [0-9][ABD-HJLNP-UW-Zabd-hjlnp-uw-z]{2}/}, + {name: 'United States', iso2: CountryISO.UnitedStates, dialCode: '1', flag: '๐Ÿ‡บ๐Ÿ‡ธ', postCodePattern: /(\d{5}(-\d{4})?)/}, {name: 'Uruguay', iso2: CountryISO.Uruguay, dialCode: '598', flag: '๐Ÿ‡บ๐Ÿ‡พ'}, {name: 'Uzbekistan', iso2: CountryISO.Uzbekistan, dialCode: '998', flag: '๐Ÿ‡บ๐Ÿ‡ฟ'}, {name: 'Vanuatu', iso2: CountryISO.Vanuatu, dialCode: '678', flag: '๐Ÿ‡ป๐Ÿ‡บ'}, @@ -530,6 +532,7 @@ export class CountryData { {name: 'Yemen', iso2: CountryISO.Yemen, dialCode: '967', flag: '๐Ÿ‡พ๐Ÿ‡ช'}, {name: 'Zambia', iso2: CountryISO.Zambia, dialCode: '260', flag: '๐Ÿ‡ฟ๐Ÿ‡ฒ'}, {name: 'Zimbabwe', iso2: CountryISO.Zimbabwe, dialCode: '263', flag: '๐Ÿ‡ฟ๐Ÿ‡ผ'}, - {name: 'ร…land Islands', iso2: CountryISO.ร…landIslands, dialCode: '358', flag: '๐Ÿ‡ฆ๐Ÿ‡ฝ'} + {name: 'ร…land Islands', iso2: CountryISO.AlandIslands, dialCode: '358', flag: '๐Ÿ‡ฆ๐Ÿ‡ฝ'} ]; } +/* eslint-enable max-len */ diff --git a/ui-ngx/src/app/shared/shared.module.ts b/ui-ngx/src/app/shared/shared.module.ts index 3d4edacd1d..21c912edf5 100644 --- a/ui-ngx/src/app/shared/shared.module.ts +++ b/ui-ngx/src/app/shared/shared.module.ts @@ -222,6 +222,7 @@ import { WidgetButtonComponent } from '@shared/components/button/widget-button.c import { HexInputComponent } from '@shared/components/color-picker/hex-input.component'; import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe'; import { ScadaSymbolInputComponent } from '@shared/components/image/scada-symbol-input.component'; +import { CountryAutocompleteComponent } from '@shared/components/country-autocomplete.component'; export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) { return markedOptionsService; @@ -383,6 +384,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) TogglePasswordComponent, ProtobufContentComponent, BranchAutocompleteComponent, + CountryAutocompleteComponent, PhoneInputComponent, TbScriptLangComponent, NotificationComponent, @@ -640,6 +642,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) TogglePasswordComponent, ProtobufContentComponent, BranchAutocompleteComponent, + CountryAutocompleteComponent, PhoneInputComponent, TbScriptLangComponent, NotificationComponent, diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index d9259eec78..26c955c6ea 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -992,6 +992,7 @@ }, "contact": { "country": "Country", + "country-required": "Country is required.", "city": "City", "state": "State / Province", "postal-code": "Zip / Postal Code", @@ -1001,6 +1002,8 @@ "phone": "Phone", "email": "Email", "no-address": "No address", + "no-country-found": "No countries found.", + "no-country-matching": "No country matching '{{country}}' were found.", "state-max-length": "State length should be less than 256", "phone-max-length": "Phone number should be less than 256", "city-max-length": "Specified city should be less than 256"