Skip to content

Commit 27b223a

Browse files
committed
frontend: Update service list to conditionally hide owner column and enhance UI elements
1 parent 83c77ce commit 27b223a

File tree

15 files changed

+270
-74
lines changed

15 files changed

+270
-74
lines changed

frontend/src/components/service/List.tsx

Lines changed: 54 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -30,75 +30,69 @@ import { getA8RMetadata } from './A8RServiceInfo';
3030
export default function ServiceList() {
3131
const { t } = useTranslation(['glossary', 'translation']);
3232
const { items } = Service.useList({ namespace: useNamespaces() });
33-
const showOwnerColumn = useMemo(() => {
34-
if (!items || items.length === 0) return false;
35-
return items.some(service => service?.metadata?.annotations?.['a8r.io/owner']);
36-
}, [items]);
37-
38-
// Build columns array based on whether owner annotation exists
39-
const columns = useMemo(() => {
40-
const cols: any[] = ['name', 'namespace', 'cluster'];
41-
42-
if (showOwnerColumn) {
43-
cols.push({
44-
id: 'a8r-owner',
45-
label: t('Owner'),
46-
gridTemplate: 'auto',
47-
getValue: (service: Service) => service.metadata?.annotations?.['a8r.io/owner'] ?? '-',
48-
render: (service: Service) => service.metadata?.annotations?.['a8r.io/owner'] || '-',
49-
});
50-
}
5133

52-
cols.push(
53-
{
54-
id: 'type',
55-
label: t('translation|Type'),
56-
gridTemplate: 'min-content',
57-
filterVariant: 'multi-select',
58-
getValue: (service: Service) => service.spec?.type,
59-
},
60-
{
61-
id: 'clusterIP',
62-
label: t('Cluster IP'),
63-
gridTemplate: 'min-content',
64-
getValue: (service: Service) => service.spec?.clusterIP,
65-
},
66-
{
67-
id: 'externalIP',
68-
label: t('External IP'),
69-
gridTemplate: 'min-content',
70-
getValue: (service: Service) => service.getExternalAddresses() || '-',
71-
},
72-
{
73-
id: 'ports',
74-
label: t('Ports'),
75-
gridTemplate: 'auto',
76-
getValue: (service: Service) => service.getFormattedPorts()?.join(', '),
77-
render: (service: Service) => <LabelListItem labels={service.getFormattedPorts() ?? []} />,
78-
},
79-
{
80-
id: 'selector',
81-
label: t('Selector'),
82-
gridTemplate: 'auto',
83-
getValue: (service: Service) => service.getSelector().join(', '),
84-
render: (service: Service) =>
85-
service.spec?.selector ? <MetadataDictGrid dict={service.spec.selector} /> : null,
86-
},
87-
'age'
88-
);
89-
return cols;
90-
}, [showOwnerColumn, t]);
34+
const hideOwnerColumn = useMemo(() => {
35+
if (!items || items.length === 0) return true;
36+
const hasOwner = items.some(service => service?.metadata?.annotations?.['a8r.io/owner']);
37+
return !hasOwner;
38+
}, [items]);
9139

9240
return (
9341
<ResourceListView
9442
title={t('Services')}
95-
data={items}
96-
columns={columns}
43+
resourceClass={Service}
44+
hideColumns={hideOwnerColumn ? ['a8r-owner'] : []}
45+
columns={[
46+
'name',
47+
'namespace',
48+
'cluster',
49+
{
50+
id: 'a8r-owner',
51+
label: t('Owner'),
52+
gridTemplate: 'auto',
53+
getValue: service => service.metadata?.annotations?.['a8r.io/owner'] ?? '-',
54+
},
55+
{
56+
id: 'type',
57+
label: t('translation|Type'),
58+
gridTemplate: 'min-content',
59+
filterVariant: 'multi-select',
60+
getValue: service => service.spec.type,
61+
},
62+
{
63+
id: 'clusterIP',
64+
label: t('Cluster IP'),
65+
gridTemplate: 'min-content',
66+
getValue: service => service.spec.clusterIP,
67+
},
68+
{
69+
id: 'externalIP',
70+
label: t('External IP'),
71+
gridTemplate: 'min-content',
72+
getValue: service => service.getExternalAddresses() || '-',
73+
},
74+
{
75+
id: 'ports',
76+
label: t('Ports'),
77+
gridTemplate: 'auto',
78+
getValue: service => service.getFormattedPorts()?.join(', '),
79+
render: service => <LabelListItem labels={service.getFormattedPorts() ?? []} />,
80+
},
81+
{
82+
id: 'selector',
83+
label: t('Selector'),
84+
gridTemplate: 'auto',
85+
getValue: service => service.getSelector().join(', '),
86+
render: service =>
87+
service.spec.selector ? <MetadataDictGrid dict={service.spec.selector} /> : null,
88+
},
89+
'age',
90+
]}
9791
actions={[
9892
{
9993
id: 'a8r-actions',
10094
action: ({ item, closeMenu }) => {
101-
const annotations = item.metadata?.annotations ?? {};
95+
const annotations = item.metadata.annotations ?? {};
10296
const metadata = getA8RMetadata(annotations).filter(m => m.isLink);
10397

10498
if (metadata.length === 0) return null;

frontend/src/components/service/__snapshots__/ServiceList.Items.stories.storyshot

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,108 @@
1919
</h1>
2020
<div
2121
class="MuiBox-root css-ldp2l3"
22-
/>
22+
>
23+
<button
24+
aria-label="Create Service"
25+
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium css-whz9ym-MuiButtonBase-root-MuiIconButton-root"
26+
data-mui-internal-clone-element="true"
27+
tabindex="0"
28+
type="button"
29+
>
30+
<span
31+
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
32+
/>
33+
</button>
34+
</div>
35+
</div>
36+
</div>
37+
<div
38+
class="MuiGrid-root MuiGrid-item css-13i4rnv-MuiGrid-root"
39+
>
40+
<div
41+
class="MuiGrid-root MuiGrid-container MuiGrid-item css-ztq4zc-MuiGrid-root"
42+
>
43+
<div
44+
class="MuiGrid-root MuiGrid-item css-13i4rnv-MuiGrid-root"
45+
>
46+
<div
47+
class="MuiAutocomplete-root MuiAutocomplete-hasPopupIcon css-1x6bjyf-MuiAutocomplete-root"
48+
>
49+
<div
50+
class="MuiBox-root css-1dipl1t"
51+
>
52+
<div
53+
class="MuiFormControl-root MuiFormControl-fullWidth MuiTextField-root css-wb57ya-MuiFormControl-root-MuiTextField-root"
54+
style="margin-top: 0px;"
55+
>
56+
<label
57+
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-sizeSmall MuiInputLabel-outlined MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-sizeSmall MuiInputLabel-outlined css-1f7ywh2-MuiFormLabel-root-MuiInputLabel-root"
58+
data-shrink="true"
59+
for="namespaces-filter"
60+
id="namespaces-filter-label"
61+
>
62+
Namespaces
63+
</label>
64+
<div
65+
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-sizeSmall MuiInputBase-adornedEnd MuiAutocomplete-inputRoot css-1xjtaff-MuiInputBase-root-MuiOutlinedInput-root"
66+
>
67+
<input
68+
aria-autocomplete="both"
69+
aria-expanded="false"
70+
aria-invalid="false"
71+
autocapitalize="none"
72+
autocomplete="off"
73+
class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputSizeSmall MuiInputBase-inputAdornedEnd MuiAutocomplete-input MuiAutocomplete-inputFocused css-19qh8xo-MuiInputBase-input-MuiOutlinedInput-input"
74+
id="namespaces-filter"
75+
placeholder="Filter"
76+
role="combobox"
77+
spellcheck="false"
78+
type="text"
79+
value=""
80+
/>
81+
<div
82+
class="MuiAutocomplete-endAdornment css-p1olib-MuiAutocomplete-endAdornment"
83+
>
84+
<button
85+
aria-label="Open"
86+
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium MuiAutocomplete-popupIndicator css-1aav1nn-MuiButtonBase-root-MuiIconButton-root-MuiAutocomplete-popupIndicator"
87+
tabindex="-1"
88+
title="Open"
89+
type="button"
90+
>
91+
<svg
92+
aria-hidden="true"
93+
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root"
94+
data-testid="ArrowDropDownIcon"
95+
focusable="false"
96+
viewBox="0 0 24 24"
97+
>
98+
<path
99+
d="M7 10l5 5 5-5z"
100+
/>
101+
</svg>
102+
<span
103+
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
104+
/>
105+
</button>
106+
</div>
107+
<fieldset
108+
aria-hidden="true"
109+
class="MuiOutlinedInput-notchedOutline css-1d3z3hw-MuiOutlinedInput-notchedOutline"
110+
>
111+
<legend
112+
class="css-14lo706"
113+
>
114+
<span>
115+
Namespaces
116+
</span>
117+
</legend>
118+
</fieldset>
119+
</div>
120+
</div>
121+
</div>
122+
</div>
123+
</div>
23124
</div>
24125
</div>
25126
</div>

frontend/src/components/service/__snapshots__/ServiceList.WithOwnerAnnotation.stories.storyshot

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,108 @@
1919
</h1>
2020
<div
2121
class="MuiBox-root css-ldp2l3"
22-
/>
22+
>
23+
<button
24+
aria-label="Create Service"
25+
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium css-whz9ym-MuiButtonBase-root-MuiIconButton-root"
26+
data-mui-internal-clone-element="true"
27+
tabindex="0"
28+
type="button"
29+
>
30+
<span
31+
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
32+
/>
33+
</button>
34+
</div>
35+
</div>
36+
</div>
37+
<div
38+
class="MuiGrid-root MuiGrid-item css-13i4rnv-MuiGrid-root"
39+
>
40+
<div
41+
class="MuiGrid-root MuiGrid-container MuiGrid-item css-ztq4zc-MuiGrid-root"
42+
>
43+
<div
44+
class="MuiGrid-root MuiGrid-item css-13i4rnv-MuiGrid-root"
45+
>
46+
<div
47+
class="MuiAutocomplete-root MuiAutocomplete-hasPopupIcon css-1x6bjyf-MuiAutocomplete-root"
48+
>
49+
<div
50+
class="MuiBox-root css-1dipl1t"
51+
>
52+
<div
53+
class="MuiFormControl-root MuiFormControl-fullWidth MuiTextField-root css-wb57ya-MuiFormControl-root-MuiTextField-root"
54+
style="margin-top: 0px;"
55+
>
56+
<label
57+
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-sizeSmall MuiInputLabel-outlined MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-sizeSmall MuiInputLabel-outlined css-1f7ywh2-MuiFormLabel-root-MuiInputLabel-root"
58+
data-shrink="true"
59+
for="namespaces-filter"
60+
id="namespaces-filter-label"
61+
>
62+
Namespaces
63+
</label>
64+
<div
65+
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-sizeSmall MuiInputBase-adornedEnd MuiAutocomplete-inputRoot css-1xjtaff-MuiInputBase-root-MuiOutlinedInput-root"
66+
>
67+
<input
68+
aria-autocomplete="both"
69+
aria-expanded="false"
70+
aria-invalid="false"
71+
autocapitalize="none"
72+
autocomplete="off"
73+
class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputSizeSmall MuiInputBase-inputAdornedEnd MuiAutocomplete-input MuiAutocomplete-inputFocused css-19qh8xo-MuiInputBase-input-MuiOutlinedInput-input"
74+
id="namespaces-filter"
75+
placeholder="Filter"
76+
role="combobox"
77+
spellcheck="false"
78+
type="text"
79+
value=""
80+
/>
81+
<div
82+
class="MuiAutocomplete-endAdornment css-p1olib-MuiAutocomplete-endAdornment"
83+
>
84+
<button
85+
aria-label="Open"
86+
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium MuiAutocomplete-popupIndicator css-1aav1nn-MuiButtonBase-root-MuiIconButton-root-MuiAutocomplete-popupIndicator"
87+
tabindex="-1"
88+
title="Open"
89+
type="button"
90+
>
91+
<svg
92+
aria-hidden="true"
93+
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root"
94+
data-testid="ArrowDropDownIcon"
95+
focusable="false"
96+
viewBox="0 0 24 24"
97+
>
98+
<path
99+
d="M7 10l5 5 5-5z"
100+
/>
101+
</svg>
102+
<span
103+
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
104+
/>
105+
</button>
106+
</div>
107+
<fieldset
108+
aria-hidden="true"
109+
class="MuiOutlinedInput-notchedOutline css-1d3z3hw-MuiOutlinedInput-notchedOutline"
110+
>
111+
<legend
112+
class="css-14lo706"
113+
>
114+
<span>
115+
Namespaces
116+
</span>
117+
</legend>
118+
</fieldset>
119+
</div>
120+
</div>
121+
</div>
122+
</div>
123+
</div>
23124
</div>
24125
</div>
25126
</div>

frontend/src/i18n/locales/de/glossary.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,8 @@
197197
"RuntimeClass": "Laufzeit-Klasse",
198198
"Secrets": "Secrets",
199199
"Service Information": "",
200-
"Owner": "",
201200
"Services": "Dienste",
201+
"Owner": "",
202202
"Map": "",
203203
"Workloads": "Workloads",
204204
"Stateful Sets": "Stateful Sets",

frontend/src/i18n/locales/en/glossary.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,8 @@
197197
"RuntimeClass": "RuntimeClass",
198198
"Secrets": "Secrets",
199199
"Service Information": "Service Information",
200-
"Owner": "Owner",
201200
"Services": "Services",
201+
"Owner": "Owner",
202202
"Map": "Map",
203203
"Workloads": "Workloads",
204204
"Stateful Sets": "Stateful Sets",

frontend/src/i18n/locales/es/glossary.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,8 @@
197197
"RuntimeClass": "RuntimeClass",
198198
"Secrets": "Secrets",
199199
"Service Information": "",
200-
"Owner": "",
201200
"Services": "Services",
201+
"Owner": "",
202202
"Map": "",
203203
"Workloads": "Cargas de Trabajo",
204204
"Stateful Sets": "Stateful Sets",

frontend/src/i18n/locales/fr/glossary.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,8 @@
197197
"RuntimeClass": "RuntimeClass",
198198
"Secrets": "Secrets",
199199
"Service Information": "",
200-
"Owner": "",
201200
"Services": "Services",
201+
"Owner": "",
202202
"Map": "",
203203
"Workloads": "Charges de travail",
204204
"Stateful Sets": "Stateful Sets",

frontend/src/i18n/locales/hi/glossary.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,8 @@
197197
"RuntimeClass": "रनटाइमक्लास",
198198
"Secrets": "सिक्रेट्स",
199199
"Service Information": "",
200-
"Owner": "",
201200
"Services": "सर्विसेज",
201+
"Owner": "",
202202
"Map": "मैप",
203203
"Workloads": "वर्कलोड्स",
204204
"Stateful Sets": "स्टेटफुल सेट्स",

0 commit comments

Comments
 (0)