@saooti/octopus-sdk 41.1.14 → 41.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/index.ts +24 -1
  3. package/package.json +1 -1
  4. package/src/api/groupsApi.ts +214 -0
  5. package/src/api/podcastApi.ts +47 -9
  6. package/src/components/buttons/ActionButton.vue +99 -0
  7. package/src/components/buttons/index.ts +5 -0
  8. package/src/components/composable/route/types.ts +11 -3
  9. package/src/components/composable/route/useAdvancedParamInit.ts +38 -13
  10. package/src/components/composable/useErrorHandler.ts +3 -2
  11. package/src/components/composable/useNotifications.ts +50 -0
  12. package/src/components/display/emission/EmissionGroupChooser.vue +56 -0
  13. package/src/components/display/emission/EmissionItem.vue +23 -3
  14. package/src/components/display/emission/EmissionList.vue +8 -2
  15. package/src/components/display/filter/AdvancedSearch.vue +82 -23
  16. package/src/components/display/list/ListPaginate.vue +4 -1
  17. package/src/components/display/podcasts/PodcastList.vue +12 -5
  18. package/src/components/display/podcasts/PodcastPlayButton.vue +2 -2
  19. package/src/components/display/podcasts/TagList.vue +4 -1
  20. package/src/components/form/ClassicMultiselect.vue +43 -37
  21. package/src/components/icons.ts +13 -0
  22. package/src/components/misc/ClassicAlert.vue +8 -1
  23. package/src/components/misc/ClassicBigChip.vue +84 -0
  24. package/src/components/misc/ClassicDataTable.vue +98 -0
  25. package/src/components/misc/ClassicDataTable_Internal.vue +132 -0
  26. package/src/components/misc/ClassicHelpButton.vue +3 -3
  27. package/src/components/misc/ClassicNotifications.vue +23 -0
  28. package/src/components/misc/ClassicPopover.vue +1 -0
  29. package/src/components/pages/EmissionPage.vue +2 -2
  30. package/src/components/pages/EmissionsPage.vue +10 -15
  31. package/src/components/pages/PodcastPage.vue +1 -1
  32. package/src/components/pages/PodcastsPage.vue +8 -20
  33. package/src/helper/fetchHelper.ts +1 -0
  34. package/src/locale/de.ts +2 -0
  35. package/src/locale/en.ts +2 -0
  36. package/src/locale/es.ts +2 -0
  37. package/src/locale/fr.ts +5 -3
  38. package/src/locale/it.ts +2 -0
  39. package/src/locale/sl.ts +2 -0
  40. package/src/router/router.ts +38 -53
  41. package/src/stores/class/general/emission.ts +8 -2
  42. package/src/style/_variables.scss +3 -0
  43. package/src/style/bootstrap.scss +5 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 41.2.0 (05/01/2026)
4
+
5
+ **Features**
6
+
7
+ - Ajout d'un système de notifications
8
+ - Intégrez `ClassicNotification` dans la vue principale pour afficher les
9
+ notifications
10
+ - Utilisez le composable `useNotifications` pour contrôler l'affichage des
11
+ notification depuis n'importe quel composant
12
+ - Ajout du composant `ClassicDataTable` pour afficher des tableaux de données
13
+ facilement
14
+ - Ajout du composant `ActionButton` pour faire un bouton déclenchant une action,
15
+ avec confirmation optionnelle
16
+ - Ajout du composant `ClassicBigChip` pour afficher des éléments simples
17
+ - Ajout du composant `EmissionGroupChooser` pour sélectionner un groupe
18
+ d'émissions parmis ceux définis
19
+ - Ajout de la bibliothèque d'icones `src/components/icons.ts` pour uniformiser
20
+ les icones au sein des différents projets
21
+ - Ajout de l'API groupes
22
+ - Ajout du filtrage par groupe sur les podcasts
23
+
24
+ **Fixes**
25
+
26
+ - Les mots-clés définis à la fois sur une émission et sur un épisode de cette
27
+ émissions ne s'affichent qu'une seule fois lors de la consultation de cet
28
+ épisode
29
+ - Le bouton de lecture vidéo ne disparait plus quand on lit une autre vidéo
30
+ - Correction des épisodes avec vidéos n'apparaissant plus lors de la
31
+ consultation des émissions
32
+ - `ClassicHelpButton` utilise le string `relative-class` au lieu du booléen
33
+ `relative` pour déterminer l'élément parent.
34
+
35
+ ## 41.1.15 (19/12/2025)
36
+
37
+ **Fixes**
38
+
39
+ - Correction de l'affichage de certaines émission sur iPhone
40
+
41
+ **Misc**
42
+
43
+ - Troncature des descriptions d'émissions sur mobile
44
+
3
45
  ## 41.1.14 (18/12/2025)
