Skip to content

Commit e99e488

Browse files
authored
Showcase: Convert table to gts (#3098)
1 parent ea61722 commit e99e488

File tree

22 files changed

+3161
-2573
lines changed

22 files changed

+3161
-2573
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/**
2+
* Copyright (c) HashiCorp, Inc.
3+
* SPDX-License-Identifier: MPL-2.0
4+
*/
5+
import type { TemplateOnlyComponent } from '@ember/component/template-only';
6+
import { get } from '@ember/helper';
7+
import { eq } from 'ember-truth-helpers';
8+
9+
import CLUSTERS from 'showcase/mocks/cluster-data';
10+
11+
import {
12+
HdsBadge,
13+
HdsDropdown,
14+
HdsTable,
15+
} from '@hashicorp/design-system-components/components';
16+
import type { HdsTableSignature } from '@hashicorp/design-system-components/components/hds/table/index';
17+
18+
export interface CodeFragmentWithClusterDataSignature {
19+
Args: {
20+
extraData?: boolean;
21+
columns: HdsTableSignature['Args']['columns'];
22+
sortBy?: HdsTableSignature['Args']['sortBy'];
23+
sortOrder?: HdsTableSignature['Args']['sortOrder'];
24+
onSort?: HdsTableSignature['Args']['onSort'];
25+
};
26+
Element: HTMLDivElement;
27+
}
28+
29+
const CUSTOM_SORTING_CRITERIA = [
30+
'failing',
31+
'active',
32+
'establishing',
33+
'pending',
34+
];
35+
36+
const CLUSTERS_WITH_EXTRA_DATA = CLUSTERS.map((record) => {
37+
return {
38+
...record,
39+
'status-sort-order': CUSTOM_SORTING_CRITERIA.indexOf(record['status']),
40+
};
41+
});
42+
43+
const CodeFragmentWithClusterData: TemplateOnlyComponent<CodeFragmentWithClusterDataSignature> =
44+
<template>
45+
<HdsTable
46+
@model={{if @extraData CLUSTERS_WITH_EXTRA_DATA CLUSTERS}}
47+
@columns={{@columns}}
48+
@sortBy={{@sortBy}}
49+
@sortOrder={{@sortOrder}}
50+
@onSort={{@onSort}}
51+
>
52+
<:body as |B|>
53+
<B.Tr>
54+
<B.Td>{{B.data.peer-name}}</B.Td>
55+
<B.Td>{{B.data.cluster-partition}}</B.Td>
56+
<B.Td>
57+
{{#if (eq (get B.data "status") "failing")}}
58+
<HdsBadge
59+
@text="Failing"
60+
@color="critical"
61+
@icon="x"
62+
@type="outlined"
63+
/>
64+
{{else if (eq (get B.data "status") "active")}}
65+
<HdsBadge
66+
@text="Active"
67+
@color="success"
68+
@icon="check"
69+
@type="outlined"
70+
/>
71+
{{else if (eq (get B.data "status") "pending")}}
72+
<HdsBadge
73+
@text="Pending"
74+
@color="neutral"
75+
@icon="loading"
76+
@type="outlined"
77+
/>
78+
{{else if (eq (get B.data "status") "establishing")}}
79+
<HdsBadge
80+
@text="Establishing"
81+
@color="highlight"
82+
@icon="loading"
83+
@type="outlined"
84+
/>
85+
{{/if}}
86+
</B.Td>
87+
<B.Td>{{B.data.services.imported}}</B.Td>
88+
<B.Td>{{B.data.services.exported}}</B.Td>
89+
<B.Td @align="right">
90+
<HdsDropdown @isInline={{true}} as |dd|>
91+
<dd.ToggleIcon
92+
@icon="more-horizontal"
93+
@text="Overflow Options"
94+
@hasChevron={{false}}
95+
@size="small"
96+
/>
97+
<dd.Interactive
98+
@route="page-components.table"
99+
>Create</dd.Interactive>
100+
<dd.Interactive
101+
@route="page-components.table"
102+
>Read</dd.Interactive>
103+
<dd.Interactive
104+
@route="page-components.table"
105+
>Update</dd.Interactive>
106+
<dd.Separator />
107+
<dd.Interactive
108+
@route="page-components.table"
109+
@color="critical"
110+
@icon="trash"
111+
>Delete</dd.Interactive>
112+
</HdsDropdown>
113+
</B.Td>
114+
</B.Tr>
115+
</:body>
116+
</HdsTable>
117+
</template>;
118+
119+
export default CodeFragmentWithClusterData;
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import Component from '@glimmer/component';
2+
import { array, hash } from '@ember/helper';
3+
import { tracked } from '@glimmer/tracking';
4+
import { deepTracked } from 'ember-deep-tracked';
5+
import { on } from '@ember/modifier';
6+
7+
import USERS from 'showcase/mocks/user-data';
8+
9+
import CodeFragmentWithMultiSelectTopbar from './topbar';
10+
import CodeFragmentWithUsersData from '../with-users-data';
11+
12+
// HDS Components
13+
import {
14+
HdsButton,
15+
HdsPaginationNumbered,
16+
} from '@hashicorp/design-system-components/components';
17+
18+
import type { HdsTableOnSelectionChangeSignature } from '@hashicorp/design-system-components/components/hds/table/types';
19+
import type { User } from 'showcase/mocks/user-data.ts';
20+
21+
export interface CodeFragmentWithMultiSelectDeletionSignature {
22+
Element: HTMLElement;
23+
}
24+
25+
export default class CodeFragmentWithMultiSelectDeletion extends Component<CodeFragmentWithMultiSelectDeletionSignature> {
26+
@tracked isScopeExtended = false;
27+
@tracked isDebugging = false;
28+
@deepTracked userData = [...USERS.slice(0, 16)];
29+
@tracked currentPage = 1;
30+
@tracked currentPageSize = 4;
31+
32+
updateModelWithSelectAllState = (
33+
modelData: User[],
34+
selectAllState: boolean,
35+
) => {
36+
modelData.forEach((modelRow) => {
37+
if (modelRow instanceof Object) {
38+
modelRow.isSelected = selectAllState;
39+
}
40+
});
41+
};
42+
43+
get totalItems() {
44+
return this.userData.length;
45+
}
46+
47+
get paginatedData() {
48+
const start = (this.currentPage - 1) * this.currentPageSize;
49+
const end = this.currentPage * this.currentPageSize;
50+
return this.userData.slice(start, end);
51+
}
52+
53+
toggleScope = (event: Event) => {
54+
this.isScopeExtended = (event.target as HTMLInputElement).checked;
55+
};
56+
57+
toggleDebugging = (event: Event) => {
58+
this.isDebugging = (event.target as HTMLInputElement).checked;
59+
};
60+
61+
onPageChange = (page: number) => {
62+
this.currentPage = page;
63+
};
64+
65+
onPageSizeChange = (pageSize: number) => {
66+
// we agreed to reset the pagination to the first element (any alternative would result in an unpredictable UX)
67+
this.currentPage = 1;
68+
this.currentPageSize = pageSize;
69+
};
70+
71+
onSelectionChange = ({
72+
selectionKey,
73+
selectionCheckboxElement,
74+
selectableRowsStates,
75+
}: HdsTableOnSelectionChangeSignature) => {
76+
console.group(
77+
'CodeFragmentWithMultiSelectDeletion onSelectionChange invoked with arguments:',
78+
);
79+
console.log('Selection Key:', selectionKey);
80+
console.log('Checkbox Element:', selectionCheckboxElement);
81+
console.log('Selectable Rows States:', selectableRowsStates);
82+
console.groupEnd();
83+
if (selectionKey === 'all' && this.isScopeExtended) {
84+
this.updateModelWithSelectAllState(
85+
this.userData,
86+
selectionCheckboxElement ? selectionCheckboxElement.checked : false,
87+
);
88+
} else {
89+
selectableRowsStates.forEach((row) => {
90+
const recordToUpdate = this.userData.find(
91+
(modelRow) => String(modelRow.id) === row.selectionKey,
92+
);
93+
if (recordToUpdate) {
94+
recordToUpdate.isSelected = row.isSelected;
95+
}
96+
});
97+
}
98+
};
99+
100+
deleteSelectedUsers = () => {
101+
const newData = this.userData.filter((user) => !user.isSelected);
102+
this.userData = [...newData];
103+
};
104+
105+
<template>
106+
<CodeFragmentWithMultiSelectTopbar
107+
@isScopeExtended={{this.isScopeExtended}}
108+
@isDebugging={{this.isDebugging}}
109+
@onChangeScope={{this.toggleScope}}
110+
@onChangeDebugging={{this.toggleDebugging}}
111+
>
112+
<HdsButton
113+
@text="Delete users"
114+
@icon="trash"
115+
{{on "click" this.deleteSelectedUsers}}
116+
/>
117+
</CodeFragmentWithMultiSelectTopbar>
118+
119+
<div class="shw-component-table-with-pagination-demo-wrapper">
120+
<CodeFragmentWithUsersData
121+
@isSelectable={{true}}
122+
@model={{this.paginatedData}}
123+
@columns={{array
124+
(hash key="id" label="ID")
125+
(hash key="name" label="Name")
126+
(hash key="email" label="Email")
127+
(hash key="role" label="Role")
128+
}}
129+
@dataSize="small"
130+
@onSelectionChange={{this.onSelectionChange}}
131+
/>
132+
<HdsPaginationNumbered
133+
@totalItems={{this.totalItems}}
134+
@currentPageSize={{this.currentPageSize}}
135+
@pageSizes={{array 4 8}}
136+
@currentPage={{this.currentPage}}
137+
@onPageChange={{this.onPageChange}}
138+
@onPageSizeChange={{this.onPageSizeChange}}
139+
@ariaLabel="Pagination for multi-select table with delete action"
140+
/>
141+
{{#if this.isDebugging}}
142+
{{#each this.userData as |row|}}
143+
<pre>row{{row.id}} = {{if row.isSelected ""}}</pre>
144+
{{/each}}
145+
{{/if}}
146+
</div>
147+
</template>
148+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import Component from '@glimmer/component';
2+
import { array, hash } from '@ember/helper';
3+
import { deepTracked } from 'ember-deep-tracked';
4+
import { on } from '@ember/modifier';
5+
import { later } from '@ember/runloop';
6+
7+
import USERS from 'showcase/mocks/user-data';
8+
import CodeFragmentWithUsersData from '../with-users-data';
9+
10+
// HDS Components
11+
import { HdsButton } from '@hashicorp/design-system-components/components';
12+
13+
import type { HdsTableOnSelectionChangeSignature } from '@hashicorp/design-system-components/components/hds/table/types';
14+
15+
export interface CodeFragmentWithMultiSelectExternalActionSignature {
16+
Element: HTMLElement;
17+
}
18+
19+
export default class CodeFragmentWithMultiSelectExternalAction extends Component<CodeFragmentWithMultiSelectExternalActionSignature> {
20+
@deepTracked userData = USERS.slice(0, 4).map((user) => ({
21+
...user,
22+
isAnimated: false,
23+
}));
24+
25+
onSelectionChange = ({
26+
selectedRowsKeys,
27+
}: HdsTableOnSelectionChangeSignature) => {
28+
console.group(
29+
'CodeFragmentWithMultiSelectExternalAction onSelectionChange invoked with arguments:',
30+
);
31+
console.log('Selected Row Keys:', selectedRowsKeys);
32+
console.groupEnd();
33+
this.userData.forEach((user) => {
34+
user.isSelected = selectedRowsKeys.includes(String(user.id));
35+
});
36+
};
37+
38+
animateSelectedUsers = () => {
39+
this.userData.forEach((user) => {
40+
user.isAnimated = user.isSelected ? user.isSelected : false;
41+
});
42+
// eslint-disable-next-line ember/no-runloop
43+
later(() => {
44+
this.resetUserAnimation();
45+
}, 5000);
46+
};
47+
48+
resetUserAnimation = () => {
49+
this.userData.forEach((user) => {
50+
user.isAnimated = false;
51+
});
52+
};
53+
54+
<template>
55+
<div class="shw-component-table-demo-topbar">
56+
<div class="shw-component-table-demo-topbar__action">
57+
<HdsButton
58+
@text="Animate users"
59+
@icon="play"
60+
{{on "click" this.animateSelectedUsers}}
61+
/>
62+
</div>
63+
</div>
64+
65+
<CodeFragmentWithUsersData
66+
@isSelectable={{true}}
67+
@onSelectionChange={{this.onSelectionChange}}
68+
@model={{this.userData}}
69+
@columns={{array
70+
(hash key="id" label="ID")
71+
(hash key="name" label="Name")
72+
(hash key="email" label="Email")
73+
(hash key="role" label="Role")
74+
}}
75+
@dataSize="small"
76+
/>
77+
</template>
78+
}

0 commit comments

Comments
 (0)