Repository: bcgov/business-filings-ui
Pull request #737: 26915 - Update Amalgamate Out filing page
Author: login: ArwenQin
Created: 2025-04-02T21:03:24Z | Merged: 2025-04-03T18:35:41Z

*Issue #:* /bcgov/entity#26915

*Description of changes:*
- Jurisdiction should list Canada and United States of America at the top
- Canada and US are at the top and repeated in the list alphabetically. (Applies to Continuation Out too)
- Jurisdiction dropdown should be a type ahead and should show the matching entries in an abbreviated list
- Dropdown for Jurisdiction should appear under the input box

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the business-filings-ui license (Apache 2.0).



Diff:
diff --git a/package-lock.json b/package-lock.json
index bbb32a0f6..57f46482f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "business-filings-ui",
-  "version": "7.4.29",
+  "version": "7.4.30",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "business-filings-ui",
-      "version": "7.4.29",
+      "version": "7.4.30",
       "dependencies": {
         "@babel/compat-data": "^7.21.5",
         "@bcrs-shared-components/base-address": "2.0.45",
diff --git a/package.json b/package.json
index 179e13244..62a80c50d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "business-filings-ui",
-  "version": "7.4.29",
+  "version": "7.4.30",
   "private": true,
   "appName": "Business Filings UI",
   "sbcName": "SBC Common Components",
diff --git a/src/components/common/ForeignJurisdiction.vue b/src/components/common/ForeignJurisdiction.vue
index 0e28e67a1..89025f6d8 100644
--- a/src/components/common/ForeignJurisdiction.vue
+++ b/src/components/common/ForeignJurisdiction.vue
@@ -14,19 +14,30 @@
         cols="12"
         sm="9"
       >
-        <v-select
+        <v-autocomplete
           id="country-selector"
           ref="countrySelectRef"
-          v-model="selectedCountryName"
-          :items="getCountries()"
+          v-model="selectedCountryCode"
+          :items="getCountriesList()"
           item-text="name"
+          item-value="code"
           filled
           placeholder="Jurisdiction Country"
           :rules="countryRules"
-          menu-props="auto"
+          hide-no-data
+          :filter="customFilter"
+          :menu-props="{
+            auto: false,
+            bottom: true
+          }"
           @input="emitChangedCountry()"
-        />
-        <v-select
+        >
+          <template #item="{ item }">
+            {{ item.name }}
+          </template>
+        </v-autocomplete>
+
+        <v-autocomplete
           v-if="canadaUsaRegions.length > 0"
           id="region-selector"
           ref="regionSelectRef"
@@ -36,8 +47,18 @@
           filled
           placeholder="Jurisdiction Region"
           :rules="regionRules"
+          hide-no-data
+          :filter="customFilter"
+          :menu-props="{
+            auto: false,
+            bottom: true
+          }"
           @input="emitChangedRegion()"
-        />
+        >
+          <template #item="{ item }">
+            {{ item.name }}
+          </template>
+        </v-autocomplete>
       </v-col>
     </v-row>
   </v-card>
@@ -64,13 +85,13 @@ export default class ForeignJurisdiction extends Mixins(CountriesProvincesMixin)
   /** Prompt the validations. Used for global validations. */
   @Prop({ default: false }) readonly validateForm!: boolean
 
-  selectedCountryName = ''
+  selectedCountryCode = ''
   selectedRegionName = ''
 
   /** Restore the selected country and region from draft filing if applicable. */
   mounted (): void {
     if (this.draftCountry) {
-      this.selectedCountryName = this.getCountryNameFromCode(this.draftCountry)
+      this.selectedCountryCode = this.draftCountry
       this.emitChangedCountry()
     }
     if (this.draftRegion) {
@@ -79,14 +100,24 @@ export default class ForeignJurisdiction extends Mixins(CountriesProvincesMixin)
     }
   }
 
+  /** Get the matching results from the country/region seach lists. */
+  customFilter (item, query, itemText) {
+    if (!query) return true
+    /** Only show Canada and US once in the search results. */
+    if (item.code === 'CA-1' || item.code === 'US-1') return false
+    const text = itemText.toString().toLowerCase()
+    const search = query.toLowerCase()
+    return text.indexOf(search) !== -1
+  }
+
   /** Get the respective regions of the country selected as an array of objects. */
   get canadaUsaRegions (): Array<any> {
-    if (this.selectedCountryName === 'Canada') {
+    if (this.selectedCountryCode === 'CA') {
       let regions = this.getCountryRegions('CA') as any[]
       regions = regions.filter(province => province.short !== 'BC')
       regions.push({ name: 'Federal', short: 'FEDERAL' })
       return regions
-    } else if (this.selectedCountryName === 'United States of America') {
+    } else if (this.selectedCountryCode === 'US') {
       return this.getCountryRegions('US')
     }
     return []
@@ -99,6 +130,22 @@ export default class ForeignJurisdiction extends Mixins(CountriesProvincesMixin)
     ]
   }
 
