@saooti/octopus-sdk 41.1.15 → 41.2.1
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.
- package/CHANGELOG.md +44 -0
- package/index.ts +29 -2
- package/package.json +1 -1
- package/src/api/groupsApi.ts +214 -0
- package/src/api/podcastApi.ts +47 -9
- package/src/components/buttons/ActionButton.vue +99 -0
- package/src/components/buttons/index.ts +5 -0
- package/src/components/composable/route/types.ts +11 -3
- package/src/components/composable/route/useAdvancedParamInit.ts +40 -13
- package/src/components/composable/useErrorHandler.ts +3 -2
- package/src/components/composable/useNotifications.ts +50 -0
- package/src/components/display/emission/EmissionGroupChooser.vue +56 -0
- package/src/components/display/emission/EmissionList.vue +8 -2
- package/src/components/display/filter/AdvancedSearch.vue +83 -23
- package/src/components/display/list/ListPaginate.vue +4 -1
- package/src/components/display/podcasts/PodcastList.vue +12 -5
- package/src/components/display/podcasts/PodcastPlayButton.vue +2 -2
- package/src/components/display/podcasts/TagList.vue +4 -1
- package/src/components/form/ClassicMultiselect.vue +43 -37
- package/src/components/icons.ts +13 -0
- package/src/components/misc/ClassicAlert.vue +8 -1
- package/src/components/misc/ClassicBigChip.vue +84 -0
- package/src/components/misc/ClassicDataTable.vue +98 -0
- package/src/components/misc/ClassicDataTable_Internal.vue +132 -0
- package/src/components/misc/ClassicHelpButton.vue +3 -3
- package/src/components/misc/ClassicNotifications.vue +23 -0
- package/src/components/misc/ClassicPopover.vue +1 -0
- package/src/components/pages/EmissionPage.vue +2 -2
- package/src/components/pages/EmissionsPage.vue +10 -15
- package/src/components/pages/PodcastPage.vue +1 -1
- package/src/components/pages/PodcastsPage.vue +8 -20
- package/src/helper/fetchHelper.ts +1 -0
- package/src/locale/de.ts +2 -0
- package/src/locale/en.ts +2 -0
- package/src/locale/es.ts +2 -0
- package/src/locale/fr.ts +5 -3
- package/src/locale/it.ts +2 -0
- package/src/locale/sl.ts +2 -0
- package/src/router/router.ts +14 -288
- package/src/router/routes.ts +236 -0
- package/src/router/utils.ts +43 -2
- package/src/stores/class/general/emission.ts +8 -2
- package/src/style/_variables.scss +3 -0
- package/src/style/bootstrap.scss +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 41.2.1 (05/01/2026)
|
|
4
|
+
|
|
5
|
+
**Fixes**
|
|
6
|
+
|
|
7
|
+
- Recherche avancées
|
|
8
|
+
- Correction chargements groupes & ayants-droits depuis routing
|
|
9
|
+
- Filtrage des groupes par organisation
|
|
10
|
+
|
|
11
|
+
**Misc**
|
|
12
|
+
|
|
13
|
+
- Export des routes principales pour réutilisation dans projets incluant le SDK
|
|
14
|
+
|
|
15
|
+
## 41.2.0 (05/01/2026)
|
|
16
|
+
|
|
17
|
+
**Features**
|
|
18
|
+
|
|
19
|
+
- Ajout d'un système de notifications
|
|
20
|
+
- Intégrez `ClassicNotification` dans la vue principale pour afficher les
|
|
21
|
+
notifications
|
|
22
|
+
- Utilisez le composable `useNotifications` pour contrôler l'affichage des
|
|
23
|
+
notification depuis n'importe quel composant
|
|
24
|
+
- Ajout du composant `ClassicDataTable` pour afficher des tableaux de données
|
|
25
|
+
facilement
|
|
26
|
+
- Ajout du composant `ActionButton` pour faire un bouton déclenchant une action,
|
|
27
|
+
avec confirmation optionnelle
|
|
28
|
+
- Ajout du composant `ClassicBigChip` pour afficher des éléments simples
|
|
29
|
+
- Ajout du composant `EmissionGroupChooser` pour sélectionner un groupe
|
|
30
|
+
d'émissions parmis ceux définis
|
|
31
|
+
- Ajout de la bibliothèque d'icones `src/components/icons.ts` pour uniformiser
|
|
32
|
+
les icones au sein des différents projets
|
|
33
|
+
- Ajout de l'API groupes
|
|
34
|
+
- Ajout du filtrage par groupe sur les podcasts
|
|
35
|
+
|
|
36
|
+
**Fixes**
|
|
37
|
+
|
|
38
|
+
- Les mots-clés définis à la fois sur une émission et sur un épisode de cette
|
|
39
|
+
émissions ne s'affichent qu'une seule fois lors de la consultation de cet
|
|
40
|
+
épisode
|
|
41
|
+
- Le bouton de lecture vidéo ne disparait plus quand on lit une autre vidéo
|
|
42
|
+
- Correction des épisodes avec vidéos n'apparaissant plus lors de la
|
|
43
|
+
consultation des émissions
|
|
44
|
+
- `ClassicHelpButton` utilise le string `relative-class` au lieu du booléen
|
|
45
|
+
`relative` pour déterminer l'élément parent.
|
|
46
|
+
|
|
3
47
|
## 41.1.15 (19/12/2025)
|
|
4
48
|
|
|
5
49
|
**Fixes**
|
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");
|
|
@@ -155,12 +176,14 @@ export const getTuninIcon = () => import("./src/components/icons/TuninIcon.vue")
|
|
|
155
176
|
export const getXIcon = () => import("./src/components/icons/XIcon.vue");
|
|
156
177
|
|
|
157
178
|
// Routing
|
|
158
|
-
import { setupRouter } from './src/router/utils';
|
|
179
|
+
import { setupRouter, getSimpleRouteProps, getRouteProps } from './src/router/utils';
|
|
180
|
+
import { routes as sdkRoutes } from './src/router/routes';
|
|
159
181
|
|
|
160
182
|
// Types
|
|
161
183
|
import { type SelectOption } from "./src/components/form/ClassicSelect.vue";
|
|
162
184
|
|
|
163
185
|
import { ROUTE_PARAMS } from "./src/components/composable/route/types";
|
|
186
|
+
import { defineAsyncComponent } from "vue";
|
|
164
187
|
|
|
165
188
|
export {
|
|
166
189
|
useResizePhone,
|
|
@@ -173,6 +196,7 @@ export {
|
|
|
173
196
|
useInit,
|
|
174
197
|
useErrorHandler,
|
|
175
198
|
useSimplePageParam,
|
|
199
|
+
useNotifications,
|
|
176
200
|
debounce,
|
|
177
201
|
useVastStore,
|
|
178
202
|
useSaveFetchStore,
|
|
@@ -194,6 +218,9 @@ export {
|
|
|
194
218
|
downloadHelper,
|
|
195
219
|
displayHelper,
|
|
196
220
|
setupRouter,
|
|
221
|
+
getSimpleRouteProps,
|
|
222
|
+
getRouteProps,
|
|
223
|
+
sdkRoutes,
|
|
197
224
|
SelectOption,
|
|
198
225
|
ROUTE_PARAMS
|
|
199
226
|
};
|
package/package.json
CHANGED
|
@@ -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
|
+
};
|
package/src/api/podcastApi.ts
CHANGED
|
@@ -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>
|
|
@@ -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,
|
|
57
|
-
watch(() => props.routeMonetisable,
|
|
58
|
-
watch(() => props.routeSort,
|
|
59
|
-
watch(() => props.routeIncludeHidden,
|
|
60
|
-
watch(() => props.routeValidity,
|
|
61
|
-
watch(() => props.routeFrom,
|
|
62
|
-
watch(() => props.routeTo,
|
|
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,
|
|
65
|
-
watch(() => props.routeRubriques,
|
|
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;
|
|
@@ -84,6 +86,8 @@ export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) =>
|
|
|
84
86
|
initSort();
|
|
85
87
|
initFromDate();
|
|
86
88
|
initToDate();
|
|
89
|
+
initBeneficiariesFilter();
|
|
90
|
+
initEmissionGroups();
|
|
87
91
|
nextTick(() => {
|
|
88
92
|
isInit.value = true;
|
|
89
93
|
});
|
|
@@ -135,7 +139,7 @@ export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) =>
|
|
|
135
139
|
return
|
|
136
140
|
}
|
|
137
141
|
const rubriqueFilterToUpdate = [];
|
|
138
|
-
if(props.routeRubriques
|
|
142
|
+
if(props.routeRubriques?.trim().length){
|
|
139
143
|
const arrayFilter = props.routeRubriques.split(",");
|
|
140
144
|
for(const filter of arrayFilter){
|
|
141
145
|
const rubriqueFilter = filter.split(":");
|
|
@@ -151,7 +155,7 @@ export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) =>
|
|
|
151
155
|
}
|
|
152
156
|
|
|
153
157
|
function initBeneficiariesFilter() {
|
|
154
|
-
const data = props.routeBeneficiaries
|
|
158
|
+
const data = props.routeBeneficiaries;
|
|
155
159
|
// No beneficiaries
|
|
156
160
|
if (
|
|
157
161
|
data === undefined ||
|
|
@@ -170,6 +174,28 @@ export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) =>
|
|
|
170
174
|
beneficiaries.value = data;
|
|
171
175
|
}
|
|
172
176
|
|
|
177
|
+
async function initEmissionGroups(): Promise<void> {
|
|
178
|
+
const data = props.routeEmissionGroups;
|
|
179
|
+
// No groups
|
|
180
|
+
if (
|
|
181
|
+
data === undefined ||
|
|
182
|
+
data === null ||
|
|
183
|
+
data.length === 0
|
|
184
|
+
) {
|
|
185
|
+
emissionGroups.value = null;
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// No changes
|
|
190
|
+
if(emissionGroups.value && data === emissionGroups.value.map(g => g.groupId)){
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const groups = await groupsApi.getAllById(data);
|
|
195
|
+
|
|
196
|
+
emissionGroups.value = Object.values(groups);
|
|
197
|
+
}
|
|
198
|
+
|
|
173
199
|
return {
|
|
174
200
|
organisationId,
|
|
175
201
|
searchPattern,
|
|
@@ -185,6 +211,7 @@ export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) =>
|
|
|
185
211
|
validity,
|
|
186
212
|
rubriquesFilterArrayIds,
|
|
187
213
|
isInit,
|
|
188
|
-
beneficiaries
|
|
214
|
+
beneficiaries,
|
|
215
|
+
emissionGroups
|
|
189
216
|
};
|
|
190
217
|
}
|