From 6aa97ce958ff94a7d5522edefc96ea195c83ead1 Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer Date: Tue, 23 Apr 2024 16:44:47 +0200 Subject: [PATCH] docs(components): document gs-location-filter Refs: #129 --- .github/pull_request_template.md | 1 + .github/workflows/storybook.yml | 4 +- .github/workflows/tests.yml | 4 +- components/.storybook-preact/main.ts | 2 +- components/.storybook/preview.ts | 5 ++- components/README.md | 3 +- .../src/web-components/PreactLitAdapter.tsx | 16 ++++++++ .../location-filter-component.stories.ts | 16 ++++---- .../input/location-filter-component.tsx | 40 ++++++++++++++++++- .../web-components/input/location-filter.mdx | 25 ++++++++++++ .../input/text-input-component.stories.ts | 1 + 11 files changed, 103 insertions(+), 14 deletions(-) create mode 100644 components/src/web-components/input/location-filter.mdx diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index d1893934..f2439bcd 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -16,4 +16,5 @@ This helps others quickly grasping what you did even if they are not familiar wi ### PR Checklist +- [ ] All necessary documentation has been adapted. - [ ] The implemented feature is covered by an appropriate test. diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index 550d2d72..cbe21919 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -16,7 +16,7 @@ jobs: uses: bitovi/github-actions-storybook-to-github-pages@v1.0.3 with: path: components/storybook-static - install_command: cd components && npm ci && cd .. - build_command: cd components && npm run build-storybook && cd .. + install_command: cd components && npm ci&& cd .. + build_command: cd components && npm run generate-manifest && npm run build-storybook && cd .. env: DISABLE_PREACT_STORYBOOK: true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index df0c1a39..d08a35ed 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -71,7 +71,9 @@ jobs: key: ${{ runner.os }}-node-${{ hashFiles('components/**/package-lock.json') }} - name: Install npm packages - run: npm ci + run: | + npm ci + npm run generate-manifest - name: Get Installed Playwright Version id: playwright-version diff --git a/components/.storybook-preact/main.ts b/components/.storybook-preact/main.ts index 16b16d07..ff518e32 100644 --- a/components/.storybook-preact/main.ts +++ b/components/.storybook-preact/main.ts @@ -1,7 +1,7 @@ import type { StorybookConfig } from '@storybook/preact-vite'; const config: StorybookConfig = { - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(jsx|tsx)'], + stories: ['../src/**/*.stories.@(jsx|tsx)'], addons: [ '@storybook/addon-links', '@storybook/addon-essentials', diff --git a/components/.storybook/preview.ts b/components/.storybook/preview.ts index 01d4e8ad..ac810ff8 100644 --- a/components/.storybook/preview.ts +++ b/components/.storybook/preview.ts @@ -1,8 +1,11 @@ -import type { Preview } from '@storybook/web-components'; +import { Preview, setCustomElementsManifest } from '@storybook/web-components'; import '../src/styles/tailwind.css'; import { REFERENCE_GENOME_ENDPOINT } from '../src/constants'; import referenceGenome from '../src/lapisApi/__mockData__/referenceGenome.json'; +import customElements from '../custom-elements.json'; + +setCustomElementsManifest(customElements); const preview: Preview = { parameters: { diff --git a/components/README.md b/components/README.md index a53686a6..2f740beb 100644 --- a/components/README.md +++ b/components/README.md @@ -59,9 +59,10 @@ npm run generate-manifest:watch We use Storybook to develop our components. -To start Storybook, run: +To start Storybook, run (`npm run generate-manifest` makes sure to generate the `custom-elements.json` first): ```bash +npm run generate-manifest npm run storybook-preact npm run storybook ``` diff --git a/components/src/web-components/PreactLitAdapter.tsx b/components/src/web-components/PreactLitAdapter.tsx index 53c8555c..75e681b2 100644 --- a/components/src/web-components/PreactLitAdapter.tsx +++ b/components/src/web-components/PreactLitAdapter.tsx @@ -21,9 +21,24 @@ const minMaxPercentSliderElementCss = unsafeCSS(minMaxPercentSliderCss); export abstract class PreactLitAdapter extends ReactiveElement { static override styles = [tailwindElementCss, minMaxPercentSliderElementCss]; + /** + * @internal + * The URL of the Lapis instance. + * + * This component must be a child of a `gs-app` component. + * This value will automatically be injected by the parent `gs-app` component. + */ @consume({ context: lapisContext }) lapis: string = ''; + /** + * @internal + * The reference genomes of the underlying organism. + * These will be fetched from the Lapis instance. + * + * This component must be a child of a `gs-app` component. + * This value will automatically be injected by the parent `gs-app` component. + */ @consume({ context: referenceGenomeContext, subscribe: true }) referenceGenome: ReferenceGenome = { nucleotideSequences: [], @@ -31,6 +46,7 @@ export abstract class PreactLitAdapter extends ReactiveElement { }; override update(changedProperties: PropertyValues) { + console.log('this.lapis', this.lapis); const vdom = ( diff --git a/components/src/web-components/input/location-filter-component.stories.ts b/components/src/web-components/input/location-filter-component.stories.ts index 0c555afc..d5549cf6 100644 --- a/components/src/web-components/input/location-filter-component.stories.ts +++ b/components/src/web-components/input/location-filter-component.stories.ts @@ -2,11 +2,13 @@ import { withActions } from '@storybook/addon-actions/decorator'; import { expect, fn, userEvent, waitFor } from '@storybook/test'; import type { Meta, StoryObj } from '@storybook/web-components'; import { html } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants'; import '../app'; import './location-filter-component'; import data from '../../preact/locationFilter/__mockData__/aggregated.json'; +import { type LocationFilterProps } from '../../preact/locationFilter/location-filter'; import { withinShadowRoot } from '../withinShadowRoot.story'; const meta: Meta = { @@ -18,21 +20,21 @@ const meta: Meta = { }, }, decorators: [withActions], - tags: ['autodocs'], }; export default meta; -const Template: StoryObj<{ fields: string[] }> = { +const Template: StoryObj = { render: (args) => { return html`
- +
`; }, args: { fields: ['region', 'country', 'division', 'location'], + value: '', }, }; @@ -44,7 +46,7 @@ const aggregatedEndpointMatcher = { }, }; -export const LocationFilter: StoryObj<{ fields: string[] }> = { +export const LocationFilter: StoryObj = { ...Template, parameters: { fetchMock: { @@ -67,7 +69,7 @@ export const LocationFilter: StoryObj<{ fields: string[] }> = { }, }; -export const DelayToShowLoadingState: StoryObj<{ fields: string[] }> = { +export const DelayToShowLoadingState: StoryObj = { ...Template, parameters: { fetchMock: { @@ -87,7 +89,7 @@ export const DelayToShowLoadingState: StoryObj<{ fields: string[] }> = { }, }; -export const FetchingLocationsFails: StoryObj<{ fields: string[] }> = { +export const FetchingLocationsFails: StoryObj = { ...Template, parameters: { fetchMock: { @@ -113,7 +115,7 @@ export const FetchingLocationsFails: StoryObj<{ fields: string[] }> = { }, }; -export const FiresEvent: StoryObj<{ fields: string[] }> = { +export const FiresEvent: StoryObj = { ...Template, parameters: { fetchMock: { diff --git a/components/src/web-components/input/location-filter-component.tsx b/components/src/web-components/input/location-filter-component.tsx index 7cf0f6de..19432e9c 100644 --- a/components/src/web-components/input/location-filter-component.tsx +++ b/components/src/web-components/input/location-filter-component.tsx @@ -4,13 +4,51 @@ import { LocationFilter } from '../../preact/locationFilter/location-filter'; import { PreactLitAdapter } from '../PreactLitAdapter'; /** - * @fires {CustomEvent>} gs-location-changed - When the location has changed + * ## Tag + * + * `gs-location-filter` + * + * ## Context + * + * This component provides an input field to specify filters for locations. + * + * It expects a list of fields that form a strict hierarchical order, such as continent, country, and city. + * The component retrieves a list of all possible values for these fields from the Lapis instance. + * This list is then utilized to display autocomplete suggestions and to validate the input. + * + * Given `fields` are `['field1', 'field2', ..., 'fieldN']`, + * then valid values for the location filter must be in the form `valueForField1 / valueForField2 / ... / valueForFieldK`, + * where `1 <= K <= N`. + * Values for the fields `i > K` are considered `undefined`. + * + * @fires {CustomEvent>} gs-location-changed + * Fired when the field is submitted with a valid location value. + * The `details` of this event contain an object with all `fields` as keys + * and the corresponding values as values, if they are not `undefined`. + * Example: + * ``` + * { + * continent: "Asia", + * country: "China", + * city: "Beijing" + * } + * ``` */ @customElement('gs-location-filter') export class LocationFilterComponent extends PreactLitAdapter { + /** + * The initial value to use for this location filter. + * Must be of the form `valueForField1 / valueForField2 / ... / valueForFieldN`. + */ @property() value = ''; + /** + * The fields to display in the location filter, in hierarchical order. + * The top-level field should be the first entry in the array. + * This component assumes that the values for each field form a strict hierarchy + * (e.g., `fields = ['continent', 'country', 'city']`). + */ @property({ type: Array }) fields: string[] = []; diff --git a/components/src/web-components/input/location-filter.mdx b/components/src/web-components/input/location-filter.mdx new file mode 100644 index 00000000..e0d63dd4 --- /dev/null +++ b/components/src/web-components/input/location-filter.mdx @@ -0,0 +1,25 @@ +import { ArgTypes, Description, Meta, Story, Title, Source } from '@storybook/blocks'; + +import * as LocationFilterStories from './location-filter-component.stories.ts'; + + + + + +<Description of={LocationFilterStories} /> + +## Specification + +<ArgTypes of={LocationFilterStories} /> + +## Example + +<Source + code={`<gs-location-filter fields="['continent', 'country']" value='Europe / Switzerland'></gs-location-filter>`} +/> + +### Live Example + +[See here](?path=/story/input-location-filter--location-filter) + +<Story of={LocationFilterStories.LocationFilter} /> diff --git a/components/src/web-components/input/text-input-component.stories.ts b/components/src/web-components/input/text-input-component.stories.ts index b6dcc0e3..f9f2a1d0 100644 --- a/components/src/web-components/input/text-input-component.stories.ts +++ b/components/src/web-components/input/text-input-component.stories.ts @@ -35,6 +35,7 @@ const meta: Meta = { }, }, decorators: [withActions], + tags: ['autodocs'], }; export default meta;