Skip to content

Commit c426996

Browse files
Zorin95670jcabannes
authored andcommitted
feat(catalog-ui): delete favorite from smart-filter
1 parent f27f99c commit c426996

5 files changed

Lines changed: 160 additions & 1 deletion

File tree

apps/catalog-ui/docs/design.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,19 @@ A full example showing all CatalogUI components configured together:
795795
}
796796
}
797797
},
798+
"confirmation-dialog": {
799+
"q-dialog": { "persistent": false },
800+
"q-card": { "flat": true, "bordered": true },
801+
"buttons-card": {
802+
"q-card": { "flat": true },
803+
"confirm-button": {
804+
"q-btn": { "color": "primary", "icon": "check" }
805+
},
806+
"cancel-button": {
807+
"q-btn": { "color": "negative", "outline": true }
808+
}
809+
}
810+
},
798811
"linid-filter-panel": {
799812
"header": {
800813
"q-icon": { "name": "filter_alt" },

apps/catalog-ui/docs/i18n.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ The `FormDialog` component uses the following keys for internationalization:
379379
| `[INSTANCE_ID].seeButton` | Label for the “see details” action button | Table row action | - |
380380
| `[INSTANCE_ID].ButtonsCard` | Base translation scope for the actions card (e.g. create button label) | Page actions section | - |
381381
| `[INSTANCE_ID].GenericEntityTable` | Base translation scope for the GenericEntityTable | Page table section | - |
382+
| `[INSTANCE_ID].ConfirmationDialog` | Base translation scope for the ConfirmationDialog | Page dialog section | - |
383+
| `[INSTANCE_ID].LinidSmartFilter` | Base translation scope for the LinidSmartFilter | Page search section | - |
382384
| `[INSTANCE_ID].[FIELD_LABEL]` | Label displayed for a table column header | Table column header | - |
383385

384386
**Example:**
@@ -398,6 +400,18 @@ The `FormDialog` component uses the following keys for internationalization:
398400
"noData": "No data available",
399401
"rowsPerPage": "Rows per page:",
400402
"paginationLabel": "{start}-{end} of {total}"
403+
},
404+
"ConfirmationDialog": {
405+
"title": "Delete a favorite?",
406+
"content": "Confirm to delete favorite \"{label}\"?",
407+
"ButtonsCard": {
408+
"confirm": "Save",
409+
"cancel": "Cancel",
410+
"confirmLoading": "Saving..."
411+
}
412+
},
413+
"LinidSmartFilter": {
414+
//(...) see next section
401415
}
402416
}
403417
}
@@ -755,6 +769,97 @@ export default {
755769
rowsPerPage: 'Rows per page:',
756770
paginationLabel: '{start}-{end} of {total}',
757771
},
772+
ConfirmationDialog: {
773+
title: 'Delete a favorite?',
774+
content: 'Confirm to delete favorite "{label}"?',
775+
ButtonsCard: {
776+
confirm: 'Save',
777+
cancel: 'Cancel',
778+
confirmLoading: 'Saving...',
779+
},
780+
},
781+
LinidSmartFilter: {
782+
label: 'Search',
783+
hint: 'Enter your search criteria',
784+
prefix: '',
785+
suffix: '',
786+
LinidFilterChip: {
787+
[FILTER]: {
788+
type: 'Filter name',
789+
separator: 'or',
790+
},
791+
},
792+
LinidFilterPanel: {
793+
title: 'Filter By',
794+
},
795+
LinidFavoritePanel: {
796+
title: 'Favorites',
797+
noData: 'No available favorites',
798+
createFavorite: 'Create Favorite',
799+
overrideFavorite: 'Override Favorite',
800+
deleteButton: 'Delete',
801+
},
802+
TextSearchFilterPanel: {
803+
inputLabel: 'Value',
804+
inputHint: 'Enter a value to search',
805+
inputPrefix: '~',
806+
inputSuffix: '*',
807+
negateLabel: 'Negate',
808+
searchButton: 'Search',
809+
operators: {
810+
contains: 'contains',
811+
startsWith: 'startsWith',
812+
endsWith: 'endsWith',
813+
equals: 'equals',
814+
notContains: 'not contains',
815+
notStartsWith: 'not startsWith',
816+
notEndsWith: 'not endsWith',
817+
notEquals: 'not equals',
818+
},
819+
},
820+
NumberSearchFilterPanel: {
821+
inputLabel: 'Value',
822+
inputHint: 'Enter a number to search',
823+
inputPrefix: '$',
824+
inputSuffix: 'kg',
825+
negateLabel: 'Negate',
826+
searchButton: 'Search',
827+
operators: {
828+
inferior: 'inferior',
829+
superior: 'superior',
830+
equals: 'equals',
831+
notInferior: 'not inferior',
832+
notSuperior: 'not superior',
833+
notEquals: 'not equals',
834+
},
835+
},
836+
TreeSearchFilterPanel: {
837+
searchButton: 'Search',
838+
},
839+
ListSearchFilterPanel: {
840+
searchButton: 'Search',
841+
},
842+
DateSearchFilterPanel: {
843+
inputLabel: 'Date',
844+
inputHint: 'Select or enter a date',
845+
inputPrefix: '',
846+
inputSuffix: '(UTC)',
847+
negateLabel: 'Negate',
848+
close: 'Close',
849+
searchButton: 'Search',
850+
operators: {
851+
inferior: 'inferior',
852+
superior: 'superior',
853+
equals: 'equals',
854+
notInferior: 'not inferior',
855+
notSuperior: 'not superior',
856+
notEquals: 'not equals',
857+
},
858+
validation: {
859+
invalidDate: 'Invalid date. Expected format: {format}',
860+
},
861+
},
862+
},
758863
},
759864
};
760865
```

apps/catalog-ui/src/federation/module-page-lifecycle.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
BasicRemoteModule,
3333
getI18nInstance,
3434
useLinidUiStore,
35+
useLinidZoneStore,
3536
} from '@linagora/linid-im-front-corelib';
3637
import type { ModulePageOptions } from '../types/ModulePageOptions';
3738

@@ -73,6 +74,7 @@ class ModulePage extends BasicRemoteModule<ModulePageOptions> {
7374
config: ModuleHostConfig<ModulePageOptions>
7475
): Promise<ModuleLifecycleResult> {
7576
const uiStore = useLinidUiStore();
77+
const linidZoneStore = useLinidZoneStore();
7678
const { t } = getI18nInstance().global;
7779

7880
uiStore.addMainNavigationMenuItems({
@@ -81,6 +83,10 @@ class ModulePage extends BasicRemoteModule<ModulePageOptions> {
8183
path: config.basePath,
8284
});
8385

86+
linidZoneStore.registerOnce('base-layout.dialogComponent', {
87+
plugin: 'catalogUI/ConfirmationDialog',
88+
});
89+
8490
return { success: true };
8591
}
8692
}

apps/catalog-ui/src/pages/GenericTablePage.vue

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
class="q-mb-md"
7979
@update:filters="onFiltersChange"
8080
@apply:favorite="onFavoriteApply"
81+
@delete:favorite="openDeleteFavoriteDialog"
8182
/>
8283

8384
<GenericEntityTable
@@ -143,6 +144,7 @@ import {
143144
useScopedI18n,
144145
useUiDesign,
145146
useLinidUserPreference,
147+
uiEventSubject,
146148
} from '@linagora/linid-im-front-corelib';
147149
import type { ModuleGenericTablePageOptions } from '../types/ModuleGenericTablePageOptions';
148150
import type { QTableColumn } from 'quasar';
@@ -163,7 +165,7 @@ const options = computed(
163165
);
164166
165167
const { t, te } = useScopedI18n(i18nScope.value);
166-
const { userPreferenceStore } = useLinidUserPreference();
168+
const { userPreferenceStore, deleteUserPreference } = useLinidUserPreference();
167169
const items = ref<Record<string, unknown>[]>([]);
168170
const isLoading = ref<boolean>(false);
169171
const { Notify } = useNotify();
@@ -269,6 +271,32 @@ function onFavoriteApply(favorite: LinidFilterSet) {
269271
onFiltersChange(favorite.filters);
270272
}
271273
274+
/**
275+
* Opens a confirmation dialog to delete a saved favorite filter set.
276+
*
277+
* If the user confirms the action, the corresponding favorite is removed from
278+
* the user preferences store using its identifier.
279+
* @param favorite - The favorite filter set to delete.
280+
*/
281+
function openDeleteFavoriteDialog(favorite: LinidFilterSet): void {
282+
uiEventSubject.next({
283+
key: 'confirmation',
284+
data: {
285+
type: 'open',
286+
title: t('ConfirmationDialog.title'),
287+
content: t('ConfirmationDialog.content', {
288+
label: favorite.label,
289+
}),
290+
uiNamespace: uiNamespace.value,
291+
i18nScope: `${i18nScope.value}.ConfirmationDialog`,
292+
onConfirm: () =>
293+
deleteUserPreference(
294+
`${favoritesBaseConfigurationKey.value}${favorite.id}`
295+
),
296+
},
297+
});
298+
}
299+
272300
/**
273301
* Parses a serialized favorite filter set from a JSON string and validates its structure.
274302
*

apps/catalog-ui/tests/unit/federation/module-page-lifecycle.spec.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,18 @@ const mockT = vi.fn((key) => `translated_${key}`);
3131

3232
vi.mock('@linagora/linid-im-front-corelib', async () => {
3333
const actual = await vi.importActual('@linagora/linid-im-front-corelib');
34+
3435
return {
3536
...actual,
37+
3638
useLinidUiStore: () => ({
3739
addMainNavigationMenuItems: mockAddMainNavigationMenuItems,
3840
}),
41+
42+
useLinidZoneStore: () => ({
43+
registerOnce: vi.fn(),
44+
}),
45+
3946
getI18nInstance: () => ({
4047
global: {
4148
t: mockT,

0 commit comments

Comments
 (0)