+  /** Prioritize Canada and US in the Countries List. */
+  getCountriesList (): Array<object> {
+    const countries = this.getCountries()
+    // List of priority countries
+    const priorityCountries = [
+      { name: 'Canada', code: 'CA-1' },
+      { name: 'United States of America', code: 'US-1' },
+      { divider: true }
+    ]
+
+    return [
+      ...priorityCountries,
+      ...countries
+    ]
+  }
+
   /** Validation rules for the Jurisdiction Region dropdown. */
   get regionRules (): Array<(val) => boolean | string> {
     return [
@@ -106,22 +153,6 @@ export default class ForeignJurisdiction extends Mixins(CountriesProvincesMixin)
     ]
   }
 
-  /** Get the selected country's code. */
-  get selectedCountryCode (): string {
-    const countries = this.getCountries() as any[]
-    const countryCode = countries.find(country => country.name === this.selectedCountryName)
-    return countryCode?.code
-  }
-
-  /** Helper function to get a country's name when given the code.
-   * @example ('CA') -> 'Canada'
-   */
-  private getCountryNameFromCode (code: string): string {
-    const countries = this.getCountries() as any[]
-    const country = countries.find(country => country.code === code)
-    return country?.name
-  }
-
   /** Helper function to get a region's name when given the short.
    * @example ('AB') -> 'Alberta'
    * @example ('NY') -> 'New York'
@@ -133,7 +164,7 @@ export default class ForeignJurisdiction extends Mixins(CountriesProvincesMixin)
 
   @Watch('draftCountry')
   onDraftCountryChanged (val: string): void {
-    this.selectedCountryName = val
+    this.selectedCountryCode = val
   }
 
   @Watch('draftRegion')
@@ -144,19 +175,19 @@ export default class ForeignJurisdiction extends Mixins(CountriesProvincesMixin)
   /** Validate country field */
   @Watch('validateForm')
   validateForeignJurisdiction (): void {
-    if (this.validateForm && !this.selectedCountryName) {
+    if (this.validateForm && !this.selectedCountryCode) {
       this.$refs.countrySelectRef.validate()
       this.$refs.countrySelectRef.error = true
     }
   }
 
   /** Validate region field */
-  @Watch('selectedCountryName')
+  @Watch('selectedCountryCode')
   @Watch('validateForm')
   async onCountrychanged (): Promise<void> {
     if (this.validateForm) {
       await this.$nextTick()
-      if (this.selectedCountryName === 'Canada' || this.selectedCountryName === 'United States of America') {
+      if (this.selectedCountryCode === 'CA' || this.selectedCountryCode === 'US') {
         this.$refs.regionSelectRef.validate()
         this.$refs.regionSelectRef.error = true
       }
@@ -166,9 +197,14 @@ export default class ForeignJurisdiction extends Mixins(CountriesProvincesMixin)
   /** Emit the selected country's code whenever a new country is selected. */
   @Emit('update:country')
   emitChangedCountry (): string {
+    if (['CA', 'CA-1'].includes(this.selectedCountryCode)) {
+      this.selectedCountryCode = 'CA'
+    } else if (['US', 'US-1'].includes(this.selectedCountryCode)) {
+      this.selectedCountryCode = 'US'
+    }
     this.selectedRegionName = ''
     this.emitChangedRegion()
-    if (this.selectedCountryName === 'Canada' || this.selectedCountryName === 'United States of America') {
+    if (this.selectedCountryCode === 'CA' || this.selectedCountryCode === 'US') {
       this.emitValid(false)
     } else {
       this.emitValid(true)
diff --git a/tests/unit/ForeignJurisdiction.spec.ts b/tests/unit/ForeignJurisdiction.spec.ts
index ab3599913..cc358c5f3 100644
--- a/tests/unit/ForeignJurisdiction.spec.ts
+++ b/tests/unit/ForeignJurisdiction.spec.ts
@@ -18,9 +18,11 @@ describe('ForeignJurisdiction', () => {
       })
     const vm: any = wrapper.vm
 
-    expect(vm.selectedCountryName).toEqual('')
+    expect(vm.selectedCountryCode).toEqual('')
     expect(vm.selectedRegionName).toEqual('')
     expect(vm.getCountries().length).toEqual(249) // This number might change someday.
+    // This number might change someday, including divider and pinned US/CA
+    expect(vm.getCountriesList().length).toEqual(252)
     expect(wrapper.emitted('valid')).toBeFalsy()
     wrapper.destroy()
   })
@@ -32,10 +34,8 @@ describe('ForeignJurisdiction', () => {
       })
     const vm: any = wrapper.vm
 
-    await wrapper.find('#country-selector').trigger('click')
-    await wrapper.findAll('.v-list-item').at(123).trigger('click')
+    vm.selectedCountryCode = 'LB'
 
-    expect(vm.selectedCountryName).toEqual('Lebanon')
     expect(vm.selectedCountryCode).toEqual('LB')
     expect(vm.selectedRegionName).toEqual('')
     wrapper.destroy()
@@ -48,14 +48,8 @@ describe('ForeignJurisdiction', () => {
       })
     const vm: any = wrapper.vm
 
-    await wrapper.find('#country-selector').trigger('click')
-    await wrapper.findAll('.v-list-item').at(39).trigger('click')
-
-    const region = wrapper.find('#region-selector')
-    await region.setValue('Ontario')
-
-    expect(vm.selectedCountryName).toEqual('Canada')
-    expect(vm.selectedCountryCode).toEqual('CA')
+    vm.selectedRegionName = 'Ontario'
+    expect(vm.selectedCountryCode).toEqual('')
     expect(vm.selectedRegionName).toEqual('Ontario')
     wrapper.destroy()
   })
@@ -65,13 +59,14 @@ describe('ForeignJurisdiction', () => {
       {
         vuetify
       })
+    const vm: any = wrapper.vm
 
-    await wrapper.find('#country-selector').trigger('click')
-    await wrapper.findAll('.v-list-item').at(39).trigger('click')
-
-    const provinces = wrapper.findAll('.v-select').at(1).props('items')
+    vm.selectedCountryCode = 'CA'
+    vm.emitChangedCountry()
+    vm.selectedRegionName = 'British Columnbia'
+    vm.emitChangedRegion()
 
-    expect(provinces).toEqual(expect.not.arrayContaining([{ name: 'British Columbia', short: 'BC' }]))
+    expect(wrapper.emitted('update:region').pop()[0]).toBeUndefined()
     wrapper.destroy()
   })
 
@@ -80,13 +75,15 @@ describe('ForeignJurisdiction', () => {
       {
         vuetify
       })
+    const vm: any = wrapper.vm
 
-    await wrapper.find('#country-selector').trigger('click')
-    await wrapper.findAll('.v-list-item').at(39).trigger('click')
-
-    const provinces = wrapper.findAll('.v-select').at(1).props('items')
+    vm.selectedCountryCode = 'CA'
+    vm.emitChangedCountry()
+    vm.selectedRegionName = 'Federal'
+    vm.emitChangedRegion()
 
-    expect(provinces).toEqual(expect.arrayContaining([{ name: 'Federal', short: 'FEDERAL' }]))
+    expect(wrapper.emitted('update:country').pop()[0]).toEqual('CA')
+    expect(wrapper.emitted('update:region').pop()[0]).toEqual('FEDERAL')
     wrapper.destroy()
   })
 
@@ -97,13 +94,12 @@ describe('ForeignJurisdiction', () => {
       })
     const vm: any = wrapper.vm
 
-    await wrapper.find('#country-selector').trigger('click')
-    await wrapper.findAll('.v-list-item').at(235).trigger('click')
+    vm.selectedCountryCode = 'US-1'
+    vm.emitChangedCountry()
+    vm.selectedRegionName = 'New York'
+    vm.emitChangedRegion()
 
-    const region = wrapper.find('#region-selector')
-    await region.setValue('New York')
-
-    expect(vm.selectedCountryName).toEqual('United States of America')
+    expect(vm.selectedCountryCode).toEqual('US')
     expect(vm.selectedRegionName).toEqual('New York')
     wrapper.destroy()
   })
