From 6d0d949a832c32ee863434c64aa63b6864511f2b Mon Sep 17 00:00:00 2001 From: Dylan Hyun Date: Tue, 2 Sep 2025 12:11:25 -0400 Subject: [PATCH 1/3] HDS-5428 SuperSelect filtering spike --- showcase/app/components/mock/app/index.gts | 8 + .../generic-filter/filter-bar/checkbox.gts | 66 ++ .../generic-filter/filter-bar/dropdown.gts | 144 ++++ .../main/generic-filter/filter-bar/index.gts | 142 ++++ .../main/generic-filter/filter-bar/radio.gts | 66 ++ .../filter-bar/segmented-group.gts | 64 ++ .../filter-bar/super-select.gts | 112 +++ .../generic-dropdown-filter.gts | 703 ++++++++++++++++++ .../generic-super-select-filter.gts | 671 +++++++++++++++++ .../app/main/generic-super-select-filter.gts | 627 ++++++++++++++++ showcase/app/router.ts | 2 + showcase/app/styles/app.scss | 1 + .../styles/mock-components/filter-bar.scss | 25 + ...mo-full-app-frame-with-dropdown-filter.hbs | 13 + ...ull-app-frame-with-super-select-filter.hbs | 13 + 15 files changed, 2657 insertions(+) create mode 100644 showcase/app/components/mock/app/main/generic-filter/filter-bar/checkbox.gts create mode 100644 showcase/app/components/mock/app/main/generic-filter/filter-bar/dropdown.gts create mode 100644 showcase/app/components/mock/app/main/generic-filter/filter-bar/index.gts create mode 100644 showcase/app/components/mock/app/main/generic-filter/filter-bar/radio.gts create mode 100644 showcase/app/components/mock/app/main/generic-filter/filter-bar/segmented-group.gts create mode 100644 showcase/app/components/mock/app/main/generic-filter/filter-bar/super-select.gts create mode 100644 showcase/app/components/mock/app/main/generic-filter/generic-dropdown-filter.gts create mode 100644 showcase/app/components/mock/app/main/generic-filter/generic-super-select-filter.gts create mode 100644 showcase/app/components/mock/app/main/generic-super-select-filter.gts create mode 100644 showcase/app/styles/mock-components/filter-bar.scss create mode 100644 showcase/app/templates/page-layouts/app-frame/frameless/demo-full-app-frame-with-dropdown-filter.hbs create mode 100644 showcase/app/templates/page-layouts/app-frame/frameless/demo-full-app-frame-with-super-select-filter.hbs diff --git a/showcase/app/components/mock/app/index.gts b/showcase/app/components/mock/app/index.gts index e8ffe853e0b..ed015abfa17 100644 --- a/showcase/app/components/mock/app/index.gts +++ b/showcase/app/components/mock/app/index.gts @@ -11,6 +11,8 @@ import MockAppSidebarOldSideNav from './sidebar/side-nav'; import MockAppMainPageHeader from './main/page-header'; import MockAppMainGenericTextContent from './main/generic-text-content'; import MockAppMainGenericAdvancedTable from './main/generic-advanced-table'; +import MockAppMainGenericDropdownFilter from './main/generic-filter/generic-dropdown-filter'; +import MockAppMainGenericSuperSelectFilter from './main/generic-filter/generic-super-select-filter'; import MockAppFooterAppFooter from './footer/app-footer'; // HDS components @@ -25,6 +27,8 @@ import type { MockAppSidebarOldSideNavSignature } from './sidebar/side-nav'; import type { MockAppMainPageHeaderSignature } from './main/page-header'; import type { MockAppMainGenericTextContentSignature } from './main/generic-text-content'; import type { MockAppMainGenericAdvancedTableSignature } from './main/generic-advanced-table'; +import type { MockAppMainGenericDropdownFilterSignature } from './main/generic-filter/generic-dropdown-filter'; +import type { MockAppMainGenericSuperSelectFilterSignature } from './main/generic-super-select-filter'; import type { MockAppFooterAppFooterSignature } from './footer/app-footer'; export interface MockAppSignature { @@ -52,6 +56,8 @@ export interface MockAppSignature { PageHeader?: ComponentLike; GenericTextContent?: ComponentLike; GenericAdvancedTable?: ComponentLike; + GenericDropdownFilter?: ComponentLike; + GenericSuperSelectFilter?: ComponentLike; }, ]; footer?: [ @@ -98,6 +104,8 @@ export default class MockApp extends Component { PageHeader=MockAppMainPageHeader GenericTextContent=MockAppMainGenericTextContent GenericAdvancedTable=MockAppMainGenericAdvancedTable + GenericDropdownFilter=MockAppMainGenericDropdownFilter + GenericSuperSelectFilter=MockAppMainGenericSuperSelectFilter ) to="main" }} diff --git a/showcase/app/components/mock/app/main/generic-filter/filter-bar/checkbox.gts b/showcase/app/components/mock/app/main/generic-filter/filter-bar/checkbox.gts new file mode 100644 index 00000000000..15ac2ba7172 --- /dev/null +++ b/showcase/app/components/mock/app/main/generic-filter/filter-bar/checkbox.gts @@ -0,0 +1,66 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { on } from '@ember/modifier'; +import type { WithBoundArgs } from '@glint/template'; + +import type { Filter } from './index'; + +// HDS components +import { + HdsDropdownListItemCheckbox, +} from '@hashicorp/design-system-components/components'; + +import type { HdsDropdownSignature } from '@hashicorp/design-system-components/components/hds/dropdown/index'; + +export interface MockAppMainGenericFilterBarCheckboxSignature { + Args: HdsDropdownSignature['Args'] & { + checkbox?: WithBoundArgs< + typeof HdsDropdownListItemCheckbox, + never + >; + value?: string; + keyFilter: Filter[] | Filter | undefined; + onChange?: (event: Event) => void; + } + Blocks: { + default: [], + } + Element: HTMLDivElement; +} + +export default class MockAppMainGenericFilterBarCheckbox extends Component { + @action + onChange(event: Event): void { + const { onChange } = this.args; + if (onChange && typeof onChange === 'function') { + onChange(event); + } + } + + get isChecked(): boolean { + const { keyFilter, value } = this.args; + if (Array.isArray(keyFilter)) { + return keyFilter.some((filter) => filter.value === value); + } else if (keyFilter && value) { + return keyFilter.value === value; + } + return false; + } + + +} diff --git a/showcase/app/components/mock/app/main/generic-filter/filter-bar/dropdown.gts b/showcase/app/components/mock/app/main/generic-filter/filter-bar/dropdown.gts new file mode 100644 index 00000000000..b70f1c93dad --- /dev/null +++ b/showcase/app/components/mock/app/main/generic-filter/filter-bar/dropdown.gts @@ -0,0 +1,144 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import type { WithBoundArgs } from '@glint/template'; +import { hash } from '@ember/helper'; + +import MockAppMainGenericFilterBarCheckbox from './checkbox'; +import MockAppMainGenericFilterBarRadio from './radio'; + +// HDS components +import { + HdsDropdown, + HdsDropdownToggleButton, +} from '@hashicorp/design-system-components/components'; + +import type { Filters, Filter } from './index'; +import type { HdsDropdownSignature } from '@hashicorp/design-system-components/components/hds/dropdown/index'; + + +export interface MockAppMainGenericFilterBarDropdownSignature { + Args: HdsDropdownSignature['Args'] & { + dropdown?: WithBoundArgs< + typeof HdsDropdown, + never + >; + key: string; + isMultiSelect?: boolean; + filters: Filters; + onChange: (key: string, keyFilter?: Filter[]) => void; + } + Blocks: { + default: [ + { + ToggleButton?: WithBoundArgs< + typeof HdsDropdownToggleButton, + | 'color' + | 'text' + >; + Checkbox?: WithBoundArgs< + typeof MockAppMainGenericFilterBarCheckbox, + | 'checkbox' + | 'keyFilter' + | 'onChange' + >; + Radio?: WithBoundArgs< + typeof MockAppMainGenericFilterBarRadio, + | 'radio' + | 'keyFilter' + | 'onChange' + >; + }, + ]; + }; + Element: HTMLDivElement; +} + +export default class MockAppMainGenericFilterBarDropdown extends Component { + get keyFilter(): Filter[] | Filter | undefined { + const { filters, key } = this.args; + + if (!filters) { + return undefined; + } + return filters[key]; + } + + @action + onChange(event: Event): void { + const addFilter = (value: unknown): Filter[] => { + const newFilter = { + text: value as string, + value: value, + } + if (Array.isArray(this.keyFilter) && input.classList.contains('hds-form-checkbox')) { + this.keyFilter.push(newFilter); + return this.keyFilter; + } else { + return [newFilter]; + } + } + + const removeFilter = (value: string): Filter[] => { + const newFilter = [] as Filter[]; + if (Array.isArray(this.keyFilter)) { + this.keyFilter.forEach((filter) => { + if (filter.value != value) { + newFilter.push(filter); + } + }); + } + return newFilter; + } + + const input = event.target as HTMLInputElement; + + let newFilter = [] as Filter[]; + + if (input.checked) { + newFilter = addFilter(input.value) + } else { + newFilter = removeFilter(input.value) + } + + const { onChange } = this.args; + if (onChange && typeof onChange === 'function') { + if (newFilter.length === 0) { + onChange(this.args.key, undefined); + } else { + onChange(this.args.key, newFilter); + } + } + } + + +} diff --git a/showcase/app/components/mock/app/main/generic-filter/filter-bar/index.gts b/showcase/app/components/mock/app/main/generic-filter/filter-bar/index.gts new file mode 100644 index 00000000000..21cc46b2727 --- /dev/null +++ b/showcase/app/components/mock/app/main/generic-filter/filter-bar/index.gts @@ -0,0 +1,142 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; +import { deepTracked } from 'ember-deep-tracked'; +import { fn, hash } from '@ember/helper'; +import { on } from '@ember/modifier'; + +// HDS components +import { + HdsButton, + HdsTag, + HdsTextBody, +} from '@hashicorp/design-system-components/components'; + +import type { WithBoundArgs } from '@glint/template'; +import MockAppMainGenericFilterBarDropdown from './dropdown'; +import MockAppMainGenericFilterBarSegmentedGroup from './segmented-group'; +import MockAppMainGenericFilterBarSuperSelect from './super-select'; + +export interface Filter { + text: string; + value: unknown; +} + +export interface Filters { + [name: string]: Filter | Filter[] | undefined; +} + +export interface MockAppMainGenericFilterBarSignature { + Args: { + filters: Filters; + onFilter?: (filters: Filters) => void; + }; + Blocks: { + default?: [ + { + SuperSelect?: WithBoundArgs; + Dropdown?: WithBoundArgs; + SegmentedGroup?: WithBoundArgs; + } + ]; + }; + Element: HTMLDivElement; +} +export default class MockAppMainGenericFilterBar extends Component { + @deepTracked filters: Filters = this.args.filters; + @tracked hasActiveFilters: boolean = Object.keys(this.filters).length > 0; + + @action + onFilter(key: string, keyFilter?: Filter[]): void { + this._updateFilter(key, keyFilter); + + this.hasActiveFilters = Object.keys(this.filters).length > 0; + + const { onFilter } = this.args; + if (onFilter && typeof onFilter === 'function') { + onFilter(this.filters); + } + } + + @action + clearFilters(): void { + this.filters = {}; + this.hasActiveFilters = false; + const { onFilter } = this.args; + if (onFilter && typeof onFilter === 'function') { + onFilter(this.filters); + } + } + + private _updateFilter(key: string, keyFilter?: Filter[]): void { + const newFilters = {...this.filters}; + if (!keyFilter || (keyFilter && Array.isArray(keyFilter) && keyFilter.length === 0)) { + delete newFilters[key]; + } else { + newFilters[key] = keyFilter; + } + this.filters = newFilters; + } + + private onFilterDismiss = (key: string, filterValue: string): void => { + const oldFilter = this.filters[key]; + let newFilter: Filter[] = []; + if (Array.isArray(oldFilter)) { + newFilter = oldFilter.filter((filter) => filter.value !== filterValue); + } + this.onFilter(key, newFilter); + } + + +} diff --git a/showcase/app/components/mock/app/main/generic-filter/filter-bar/radio.gts b/showcase/app/components/mock/app/main/generic-filter/filter-bar/radio.gts new file mode 100644 index 00000000000..9855af2f5b8 --- /dev/null +++ b/showcase/app/components/mock/app/main/generic-filter/filter-bar/radio.gts @@ -0,0 +1,66 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { on } from '@ember/modifier'; +import type { WithBoundArgs } from '@glint/template'; + +import type { Filter } from './index'; + +// HDS components +import { + HdsDropdownListItemRadio, +} from '@hashicorp/design-system-components/components'; + +import type { HdsDropdownSignature } from '@hashicorp/design-system-components/components/hds/dropdown/index'; + +export interface MockAppMainGenericFilterBarRadioSignature { + Args: HdsDropdownSignature['Args'] & { + radio?: WithBoundArgs< + typeof HdsDropdownListItemRadio, + never + >; + value?: string; + keyFilter: Filter[] | Filter | undefined; + onChange?: (event: Event) => void; + } + Blocks: { + default: [], + } + Element: HTMLDivElement; +} + +export default class MockAppMainGenericFilterBarRadio extends Component { + @action + onChange(event: Event): void { + const { onChange } = this.args; + if (onChange && typeof onChange === 'function') { + onChange(event); + } + } + + get isChecked(): boolean { + const { keyFilter, value } = this.args; + if (Array.isArray(keyFilter)) { + return keyFilter.some((filter) => filter.value === value); + } else if (keyFilter && value) { + return keyFilter.value === value; + } + return false; + } + + +} diff --git a/showcase/app/components/mock/app/main/generic-filter/filter-bar/segmented-group.gts b/showcase/app/components/mock/app/main/generic-filter/filter-bar/segmented-group.gts new file mode 100644 index 00000000000..a8f8ea56c24 --- /dev/null +++ b/showcase/app/components/mock/app/main/generic-filter/filter-bar/segmented-group.gts @@ -0,0 +1,64 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import type { WithBoundArgs } from '@glint/template'; +import { hash } from '@ember/helper'; + +import MockAppMainGenericFilterBarDropdown from './dropdown'; + +// HDS components +import { + HdsSegmentedGroup, +} from '@hashicorp/design-system-components/components'; + +import type { Filters, Filter } from './index'; + +export interface MockAppMainGenericFilterBarSegmentedGroupSignature { + Args: { + filters: Filters; + onChange: (key: string, keyFilter?: Filter[]) => void; + } + Blocks: { + default: [ + { + Dropdown?: WithBoundArgs< + typeof MockAppMainGenericFilterBarDropdown, + | 'dropdown' + | 'filters' + | 'onChange' + >; + }, + ]; + }; + Element: HTMLDivElement; +} + +export default class MockAppMainGenericFilterBarSegmentedGroup extends Component { + + @action + onChange(key: string, keyFilter?: Filter[]): void { + const { onChange } = this.args; + if (onChange && typeof onChange === 'function') { + onChange(key, keyFilter); + } + } + + +} diff --git a/showcase/app/components/mock/app/main/generic-filter/filter-bar/super-select.gts b/showcase/app/components/mock/app/main/generic-filter/filter-bar/super-select.gts new file mode 100644 index 00000000000..dc93df343ff --- /dev/null +++ b/showcase/app/components/mock/app/main/generic-filter/filter-bar/super-select.gts @@ -0,0 +1,112 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + +import type { HdsFormSuperSelectSingleFieldSignature } from '@hashicorp/design-system-components/components/hds/form/super-select/single/field'; +import type { HdsFormSuperSelectMultipleFieldSignature } from '@hashicorp/design-system-components/components/hds/form/super-select/multiple/field'; + +// HDS components +import { + HdsFormSuperSelectMultipleField, + HdsFormSuperSelectSingleField, +} from '@hashicorp/design-system-components/components'; + +import type { Filters, Filter } from './index'; + +export interface MockAppMainGenericFilterBarSuperSelectSignature { + Args: HdsFormSuperSelectMultipleFieldSignature['Args'] & HdsFormSuperSelectSingleFieldSignature['Args'] & { + key: string; + text: string; + filters: Filters; + options: Array; + isMultiSelect?: boolean; + onChange: (key: string, keyFilter?: Filter[]) => void; + } + Element: HTMLDivElement; +} + +export default class MockAppMainGenericFilterBarSuperSelectFilter extends Component { + get keyFilter(): Filter[] | Filter | undefined { + const { filters, key } = this.args; + + if (!filters) { + return undefined; + } + return filters[key]; + } + + get selectedOptions(): string | string[] | null { + if (this.keyFilter) { + if (Array.isArray(this.keyFilter)) { + const values = this.keyFilter.map((filter) => filter.value as string); + return values; + } else { + return this.keyFilter.value as string; + } + } + return null; + } + + @action + onChange(selectedValues: string | string[] | null): void { + let filters: Filter[] | undefined; + + if (Array.isArray(selectedValues)) { + if (selectedValues.length === 0) { + filters = undefined; + } else { + filters = selectedValues.map((value) => ({ + text: value, + value: value, + })); + } + } else if (selectedValues != null) { + filters = [{ + text: selectedValues, + value: selectedValues, + }]; + } + + const { onChange } = this.args; + if (onChange && typeof onChange === 'function') { + onChange(this.args.key, filters); + } + } + + +} diff --git a/showcase/app/components/mock/app/main/generic-filter/generic-dropdown-filter.gts b/showcase/app/components/mock/app/main/generic-filter/generic-dropdown-filter.gts new file mode 100644 index 00000000000..019ef13f4e3 --- /dev/null +++ b/showcase/app/components/mock/app/main/generic-filter/generic-dropdown-filter.gts @@ -0,0 +1,703 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { deepTracked } from 'ember-deep-tracked'; +import { get } from '@ember/helper'; + +// HDS components +import { + HdsAdvancedTable, + HdsLinkInline, + HdsBadge, + HdsBadgeColorValues, +} from '@hashicorp/design-system-components/components'; + +import type { HdsAdvancedTableSignature } from '@hashicorp/design-system-components/components/hds/advanced-table/index'; +import type { HdsAdvancedTableOnSelectionChangeSignature } from '@hashicorp/design-system-components/components/hds/advanced-table/types'; + +import MockAppMainGenericFilterBar from './filter-bar/index'; + +import type { Filters } from './filter-bar/index'; + +export interface MockAppMainGenericDropdownFilterSignature { + Element: HTMLDivElement; +} + +const SAMPLE_COLUMNS = [ + { + isSortable: true, + label: 'Name', + key: 'name', + width: 'max-content', + }, + { + label: 'Project name', + key: 'project-name', + isSortable: true, + width: 'max-content', + }, + { + label: 'Current run ID', + key: 'current-run-id', + isSortable: true, + width: 'max-content', + }, + { + label: 'Run status', + key: 'run-status', + isSortable: true, + width: 'max-content', + }, + { + label: 'Current run applied', + key: 'current-run-applied', + isSortable: true, + width: 'max-content', + }, + { + label: 'VCS repo', + key: 'vcs-repo', + isSortable: true, + width: 'max-content', + }, + { + label: 'Module count', + key: 'module-count', + isSortable: true, + width: 'max-content', + }, + { + label: 'Modules', + key: 'modules', + isSortable: true, + width: 'max-content', + }, + { + label: 'Provider count', + key: 'provider-count', + isSortable: true, + width: 'max-content', + }, + { + label: 'Providers', + key: 'providers', + isSortable: true, + width: 'max-content', + }, + { + label: 'Terraform version', + key: 'terraform-version', + isSortable: true, + width: 'max-content', + }, + { + label: 'State terraform version', + key: 'state-terraform-version', + isSortable: true, + width: 'max-content', + }, + { + label: 'Created', + key: 'created', + isSortable: true, + width: 'max-content', + }, + { + label: 'Updated', + key: 'updated', + isSortable: true, + width: 'max-content', + }, +]; + +const SAMPLE_MODEL = [ + { + name: 'zoguve-guw-mannaz', + 'project-name': 'do uk guzvas', + 'current-run-id': 'run-0Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 09:10:14 am', + 'vcs-repo': 'example/a))!hzfpKcBl0', + 'module-count': 46, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 118, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 6 2025', + updated: 'Mar 6 2025', + }, + { + name: 'ce-pojzu-dape', + 'project-name': 'ga vujlis de', + 'current-run-id': 'run-1Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:09:14 am', + 'vcs-repo': 'example/tp7Xe!mDHlI[70ZO1', + 'module-count': 152, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 27, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 5 2025', + updated: 'Mar 5 2025', + }, + { + name: 'tehmi-wudvakhe-ve', + 'project-name': 'jize perori gu', + 'current-run-id': 'run-2Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:08:14 am', + 'vcs-repo': 'example/sClKKTBbyCIzf@d8NxH2', + 'module-count': 31, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 42, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 4 2025', + updated: 'Mar 4 2025', + }, + { + name: 'awudulnak-jebtafcel-ruadeim', + 'project-name': 'jokbopu vipsu umbi', + 'current-run-id': 'run-3Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 09:07:14 am', + 'vcs-repo': 'example/y0^(Nm*63', + 'module-count': 58, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 140, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 3 2025', + updated: 'Mar 3 2025', + }, + { + name: 'ma-guz-vomfa', + 'project-name': 'avjusfoj lihijor kailoluh', + 'current-run-id': 'run-4Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:06:14 am', + 'vcs-repo': 'example/ljPWe[4', + 'module-count': 32, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 50, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 2 2025', + updated: 'Mar 2 2025', + }, + { + name: 'empe-zewik-gazofe', + 'project-name': 'su ja keosus', + 'current-run-id': 'run-5Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 09:05:14 am', + 'vcs-repo': 'example/E*fcS4mn@BoDgZu0O5', + 'module-count': 94, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 113, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 1 2025', + updated: 'Mar 1 2025', + }, + { + name: 'indow-suuhi-co', + 'project-name': 'kic nuva wif', + 'current-run-id': 'run-5Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:04:14 am', + 'vcs-repo': 'example/&j[RmmtjpQX6', + 'module-count': 117, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 80, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 28 2025', + updated: 'Feb 28 2025', + }, + { + name: 'kitobi-okaopuaja-civna', + 'project-name': 'tamigeki iwe isnetpi', + 'current-run-id': 'run-7Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 09:03:14 am', + 'vcs-repo': 'example/(DCFjSEKcBuU44J8AB87', + 'module-count': 114, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 107, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.16.0', + created: 'Feb 27 2025', + updated: 'Feb 27 2025', + }, + { + name: 'cos-rekcepfih-dedwez', + 'project-name': 'jigemtu kutnim pohwi', + 'current-run-id': 'run-8Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 09:02:14 am', + 'vcs-repo': 'example/9YURY8', + 'module-count': 106, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 185, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.16.0', + created: 'Feb 26 2025', + updated: 'Feb 26 2025', + }, + { + name: 'pe-fo-oj', + 'project-name': 'wirbidjic ow akasa', + 'current-run-id': 'run-9Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 09:01:14 am', + 'vcs-repo': 'example/9YURY8', + 'module-count': 124, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 175, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.16.0', + created: 'Feb 25 2025', + updated: 'Feb 25 2025', + }, + { + name: 'ti-gecruw-bob', + 'project-name': 'acamo almov ke', + 'current-run-id': 'run-10Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:00:14 am', + 'vcs-repo': 'example/d2s3B46I10', + 'module-count': 70, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 168, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.16.0', + created: 'Feb 24 2025', + updated: 'Feb 24 2025', + }, + { + name: 'ti-gecruw-bob', + 'project-name': 'acamo almov ke', + 'current-run-id': 'run-10Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:00:14 am', + 'vcs-repo': 'example/d2s3B46I10', + 'module-count': 70, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 168, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.16.0', + created: 'Feb 23 2025', + updated: 'Feb 23 2025', + }, + { + name: 'besakve-mezlevwa-aw', + 'project-name': 'do ukate galtem', + 'current-run-id': 'run-11Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 08:59:14 am', + 'vcs-repo': 'example/v@C6&hBTou11', + 'module-count': 106, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 61, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.16.0', + created: 'Feb 22 2025', + updated: 'Feb 22 2025', + }, + { + name: 'no-jitwat-awsulnu', + 'project-name': 'tipa ubidu oh', + 'current-run-id': 'run-12Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 08:58:14 am', + 'vcs-repo': 'example/@t23^12', + 'module-count': 14, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 143, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 21 2025', + updated: 'Feb 21 2025', + }, + { + name: 'sefnut-suju-vakunaj', + 'project-name': 'wumenho ful decre', + 'current-run-id': 'run-13Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 08:58:14 am', + 'vcs-repo': 'example/@t23^12', + 'module-count': 14, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 143, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 20 2025', + updated: 'Feb 20 2025', + }, + { + name: 'oveso-sagcein-renjuli', + 'project-name': 'sesac duheceul ufeesafem', + 'current-run-id': 'run-14Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 08:57:14 am', + 'vcs-repo': 'example/JUha^7zr14', + 'module-count': 114, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 98, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 19 2025', + updated: 'Feb 19 2025', + }, + { + name: 'usitod-ve-citibmam', + 'project-name': 'la ha kadosso', + 'current-run-id': 'run-15Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 08:56:14 am', + 'vcs-repo': 'example/JUha^7zr14', + 'module-count': 99, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 170, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 18 2025', + updated: 'Feb 18 2025', + }, + { + name: 'ko-dozuba-gukum', + 'project-name': 'betrodjar gogwopel lonnege', + 'current-run-id': 'run-16Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 08:57:14 am', + 'vcs-repo': 'example/t*vN3@*BxJnG116', + 'module-count': 139, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 170, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 17 2025', + updated: 'Feb 17 2025', + }, + { + name: 'fo-liszod-wokiso', + 'project-name': 'robagbof lim fowog', + 'current-run-id': 'run-17Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 08:57:14 am', + 'vcs-repo': 'example/8G3C81*u*q*O$17', + 'module-count': 107, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 83, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 16 2025', + updated: 'Feb 16 2025', + }, + { + name: 'taju-ewefir-novawnej', + 'project-name': 'le juzasri ni', + 'current-run-id': 'run-18Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 08:56:14 am', + 'vcs-repo': 'example/gt]5*c!N1*N%I!m)18', + 'module-count': 80, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 152, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 15 2025', + updated: 'Feb 15 2025', + }, + { + name: 'fu-ip-ta', + 'project-name': 'ca reba be', + 'current-run-id': 'run-19Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 08:57:14 am', + 'vcs-repo': 'example/gt]5*c!N1*N%I!m)18', + 'module-count': 158, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 11, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 14 2025', + updated: 'Feb 14 2025', + }, +]; + +const SAMPLE_MODEL_VALUES = { + 'name': Array.from(new Set(SAMPLE_MODEL.map((item) => item['name']))), + 'project-name': Array.from(new Set(SAMPLE_MODEL.map((item) => item['project-name']))), + 'run-status': Array.from(new Set(SAMPLE_MODEL.map((item) => item['run-status']))), + 'vcs-repo': Array.from(new Set(SAMPLE_MODEL.map((item) => item['vcs-repo']))), + 'terraform-version': Array.from(new Set(SAMPLE_MODEL.map((item) => item['terraform-version']))), + 'state-terraform-version': Array.from(new Set(SAMPLE_MODEL.map((item) => item['state-terraform-version']))), +}; + +const updateModelWithSelectAllState = ( + modelData: HdsAdvancedTableSignature['Args']['model'], + selectAllState: boolean, +) => { + modelData.forEach((modelRow) => { + modelRow['isSelected'] = selectAllState; + }); +}; + +const updateModelWithSelectableRowsStates = ( + modelData: HdsAdvancedTableSignature['Args']['model'], + selectableRowsStates: HdsAdvancedTableOnSelectionChangeSignature['selectableRowsStates'], +) => { + const modelDataMap = new Map( + modelData.map((modelRow) => [modelRow['id'], modelRow]), + ); + selectableRowsStates.forEach((row) => { + // safe to assume that there is always a record for the "selectionKey" since it's coming from the model (the selectable "rows" are a subset of the model dataset) + const rowFromModel = modelDataMap.get(row.selectionKey); + if (rowFromModel) { + rowFromModel['isSelected'] = row.isSelected; + } + }); +}; + +export default class MockAppMainGenericDropdownFilter extends Component { + demoColumns = SAMPLE_COLUMNS; + @deepTracked demoModel: HdsAdvancedTableSignature['Args']['model'] = [ + ...SAMPLE_MODEL, + ]; + @deepTracked filters: Filters = {}; + + @action onSelectionChange({ + selectionKey, + selectionCheckboxElement, + selectableRowsStates, + }: HdsAdvancedTableOnSelectionChangeSignature) { + // eslint-disable-next-line prefer-rest-params + console.log(...arguments); + + if (selectionKey === 'all' && this.demoModel) { + const state = selectionCheckboxElement + ? selectionCheckboxElement.checked + : false; + + updateModelWithSelectAllState(this.demoModel, state); + } else { + updateModelWithSelectableRowsStates(this.demoModel, selectableRowsStates); + } + } + + valuesFromFilter = (filters: Filters, name: string) => { + const filter = filters[name]; + if (!filter) return; + + if (Array.isArray(filter)) { + if (filter.length === 1) return filter[0]?.value; + return filter.map((f: Filter) => f.value) as Filters[]; + } + return filter.value; + }; + + @action + onFilter(filters: Filters) { + console.log('onFilter called with filters:', filters); + this.filters = filters; + } + + get demoModelFilteredData() { + const filterItems = (item: any[]): boolean => { + if (Object.keys(this.filters).length === 0) return true; + let match = true; + Object.keys(this.filters).forEach((key) => { + const keyFilters = this.valuesFromFilter(this.filters, key); + if (Array.isArray(keyFilters)) { + if (!keyFilters.includes(item[key])) { + match = false; + } + } else if (item[key] !== keyFilters) { + match = false; + } + }); + return match; + } + + return this.demoModel.filter(filterItems); + } + + +} diff --git a/showcase/app/components/mock/app/main/generic-filter/generic-super-select-filter.gts b/showcase/app/components/mock/app/main/generic-filter/generic-super-select-filter.gts new file mode 100644 index 00000000000..7099f533051 --- /dev/null +++ b/showcase/app/components/mock/app/main/generic-filter/generic-super-select-filter.gts @@ -0,0 +1,671 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { deepTracked } from 'ember-deep-tracked'; +import { get } from '@ember/helper'; + +// HDS components +import { + HdsAdvancedTable, + HdsLinkInline, + HdsBadge, + HdsBadgeColorValues, +} from '@hashicorp/design-system-components/components'; + +import type { HdsAdvancedTableSignature } from '@hashicorp/design-system-components/components/hds/advanced-table/index'; +import type { HdsAdvancedTableOnSelectionChangeSignature } from '@hashicorp/design-system-components/components/hds/advanced-table/types'; + +import MockAppMainGenericFilterBar from './filter-bar/index'; + +import type { Filters } from './filter-bar/index'; + +export interface MockAppMainGenericSuperSelectFilterSignature { + Element: HTMLDivElement; +} + +const SAMPLE_COLUMNS = [ + { + isSortable: true, + label: 'Name', + key: 'name', + width: 'max-content', + }, + { + label: 'Project name', + key: 'project-name', + isSortable: true, + width: 'max-content', + }, + { + label: 'Current run ID', + key: 'current-run-id', + isSortable: true, + width: 'max-content', + }, + { + label: 'Run status', + key: 'run-status', + isSortable: true, + width: 'max-content', + }, + { + label: 'Current run applied', + key: 'current-run-applied', + isSortable: true, + width: 'max-content', + }, + { + label: 'VCS repo', + key: 'vcs-repo', + isSortable: true, + width: 'max-content', + }, + { + label: 'Module count', + key: 'module-count', + isSortable: true, + width: 'max-content', + }, + { + label: 'Modules', + key: 'modules', + isSortable: true, + width: 'max-content', + }, + { + label: 'Provider count', + key: 'provider-count', + isSortable: true, + width: 'max-content', + }, + { + label: 'Providers', + key: 'providers', + isSortable: true, + width: 'max-content', + }, + { + label: 'Terraform version', + key: 'terraform-version', + isSortable: true, + width: 'max-content', + }, + { + label: 'State terraform version', + key: 'state-terraform-version', + isSortable: true, + width: 'max-content', + }, + { + label: 'Created', + key: 'created', + isSortable: true, + width: 'max-content', + }, + { + label: 'Updated', + key: 'updated', + isSortable: true, + width: 'max-content', + }, +]; + +const SAMPLE_MODEL = [ + { + name: 'zoguve-guw-mannaz', + 'project-name': 'do uk guzvas', + 'current-run-id': 'run-0Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 09:10:14 am', + 'vcs-repo': 'example/a))!hzfpKcBl0', + 'module-count': 46, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 118, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 6 2025', + updated: 'Mar 6 2025', + }, + { + name: 'ce-pojzu-dape', + 'project-name': 'ga vujlis de', + 'current-run-id': 'run-1Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:09:14 am', + 'vcs-repo': 'example/tp7Xe!mDHlI[70ZO1', + 'module-count': 152, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 27, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 5 2025', + updated: 'Mar 5 2025', + }, + { + name: 'tehmi-wudvakhe-ve', + 'project-name': 'jize perori gu', + 'current-run-id': 'run-2Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:08:14 am', + 'vcs-repo': 'example/sClKKTBbyCIzf@d8NxH2', + 'module-count': 31, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 42, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 4 2025', + updated: 'Mar 4 2025', + }, + { + name: 'awudulnak-jebtafcel-ruadeim', + 'project-name': 'jokbopu vipsu umbi', + 'current-run-id': 'run-3Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 09:07:14 am', + 'vcs-repo': 'example/y0^(Nm*63', + 'module-count': 58, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 140, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 3 2025', + updated: 'Mar 3 2025', + }, + { + name: 'ma-guz-vomfa', + 'project-name': 'avjusfoj lihijor kailoluh', + 'current-run-id': 'run-4Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:06:14 am', + 'vcs-repo': 'example/ljPWe[4', + 'module-count': 32, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 50, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 2 2025', + updated: 'Mar 2 2025', + }, + { + name: 'empe-zewik-gazofe', + 'project-name': 'su ja keosus', + 'current-run-id': 'run-5Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 09:05:14 am', + 'vcs-repo': 'example/E*fcS4mn@BoDgZu0O5', + 'module-count': 94, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 113, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 1 2025', + updated: 'Mar 1 2025', + }, + { + name: 'indow-suuhi-co', + 'project-name': 'kic nuva wif', + 'current-run-id': 'run-5Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:04:14 am', + 'vcs-repo': 'example/&j[RmmtjpQX6', + 'module-count': 117, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 80, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 28 2025', + updated: 'Feb 28 2025', + }, + { + name: 'kitobi-okaopuaja-civna', + 'project-name': 'tamigeki iwe isnetpi', + 'current-run-id': 'run-7Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 09:03:14 am', + 'vcs-repo': 'example/(DCFjSEKcBuU44J8AB87', + 'module-count': 114, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 107, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.16.0', + created: 'Feb 27 2025', + updated: 'Feb 27 2025', + }, + { + name: 'cos-rekcepfih-dedwez', + 'project-name': 'jigemtu kutnim pohwi', + 'current-run-id': 'run-8Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 09:02:14 am', + 'vcs-repo': 'example/9YURY8', + 'module-count': 106, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 185, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.16.0', + created: 'Feb 26 2025', + updated: 'Feb 26 2025', + }, + { + name: 'pe-fo-oj', + 'project-name': 'wirbidjic ow akasa', + 'current-run-id': 'run-9Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 09:01:14 am', + 'vcs-repo': 'example/9YURY8', + 'module-count': 124, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 175, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.16.0', + created: 'Feb 25 2025', + updated: 'Feb 25 2025', + }, + { + name: 'ti-gecruw-bob', + 'project-name': 'acamo almov ke', + 'current-run-id': 'run-10Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:00:14 am', + 'vcs-repo': 'example/d2s3B46I10', + 'module-count': 70, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 168, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.16.0', + created: 'Feb 24 2025', + updated: 'Feb 24 2025', + }, + { + name: 'ti-gecruw-bob', + 'project-name': 'acamo almov ke', + 'current-run-id': 'run-10Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:00:14 am', + 'vcs-repo': 'example/d2s3B46I10', + 'module-count': 70, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 168, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.16.0', + created: 'Feb 23 2025', + updated: 'Feb 23 2025', + }, + { + name: 'besakve-mezlevwa-aw', + 'project-name': 'do ukate galtem', + 'current-run-id': 'run-11Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 08:59:14 am', + 'vcs-repo': 'example/v@C6&hBTou11', + 'module-count': 106, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 61, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.16.0', + created: 'Feb 22 2025', + updated: 'Feb 22 2025', + }, + { + name: 'no-jitwat-awsulnu', + 'project-name': 'tipa ubidu oh', + 'current-run-id': 'run-12Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 08:58:14 am', + 'vcs-repo': 'example/@t23^12', + 'module-count': 14, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 143, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 21 2025', + updated: 'Feb 21 2025', + }, + { + name: 'sefnut-suju-vakunaj', + 'project-name': 'wumenho ful decre', + 'current-run-id': 'run-13Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 08:58:14 am', + 'vcs-repo': 'example/@t23^12', + 'module-count': 14, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 143, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 20 2025', + updated: 'Feb 20 2025', + }, + { + name: 'oveso-sagcein-renjuli', + 'project-name': 'sesac duheceul ufeesafem', + 'current-run-id': 'run-14Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 08:57:14 am', + 'vcs-repo': 'example/JUha^7zr14', + 'module-count': 114, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 98, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 19 2025', + updated: 'Feb 19 2025', + }, + { + name: 'usitod-ve-citibmam', + 'project-name': 'la ha kadosso', + 'current-run-id': 'run-15Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 08:56:14 am', + 'vcs-repo': 'example/JUha^7zr14', + 'module-count': 99, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 170, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 18 2025', + updated: 'Feb 18 2025', + }, + { + name: 'ko-dozuba-gukum', + 'project-name': 'betrodjar gogwopel lonnege', + 'current-run-id': 'run-16Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 08:57:14 am', + 'vcs-repo': 'example/t*vN3@*BxJnG116', + 'module-count': 139, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 170, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 17 2025', + updated: 'Feb 17 2025', + }, + { + name: 'fo-liszod-wokiso', + 'project-name': 'robagbof lim fowog', + 'current-run-id': 'run-17Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 08:57:14 am', + 'vcs-repo': 'example/8G3C81*u*q*O$17', + 'module-count': 107, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 83, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 16 2025', + updated: 'Feb 16 2025', + }, + { + name: 'taju-ewefir-novawnej', + 'project-name': 'le juzasri ni', + 'current-run-id': 'run-18Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 08:56:14 am', + 'vcs-repo': 'example/gt]5*c!N1*N%I!m)18', + 'module-count': 80, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 152, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 15 2025', + updated: 'Feb 15 2025', + }, + { + name: 'fu-ip-ta', + 'project-name': 'ca reba be', + 'current-run-id': 'run-19Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 08:57:14 am', + 'vcs-repo': 'example/gt]5*c!N1*N%I!m)18', + 'module-count': 158, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 11, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.5', + 'state-terraform-version': '0.15.0', + created: 'Feb 14 2025', + updated: 'Feb 14 2025', + }, +]; + +const SAMPLE_MODEL_VALUES = { + 'name': Array.from(new Set(SAMPLE_MODEL.map((item) => item['name']))), + 'project-name': Array.from(new Set(SAMPLE_MODEL.map((item) => item['project-name']))), + 'run-status': Array.from(new Set(SAMPLE_MODEL.map((item) => item['run-status']))), + 'vcs-repo': Array.from(new Set(SAMPLE_MODEL.map((item) => item['vcs-repo']))), + 'terraform-version': Array.from(new Set(SAMPLE_MODEL.map((item) => item['terraform-version']))), + 'state-terraform-version': Array.from(new Set(SAMPLE_MODEL.map((item) => item['state-terraform-version']))), +}; + +const updateModelWithSelectAllState = ( + modelData: HdsAdvancedTableSignature['Args']['model'], + selectAllState: boolean, +) => { + modelData.forEach((modelRow) => { + modelRow['isSelected'] = selectAllState; + }); +}; + +const updateModelWithSelectableRowsStates = ( + modelData: HdsAdvancedTableSignature['Args']['model'], + selectableRowsStates: HdsAdvancedTableOnSelectionChangeSignature['selectableRowsStates'], +) => { + const modelDataMap = new Map( + modelData.map((modelRow) => [modelRow['id'], modelRow]), + ); + selectableRowsStates.forEach((row) => { + // safe to assume that there is always a record for the "selectionKey" since it's coming from the model (the selectable "rows" are a subset of the model dataset) + const rowFromModel = modelDataMap.get(row.selectionKey); + if (rowFromModel) { + rowFromModel['isSelected'] = row.isSelected; + } + }); +}; + +export default class MockAppMainGenericSuperSelectFilter extends Component { + demoColumns = SAMPLE_COLUMNS; + @deepTracked demoModel: HdsAdvancedTableSignature['Args']['model'] = [ + ...SAMPLE_MODEL, + ]; + @deepTracked filters: Filters = {}; + + @action onSelectionChange({ + selectionKey, + selectionCheckboxElement, + selectableRowsStates, + }: HdsAdvancedTableOnSelectionChangeSignature) { + // eslint-disable-next-line prefer-rest-params + console.log(...arguments); + + if (selectionKey === 'all' && this.demoModel) { + const state = selectionCheckboxElement + ? selectionCheckboxElement.checked + : false; + + updateModelWithSelectAllState(this.demoModel, state); + } else { + updateModelWithSelectableRowsStates(this.demoModel, selectableRowsStates); + } + } + + valuesFromFilter = (filters: Filters, name: string) => { + const filter = filters[name]; + if (!filter) return; + + if (Array.isArray(filter)) { + if (filter.length === 1) return filter[0]?.value; + return filter.map((f: Filter[]) => f.value); + } + return filter.value; + }; + + @action + onFilter(filters: Filters) { + console.log('onFilter called with filters:', filters); + this.filters = filters; + } + + get demoModelFilteredData() { + const filterItem = (item: Filters): boolean => { + if (Object.keys(this.filters).length === 0) return true; + let match = true; + Object.keys(this.filters).forEach((key) => { + const keyFilters = this.valuesFromFilter(this.filters, key); + if (Array.isArray(keyFilters)) { + if (!keyFilters.includes(item[key])) { + match = false; + } + } else if (item[key] !== keyFilters) { + match = false; + } + }); + return match; + } + + return this.demoModel.filter(filterItem); + } + + +} diff --git a/showcase/app/components/mock/app/main/generic-super-select-filter.gts b/showcase/app/components/mock/app/main/generic-super-select-filter.gts new file mode 100644 index 00000000000..e6a07d9ebff --- /dev/null +++ b/showcase/app/components/mock/app/main/generic-super-select-filter.gts @@ -0,0 +1,627 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { deepTracked } from 'ember-deep-tracked'; +import { get } from '@ember/helper'; + +// HDS components +import { + HdsAdvancedTable, + HdsLinkInline, + HdsBadge, + HdsBadgeColorValues, + HdsFormSuperSelectMultipleField, + type HdsAdvancedTableOnSelectionChangeSignature, +} from '@hashicorp/design-system-components/components'; + +import type { HdsAdvancedTableSignature } from '@hashicorp/design-system-components/components/hds/advanced-table/index'; + +export interface MockAppMainGenericSuperSelectFilterSignature { + Element: HTMLDivElement; +} + +const SAMPLE_COLUMNS = [ + { + isSortable: true, + label: 'Name', + key: 'name', + width: 'max-content', + }, + { + label: 'Project name', + key: 'project-name', + isSortable: true, + width: 'max-content', + }, + { + label: 'Current run ID', + key: 'current-run-id', + isSortable: true, + width: 'max-content', + }, + { + label: 'Run status', + key: 'run-status', + isSortable: true, + width: 'max-content', + }, + { + label: 'Current run applied', + key: 'current-run-applied', + isSortable: true, + width: 'max-content', + }, + { + label: 'VCS repo', + key: 'vcs-repo', + isSortable: true, + width: 'max-content', + }, + { + label: 'Module count', + key: 'module-count', + isSortable: true, + width: 'max-content', + }, + { + label: 'Modules', + key: 'modules', + isSortable: true, + width: 'max-content', + }, + { + label: 'Provider count', + key: 'provider-count', + isSortable: true, + width: 'max-content', + }, + { + label: 'Providers', + key: 'providers', + isSortable: true, + width: 'max-content', + }, + { + label: 'Terraform version', + key: 'terraform-version', + isSortable: true, + width: 'max-content', + }, + { + label: 'State terraform version', + key: 'state-terraform-version', + isSortable: true, + width: 'max-content', + }, + { + label: 'Created', + key: 'created', + isSortable: true, + width: 'max-content', + }, + { + label: 'Updated', + key: 'updated', + isSortable: true, + width: 'max-content', + }, +]; + +const SAMPLE_MODEL = [ + { + name: 'zoguve-guw-mannaz', + 'project-name': 'do uk guzvas', + 'current-run-id': 'run-0Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 09:10:14 am', + 'vcs-repo': 'example/a))!hzfpKcBl0', + 'module-count': 46, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 118, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 6 2025', + updated: 'Mar 6 2025', + }, + { + name: 'ce-pojzu-dape', + 'project-name': 'ga vujlis de', + 'current-run-id': 'run-1Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:09:14 am', + 'vcs-repo': 'example/tp7Xe!mDHlI[70ZO1', + 'module-count': 152, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 27, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 5 2025', + updated: 'Mar 5 2025', + }, + { + name: 'tehmi-wudvakhe-ve', + 'project-name': 'jize perori gu', + 'current-run-id': 'run-2Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:08:14 am', + 'vcs-repo': 'example/sClKKTBbyCIzf@d8NxH2', + 'module-count': 31, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 42, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 4 2025', + updated: 'Mar 4 2025', + }, + { + name: 'awudulnak-jebtafcel-ruadeim', + 'project-name': 'jokbopu vipsu umbi', + 'current-run-id': 'run-3Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 09:07:14 am', + 'vcs-repo': 'example/y0^(Nm*63', + 'module-count': 58, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 140, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 3 2025', + updated: 'Mar 3 2025', + }, + { + name: 'ma-guz-vomfa', + 'project-name': 'avjusfoj lihijor kailoluh', + 'current-run-id': 'run-4Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:06:14 am', + 'vcs-repo': 'example/ljPWe[4', + 'module-count': 32, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 50, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 2 2025', + updated: 'Mar 2 2025', + }, + { + name: 'empe-zewik-gazofe', + 'project-name': 'su ja keosus', + 'current-run-id': 'run-5Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 09:05:14 am', + 'vcs-repo': 'example/E*fcS4mn@BoDgZu0O5', + 'module-count': 94, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 113, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Mar 1 2025', + updated: 'Mar 1 2025', + }, + { + name: 'indow-suuhi-co', + 'project-name': 'kic nuva wif', + 'current-run-id': 'run-5Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:04:14 am', + 'vcs-repo': 'example/&j[RmmtjpQX6', + 'module-count': 117, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 80, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 28 2025', + updated: 'Feb 28 2025', + }, + { + name: 'kitobi-okaopuaja-civna', + 'project-name': 'tamigeki iwe isnetpi', + 'current-run-id': 'run-7Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 09:03:14 am', + 'vcs-repo': 'example/(DCFjSEKcBuU44J8AB87', + 'module-count': 114, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 107, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 27 2025', + updated: 'Feb 27 2025', + }, + { + name: 'cos-rekcepfih-dedwez', + 'project-name': 'jigemtu kutnim pohwi', + 'current-run-id': 'run-8Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 09:02:14 am', + 'vcs-repo': 'example/9YURY8', + 'module-count': 106, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 185, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 26 2025', + updated: 'Feb 26 2025', + }, + { + name: 'pe-fo-oj', + 'project-name': 'wirbidjic ow akasa', + 'current-run-id': 'run-9Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 09:01:14 am', + 'vcs-repo': 'example/9YURY8', + 'module-count': 124, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 175, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 25 2025', + updated: 'Feb 25 2025', + }, + { + name: 'ti-gecruw-bob', + 'project-name': 'acamo almov ke', + 'current-run-id': 'run-10Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:00:14 am', + 'vcs-repo': 'example/d2s3B46I10', + 'module-count': 70, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 168, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 24 2025', + updated: 'Feb 24 2025', + }, + { + name: 'ti-gecruw-bob', + 'project-name': 'acamo almov ke', + 'current-run-id': 'run-10Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 09:00:14 am', + 'vcs-repo': 'example/d2s3B46I10', + 'module-count': 70, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 168, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 23 2025', + updated: 'Feb 23 2025', + }, + { + name: 'besakve-mezlevwa-aw', + 'project-name': 'do ukate galtem', + 'current-run-id': 'run-11Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 08:59:14 am', + 'vcs-repo': 'example/v@C6&hBTou11', + 'module-count': 106, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 61, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 22 2025', + updated: 'Feb 22 2025', + }, + { + name: 'no-jitwat-awsulnu', + 'project-name': 'tipa ubidu oh', + 'current-run-id': 'run-12Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 08:58:14 am', + 'vcs-repo': 'example/@t23^12', + 'module-count': 14, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 143, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 21 2025', + updated: 'Feb 21 2025', + }, + { + name: 'sefnut-suju-vakunaj', + 'project-name': 'wumenho ful decre', + 'current-run-id': 'run-13Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 08:58:14 am', + 'vcs-repo': 'example/@t23^12', + 'module-count': 14, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 143, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 20 2025', + updated: 'Feb 20 2025', + }, + { + name: 'oveso-sagcein-renjuli', + 'project-name': 'sesac duheceul ufeesafem', + 'current-run-id': 'run-14Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 08:57:14 am', + 'vcs-repo': 'example/JUha^7zr14', + 'module-count': 114, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 98, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 19 2025', + updated: 'Feb 19 2025', + }, + { + name: 'usitod-ve-citibmam', + 'project-name': 'la ha kadosso', + 'current-run-id': 'run-15Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 08:56:14 am', + 'vcs-repo': 'example/JUha^7zr14', + 'module-count': 99, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 170, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 18 2025', + updated: 'Feb 18 2025', + }, + { + name: 'ko-dozuba-gukum', + 'project-name': 'betrodjar gogwopel lonnege', + 'current-run-id': 'run-16Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 08:57:14 am', + 'vcs-repo': 'example/t*vN3@*BxJnG116', + 'module-count': 139, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 170, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 17 2025', + updated: 'Feb 17 2025', + }, + { + name: 'fo-liszod-wokiso', + 'project-name': 'robagbof lim fowog', + 'current-run-id': 'run-17Yks9WCFeD9xRTWo', + 'run-status': 'planned', + 'run-status-color': HdsBadgeColorValues.Warning, + 'current-run-applied': 'Mar 06, 2025 08:57:14 am', + 'vcs-repo': 'example/8G3C81*u*q*O$17', + 'module-count': 107, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 83, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 16 2025', + updated: 'Feb 16 2025', + }, + { + name: 'taju-ewefir-novawnej', + 'project-name': 'le juzasri ni', + 'current-run-id': 'run-18Yks9WCFeD9xRTWo', + 'run-status': 'errored', + 'run-status-color': HdsBadgeColorValues.Critical, + 'current-run-applied': 'Mar 06, 2025 08:56:14 am', + 'vcs-repo': 'example/gt]5*c!N1*N%I!m)18', + 'module-count': 80, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 152, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 15 2025', + updated: 'Feb 15 2025', + }, + { + name: 'fu-ip-ta', + 'project-name': 'ca reba be', + 'current-run-id': 'run-19Yks9WCFeD9xRTWo', + 'run-status': 'applied', + 'run-status-color': HdsBadgeColorValues.Success, + 'current-run-applied': 'Mar 06, 2025 08:57:14 am', + 'vcs-repo': 'example/gt]5*c!N1*N%I!m)18', + 'module-count': 158, + modules: 'wad-bedzeaje-rogmejca', + 'provider-count': 11, + providers: 'susnup-da-zuw', + 'terraform-version': '0.14.0', + 'state-terraform-version': '0.15.0', + created: 'Feb 14 2025', + updated: 'Feb 14 2025', + }, +]; + +const updateModelWithSelectAllState = ( + modelData: HdsAdvancedTableSignature['Args']['model'], + selectAllState: boolean, +) => { + modelData.forEach((modelRow) => { + modelRow['isSelected'] = selectAllState; + }); +}; + +const updateModelWithSelectableRowsStates = ( + modelData: HdsAdvancedTableSignature['Args']['model'], + selectableRowsStates: HdsAdvancedTableOnSelectionChangeSignature['selectableRowsStates'], +) => { + const modelDataMap = new Map( + modelData.map((modelRow) => [modelRow['id'], modelRow]), + ); + selectableRowsStates.forEach((row) => { + // safe to assume that there is always a record for the "selectionKey" since it's coming from the model (the selectable "rows" are a subset of the model dataset) + const rowFromModel = modelDataMap.get(row.selectionKey); + if (rowFromModel) { + rowFromModel['isSelected'] = row.isSelected; + } + }); +}; + +export default class MockAppMainGenericSuperSelectFilter extends Component { + demoColumns = SAMPLE_COLUMNS; + @deepTracked demoModel: HdsAdvancedTableSignature['Args']['model'] = [ + ...SAMPLE_MODEL, + ]; + + private _runStatusOptions = ['applied', 'errored', 'planned']; + + @action onSelectionChange({ + selectionKey, + selectionCheckboxElement, + selectableRowsStates, + }: HdsAdvancedTableOnSelectionChangeSignature) { + // eslint-disable-next-line prefer-rest-params + console.log(...arguments); + + if (selectionKey === 'all' && this.demoModel) { + const state = selectionCheckboxElement + ? selectionCheckboxElement.checked + : false; + + updateModelWithSelectAllState(this.demoModel, state); + } else { + updateModelWithSelectableRowsStates(this.demoModel, selectableRowsStates); + } + } + + private onChange() { + // no-op + } + + +} diff --git a/showcase/app/router.ts b/showcase/app/router.ts index 3defc276327..854199cf61f 100644 --- a/showcase/app/router.ts +++ b/showcase/app/router.ts @@ -127,6 +127,8 @@ Router.map(function () { this.route('demo-full-app-frame-with-app-header-and-app-side-nav'); this.route('demo-full-app-frame-with-side-nav'); this.route('demo-full-app-frame-with-advanced-table'); + this.route('demo-full-app-frame-with-dropdown-filter'); + this.route('demo-full-app-frame-with-super-select-filter'); }); }); this.route('flex'); diff --git a/showcase/app/styles/app.scss b/showcase/app/styles/app.scss index fb06fee50bd..dae513681b6 100644 --- a/showcase/app/styles/app.scss +++ b/showcase/app/styles/app.scss @@ -24,6 +24,7 @@ @use "./showcase-components/outliner"; @use "./showcase-components/placeholder"; @use "./mock-components/app"; +@use "./mock-components/filter-bar"; @use "./mock-components/demo/breakpoints"; diff --git a/showcase/app/styles/mock-components/filter-bar.scss b/showcase/app/styles/mock-components/filter-bar.scss new file mode 100644 index 00000000000..86d94bc7395 --- /dev/null +++ b/showcase/app/styles/mock-components/filter-bar.scss @@ -0,0 +1,25 @@ +// Mock Filter Bar +.mock-app-main-generic-filter-bar { + display: grid; + gap: 16px; + padding-bottom: 16px; + + .filters { + display: flex; + flex-wrap: wrap; + gap: 12px; + + .filter__super-select { + min-width: 200px; + max-width: 300px; + } + } + + .filter-actions { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 8px; + align-items: center; + } +} \ No newline at end of file diff --git a/showcase/app/templates/page-layouts/app-frame/frameless/demo-full-app-frame-with-dropdown-filter.hbs b/showcase/app/templates/page-layouts/app-frame/frameless/demo-full-app-frame-with-dropdown-filter.hbs new file mode 100644 index 00000000000..b301b2c9d8f --- /dev/null +++ b/showcase/app/templates/page-layouts/app-frame/frameless/demo-full-app-frame-with-dropdown-filter.hbs @@ -0,0 +1,13 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: MPL-2.0 +}} + +{{page-title "AppFrame Component - Frameless"}} + + + <:main as |M|> + + + + \ No newline at end of file diff --git a/showcase/app/templates/page-layouts/app-frame/frameless/demo-full-app-frame-with-super-select-filter.hbs b/showcase/app/templates/page-layouts/app-frame/frameless/demo-full-app-frame-with-super-select-filter.hbs new file mode 100644 index 00000000000..81c01a7d323 --- /dev/null +++ b/showcase/app/templates/page-layouts/app-frame/frameless/demo-full-app-frame-with-super-select-filter.hbs @@ -0,0 +1,13 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: MPL-2.0 +}} + +{{page-title "AppFrame Component - Frameless"}} + + + <:main as |M|> + + + + \ No newline at end of file From 85012299bfe0d70767ebf294c40e3cfe1bfbf100 Mon Sep 17 00:00:00 2001 From: Dylan Hyun Date: Wed, 3 Sep 2025 10:51:49 -0400 Subject: [PATCH 2/3] Feat: Live and delayed filtering options --- .../generic-filter/filter-bar/checkbox.gts | 15 +- .../generic-filter/filter-bar/dropdown.gts | 129 ++++++++++++------ .../main/generic-filter/filter-bar/index.gts | 58 +++++--- .../main/generic-filter/filter-bar/radio.gts | 15 +- .../filter-bar/segmented-group.gts | 19 +-- .../filter-bar/super-select-footer.gts | 45 ++++++ .../filter-bar/super-select.gts | 90 +++++++++--- .../generic-dropdown-filter.gts | 72 ++++++---- .../generic-super-select-filter.gts | 70 ++++++++-- .../styles/mock-components/filter-bar.scss | 24 +++- 10 files changed, 389 insertions(+), 148 deletions(-) create mode 100644 showcase/app/components/mock/app/main/generic-filter/filter-bar/super-select-footer.gts diff --git a/showcase/app/components/mock/app/main/generic-filter/filter-bar/checkbox.gts b/showcase/app/components/mock/app/main/generic-filter/filter-bar/checkbox.gts index 15ac2ba7172..10190c8d658 100644 --- a/showcase/app/components/mock/app/main/generic-filter/filter-bar/checkbox.gts +++ b/showcase/app/components/mock/app/main/generic-filter/filter-bar/checkbox.gts @@ -11,25 +11,20 @@ import type { WithBoundArgs } from '@glint/template'; import type { Filter } from './index'; // HDS components -import { - HdsDropdownListItemCheckbox, -} from '@hashicorp/design-system-components/components'; +import { HdsDropdownListItemCheckbox } from '@hashicorp/design-system-components/components'; import type { HdsDropdownSignature } from '@hashicorp/design-system-components/components/hds/dropdown/index'; export interface MockAppMainGenericFilterBarCheckboxSignature { Args: HdsDropdownSignature['Args'] & { - checkbox?: WithBoundArgs< - typeof HdsDropdownListItemCheckbox, - never - >; + checkbox?: WithBoundArgs; value?: string; keyFilter: Filter[] | Filter | undefined; onChange?: (event: Event) => void; - } + }; Blocks: { - default: [], - } + default: []; + }; Element: HTMLDivElement; } diff --git a/showcase/app/components/mock/app/main/generic-filter/filter-bar/dropdown.gts b/showcase/app/components/mock/app/main/generic-filter/filter-bar/dropdown.gts index b70f1c93dad..1afa9f04df0 100644 --- a/showcase/app/components/mock/app/main/generic-filter/filter-bar/dropdown.gts +++ b/showcase/app/components/mock/app/main/generic-filter/filter-bar/dropdown.gts @@ -5,14 +5,19 @@ import Component from '@glimmer/component'; import { action } from '@ember/object'; -import type { WithBoundArgs } from '@glint/template'; import { hash } from '@ember/helper'; +import { tracked } from '@glimmer/tracking'; +import { on } from '@ember/modifier'; +import { modifier } from 'ember-modifier'; +import type { WithBoundArgs } from '@glint/template'; import MockAppMainGenericFilterBarCheckbox from './checkbox'; import MockAppMainGenericFilterBarRadio from './radio'; // HDS components import { + HdsButton, + HdsButtonSet, HdsDropdown, HdsDropdownToggleButton, } from '@hashicorp/design-system-components/components'; @@ -20,37 +25,29 @@ import { import type { Filters, Filter } from './index'; import type { HdsDropdownSignature } from '@hashicorp/design-system-components/components/hds/dropdown/index'; - export interface MockAppMainGenericFilterBarDropdownSignature { Args: HdsDropdownSignature['Args'] & { - dropdown?: WithBoundArgs< - typeof HdsDropdown, - never - >; + dropdown?: WithBoundArgs; key: string; - isMultiSelect?: boolean; filters: Filters; + isMultiSelect?: boolean; + isLiveFilter?: boolean; onChange: (key: string, keyFilter?: Filter[]) => void; - } + }; Blocks: { default: [ { ToggleButton?: WithBoundArgs< typeof HdsDropdownToggleButton, - | 'color' - | 'text' + 'color' | 'text' >; Checkbox?: WithBoundArgs< typeof MockAppMainGenericFilterBarCheckbox, - | 'checkbox' - | 'keyFilter' - | 'onChange' + 'checkbox' | 'keyFilter' | 'onChange' >; Radio?: WithBoundArgs< typeof MockAppMainGenericFilterBarRadio, - | 'radio' - | 'keyFilter' - | 'onChange' + 'radio' | 'keyFilter' | 'onChange' >; }, ]; @@ -58,7 +55,15 @@ export interface MockAppMainGenericFilterBarDropdownSignature { Element: HTMLDivElement; } -export default class MockAppMainGenericFilterBarDropdown extends Component { +export default class MockAppMainGenericFilterBarDropdown extends Component< + HdsDropdownSignature & MockAppMainGenericFilterBarDropdownSignature +> { + @tracked internalFilters: Filter[] | Filter | undefined = []; + + private _updateInternalFilters = modifier(() => { + this.internalFilters = this.keyFilter; + }); + get keyFilter(): Filter[] | Filter | undefined { const { filters, key } = this.args; @@ -74,71 +79,115 @@ export default class MockAppMainGenericFilterBarDropdown extends Component { const newFilter = [] as Filter[]; - if (Array.isArray(this.keyFilter)) { - this.keyFilter.forEach((filter) => { + if (Array.isArray(this.internalFilters)) { + this.internalFilters.forEach((filter) => { if (filter.value != value) { newFilter.push(filter); } }); } return newFilter; - } + }; const input = event.target as HTMLInputElement; let newFilter = [] as Filter[]; if (input.checked) { - newFilter = addFilter(input.value) + newFilter = addFilter(input.value); } else { - newFilter = removeFilter(input.value) + newFilter = removeFilter(input.value); + } + + this.internalFilters = newFilter; + + if (this.args.isLiveFilter) { + const { onChange } = this.args; + if (onChange && typeof onChange === 'function') { + if (newFilter.length === 0) { + onChange(this.args.key, undefined); + } else { + onChange(this.args.key, newFilter); + } + } } + } + @action + onApply(): void { const { onChange } = this.args; if (onChange && typeof onChange === 'function') { - if (newFilter.length === 0) { - onChange(this.args.key, undefined); - } else { - onChange(this.args.key, newFilter); - } + onChange(this.args.key, this.internalFilters); + } + } + + @action + onClear(): void { + this.internalFilters = []; + + const { onChange } = this.args; + if (onChange && typeof onChange === 'function') { + onChange(this.args.key, this.internalFilters); } } } diff --git a/showcase/app/components/mock/app/main/generic-filter/filter-bar/index.gts b/showcase/app/components/mock/app/main/generic-filter/filter-bar/index.gts index 21cc46b2727..ef21e60f20b 100644 --- a/showcase/app/components/mock/app/main/generic-filter/filter-bar/index.gts +++ b/showcase/app/components/mock/app/main/generic-filter/filter-bar/index.gts @@ -9,12 +9,14 @@ import { tracked } from '@glimmer/tracking'; import { deepTracked } from 'ember-deep-tracked'; import { fn, hash } from '@ember/helper'; import { on } from '@ember/modifier'; +import { eq, notEq, and } from 'ember-truth-helpers'; // HDS components import { HdsButton, HdsTag, HdsTextBody, + HdsFormTextInputBase, } from '@hashicorp/design-system-components/components'; import type { WithBoundArgs } from '@glint/template'; @@ -34,24 +36,26 @@ export interface Filters { export interface MockAppMainGenericFilterBarSignature { Args: { filters: Filters; + type?: 'super-select' | 'dropdown'; + isLiveFilter?: boolean; onFilter?: (filters: Filters) => void; }; Blocks: { default?: [ { - SuperSelect?: WithBoundArgs; - Dropdown?: WithBoundArgs; - SegmentedGroup?: WithBoundArgs; - } + }, ]; }; Element: HTMLDivElement; @@ -83,8 +87,11 @@ export default class MockAppMainGenericFilterBar extends Component filter.value !== filterValue); } this.onFilter(key, newFilter); - } + };