Skip to content

Commit 4143754

Browse files
Adrienjcabannes
authored andcommitted
feat(catalog-ui): add create favorite form dailog
1 parent b1982a8 commit 4143754

3 files changed

Lines changed: 98 additions & 10 deletions

File tree

apps/catalog-ui/docs/i18n.md

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -372,17 +372,18 @@ The `FormDialog` component uses the following keys for internationalization:
372372

373373
**File:** apps/catalog-ui/src/pages/GenericTablePage.vue
374374

375-
| Key | Description | Usage | Parameters |
376-
|-----------------------------------| ---------------------------------------------------------------------- | -------------------- | ---------- |
377-
| `[INSTANCE_ID].title` | Title displayed at the top of the page (if present) | Page header | - |
378-
| `[INSTANCE_ID].error` | Error message when data loading fails. | Page toaster | - |
379-
| `[INSTANCE_ID].seeButton` | Label for the “see details” action button | Table row action | - |
380-
| `[INSTANCE_ID].ButtonsCard` | Base translation scope for the actions card (e.g. create button label) | Page actions section | - |
375+
| Key | Description | Usage | Parameters |
376+
| ---------------------------------- | ---------------------------------------------------------------------- | -------------------- | ---------- |
377+
| `[INSTANCE_ID].title` | Title displayed at the top of the page (if present) | Page header | - |
378+
| `[INSTANCE_ID].error` | Error message when data loading fails. | Page toaster | - |
379+
| `[INSTANCE_ID].seeButton` | Label for the “see details” action button | Table row action | - |
380+
| `[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].DeleteDialog` | Base translation scope for the delete-favorite ConfirmationDialog | Page dialog section | - |
383-
| `[INSTANCE_ID].OverrideDialog` | Base translation scope for the override-favorite FormDialog | Page dialog section | - |
384-
| `[INSTANCE_ID].LinidSmartFilter` | Base translation scope for the LinidSmartFilter | Page search section | - |
385-
| `[INSTANCE_ID].[FIELD_LABEL]` | Label displayed for a table column header | Table column header | - |
382+
| `[INSTANCE_ID].DeleteDialog` | Base translation scope for the delete-favorite ConfirmationDialog | Page dialog section | - |
383+
| `[INSTANCE_ID].OverrideDialog` | Base translation scope for the override-favorite FormDialog | Page dialog section | - |
384+
| `[INSTANCE_ID].CreateDialog` | Base translation scope for the create-favorite FormDialog | Page dialog section | - |
385+
| `[INSTANCE_ID].LinidSmartFilter` | Base translation scope for the LinidSmartFilter | Page search section | - |
386+
| `[INSTANCE_ID].[FIELD_LABEL]` | Label displayed for a table column header | Table column header | - |
386387

387388
**Example:**
388389

@@ -425,6 +426,16 @@ The `FormDialog` component uses the following keys for internationalization:
425426
}
426427
}
427428
},
429+
"CreateDialog": {
430+
"title": "Create a favorite?",
431+
"content": "Name of the favorite.",
432+
"duplicateName": "A favorite with the name \"{name}\" already exists.",
433+
"ButtonsCard": {
434+
"cancel": "Cancel",
435+
"confirm": "Create",
436+
"confirmLoading": "Creating..."
437+
}
438+
},
428439
"LinidSmartFilter": {
429440
//(...) see next section
430441
}
@@ -807,6 +818,16 @@ export default {
807818
},
808819
},
809820
},
821+
CreateDialog: {
822+
title: 'Create a favorite?',
823+
content: 'Name of the favorite.',
824+
duplicateName: 'A favorite with the name "{name}" already exists.',
825+
ButtonsCard: {
826+
cancel: 'Cancel',
827+
confirm: 'Create',
828+
confirmLoading: 'Creating...',
829+
},
830+
},
810831
LinidSmartFilter: {
811832
label: 'Search',
812833
hint: 'Enter your search criteria',

apps/catalog-ui/docs/pages/GenericTablePage.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ Each active filter is serialized to a query param using `filter.toString()`, key
197197
- `DeleteDialog.content` — body of the delete-favorite confirmation dialog (`{label}` placeholder available)
198198
- `OverrideDialog.title` — title of the override-favorite form dialog
199199
- `OverrideDialog.content` — body of the override-favorite form dialog
200+
- `CreateDialog.title` — title of the create-favorite form dialog
201+
- `CreateDialog.content` — body of the create-favorite form dialog
200202

201203
---
202204

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

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
@apply:favorite="onFavoriteApply"
8181
@delete:favorite="openDeleteFavoriteDialog"
8282
@override:favorite="openOverrideFavoriteDialog"
83+
@create:favorite="openCreateFavoriteDialog"
8384
/>
8485

8586
<GenericEntityTable
@@ -344,6 +345,70 @@ function openOverrideFavoriteDialog(): void {
344345
});
345346
}
346347
348+
/**
349+
* Generates a unique favorite ID by looping on crypto.randomUUID until an ID is found.
350+
* @returns A unique UUID string that is not already used in favorites.
351+
*/
352+
function generateUniqueFavoriteId(): string {
353+
let newId = crypto.randomUUID();
354+
while (favorites.value.some((fav) => fav.id === newId)) {
355+
newId = crypto.randomUUID();
356+
}
357+
return newId;
358+
}
359+
360+
/**
361+
* Opens a form dialog to create a favorite filter set with the current filters.
362+
*/
363+
function openCreateFavoriteDialog(): void {
364+
uiEventSubject.next({
365+
key: 'form',
366+
data: {
367+
type: 'open',
368+
title: t('CreateDialog.title'),
369+
content: t('CreateDialog.content'),
370+
uiNamespace: uiNamespace.value,
371+
i18nScope: `${i18nScope.value}.CreateDialog`,
372+
formFields: [
373+
{
374+
name: 'favoriteName',
375+
type: 'String',
376+
input: 'Text',
377+
required: true,
378+
inputSettings: {},
379+
},
380+
],
381+
// eslint-disable-next-line jsdoc/require-jsdoc
382+
onSubmit: (formData: { favoriteName: string }) => {
383+
const trimmedFavoriteName = formData.favoriteName.trim();
384+
if (favorites.value.some((fav) => fav.label === trimmedFavoriteName)) {
385+
Notify({
386+
type: 'negative',
387+
message: t('CreateDialog.duplicateName', {
388+
name: trimmedFavoriteName,
389+
}),
390+
});
391+
return;
392+
}
393+
394+
const favoriteId = generateUniqueFavoriteId();
395+
saveUserPreference(
396+
`${favoritesBaseConfigurationKey.value}${favoriteId}`,
397+
JSON.stringify({
398+
id: favoriteId,
399+
label: trimmedFavoriteName,
400+
value: new LinidFilterSet(
401+
favoriteId,
402+
trimmedFavoriteName,
403+
filters.value
404+
).toString(),
405+
})
406+
);
407+
},
408+
},
409+
});
410+
}
411+
347412
/**
348413
* Parses a serialized favorite filter set from a JSON string and validates its structure.
349414
*

0 commit comments

Comments
 (0)