@@ -113,9 +109,10 @@ describe('ForeignJurisdiction', () => {
       {
         vuetify
       })
+    const vm: any = wrapper.vm
 
-    await wrapper.find('#country-selector').trigger('click')
-    await wrapper.findAll('.v-list-item').at(123).trigger('click')
+    vm.selectedCountryCode = 'LB'
+    vm.emitChangedCountry()
 
     expect(wrapper.emitted('update:country').pop()[0]).toEqual('LB')
     expect(wrapper.emitted('update:region').pop()[0]).toBeUndefined()
@@ -130,8 +127,8 @@ describe('ForeignJurisdiction', () => {
       })
     const vm: any = wrapper.vm
 
-    await wrapper.find('#country-selector').trigger('click')
-    await wrapper.findAll('.v-list-item').at(39).trigger('click')
+    vm.selectedCountryCode = 'CA'
+    vm.emitChangedCountry()
 
     expect(vm.selectedRegionName).toEqual('')
     expect(wrapper.emitted('update:country').pop()[0]).toEqual('CA')
@@ -145,12 +142,12 @@ describe('ForeignJurisdiction', () => {
       {
         vuetify
       })
+    const vm: any = wrapper.vm
 
-    await wrapper.find('#country-selector').trigger('click')
-    await wrapper.findAll('.v-list-item').at(39).trigger('click')
-
-    const region = wrapper.find('#region-selector')
-    await region.setValue('Ontario')
+    vm.selectedCountryCode = 'CA'
+    vm.emitChangedCountry()
+    vm.selectedRegionName = 'Ontario'
+    vm.emitChangedRegion()
 
     expect(wrapper.emitted('update:country').pop()[0]).toEqual('CA')
     expect(wrapper.emitted('update:region').pop()[0]).toEqual('ON')
@@ -168,7 +165,7 @@ describe('ForeignJurisdiction', () => {
       })
     const vm: any = wrapper.vm
 
-    expect(vm.selectedCountryName).toEqual('Lebanon')
+    expect(vm.selectedCountryCode).toEqual('LB')
     expect(vm.selectedRegionName).toEqual('')
     expect(wrapper.emitted('update:country').pop()[0]).toEqual('LB')
     expect(wrapper.emitted('update:region').pop()[0]).toBeUndefined()
@@ -186,7 +183,7 @@ describe('ForeignJurisdiction', () => {
       })
     const vm: any = wrapper.vm
 
-    expect(vm.selectedCountryName).toEqual('Canada')
+    expect(vm.selectedCountryCode).toEqual('CA')
     expect(vm.selectedRegionName).toEqual('')
     expect(wrapper.emitted('update:country').pop()[0]).toEqual('CA')
     expect(wrapper.emitted('update:region').pop()[0]).toBeUndefined()
@@ -205,7 +202,7 @@ describe('ForeignJurisdiction', () => {
       })
     const vm: any = wrapper.vm
 
-    expect(vm.selectedCountryName).toEqual('Canada')
+    expect(vm.selectedCountryCode).toEqual('CA')
     expect(vm.selectedRegionName).toEqual('Ontario')
     expect(wrapper.emitted('update:country').pop()[0]).toEqual('CA')
     expect(wrapper.emitted('update:region').pop()[0]).toEqual('ON')
@@ -224,7 +221,7 @@ describe('ForeignJurisdiction', () => {
       })
     const vm: any = wrapper.vm
 
-    expect(vm.selectedCountryName).toEqual('Canada')
+    expect(vm.selectedCountryCode).toEqual('CA')
     expect(vm.selectedRegionName).toBeUndefined()
     expect(wrapper.emitted('update:country').pop()[0]).toEqual('CA')
     expect(wrapper.emitted('update:region').pop()[0]).toBeUndefined()
@@ -243,7 +240,7 @@ describe('ForeignJurisdiction', () => {
       })
     const vm: any = wrapper.vm
 
-    expect(vm.selectedCountryName).toEqual('Canada')
+    expect(vm.selectedCountryCode).toEqual('CA')
     expect(vm.selectedRegionName).toEqual('Federal')
     expect(wrapper.emitted('update:country').pop()[0]).toEqual('CA')
     expect(wrapper.emitted('update:region').pop()[0]).toEqual('FEDERAL')


Reviews:
user: login: ArwenQin
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T21:06:11Z
user: login: ArwenQin
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T21:07:06Z
user: login: ArwenQin
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T21:08:14Z
user: login: severinbeauvais
body: Very clever. Great job! The UI looks good and works perfectly. 👍 👍 

Please wait for more reviews before merging.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T17:24:16Z
user: login: meawong
body: Tested and LGTM!
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-03T17:30:49Z
user: login: JazzarKarim
body: LGTM!
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-03T17:37:17Z

Review comments:
diff_hunk: @@ -99,29 +130,29 @@ export default class ForeignJurisdiction extends Mixins(CountriesProvincesMixin)
     ]
   }
 