4
46
 
5
47
  **Misc**
package/index.ts CHANGED
@@ -40,11 +40,27 @@ export const getContractPreviewModal = () => import("./src/components/misc/modal
40
40
  export const getClassicModalInBody = () => import("./src/components/misc/modal/ClassicModalInBody.vue");
41
41
  export const getClassicHelpButton = () => import("./src/components/misc/ClassicHelpButton.vue");
42
42
  export const getClassicAlert = () => import("./src/components/misc/ClassicAlert.vue");
43
+ export const getClassicBigChip = () => import("./src/components/misc/ClassicBigChip.vue");
44
+
45
+ import ClassicDataTable, { type ClassicDataTableHeader } from "./src/components/misc/ClassicDataTable.vue";
46
+ import ClassicNotifications from "./src/components/misc/ClassicNotifications.vue";
47
+
48
+ export {
49
+ ClassicDataTable,
50
+ type ClassicDataTableHeader,
51
+ ClassicNotifications
52
+ }
53
+
54
+ // Buttons
55
+ import ActionButton from "./src/components/buttons/ActionButton.vue";
56
+ export { ActionButton };
57
+
43
58
  //Display
44
59
  export const getCategoryChooser = () => import("./src/components/display/categories/CategoryChooser.vue");
45
60
  export const getCategoryList = () => import("./src/components/display/categories/CategoryList.vue");
46
61
  export const getCategoryFilter = () => import("./src/components/display/categories/CategoryFilter.vue");
47
62
  export const getEmissionList = () => import("./src/components/display/emission/EmissionList.vue");
63
+ export const getEmissionGroupChooser = () => import("./src/components/display/emission/EmissionGroupChooser.vue");
48
64
  export const getOrganisationChooser = () => import("./src/components/display/organisation/OrganisationChooser.vue");
49
65
  export const getPodcastFilterList = () => import("./src/components/display/podcasts/PodcastFilterList.vue");
50
66
  export const getPodcastInlineList = () => import("./src/components/display/podcasts/PodcastInlineList.vue");
@@ -110,7 +126,7 @@ import {useOrganisationFilter} from "./src/components/composable/useOrganisation
110
126
  import {useInit} from "./src/components/composable/useInit.ts";
111
127
  import {useErrorHandler} from "./src/components/composable/useErrorHandler.ts";
112
128
  import { useSimplePageParam } from "./src/components/composable/route/useSimplePageParam";
113
-
129
+ import { useNotifications } from "./src/components/composable/useNotifications.ts";
114
130
 
115
131
  //helper
116
132
  import domHelper from "./src/helper/domHelper.ts";
@@ -135,11 +151,16 @@ import {useAuthStore} from "./src/stores/AuthStore.ts";
135
151
  import {getApiUrl, ModuleApi} from "./src/api/apiConnection.ts";
136
152
  import classicApi from "./src/api/classicApi.ts";
137
153
 
154
+ // API
138
155
  export { emissionApi } from "./src/api/emissionApi.ts";
156
+ export * from "./src/api/groupsApi.ts";
139
157
  export { organisationApi } from "./src/api/organisationApi.ts";
140
158
  export { playlistApi } from "./src/api/playlistApi.ts";
141
159
  export { podcastApi, PodcastSort, type PodcastSearchOptions } from "./src/api/podcastApi.ts";
142
160
 
161
+ // Types
162
+ export { type Emission, emptyEmissionData } from "./src/stores/class/general/emission.ts";
163
+
143
164
  //Icons
144
165
  export const getAmazonMusicIcon = () => import("./src/components/icons/AmazonMusicIcon.vue");
145
166
  export const getApplePodcastIcon = () => import("./src/components/icons/ApplePodcastIcon.vue");
@@ -161,6 +182,7 @@ import { setupRouter } from './src/router/utils';
161
182
  import { type SelectOption } from "./src/components/form/ClassicSelect.vue";
162
183
 
163
184
  import { ROUTE_PARAMS } from "./src/components/composable/route/types";
185
+ import { defineAsyncComponent } from "vue";
164
186
 
165
187
  export {
166
188
  useResizePhone,
@@ -173,6 +195,7 @@ export {
173
195
  useInit,
174
196
  useErrorHandler,
175
197
  useSimplePageParam,
198
+ useNotifications,
176
199
  debounce,
177
200
  useVastStore,
178
201
  useSaveFetchStore,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saooti/octopus-sdk",
3
- "version": "41.1.14",
3
+ "version": "41.2.0",
4
4
  "private": false,
5
5
  "description": "Javascript SDK for using octopus",
6
6
  "author": "Saooti",
@@ -0,0 +1,214 @@
1
+ import classicApi from "./classicApi";
2
+ import { ModuleApi } from "./apiConnection";
3
+ import { ListClassicReturn } from "../stores/class/general/listReturn";
4
+ import { Emission } from "@/stores/class/general/emission";
5
+ import { mapFromGetAll } from "./apiUtils";
6
+
7
+ const BASE_PATH = 'emission/groups/';
8
+
9
+ /** Group of emissions */
10
+ export interface EmissionGroup {
11
+ /** Name of the group */
12
+ name: string;
13
+ /** Id of the group */
14
+ groupId: number;
15
+ /** Simple description */
16
+ description?: string;
17
+ /** The id of the organisation this group belongs to */
18
+ organisationId: string;
19
+ /** The list of ids of emissions in this group */
20
+ emissionIds: Array<number>|null;
21
+ /** If set, defines this group as a "marque" group. */
22
+ acpmMarque: string|null;
23
+ }
24
+
25
+ interface Pagination {
26
+ /** Pagination */
27
+ first: number;
28
+ /** Number of elements */
29
+ size: number;
30
+ }
31
+
32
+ interface SearchParams {
33
+ /** Filter by acpm */
34
+ acpmMarque: string;
35
+ /** Filter by name */
36
+ search: string;
37
+ /** Filter by organisations */
38
+ organisationIds: Array<string>;
39
+ }
40
+
41
+ /**
42
+ * Add an emission to a list of groups
43
+ * @param emission The emission to add to the groups
44
+ * @param groups The list of groups to add the emission to
45
+ */
46
+ async function addToGroups(emission: Emission|number, groups: Array<EmissionGroup>|Array<number>): Promise<void> {
47
+ if (groups.length === 0) {
48
+ return;
49
+ }
50
+
51
+ let emissionId: number;
52
+ if (typeof emission === 'object') {
53
+ emissionId = emission.emissionId;
54
+ } else {
55
+ emissionId = emission;
56
+ }
57
+ let groupIds: Array<number>;
58
+ if (typeof groups[0] === 'object') {
59
+ groupIds = (groups as Array<EmissionGroup>).map(g => g.groupId);
60
+ } else {
61
+ groupIds = groups as Array<number>;
62
+ }
63
+
64
+ return classicApi.putData({
65
+ api: ModuleApi.DEFAULT,
66
+ path: BASE_PATH + 'add/' + emissionId,
67
+ dataToSend: groupIds
68
+ });
69
+ }
70
+
71
+ /**
72
+ * Create a new group
73
+ */
74
+ async function create(group: Omit<EmissionGroup, 'groupId'|'emissionIds'>): Promise<EmissionGroup> {
75
+ return classicApi.postData<EmissionGroup>({
76
+ api: ModuleApi.DEFAULT,
77
+ path: BASE_PATH,
78
+ dataToSend: group
79
+ });
80
+ }
81
+
82
+ /**
83
+ * Delete a group
84
+ */
85
+ async function remove(groupId: number): Promise<void> {
86
+ return classicApi.deleteData({
87
+ api: ModuleApi.DEFAULT,
88
+ path: BASE_PATH + groupId
89
+ });
90
+ }
91
+
92
+ /**
93
+ * Retrieve a group by its ID
94
+ * @param groupId The ID of the group to retrieve
95
+ * @return The group
96
+ */
97
+ async function get(groupId: number): Promise<EmissionGroup> {
98
+ return classicApi.fetchData<EmissionGroup>({
99
+ api: ModuleApi.DEFAULT,
100
+ path: BASE_PATH + groupId
101
+ });
102
+ }
103
+
104
+ /**
105
+ * Retrieve all groups specified by their IDs
106
+ * @param groupIds A list of group IDs. For better result, they
107
+ should be unique.
108
+ * @return The matching groups
109
+ */
110
+ async function getAllById(groupIds: Array<number>): Promise<Record<string, EmissionGroup>> {
111
+ return mapFromGetAll(groupIds, get, 'groupId');
112
+ }
113
+
114
+ /**
115
+ * Remove an emission from a list of groups
116
+ * @param emission The emission to remove from the groups
117
+ * @param groups The list of groups to remove the emission from
118
+ */
119
+ async function removeFromGroups(emission: Emission|number, groups: Array<EmissionGroup>|Array<number>): Promise<void> {
120
+ if (groups.length === 0) {
121
+ return;
122
+ }
123
+
124
+ let emissionId: number;
125
+ if (typeof emission === 'object') {
126
+ emissionId = emission.emissionId;
127
+ } else {
128
+ emissionId = emission;
129
+ }
130
+ let groupIds: Array<number>;
131
+ if (typeof groups[0] === 'object') {
132
+ groupIds = (groups as Array<EmissionGroup>).map(g => g.groupId);
133
+ } else {
134
+ groupIds = groups as Array<number>;
135
+ }
136
+
137
+ return classicApi.putData({
138
+ api: ModuleApi.DEFAULT,
139
+ path: BASE_PATH + 'remove/' + emissionId,
140
+ dataToSend: groupIds
141
+ });
142
+ }
143
+
144
+ /**
145
+ * Update a group
146
+ */
147
+ async function update(group: Omit<EmissionGroup, 'emissionIds'>): Promise<EmissionGroup> {
148
+ return classicApi.putData({
149
+ api: ModuleApi.DEFAULT,
150
+ path: BASE_PATH,
151
+ dataToSend: group
152
+ });
153
+ }
154
+
155
+ /**
156
+ * Count number of groups
157
+ */
158
+ async function count(parameters: Partial<SearchParams>): Promise<number> {
159
+ const result = await search({
160
+ ...parameters,
161
+ size: 0
162
+ });
163
+
164
+ return result.count;
165
+ }
166
+
167
+ /**
168
+ * Search groups
169
+ */
170
+ async function search(parameters: Partial<SearchParams & Pagination>): Promise<ListClassicReturn<EmissionGroup>> {
171
+ return classicApi.fetchData<ListClassicReturn<EmissionGroup>>({
172
+ api: ModuleApi.DEFAULT,
173
+ path: BASE_PATH + 'search',
174
+ parameters
175
+ });
176
+ }
177
+
178
+ /**
179
+ * Search for all groups, without pagination
180
+ */
181
+ async function searchNoPagination(parameters: Partial<SearchParams>): Promise<Array<EmissionGroup>> {
182
+ const result: Array<EmissionGroup> = [];
183
+
184
+ let index = 0;
185
+ while (true) {
186
+ const response = await search({
187
+ ...parameters,
188
+ first: index,
189
+ size: 1
190
+ });
191
+
192
+ result.push(...response.result);
193
+ index += response.result.length;
194
+
195
+ if (index >= response.count || response.result.length === 0) {
196
+ break;
197
+ }
198
+ }
199
+
200
+ return result;
201
+ }
202
+
203
+ export const groupsApi = {
204
+ addToGroups,
205
+ count,
206
+ create,
207
+ remove,
208
+ get,
209
+ getAllById,
210
+ removeFromGroups,
211
+ update,
212
+ search,
213
+ searchNoPagination
214
+ };
@@ -6,6 +6,9 @@ import { ModuleApi } from './apiConnection';
6
6
  import { unique } from '../helper/arrayHelper';
7
7
  import { organisationApi } from './organisationApi';
8
8
  import { emissionApi } from './emissionApi';
9
+ import { EmissionGroup } from './groupsApi';
10
+ import { FetchParam } from '@/stores/class/general/fetchParam';
11
+ import { toRaw } from 'vue';
9
12
 
10
13
  export enum PodcastSort {
11
14
  DATE = 'DATE',
@@ -41,6 +44,8 @@ interface Paginable<S> {
41
44
  export interface PodcastSearchOptions extends Paginable<PodcastSort> {
42
45
  /** Filter by emission ID */
43
46
  emissionId?: number|number[];
47
+ /** Filter by emission groups */
48
+ emissionGroups?: EmissionGroup[];
44
49
  /** Filter by organisation ID */
45
50
  organisationId?: string[];
46
51
  /** Filter by title containing */
@@ -103,6 +108,47 @@ function get(podcastId: number): Promise<Podcast> {
103
108
  });
104
109
  }
105
110
 
111
+
112
+ /**
113
+ * Convert easy to use PodcastSearchOptions to the actual FetchParams used by
114
+ * the endpoint.
115
+ */
116
+ function processSearchParameters(search: PodcastSearchOptions): FetchParam {
117
+ const parameters: FetchParam = {};
118
+
119
+ Object.keys(search).forEach(key => {
120
+ const value = search[key];
121
+
122
+ if (value === undefined || value === null) {
123
+ return;
124
+ }
125
+
126
+ if (key === 'beneficiaries') {
127
+ parameters.beneficiary = value;
128
+ } else if (key === 'processingStatus') {
129
+ parameters.includeStatus = value;
130
+ } else if (key === 'tags') {
131
+ parameters.includeTags = value;
132
+ } else if (key === 'pubDateBefore') {
133
+ parameters.before = value;
134
+ } else if (key === 'pubDateAfter') {
135
+ parameters.after = value;
136
+ } else if (key === 'pageSize') {
137
+ parameters.size = value;
138
+ } else if (key === 'emissionGroups') {
139
+ const emissionIds = [search.emissionId ?? undefined].flat();
140
+ search.emissionGroups.forEach(group => {
141
+ emissionIds.push(...group.emissionIds);
142
+ });
143
+ parameters.emissionId = emissionIds;
144
+ } else {
145
+ parameters[key] = value;
146
+ }
147
+ });
148
+
149
+ return parameters;
150
+ }
151
+
106
152
  /**
107
153
  * Search for podcasts. Retrieved podcasts are 'incomplete', some of their
108
154
  * properties are only IDs.
@@ -115,15 +161,7 @@ function search(options: PodcastSearchOptions, adaptParameters?: boolean): Promi
115
161
  return classicApi.fetchData<ListClassicReturn<SimplifiedPodcast>>({
116
162
  api: ModuleApi.DEFAULT,
117
163
  path: 'v2/podcast/search',
118
- parameters: {
119
- ...options,
120
- beneficiary: options.beneficiaries,
121
- includeStatus: options.processingStatus,
122
- includeTags: options.tags,
123
- before: options.pubDateBefore,
124
- after: options.pubDateAfter,
125
- size: options.pageSize ?? 50
126
- },
164
+ parameters: processSearchParameters(options),
127
165
  specialTreatement: adaptParameters
128
166
  });
129
167
  }
@@ -0,0 +1,99 @@
1
+ <template>
2
+ <div>
3
+ <!-- The button with an icon to trigger the action -->
4
+ <button
5
+ class="btn btn-transparent"
6
+ :title="action"
7
+ @click="onClick"
8
+ >
9
+ <component :is="icon" />
10
+ </button>
11
+
12
+ <!-- Modal to ask for confirmation -->
13
+ <MessageModal
14
+ v-if="showModal"
15
+ :title="confirmModal.title"
16
+ :message="confirmModal.message"
17
+ :validatetext="$t('Yes')"
18
+ :canceltext="$t('No')"
19
+ @validate="onConfirmModal"
20
+ @cancel="showModal = false"
21
+ @close="showModal = false"
22
+ />
23
+ </div>
24
+ </template>
25
+
26
+ <script setup lang="ts">
27
+ import { type Component, computed, ref } from 'vue';
28
+ import MessageModal from '../misc/modal/MessageModal.vue';
29
+ import Icons from '../icons';
30
+
31
+ /** Actions available to the button */
32
+ enum Action {
33
+ Edit = 'edit',
34
+ Delete = 'delete'
35
+ }
36
+
37
+ export interface ConfirmModalData {
38
+ title: string;
39
+ message: string;
40
+ }
41
+
42
+ const { action, confirmModal } = defineProps<{
43
+ /** The type of action provided by the button */
44
+ action: Action;
45
+ /** When set, clicking on the button will first open a confirm modal */
46
+ confirmModal?: ConfirmModalData;
47
+ }>();
48
+
49
+ const emit = defineEmits<{
50
+ /**
51
+ * Event trigger when the button is clicked, or after confirmation in the
52
+ * modal if `withConfirmModal` is true.
53
+ */
54
+ (e: 'click'): void
55
+ }>();
56
+
57
+ /************************
58
+ * Using button
59
+ ***********************/
60
+
61
+ /** Method called when clicking on button */
62
+ function onClick(): void {
63
+ if (confirmModal === undefined) {
64
+ emit('click');
65
+ } else {
66
+ showModal.value = true;
67
+ }
68
+ }
69
+
70
+ /***********************
71
+ * Modal
72
+ **********************/
73
+ /** Display modal when true */
74
+ const showModal = ref(false);
75
+
76
+ /** Method called when the modal is validated */
77
+ function onConfirmModal(): void {
78
+ showModal.value = false;
79
+ emit('click');
80
+ }
81
+
82
+ /***********************
83
+ * Button appearance
84
+ **********************/
85
+
86
+ /** The icon displayed by the button */
87
+ const icon = computed((): Component => {
88
+ switch (action) {
89
+ case Action.Edit:
90
+ return Icons.Edit;
91
+
92
+ case Action.Delete:
93
+ return Icons.Delete;
94
+
95
+ default:
96
+ return;
97
+ }
98
+ });
99
+ </script>
@@ -0,0 +1,5 @@
1
+ import ActionButton from "./ActionButton.vue";
2
+
3
+ export {
4
+ ActionButton
5
+ };
@@ -14,6 +14,8 @@ export interface RouteProps {
14
14
  routeRubriques?: string;
15
15
  /** The filter on beneficiaries defined on the route props */
16
16
  routeBeneficiaries?: string[];
17
+ /** The filter on emission groups defined on the route props */
18
+ routeEmissionGroups?: number[];
17
19
  }
18
20
 
19
21
  type DateStr = string;
@@ -32,16 +34,22 @@ export interface AdvancedRouteParams extends RouteParams {
32
34
  to?: DateStr;
33
35
  /** When set, filter on beneficiaries */
34
36
  b?: string[];
37
+ /** When set, filter on topics */
38
+ r?: string;
35
39
  q?: string;
40
+ /** When set, filter on groups */
41
+ gp?: number[];
36
42
  }
37
43
 
38
44
  type RouteParamEnum =
39
45
  'Beneficiaries' |
40
- 'Query'
46
+ 'Query' |
47
+ 'EmissionGroups'
41
48
  ;
42
49
 
43
50
  /** Utility to access route params by constants instead of undefined value */
44
51
  export const ROUTE_PARAMS: Record<RouteParamEnum, keyof AdvancedRouteParams> = {
45
52
  Beneficiaries: 'b',
46
- Query: 'q'
47
- };
53
+ Query: 'q',
54
+ EmissionGroups: 'gp'
55
+ };
@@ -8,6 +8,7 @@ import { computed, nextTick, onMounted, Ref, ref, watch } from "vue";
8
8
  import dayjs from "dayjs";
9
9
 
10
10
  import { RouteProps } from "./types";
11
+ import { EmissionGroup, groupsApi } from "../../../api/groupsApi";
11
12
 
12
13
  export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) => {
13
14
 
@@ -29,7 +30,7 @@ export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) =>
29
30
  const iabId: Ref<number|undefined> = ref(undefined);
30
31
  const rubriqueFilter: Ref<Array<RubriquageFilter>> = ref([]);
31
32
  const beneficiaries = ref<string[]|null>(null);
32
-
33
+ const emissionGroups = ref<EmissionGroup[]|null>(null);
33
34
 
34
35
  const organisationRight = computed(() => isEditRights(organisationId.value));
35
36
  const organisation = computed(() => organisationId.value ?? filterStore.filterOrgaId);
@@ -53,17 +54,18 @@ export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) =>
53
54
  }
