@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.
- package/CHANGELOG.md +42 -0
- package/index.ts +24 -1
- 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 +38 -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/EmissionItem.vue +23 -3
- package/src/components/display/emission/EmissionList.vue +8 -2
- package/src/components/display/filter/AdvancedSearch.vue +82 -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 +38 -53
- 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,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
|
@@ -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;
|
|
@@ -135,7 +137,7 @@ export const useAdvancedParamInit = (props: RouteProps, isEmission: boolean) =>
|
|
|
135
137
|
return
|
|
136
138
|
}
|
|
137
139
|
const rubriqueFilterToUpdate = [];
|
|
138
|
-
if(props.routeRubriques
|
|
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
|
|
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
|
-
|
|
23
|
+
return {
|
|
23
24
|
handle403
|
|
24
|
-
|
|
25
|
+
}
|
|
25
26
|
}
|