+  /** Prioritize Canada and US in the Countries List. */
+  getCountriesList (): Array<object> {
+    const countries = this.getCountries()
+    // List of priority countries
+    const priorityCountries = [
+      { name: 'Canada', code: 'CA-1' },
+      { name: 'United States of America', code: 'US-1' },
+      { divider: true }
+    ]
+
path: src/components/common/ForeignJurisdiction.vue
user: login: ArwenQin
body: Assign different country code "CA-1" and "US-1", is to enable repeating Canada and USA in the selection menu. Otherwise the selection menu won't show duplicate options
created_at: 2025-04-02T21:06:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -79,14 +100,24 @@ export default class ForeignJurisdiction extends Mixins(CountriesProvincesMixin)
     }
   }
 
+  /** Get the matching results from the country/region seach lists. */
+  customFilter (item, query, itemText) {
+    if (!query) return true
+    /** Only show Canada and US once in the search results. */
+    if (item.code === 'CA-1' || item.code === 'US-1') return false
+    const text = itemText.toString().toLowerCase()
path: src/components/common/ForeignJurisdiction.vue
user: login: ArwenQin
body: add this check so the Canada/US search result only shows once, otherwise is as below
![image](https://github.com/user-attachments/assets/75dddacd-290a-4315-b326-fc8d3222f217)

created_at: 2025-04-02T21:07:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -99,29 +130,29 @@ export default class ForeignJurisdiction extends Mixins(CountriesProvincesMixin)
     ]
   }
 