54
55
  });
55
56
 
56
- watch(() => props.routeQuery, () => initSearchPattern());
57
- watch(() => props.routeMonetisable, () => initMonetisable());
58
- watch(() => props.routeSort, () => initSort());
59
- watch(() => props.routeIncludeHidden, () => initIncludeHidden());
60
- watch(() => props.routeValidity, () => initValidity());
61
- watch(() => props.routeFrom, () => initFromDate());
62
- watch(() => props.routeTo, () => initToDate());
57
+ watch(() => props.routeQuery, initSearchPattern);
58
+ watch(() => props.routeMonetisable, initMonetisable);
59
+ watch(() => props.routeSort, initSort);
60
+ watch(() => props.routeIncludeHidden, initIncludeHidden);
61
+ watch(() => props.routeValidity, initValidity);
62
+ watch(() => props.routeFrom, initFromDate);
63
+ watch(() => props.routeTo, initToDate);
63
64
  watch(() => props.routeIab, () => {iabId.value = props.routeIab;});
64
- watch(() => props.routeOrga, () => initOrga());
65
- watch(() => props.routeRubriques, () => initRubriquageFilter());
65
+ watch(() => props.routeOrga, initOrga);
66
+ watch(() => props.routeRubriques, initRubriquageFilter);
66
67
  watch(() => props.routeBeneficiaries, initBeneficiariesFilter);
