Skip to content

Commit

Permalink
Create country field with dropdown edit mode (#1864)
Browse files Browse the repository at this point in the history
* introduce country dropdown

* remove loading message

* fix default selection of model

* add some instances

* fix lint

* add atom format to country field
  • Loading branch information
tintinthong authored Dec 3, 2024
1 parent 2c96b3b commit 5c2c6ec
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/boxel-ui/addon/src/components/select/index.gts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const BoxelSelect: TemplateOnlyComponent<Signature> = <template>
@renderInPlace={{@renderInPlace}}
@verticalPosition={{@verticalPosition}}
@dropdownClass={{cn 'boxel-select__dropdown' @dropdownClass}}
@loadingMessage={{@loadingMessage}}
{{! We can avoid providing arguments to the triggerComponent as long as they are specified here https://github.com/cibernox/ember-power-select/blob/913c85ec82d5c6aeb80a7a3b9d9c21ca9613e900/ember-power-select/src/components/power-select.hbs#L79-L106 }}
{{! Even the custom BoxelTriggerWrapper will receive these arguments }}
@triggerComponent={{(if
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"data": {
"type": "card",
"attributes": {
"country": {
"name": null,
"code": null
},
"title": null,
"description": null,
"thumbnailURL": null
},
"meta": {
"adoptsFrom": {
"module": "../country",
"name": "CardWithCountryField"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"data": {
"type": "card",
"attributes": {
"country": {
"name": "Cambodia",
"code": "KH"
},
"title": null,
"description": null,
"thumbnailURL": null
},
"meta": {
"adoptsFrom": {
"module": "../country",
"name": "CardWithCountryField"
}
}
}
}
104 changes: 104 additions & 0 deletions packages/experiments-realm/country.gts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@ import {
field,
Component,
CardDef,
FieldDef,
} from 'https://cardstack.com/base/card-api';
import StringField from 'https://cardstack.com/base/string';
import World from '@cardstack/boxel-icons/world';
import { BoxelSelect } from '@cardstack/boxel-ui/components';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { restartableTask } from 'ember-concurrency';
import type Owner from '@ember/owner';
// @ts-ignore
import countryDataFind from 'https://esm.run/[email protected]';

export class Country extends CardDef {
static displayName = 'Country';
Expand All @@ -23,3 +31,99 @@ export class Country extends CardDef {
</template>
};
}

function getCountryFlagEmoji(countryCode: string) {
const codePoints = countryCode
.toUpperCase()
.split('')
.map((char) => 127397 + char.charCodeAt(0));
return String.fromCodePoint(...codePoints);
}

interface CountryData {
code: string;
name: string;
emoji?: string;
}

class CountryFieldEdit extends Component<typeof CountryField> {
@tracked country: CountryData | undefined =
this.args.model.name && this.args.model.code
? {
name: this.args.model.name,
code: this.args.model.code,
}
: undefined;
@tracked countries: CountryData[] = [];

constructor(owner: Owner, args: any) {
super(owner, args);
this.loadCountries.perform();
}

private loadCountries = restartableTask(async () => {
this.countries = countryDataFind.Array().map((country: any) => {
return {
code: country.ISO2_CODE,
name: country.LIST_OF_NAME.ENG[0],
emoji: getCountryFlagEmoji(country.ISO2_CODE),
} as CountryData;
});
});

@action onSelectCountry(country: CountryData) {
this.country = country;
this.args.model.name = country.name;
this.args.model.code = country.code;
}

@action countryEmoji(countryCode: string) {
return this.countries?.find((country) => country.code === countryCode)
?.emoji;
}

<template>
{{#if this.loadCountries.isRunning}}
Loading countries...
{{else}}
<BoxelSelect
@placeholder={{'Choose a country'}}
@options={{this.countries}}
@selected={{this.country}}
@onChange={{this.onSelectCountry}}
as |country|
>
{{#let (this.countryEmoji country.code) as |emoji|}}
{{emoji}}
{{/let}}
{{country.name}}
</BoxelSelect>
{{/if}}
</template>
}

export class CountryField extends FieldDef {
static displayName = 'Country';
@field name = contains(StringField);
@field code = contains(StringField);
static edit = CountryFieldEdit;

static atom = class Atom extends Component<typeof this> {
<template>
{{#if @model.name}}
{{@model.name}}
{{/if}}
</template>
};
}

export class CardWithCountryField extends CardDef {
static displayName = 'Card With Country Field';
@field country = contains(CountryField);

static isolated = class Isolated extends Component<typeof this> {
<template>
<@fields.country @format='atom' />
</template>
};
}

0 comments on commit 5c2c6ec

Please sign in to comment.