+  /** Prioritize Canada and US in the Countries List. */
+  getCountriesList (): Array<object> {
+    const countries = this.getCountries()
+    // List of priority countries
+    const priorityCountries = [
+      { name: 'Canada', code: 'CA-1' },
+      { name: 'United States of America', code: 'US-1' },
+      { divider: true }
+    ]
+
+    return [
+      ...priorityCountries,
+      ...countries
+    ]
+  }
+
   /** Validation rules for the Jurisdiction Region dropdown. */
   get regionRules (): Array<(val) => boolean | string> {
     return [
       val => !!(val) || 'Jurisdiction Region is required.'
     ]
   }
 
-  /** Get the selected country's code. */
-  get selectedCountryCode (): string {
-    const countries = this.getCountries() as any[]
-    const countryCode = countries.find(country => country.name === this.selectedCountryName)
-    return countryCode?.code
-  }
-
-  /** Helper function to get a country's name when given the code.
-   * @example ('CA') -> 'Canada'
-   */
-  private getCountryNameFromCode (code: string): string {
-    const countries = this.getCountries() as any[]
-    const country = countries.find(country => country.code === code)
-    return country?.name
-  }
-
   /** Helper function to get a region's name when given the short.
path: src/components/common/ForeignJurisdiction.vue
user: login: ArwenQin
body: We actually Don't need to get selected country name, we only need the selected Country Code, so we can have the v-model = item.code
If we have the v-model = item.name, the selection list won't be able to repeat CA and US in the abbreviated list, because they have duplicated names
created_at: 2025-04-02T21:08:14Z
author_association: CONTRIBUTOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-04-02T21:04:10Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=bcgov_business-filings-ui&pullRequest=737) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=bcgov_business-filings-ui&pullRequest=737&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=bcgov_business-filings-ui&pullRequest=737&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=bcgov_business-filings-ui&pullRequest=737&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=bcgov_business-filings-ui&pullRequest=737&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=bcgov_business-filings-ui&pullRequest=737&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=bcgov_business-filings-ui&pullRequest=737)


author_association: NONE
user: login: ArwenQin
created_at: 2025-04-02T21:04:30Z
body: /gcbrun
author_association: CONTRIBUTOR
user: login: bcregistry-sre
created_at: 2025-04-02T21:07:06Z
body: Temporary Url for review: https://business-filings-dev--pr-737-wiir7jwj.web.app
author_association: COLLABORATOR
user: login: ArwenQin
created_at: 2025-04-02T21:08:59Z
body: Test: https://business-filings-dev--pr-737-wiir7jwj.web.app/BC0887792/amalgamation-out?accountid=3040&businessid=BC0887792&filingId=186865
author_association: CONTRIBUTOR
user: login: ArwenQin
created_at: 2025-04-02T21:10:46Z
body: Example:
CA and US at the top
![image](https://github.com/user-attachments/assets/679bdbf1-2390-41f3-a1dc-43e89b8a903b)


Repeat in the list alphabetically
![image](https://github.com/user-attachments/assets/c9770d53-dcbd-4647-b37a-0a6d6e1f10d7)


Type and search
![image](https://github.com/user-attachments/assets/ff4532f7-5593-4df2-aef0-3295860f3a41)


Search and show only 1 Canada
![image](https://github.com/user-attachments/assets/d3c0f9a0-3539-4140-b1a4-fe6e747168e1)

author_association: CONTRIBUTOR