68
+ watch(() => props.routeEmissionGroups, initEmissionGroups);
67
69
  watch(organisationId, () => {
68
70
  if (!isInit.value) {
69
71
  return;
@@ -135,7 +137,7 @@ export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) =>
135
137
  return
136
138
  }
137
139
  const rubriqueFilterToUpdate = [];
138
- if(props.routeRubriques.trim().length){
140
+ if(props.routeRubriques?.trim().length){
139
141
  const arrayFilter = props.routeRubriques.split(",");
140
142
  for(const filter of arrayFilter){
141
143
  const rubriqueFilter = filter.split(":");
@@ -151,7 +153,7 @@ export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) =>
151
153
  }
152
154
 
153
155
  function initBeneficiariesFilter() {
154
- const data = props.routeBeneficiaries as string[];
156
+ const data = props.routeBeneficiaries;
155
157
  // No beneficiaries
156
158
  if (
157
159
  data === undefined ||
@@ -170,6 +172,28 @@ export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) =>
170
172
  beneficiaries.value = data;
171
173
  }
172
174
 
175
+ async function initEmissionGroups(): Promise<void> {
176
+ const data = props.routeEmissionGroups;
177
+ // No groups
178
+ if (
179
+ data === undefined ||
180
+ data === null ||
181
+ data.length === 0
182
+ ) {
183
+ emissionGroups.value = null;
184
+ return;
185
+ }
186
+
187
+ // No changes
188
+ if(emissionGroups.value && data === emissionGroups.value.map(g => g.groupId)){
189
+ return;
190
+ }
191
+
192
+ const groups = await groupsApi.getAllById(data);
193
+
194
+ emissionGroups.value = Object.values(groups);
195
+ }
196
+
173
197
  return {
174
198
  organisationId,
175
199
  searchPattern,
@@ -185,6 +209,7 @@ export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) =>
185
209
  validity,
186
210
  rubriquesFilterArrayIds,
187
211
  isInit,
188
- beneficiaries
212
+ beneficiaries,
213
+ emissionGroups
189
214
  };
190
215
  }
@@ -12,6 +12,7 @@ export const useErrorHandler = ()=>{
12
12
  if (undefined === authStore.authOrgaId) {
13
13
  window.location.href = window.location.origin + "/sso/login";
14
14
  } else {
15
+ console.error(error);
15
16
  router.push({
16
17
  path: "/main/pub/error",
17
18
  });
@@ -19,7 +20,7 @@ export const useErrorHandler = ()=>{
19
20
  }
20
21
  }
21
22
 
22
- return {
23
+ return {
23
24
  handle403
24
- }
25
+ }
25
26
  }