@communecter/cocolight-api-client 1.0.7 → 1.0.9
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/README.md +4 -4
- package/dist/22.cocolight-api-client.mjs.js +1 -0
- package/dist/320.cocolight-api-client.browser.js +1 -0
- package/dist/931.cocolight-api-client.browser.js +1 -0
- package/dist/931.cocolight-api-client.cjs +1 -0
- package/dist/cocolight-api-client.browser.js +7 -6
- package/dist/cocolight-api-client.browser.js.LICENSE.txt +1 -0
- package/dist/cocolight-api-client.cjs +1 -1
- package/dist/cocolight-api-client.mjs.js +1 -1
- package/package.json +13 -4
- package/src/Api.js +12 -8
- package/src/ApiClient.js +118 -10
- package/src/api/EndpointApi.js +1534 -0
- package/src/api/News.js +286 -0
- package/src/api/Organization.js +162 -8
- package/src/api/Project.js +163 -8
- package/src/api/User.js +150 -9
- package/src/api/UserApi.js +2 -1
- package/src/endpoints.module.js +2 -2
- package/src/error.js +11 -0
- package/src/index.js +2 -1
- package/src/mixin/EntityMixin.js +48 -0
- package/src/mixin/NewsMixin.js +8 -0
- package/src/mixin/UserMixin.js +8 -0
- package/src/mixin/UtilMixin.js +246 -0
- package/src/utils/stream-utils.node.js +10 -0
- package/src/api/EntityMixin.js +0 -43
package/src/api/News.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { ApiError } from "../error.js";
|
|
2
|
+
import { NewsMixin } from "../mixin/NewsMixin.js";
|
|
3
|
+
import { UtilMixin } from "../mixin/UtilMixin.js";
|
|
4
|
+
|
|
5
|
+
// News.js
|
|
6
|
+
export class News {
|
|
7
|
+
// Champs privés pour protéger l'état
|
|
8
|
+
#draftData = {};
|
|
9
|
+
// Data d'une news venant du serveur
|
|
10
|
+
#serverData = null;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Crée une instance de News.
|
|
14
|
+
* @param {(Organization|Project|User)} parent - L'instance de l'element parent (ex: Organization, Project, User).
|
|
15
|
+
* @param {Object} identifier - Objet contenant { id }
|
|
16
|
+
* @param {Object} deps - Dépendances injectées (ex: User).
|
|
17
|
+
* @param {EndpointApi} deps.EndpointApi - Classe EndpointApi pour éviter les dépendances circulaires.
|
|
18
|
+
* @param {User} deps.User - Classe User pour éviter les dépendances circulaires.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
constructor(parent, data = {}, deps = {}) {
|
|
22
|
+
if(!deps.EndpointApi){
|
|
23
|
+
throw new ApiError("EndpointApi class must be injected to avoid circular dependency.");
|
|
24
|
+
}
|
|
25
|
+
if (!deps.User) {
|
|
26
|
+
throw new ApiError("User class must be injected to avoid circular dependency.");
|
|
27
|
+
}
|
|
28
|
+
if (!parent) {
|
|
29
|
+
throw new ApiError("Parent is required.");
|
|
30
|
+
}
|
|
31
|
+
this.deps = deps;
|
|
32
|
+
this.UserClass = deps.User;
|
|
33
|
+
this.apiClient = parent.apiClient;
|
|
34
|
+
|
|
35
|
+
// Gérer les deux cas : fonction constructeur ou instance
|
|
36
|
+
if (typeof deps.EndpointApi === "function") {
|
|
37
|
+
this.endpointApi = new deps.EndpointApi(this.apiClient);
|
|
38
|
+
} else if (typeof deps.EndpointApi === "object") {
|
|
39
|
+
this.endpointApi = deps.EndpointApi;
|
|
40
|
+
} else {
|
|
41
|
+
throw new ApiError("deps.EndpointApi doit être une classe ou une instance valide.");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
this.#draftData = { ...data };
|
|
45
|
+
this.parent = parent;
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Getters en lecture seule pour chaque propriété
|
|
50
|
+
get id() {
|
|
51
|
+
return this.#draftData.id || null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get isConnected() {
|
|
55
|
+
return this.apiClient.isConnected;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get draftData() {
|
|
59
|
+
return this.#draftData;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
get serverData() {
|
|
63
|
+
return this.#serverData;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
get userId() {
|
|
67
|
+
return this.apiClient.userId;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get isMe() {
|
|
71
|
+
return this.isConnected && this.userId === this.parent.id;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
getEntityType() {
|
|
75
|
+
return "news";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static fromServerData(data, parent, deps) {
|
|
79
|
+
const instance = new News(parent, { id: data.id }, deps);
|
|
80
|
+
|
|
81
|
+
// Injecte les données serveur
|
|
82
|
+
instance.#serverData = { ...data };
|
|
83
|
+
|
|
84
|
+
// Construit les données draft à partir du serverData
|
|
85
|
+
instance.#draftData = instance._getDraftFromServerData(data);
|
|
86
|
+
|
|
87
|
+
return instance;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async refresh() {
|
|
91
|
+
if (!this.id) throw new ApiError("Impossible de rafraîchir sans ID.");
|
|
92
|
+
return this.get();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Récupérer des actualités par IDs : Récupère des actualités à partir d’une liste d’identifiants.
|
|
97
|
+
* Constant : GET_NEWS_BY_ID
|
|
98
|
+
*/
|
|
99
|
+
async get() {
|
|
100
|
+
if(!this.id) {
|
|
101
|
+
throw new ApiError("Vous devez fournir un id pour récupérer une news.");
|
|
102
|
+
}
|
|
103
|
+
const newsArray = await this.callIsConnected(() => this.endpointApi.getNewsById({ ids: [this.id] }));
|
|
104
|
+
if (newsArray && newsArray.length > 0) {
|
|
105
|
+
this.#serverData = newsArray[0];
|
|
106
|
+
this.#draftData = this._getDraftFromServerData(this.#serverData);
|
|
107
|
+
return this.#serverData;
|
|
108
|
+
}
|
|
109
|
+
throw new ApiError(`Aucune actualité trouvée pour l'ID ${this.id}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
_getDraftFromServerData(data) {
|
|
113
|
+
// je veux copier que certaine info si présente dans le draftData
|
|
114
|
+
// - newsArray[0].scope.type > draftData.scope
|
|
115
|
+
// - newsArray[0].text > draftData.text
|
|
116
|
+
// - newsArray[0].tags > draftData.tags
|
|
117
|
+
// - newsArray[0].mentions > draftData.mentions > draftData.mentions.count integer
|
|
118
|
+
// - newsArray[0].mediaImg > draftData.mediaImg > draftData.mediaImg.images > un array id
|
|
119
|
+
// - newsArray[0].mediaFile > draftData.mediaFile > draftData.mediaFile.files > un array id
|
|
120
|
+
const transformed = this._pickProps(
|
|
121
|
+
data,
|
|
122
|
+
["scope", "text", "tags", "mentions", "mediaImg", "mediaFile"],
|
|
123
|
+
{
|
|
124
|
+
scope: (val) => val?.type,
|
|
125
|
+
mentions: (val) =>
|
|
126
|
+
Array.isArray(val)
|
|
127
|
+
? val.map((mention) => ({
|
|
128
|
+
...mention,
|
|
129
|
+
count: parseInt(mention.count)
|
|
130
|
+
}))
|
|
131
|
+
: [],
|
|
132
|
+
mediaImg: (val) => {
|
|
133
|
+
const images = val?.images?.map((img) => img.id).filter(Boolean) || [];
|
|
134
|
+
return images.length > 0
|
|
135
|
+
? {
|
|
136
|
+
countImages: parseInt(val.countImages) || images.length,
|
|
137
|
+
images
|
|
138
|
+
}
|
|
139
|
+
: undefined;
|
|
140
|
+
},
|
|
141
|
+
mediaFile: (val) => {
|
|
142
|
+
const files = val?.files?.map((file) => file.id).filter(Boolean) || [];
|
|
143
|
+
return files.length > 0
|
|
144
|
+
? {
|
|
145
|
+
countFiles: parseInt(val.countFiles) || files.length,
|
|
146
|
+
files
|
|
147
|
+
}
|
|
148
|
+
: undefined;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
id: data.id,
|
|
155
|
+
...Object.fromEntries(Object.entries(transformed).filter(([, v]) => v !== undefined))
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Ajouter une actualité : Ajoute une nouvelle actualité.
|
|
161
|
+
* Constant : ADD_NEWS | UPDATE_NEWS
|
|
162
|
+
*/
|
|
163
|
+
async save() {
|
|
164
|
+
|
|
165
|
+
// si le texte est vide, on met un espace pour que le champ soit pris en compte car sur le serveur
|
|
166
|
+
// il y a une vérification de la taille du texte je pense
|
|
167
|
+
if(this.#draftData?.text === ""){
|
|
168
|
+
this.#draftData.text = " ";
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const payload = { ...this.#draftData };
|
|
172
|
+
payload.parentId = this.parent.id;
|
|
173
|
+
payload.parentType = this.parent.getEntityType();
|
|
174
|
+
|
|
175
|
+
if (!this.id) {
|
|
176
|
+
const reponseData = await this.callIsConnected(() => this.endpointApi.addNews(payload));
|
|
177
|
+
this.#draftData.id = reponseData.object.id;
|
|
178
|
+
// TODO : voir si j'ai ce qui faut dans reponseData de ADD_NEWS pour mettre à jour #serverData
|
|
179
|
+
// c'est dans reponseData.object
|
|
180
|
+
if(reponseData?.object){
|
|
181
|
+
this.#serverData = { ...reponseData.object };
|
|
182
|
+
}
|
|
183
|
+
// await this.refresh();
|
|
184
|
+
return reponseData;
|
|
185
|
+
} else {
|
|
186
|
+
if(payload.id){
|
|
187
|
+
delete payload.id;
|
|
188
|
+
}
|
|
189
|
+
const reponseData = await this.callIsConnected(() => this.endpointApi.updateNews({ ...payload, idNews: this.id }));
|
|
190
|
+
// TODO : voir si j'ai ce qui faut dans reponseData de UPDATE_NEWS pour mettre à jour #serverData
|
|
191
|
+
// c'est dans reponseData.object
|
|
192
|
+
if(reponseData?.object){
|
|
193
|
+
this.#serverData = { ...reponseData.object };
|
|
194
|
+
}
|
|
195
|
+
// await this.refresh();
|
|
196
|
+
return reponseData;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
async addMention({ slug, id }) {
|
|
202
|
+
try {
|
|
203
|
+
if (!slug && !id) {
|
|
204
|
+
throw new ApiError("Vous devez fournir un slug ou un id pour ajouter une mention.");
|
|
205
|
+
}
|
|
206
|
+
const userInstance = new this.UserClass(this.apiClient, { id, slug }, null , { EndpointApi: this.endpointApi });
|
|
207
|
+
const user = await userInstance.getProfil();
|
|
208
|
+
if (!this.#draftData.mentions) {
|
|
209
|
+
this.#draftData.mentions = [];
|
|
210
|
+
}
|
|
211
|
+
// Vérification si la mention existe déjà
|
|
212
|
+
if (this.#draftData.mentions.find((mention) => mention.id === user.id)) {
|
|
213
|
+
// Si la mention existe déjà, on incrémente le compteur
|
|
214
|
+
this.#draftData.mentions = this.#draftData.mentions.map((mention) => {
|
|
215
|
+
if (mention.id === user.id) {
|
|
216
|
+
mention.count += 1;
|
|
217
|
+
}
|
|
218
|
+
return mention;
|
|
219
|
+
});
|
|
220
|
+
return this.#draftData.mentions;
|
|
221
|
+
}
|
|
222
|
+
const mention = { id: user.id, slug: user.slug, type: userInstance.getEntityType(), name: user.name, value: user.name, count: 1 };
|
|
223
|
+
this.#draftData.mentions.push(mention);
|
|
224
|
+
return this.#draftData.mentions;
|
|
225
|
+
} catch (error) {
|
|
226
|
+
this.apiClient._logger.error("Erreur lors de l'ajout de la mention :", error);
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Ajouter une image à une actualité : Ajoute une images à une actualité.
|
|
234
|
+
* Constant : ADD_IMAGE_NEWS
|
|
235
|
+
*/
|
|
236
|
+
async addImage(image) {
|
|
237
|
+
image = await this.validateImage(image);
|
|
238
|
+
const data = { pathParams: { folder: this.parent.getEntityType(), ownerId: this.parent.id }, newsImage: image };
|
|
239
|
+
const dataImage = await this.callIsConnected(() => this.endpointApi.addImageNews(data));
|
|
240
|
+
if (this.#draftData.mediaImg) {
|
|
241
|
+
this.#draftData.mediaImg.countImages = this.#draftData.mediaImg.countImages + 1;
|
|
242
|
+
this.#draftData.mediaImg.images.push(dataImage.id);
|
|
243
|
+
} else {
|
|
244
|
+
this.#draftData.mediaImg = { countImages: 1, images: [dataImage.id] };
|
|
245
|
+
}
|
|
246
|
+
return dataImage;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Ajouter un fichier à une actualité : Ajoute un fichier à une actualité.
|
|
251
|
+
* Constant : ADD_FILE_NEWS
|
|
252
|
+
*/
|
|
253
|
+
async addFile(file) {
|
|
254
|
+
file = await this.validateFile(file);
|
|
255
|
+
const data = { pathParams: { folder: this.parent.getEntityType(), ownerId: this.parent.id }, newsFile: file };
|
|
256
|
+
const dataFile = await this.callIsConnected(() =>this.endpointApi.addFileNews(data));
|
|
257
|
+
if (this.#draftData.mediaFile) {
|
|
258
|
+
this.#draftData.mediaFile.countFiles = this.#draftData.mediaFile.countFiles + 1;
|
|
259
|
+
this.#draftData.mediaFile.files.push(dataFile);
|
|
260
|
+
} else {
|
|
261
|
+
this.#draftData.mediaFile = { countFiles: 1, files: [dataFile] };
|
|
262
|
+
}
|
|
263
|
+
return dataFile;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Supprimer une actualité : Supprime une actualité existante.
|
|
268
|
+
* Constant : DELETE_NEWS
|
|
269
|
+
*/
|
|
270
|
+
async delete() {
|
|
271
|
+
if(!this.id) {
|
|
272
|
+
throw new ApiError("Vous devez fournir un id pour supprimer une news.");
|
|
273
|
+
}
|
|
274
|
+
const data = { pathParams: { id: this.id } };
|
|
275
|
+
await this.callIsConnected(() => this.endpointApi.deleteNews(data));
|
|
276
|
+
this.#draftData = {};
|
|
277
|
+
this.#serverData = null;
|
|
278
|
+
this.#draftData.id = null;
|
|
279
|
+
this._isDeleted = true;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Incorporation du mixin dans Organization
|
|
285
|
+
Object.assign(News.prototype, UtilMixin, NewsMixin);
|
|
286
|
+
|
package/src/api/Organization.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ApiResponseError } from "../error.js";
|
|
2
|
+
import { News } from "./News.js";
|
|
3
|
+
import { User } from "./User.js";
|
|
4
|
+
import { EntityMixin } from "../mixin/EntityMixin.js";
|
|
5
|
+
import { NewsMixin } from "../mixin/NewsMixin.js";
|
|
6
|
+
import { UtilMixin } from "../mixin/UtilMixin.js";
|
|
2
7
|
|
|
3
8
|
// Organization.js
|
|
4
9
|
export class Organization {
|
|
@@ -11,13 +16,29 @@ export class Organization {
|
|
|
11
16
|
* Crée une instance de Organization.
|
|
12
17
|
* @param {ApiClient} apiClient - L'instance d'ApiClient.
|
|
13
18
|
* @param {Object} identifier - Objet contenant { id } ou { slug }.
|
|
19
|
+
* @param {Object} [deps={}] - Dépendances injectées (ex: User).
|
|
20
|
+
* @param {EndpointApi} deps.EndpointApi - Classe EndpointApi pour éviter les dépendances circulaires.
|
|
14
21
|
*/
|
|
15
22
|
|
|
16
|
-
constructor(apiClient, { id, slug } = {}) {
|
|
23
|
+
constructor(apiClient, { id, slug } = {}, deps = {}) {
|
|
24
|
+
if(!deps.EndpointApi){
|
|
25
|
+
throw new Error("EndpointApi class must be injected to avoid circular dependency.");
|
|
26
|
+
}
|
|
17
27
|
if (!id && !slug) {
|
|
18
|
-
throw new Error("Vous devez fournir un id ou un slug pour créer
|
|
28
|
+
throw new Error("Vous devez fournir un id ou un slug pour créer une instance User.");
|
|
19
29
|
}
|
|
20
30
|
this.apiClient = apiClient;
|
|
31
|
+
this.deps = deps;
|
|
32
|
+
|
|
33
|
+
// Gérer les deux cas : fonction constructeur ou instance
|
|
34
|
+
if (typeof deps.EndpointApi === "function") {
|
|
35
|
+
this.endpointApi = new deps.EndpointApi(this.apiClient);
|
|
36
|
+
} else if (typeof deps.EndpointApi === "object") {
|
|
37
|
+
this.endpointApi = deps.EndpointApi;
|
|
38
|
+
} else {
|
|
39
|
+
throw new Error("deps.EndpointApi doit être une classe ou une instance valide.");
|
|
40
|
+
}
|
|
41
|
+
|
|
21
42
|
this.#id = id || null;
|
|
22
43
|
this.#slug = slug || null;
|
|
23
44
|
}
|
|
@@ -26,6 +47,10 @@ export class Organization {
|
|
|
26
47
|
get id() {
|
|
27
48
|
return this.#id;
|
|
28
49
|
}
|
|
50
|
+
|
|
51
|
+
_id(newId) {
|
|
52
|
+
this.#id = newId;
|
|
53
|
+
}
|
|
29
54
|
|
|
30
55
|
get slug() {
|
|
31
56
|
return this.#slug;
|
|
@@ -64,16 +89,145 @@ export class Organization {
|
|
|
64
89
|
*
|
|
65
90
|
* @returns {Promise<Object>} Le profil complet.
|
|
66
91
|
*/
|
|
67
|
-
async
|
|
92
|
+
async getProfil() {
|
|
68
93
|
return this.apiClient.safeCall(async () => {
|
|
69
|
-
const
|
|
70
|
-
this._setData(
|
|
71
|
-
return
|
|
94
|
+
const data = await this.getPublicProfile();
|
|
95
|
+
this._setData(data);
|
|
96
|
+
return data;
|
|
72
97
|
});
|
|
73
98
|
}
|
|
74
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Mettre à jour les paramètres d'un élément : Mise à jour des paramètres spécifiques d'un élément.
|
|
102
|
+
* Constant : UPDATE_SETTINGS
|
|
103
|
+
* @param {Object} data - Les données à envoyer.
|
|
104
|
+
* @param {string} data.type - data.type
|
|
105
|
+
* @param {undefined} data.value - data.value
|
|
106
|
+
* @returns {Promise<Object>} - Les données de réponse.
|
|
107
|
+
* @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
|
|
108
|
+
* @throws {ApiAuthenticationError} - En cas d'erreur d'authentification.
|
|
109
|
+
* @throws {Error} - En cas d'erreur inattendue.
|
|
110
|
+
*/
|
|
111
|
+
async updateSettings(data = {}) {
|
|
112
|
+
data.idEntity = this.id;
|
|
113
|
+
data.typeEntity = this.getEntityType();
|
|
114
|
+
return this.callIsConnected(() => this.endpointApi.updateSettings(data));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Mettre à jour la description d'un élément : Permet de mettre à jour la description courte et complète d'un élément.
|
|
119
|
+
* Constant : UPDATE_BLOCK_DESCRIPTION
|
|
120
|
+
* @param {Object} data - Les données à envoyer.
|
|
121
|
+
* @param {string} data.descMentions - Mentions dans la description (default: "")
|
|
122
|
+
* @param {string} data.shortDescription - Courte description
|
|
123
|
+
* @param {string} data.description - Description complète
|
|
124
|
+
* @returns {Promise<Object>} - Les données de réponse.
|
|
125
|
+
* @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
|
|
126
|
+
* @throws {ApiAuthenticationError} - En cas d'erreur d'authentification.
|
|
127
|
+
* @throws {Error} - En cas d'erreur inattendue.
|
|
128
|
+
*/
|
|
129
|
+
async updateDescription(data = {}) {
|
|
130
|
+
data.typeElement = this.getEntityType();
|
|
131
|
+
data.id = this.id;
|
|
132
|
+
return this.callIsConnected(() => this.endpointApi.updateBlockDescription(data));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Mettre à jour les informations d'un élément : Permet de mettre à jour les informations générales d'un élément (nom, contacts, etc.).
|
|
137
|
+
* Constant : UPDATE_BLOCK_INFO
|
|
138
|
+
*/
|
|
139
|
+
async updateInfo(data = {}) {
|
|
140
|
+
data.typeElement = this.getEntityType();
|
|
141
|
+
data.id = this.id;
|
|
142
|
+
return this.callIsConnected(() => this.endpointApi.updateBlockInfo(data));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Mettre à jour les réseaux sociaux d'un élément : Permet de mettre à jour les liens vers les réseaux sociaux d'un élément.
|
|
147
|
+
* Constant : UPDATE_BLOCK_SOCIAL
|
|
148
|
+
*/
|
|
149
|
+
async updateSocial(data = {}) {
|
|
150
|
+
data.typeElement = this.getEntityType();
|
|
151
|
+
data.id = this.id;
|
|
152
|
+
return this.callIsConnected(() => this.endpointApi.updateBlockSocial(data));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Mettre à jour les localités d'un élément : Permet de mettre à jour l'adresse et les informations géographiques d'un élément.
|
|
157
|
+
* Constant : UPDATE_BLOCK_LOCALITY
|
|
158
|
+
*/
|
|
159
|
+
async updateLocality(data = {}) {
|
|
160
|
+
data.typeElement = this.getEntityType();
|
|
161
|
+
data.id = this.id;
|
|
162
|
+
return this.callIsConnected(() => this.endpointApi.updateBlockLocality(data));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Mettre à jour le slug d'un élément : Permet de mettre à jour le slug pour une URL simplifiée.
|
|
167
|
+
* Constant : UPDATE_BLOCK_SLUG
|
|
168
|
+
*/
|
|
169
|
+
async updateSlug(slug) {
|
|
170
|
+
try {
|
|
171
|
+
await this.endpointApi.check({ slug });
|
|
172
|
+
} catch (error) {
|
|
173
|
+
if(error instanceof ApiResponseError) {
|
|
174
|
+
throw new ApiResponseError("Erreur lors de la vérification du slug.", error.status, error.data);
|
|
175
|
+
}
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
const data = { typeElement: this.getEntityType(), id: this.id, slug };
|
|
179
|
+
return this.callIsConnected(() => this.endpointApi.updateBlockSlug(data));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Mettre à jour l'image de profil : Permet de mettre à jour l'image de profil d'un utilisateur ou d'une entité.
|
|
184
|
+
* Constant : PROFIL_IMAGE
|
|
185
|
+
*/
|
|
186
|
+
async updateImageProfil(image) {
|
|
187
|
+
image = await this.validateImage(image);
|
|
188
|
+
const data = { pathParams: { folder: this.getEntityType(), ownerId: this.id }, profil_avatar: image };
|
|
189
|
+
return this.callIsConnected(() => this.endpointApi.profilImage(data));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Récupérer les actualités : Récupère la liste d’actualités selon plusieurs critères.
|
|
194
|
+
* Constant : GET_NEWS
|
|
195
|
+
* @param {Object} data - Les données à envoyer.
|
|
196
|
+
* @param {number} data.dateLimit - Limite de date timestamp ou 0 (default: 0)
|
|
197
|
+
* @param {object} data.search - data.search
|
|
198
|
+
* @param {string} data.search.name - Nom ou terme recherché (default: "")
|
|
199
|
+
* @param {number} data.indexStep - Nombre de résultats par page (default: 12)
|
|
200
|
+
* @returns {Promise<Object>} - Les données de réponse.
|
|
201
|
+
* @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
|
|
202
|
+
* @throws {Error} - En cas d'erreur inattendue.
|
|
203
|
+
*/
|
|
204
|
+
async getNews(data = {}) {
|
|
205
|
+
data.pathParams = { type: this.getEntityType(), id: this.id };
|
|
206
|
+
const arrayObjetNews = await this.endpointApi.getNews(data);
|
|
207
|
+
if(!Array.isArray(arrayObjetNews)){
|
|
208
|
+
throw new ApiResponseError("Erreur lors de la récupération des actualités.", 500, arrayObjetNews);
|
|
209
|
+
}
|
|
210
|
+
const rawNewsList = arrayObjetNews.map((newsData) =>
|
|
211
|
+
News.fromServerData(newsData, this, { User, EndpointApi: this.deps.EndpointApi })
|
|
212
|
+
);
|
|
213
|
+
return this._createFilteredProxy(rawNewsList);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async news(newsData) {
|
|
217
|
+
try {
|
|
218
|
+
const news = new News(this, newsData, { User, EndpointApi : this.deps.EndpointApi });
|
|
219
|
+
if (newsData.id) {
|
|
220
|
+
await news.get();
|
|
221
|
+
}
|
|
222
|
+
return news;
|
|
223
|
+
} catch (error) {
|
|
224
|
+
console.error("[Api.project.news] Erreur lors de la création d'une instance news :", error.message);
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
75
229
|
}
|
|
76
230
|
|
|
77
231
|
// Incorporation du mixin dans Organization
|
|
78
|
-
Object.assign(Organization.prototype, EntityMixin);
|
|
232
|
+
Object.assign(Organization.prototype, EntityMixin, UtilMixin, NewsMixin);
|
|
79
233
|
|
package/src/api/Project.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ApiResponseError } from "../error.js";
|
|
2
|
+
import { News } from "./News.js";
|
|
3
|
+
import { User } from "./User.js";
|
|
4
|
+
import { EntityMixin } from "../mixin/EntityMixin.js";
|
|
5
|
+
import { NewsMixin } from "../mixin/NewsMixin.js";
|
|
6
|
+
import { UtilMixin } from "../mixin/UtilMixin.js";
|
|
2
7
|
|
|
3
8
|
// Project.js
|
|
4
9
|
export class Project {
|
|
@@ -11,13 +16,29 @@ export class Project {
|
|
|
11
16
|
* Crée une instance de Project.
|
|
12
17
|
* @param {ApiClient} apiClient - L'instance d'ApiClient.
|
|
13
18
|
* @param {Object} identifier - Objet contenant { id } ou { slug }.
|
|
19
|
+
* @param {Object} [deps={}] - Dépendances injectées (ex: User).
|
|
20
|
+
* @param {EndpointApi} deps.EndpointApi - Classe EndpointApi pour éviter les dépendances circulaires.
|
|
14
21
|
*/
|
|
15
22
|
|
|
16
|
-
constructor(apiClient, { id, slug } = {}) {
|
|
23
|
+
constructor(apiClient, { id, slug } = {}, deps = {}) {
|
|
24
|
+
if(!deps.EndpointApi){
|
|
25
|
+
throw new Error("EndpointApi class must be injected to avoid circular dependency.");
|
|
26
|
+
}
|
|
17
27
|
if (!id && !slug) {
|
|
18
|
-
throw new Error("Vous devez fournir un id ou un slug pour créer
|
|
28
|
+
throw new Error("Vous devez fournir un id ou un slug pour créer une instance Project.");
|
|
19
29
|
}
|
|
20
30
|
this.apiClient = apiClient;
|
|
31
|
+
this.deps = deps;
|
|
32
|
+
|
|
33
|
+
// Gérer les deux cas : fonction constructeur ou instance
|
|
34
|
+
if (typeof deps.EndpointApi === "function") {
|
|
35
|
+
this.endpointApi = new deps.EndpointApi(this.apiClient);
|
|
36
|
+
} else if (typeof deps.EndpointApi === "object") {
|
|
37
|
+
this.endpointApi = deps.EndpointApi;
|
|
38
|
+
} else {
|
|
39
|
+
throw new Error("deps.EndpointApi doit être une classe ou une instance valide.");
|
|
40
|
+
}
|
|
41
|
+
|
|
21
42
|
this.#id = id || null;
|
|
22
43
|
this.#slug = slug || null;
|
|
23
44
|
}
|
|
@@ -26,6 +47,10 @@ export class Project {
|
|
|
26
47
|
get id() {
|
|
27
48
|
return this.#id;
|
|
28
49
|
}
|
|
50
|
+
|
|
51
|
+
_id(newId) {
|
|
52
|
+
this.#id = newId;
|
|
53
|
+
}
|
|
29
54
|
|
|
30
55
|
get slug() {
|
|
31
56
|
return this.#slug;
|
|
@@ -64,16 +89,146 @@ export class Project {
|
|
|
64
89
|
*
|
|
65
90
|
* @returns {Promise<Object>} Le profil complet.
|
|
66
91
|
*/
|
|
67
|
-
async
|
|
92
|
+
async getProfil() {
|
|
68
93
|
return this.apiClient.safeCall(async () => {
|
|
69
|
-
const
|
|
70
|
-
this._setData(
|
|
71
|
-
return
|
|
94
|
+
const data = await this.getPublicProfile();
|
|
95
|
+
this._setData(data);
|
|
96
|
+
return data;
|
|
72
97
|
});
|
|
73
98
|
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Mettre à jour les paramètres d'un élément : Mise à jour des paramètres spécifiques d'un élément.
|
|
102
|
+
* Constant : UPDATE_SETTINGS
|
|
103
|
+
* @param {Object} data - Les données à envoyer.
|
|
104
|
+
* @param {string} data.type - data.type
|
|
105
|
+
* @param {undefined} data.value - data.value
|
|
106
|
+
* @returns {Promise<Object>} - Les données de réponse.
|
|
107
|
+
* @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
|
|
108
|
+
* @throws {ApiAuthenticationError} - En cas d'erreur d'authentification.
|
|
109
|
+
* @throws {Error} - En cas d'erreur inattendue.
|
|
110
|
+
*/
|
|
111
|
+
async updateSettings(data = {}) {
|
|
112
|
+
data.idEntity = this.id;
|
|
113
|
+
data.typeEntity = this.getEntityType();
|
|
114
|
+
return this.callIsConnected(() => this.endpointApi.updateSettings(data));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Mettre à jour la description d'un élément : Permet de mettre à jour la description courte et complète d'un élément.
|
|
119
|
+
* Constant : UPDATE_BLOCK_DESCRIPTION
|
|
120
|
+
* @param {Object} data - Les données à envoyer.
|
|
121
|
+
* @param {string} data.descMentions - Mentions dans la description (default: "")
|
|
122
|
+
* @param {string} data.shortDescription - Courte description
|
|
123
|
+
* @param {string} data.description - Description complète
|
|
124
|
+
* @returns {Promise<Object>} - Les données de réponse.
|
|
125
|
+
* @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
|
|
126
|
+
* @throws {ApiAuthenticationError} - En cas d'erreur d'authentification.
|
|
127
|
+
* @throws {Error} - En cas d'erreur inattendue.
|
|
128
|
+
*/
|
|
129
|
+
async updateDescription(data = {}) {
|
|
130
|
+
data.typeElement = this.getEntityType();
|
|
131
|
+
data.id = this.id;
|
|
132
|
+
return this.callIsConnected(() => this.endpointApi.updateBlockDescription(data));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Mettre à jour les informations d'un élément : Permet de mettre à jour les informations générales d'un élément (nom, contacts, etc.).
|
|
138
|
+
* Constant : UPDATE_BLOCK_INFO
|
|
139
|
+
*/
|
|
140
|
+
async updateInfo(data = {}) {
|
|
141
|
+
data.typeElement = this.getEntityType();
|
|
142
|
+
data.id = this.id;
|
|
143
|
+
return this.callIsConnected(() => this.endpointApi.updateBlockInfo(data));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Mettre à jour les réseaux sociaux d'un élément : Permet de mettre à jour les liens vers les réseaux sociaux d'un élément.
|
|
148
|
+
* Constant : UPDATE_BLOCK_SOCIAL
|
|
149
|
+
*/
|
|
150
|
+
async updateSocial(data = {}) {
|
|
151
|
+
data.typeElement = this.getEntityType();
|
|
152
|
+
data.id = this.id;
|
|
153
|
+
return this.callIsConnected(() => this.endpointApi.updateBlockSocial(data));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Mettre à jour les localités d'un élément : Permet de mettre à jour l'adresse et les informations géographiques d'un élément.
|
|
158
|
+
* Constant : UPDATE_BLOCK_LOCALITY
|
|
159
|
+
*/
|
|
160
|
+
async updateLocality(data = {}) {
|
|
161
|
+
data.typeElement = this.getEntityType();
|
|
162
|
+
data.id = this.id;
|
|
163
|
+
return this.callIsConnected(() => this.endpointApi.updateBlockLocality(data));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Mettre à jour le slug d'un élément : Permet de mettre à jour le slug pour une URL simplifiée.
|
|
168
|
+
* Constant : UPDATE_BLOCK_SLUG
|
|
169
|
+
*/
|
|
170
|
+
async updateSlug(slug) {
|
|
171
|
+
try {
|
|
172
|
+
await this.endpointApi.check({ slug });
|
|
173
|
+
} catch (error) {
|
|
174
|
+
if(error instanceof ApiResponseError) {
|
|
175
|
+
throw new ApiResponseError("Erreur lors de la vérification du slug.", error.status, error.data);
|
|
176
|
+
}
|
|
177
|
+
throw error;
|
|
178
|
+
}
|
|
179
|
+
const data = { typeElement: this.getEntityType(), id: this.id, slug };
|
|
180
|
+
return this.callIsConnected(() => this.endpointApi.updateBlockSlug(data));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Mettre à jour l'image de profil : Permet de mettre à jour l'image de profil d'un utilisateur ou d'une entité.
|
|
185
|
+
* Constant : PROFIL_IMAGE
|
|
186
|
+
*/
|
|
187
|
+
async updateImageProfil(image) {
|
|
188
|
+
image = await this.validateImage(image);
|
|
189
|
+
const data = { pathParams: { folder: this.getEntityType(), ownerId: this.id }, profil_avatar: image };
|
|
190
|
+
return this.callIsConnected(() => this.endpointApi.profilImage(data));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Récupérer les actualités : Récupère la liste d’actualités selon plusieurs critères.
|
|
195
|
+
* Constant : GET_NEWS
|
|
196
|
+
* @param {Object} data - Les données à envoyer.
|
|
197
|
+
* @param {number} data.dateLimit - Limite de date timestamp ou 0 (default: 0)
|
|
198
|
+
* @param {object} data.search - data.search
|
|
199
|
+
* @param {string} data.search.name - Nom ou terme recherché (default: "")
|
|
200
|
+
* @param {number} data.indexStep - Nombre de résultats par page (default: 12)
|
|
201
|
+
* @returns {Promise<Object>} - Les données de réponse.
|
|
202
|
+
* @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
|
|
203
|
+
* @throws {Error} - En cas d'erreur inattendue.
|
|
204
|
+
*/
|
|
205
|
+
async getNews(data = {}) {
|
|
206
|
+
data.pathParams = { type: this.getEntityType(), id: this.id };
|
|
207
|
+
const arrayObjetNews = await this.endpointApi.getNews(data);
|
|
208
|
+
if(!Array.isArray(arrayObjetNews)){
|
|
209
|
+
throw new ApiResponseError("Erreur lors de la récupération des actualités.", 500, arrayObjetNews);
|
|
210
|
+
}
|
|
211
|
+
const rawNewsList = arrayObjetNews.map((newsData) =>
|
|
212
|
+
News.fromServerData(newsData, this, { User, EndpointApi: this.deps.EndpointApi })
|
|
213
|
+
);
|
|
214
|
+
return this._createFilteredProxy(rawNewsList);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async news(newsData) {
|
|
218
|
+
try {
|
|
219
|
+
const news = new News(this, newsData, { User, EndpointApi : this.deps.EndpointApi });
|
|
220
|
+
if (newsData.id) {
|
|
221
|
+
await news.get();
|
|
222
|
+
}
|
|
223
|
+
return news;
|
|
224
|
+
} catch (error) {
|
|
225
|
+
console.error("[Api.project.news] Erreur lors de la création d'une instance news :", error.message);
|
|
226
|
+
throw error;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
74
229
|
|
|
75
230
|
}
|
|
76
231
|
|
|
77
232
|
// Incorporation du mixin dans Project
|
|
78
|
-
Object.assign(Project.prototype, EntityMixin);
|
|
233
|
+
Object.assign(Project.prototype, EntityMixin, UtilMixin, NewsMixin);
|
|
79
234
|
|