@communecter/cocolight-api-client 1.0.196 → 1.0.197

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@communecter/cocolight-api-client",
3
- "version": "1.0.196",
3
+ "version": "1.0.197",
4
4
  "description": "Client Axios simplifié pour l'API cocolight",
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,6 +22,45 @@ export interface AnswerChange {
22
22
  mutationType: "create" | "update" | "";
23
23
  changedFields: string[];
24
24
  }
25
+ /**
26
+ * Résultat d'un {@link Answer#addVote} — le backend BASCULE : re-poster le
27
+ * MÊME statut RETIRE la réaction au lieu d'en poser une seconde.
28
+ *
29
+ * Distinguer les deux cas se lit sur `inc` (`+1` ajout / `-1` retrait) ou, de
30
+ * façon non ambiguë, sur la présence de `removedVoteStatus` — `msg` ne sert à
31
+ * rien pour ça : il vaut `"Reaction succesfully saved"` à l'ajout mais la
32
+ * chaîne VIDE au retrait.
33
+ */
34
+ export interface AnswerVoteResult {
35
+ result: boolean;
36
+ userActionSaved?: boolean;
37
+ /** `+1` réaction posée, `-1` réaction retirée. */
38
+ inc?: number;
39
+ /** `""` au retrait, message traduit à l'ajout. */
40
+ msg?: string;
41
+ /** Présent UNIQUEMENT au retrait : le statut qui vient d'être enlevé. */
42
+ removedVoteStatus?: string;
43
+ user?: Record<string, unknown>;
44
+ element?: Record<string, unknown>;
45
+ [key: string]: unknown;
46
+ }
47
+ /**
48
+ * Résultat d'un {@link Answer#getVotes} — document projeté `{_id, vote, voteCount}`.
49
+ * Chaque entrée de `vote` est enrichie du profil du votant (`name`, `slug`,
50
+ * `profilThumbImageUrl`), ou vaut `null` si l'élément référencé est introuvable.
51
+ */
52
+ export interface AnswerVotesResult {
53
+ vote?: Record<string, {
54
+ status?: string;
55
+ date?: unknown;
56
+ name?: string;
57
+ slug?: string;
58
+ profilThumbImageUrl?: string;
59
+ [key: string]: unknown;
60
+ } | null>;
61
+ voteCount?: Record<string, number>;
62
+ [key: string]: unknown;
63
+ }
25
64
  /** Options de `Answer.generateProject()` — équivalent `costum.contextId`/`costum.contextType` legacy. */
26
65
  export interface GenerateProjectOptions {
27
66
  /** ID de l'entité parente (org/site porteur de l'appel). */
@@ -374,6 +413,56 @@ export declare class Answer extends BaseEntity<AnswerItemNormalized> {
374
413
  * await answer.delete();
375
414
  */
376
415
  delete(reason?: string): Promise<void>;
416
+ /**
417
+ * Ajoute OU retire une réaction sur cette réponse (`co2/action/addaction`,
418
+ * `collection: "answers"`).
419
+ *
420
+ * **Un seul appel pour les deux sens** : le backend bascule. Poster un statut
421
+ * que l'utilisateur n'a pas encore posé l'ajoute (`inc: +1`) ; re-poster le
422
+ * MÊME statut le retire (`inc: -1` + `removedVoteStatus`). Poster un statut
423
+ * DIFFÉRENT remplace le précédent. Il n'existe donc pas d'endpoint de
424
+ * suppression distinct — cf. {@link AnswerVoteResult}.
425
+ *
426
+ * Les compteurs vivent dans `serverData.voteCount` (map `statut → entier`) et
427
+ * le détail par utilisateur dans `serverData.vote` (map `userId → {status, date}`) ;
428
+ * ni l'un ni l'autre n'est renvoyé au serveur au save (`removeFields`).
429
+ * Cette instance n'est PAS resynchronisée : relire via {@link Answer#getVotes}.
430
+ *
431
+ * Droits : le serveur ne vérifie QUE la session (`AddActionAction`). N'importe quel utilisateur
432
+ * connecté peut réagir sur n'importe quelle réponse, y compris d'un formulaire auquel il n'a pas
433
+ * accès — c'est à l'appelant de n'offrir la réaction que là où elle a du sens.
434
+ *
435
+ * @param status - Statut de la réaction (`"like"`, `"love"`, `"sad"`…). Libre côté backend, mais
436
+ * non vide : il devient un nom de champ (`voteCount.<status>`), et un nom vide fait
437
+ * échouer l'écriture Mongo.
438
+ * @returns Réponse API, dont `inc` et `removedVoteStatus` disent le sens de la bascule.
439
+ * @throws {ApiError} 404 si la réponse n'a pas d'id (jamais sauvegardée) ; 400 statut vide.
440
+ *
441
+ * @example
442
+ * const res = await answer.addVote("like");
443
+ * const retiree = res.removedVoteStatus !== undefined; // true = réaction ENLEVÉE
444
+ */
445
+ addVote(status: string): Promise<AnswerVoteResult>;
446
+ /**
447
+ * Récupère les réactions posées sur cette réponse.
448
+ *
449
+ * Wrap de `SHOW_VOTE` avec auto-injection du `type` (`"answers"`) et de
450
+ * `this.id` dans `pathParams`. Le retour contient `vote` (réactions
451
+ * individuelles indexées par userId, enrichies du profil du votant) et
452
+ * `voteCount` (compteurs par statut).
453
+ *
454
+ * Endpoint PUBLIC : les réactions et le profil des votants se lisent sans session.
455
+ *
456
+ * @returns Réponse API : `{ _id, vote, voteCount }` ou variante d'erreur — ou `null` quand l'id ne
457
+ * désigne aucune réponse (le legacy renvoie le `findOne` tel quel).
458
+ * @throws {ApiError} 404 si la réponse n'a pas d'id (jamais sauvegardée).
459
+ *
460
+ * @example
461
+ * const votes = await answer.getVotes();
462
+ * votes?.voteCount?.like; // nombre de "like"
463
+ * votes?.vote?.[userId]?.status === "like"; // l'utilisateur a-t-il réagi ?
464
+ */
465
+ getVotes(): Promise<AnswerVotesResult | null>;
377
466
  /**
378
467
  * {@inheritDoc BaseEntity#deleteFile}
379
468
  *
@@ -1,6 +1,7 @@
1
1
  import type { UpdateSettingsData, UpdateBlockDescriptionData, UpdateBlockInfoData, UpdateBlockSocialData, UpdateBlockLocalityData, GetNewsData, GetGalleryData, GlobalAutocompleteCostumData, CostumEventRequestActorsData, CostumEventRequestSubeventsData, CostumEventRequestDatesData, CostumEventRequestElementEventData, CostumEventRequestCategoriesData, CostumEventRequestEventData, CostumEventRequestLinkTlToEventData, CostumEventRequestLoadContextTagData, GetOrganizationsAdminData, GetOrganizationsNoAdminData, GetProjectsAdminData, GetProjectsNoAdminData, GetPoisAdminData, GetPoisNoAdminData, GetSubscribersData, GetBadgesData, CoformAnswersSearchData, SearchMemberAutocompleteData, GetEventsData, SearchEventsCostumData, CostumFilterCoformData, CostumFilterCoformByPathData, GetCountriesData, SearchZonesData, ZoneGetShapeData, ZoneGetZonirisData, CoformAnswersByFormsData, FundingEnvelopeData, CoremuOperationData, UpdatePathValueData } from "./EndpointApi.types.js";
2
2
  import type { CostumRuntimeContext } from "../costum/runtime.js";
3
3
  import type { TransformsMap } from "../types/entities.js";
4
+ import type { AmpliParentType, CreateAmpliInput, CreateAmpliResult, RemoveAmpliResult } from "./serverDataType/Ampli.js";
4
5
  import type { CountryItem } from "./serverDataType/Country.js";
5
6
  import type { ToolEnrichmentInput, ToolEnrichmentResult, CommunListItem } from "./serverDataType/ToolsCatalog.js";
6
7
  import type { ZoneItemNormalized, ZoneShapeItem, ZonirisShapeItem } from "./serverDataType/Zone.js";
@@ -2692,6 +2693,75 @@ export declare class BaseEntity<TServerData = any> {
2692
2693
  * costum peut être un projet). `formId` en argument positionnel. Retourne le tableau NU.
2693
2694
  */
2694
2695
  getCommunList(formId: string): Promise<CommunListItem[]>;
2696
+ /**
2697
+ * Contexte de l'élément PORTEUR du costum, tel que les deux actions ampli l'exigent.
2698
+ *
2699
+ * Volontairement PAS `_withCostumContext` : ces actions ne lisent ni `contextId` ni `sourceKey`,
2700
+ * elles nomment les mêmes valeurs `parentId`/`parentType`/`parentName`, et leur contrat est en
2701
+ * `additionalProperties:false` — les alias historiques injectés par le helper y seraient rejetés
2702
+ * par l'AJV du client avant même l'envoi.
2703
+ *
2704
+ * Lit `serverData` et non le brouillon : le serveur relit l'élément en base (`PHDB::findOne`),
2705
+ * un slug modifié mais non sauvegardé désignerait un costum qui n'existe pas.
2706
+ */
2707
+ protected _requireAmpliHost(): {
2708
+ id: string;
2709
+ type: AmpliParentType;
2710
+ slug: string;
2711
+ };
2712
+ /**
2713
+ * Crée un **ampli** sur cette entité : une entrée de `costum.ampli`, l'espace de propositions du
2714
+ * costum qu'elle porte.
2715
+ *
2716
+ * BEARER + gate admin serveur (`isInterfaceAdmin`). Porté par `BaseEntity` — comme
2717
+ * {@link saveToolEnrichment} — parce que l'hôte d'un costum peut être une organisation, un
2718
+ * projet, un citoyen ou un événement, et qu'un ampli n'est pas une entité mais une clé de costum.
2719
+ *
2720
+ * DEUX MODES, exclusifs, distingués par la présence de `coform` :
2721
+ * - sans `coform` (défaut) : le serveur crée le `Form` de dépôt et ses cinq questions, et renvoie
2722
+ * les chemins obtenus dans `ampli.path` ;
2723
+ * - avec `coform` : rattachement à un formulaire existant, `namePath` et `addressPath` exigés.
2724
+ *
2725
+ * ⚠ Le serveur dérive la CLÉ de l'entrée du `name` et **écrase** une entrée de même clé, sans
2726
+ * garde. Un appelant qui a déjà la liste des amplis doit tester la collision avec le helper `ampliSlug`.
2727
+ *
2728
+ * Le cache costum est réinitialisé côté serveur après écriture : `element/about` renvoie le nouvel
2729
+ * ampli immédiatement, sans `resetcache`.
2730
+ *
2731
+ * Exige `CreateAmpliAction` de modules/costum@3ef97ef28 ou postérieur (lecture de `source`, clé
2732
+ * `slugifyLikeJS`, réponse `{slug, ampli}`). Face à une version antérieure, l'action écrit tout le
2733
+ * parcours Co et répond sans `slug` : la méthode lève alors au lieu de rendre un résultat incomplet.
2734
+ *
2735
+ * @param input - Nom, description, mots-clés, et le formulaire en mode B.
2736
+ * @returns `{ result, slug, ampli, … }` — `slug` permet d'atteindre `/ampli/<slug>` sans recharger.
2737
+ * @throws {ApiError} 404 entité non enregistrée ; 400 slug manquant, hôte de type impossible,
2738
+ * nom inexploitable, ou mode B incomplet.
2739
+ * @throws {ApiResponseError} Refus métier du serveur (droits, paramètre manquant) — il arrive en
2740
+ * HTTP 200 `{result:false}`, que `checkAndThrowApiResponseError` convertit en exception —, ou
2741
+ * réponse sans `slug` (action legacy antérieure au patch).
2742
+ *
2743
+ * @example
2744
+ * const { slug } = await orga.createAmpli({ name: "Idées d'été", tags: ["proposition"] });
2745
+ * // → navigation vers `/ampli/idees-d-ete`
2746
+ */
2747
+ createAmpli(input: CreateAmpliInput): Promise<CreateAmpliResult>;
2748
+ /**
2749
+ * Supprime un ampli de `costum.ampli`, avec ses pages CMS et son bouton de menu s'il en a.
2750
+ *
2751
+ * ⚠ DEUX EFFETS DE BORD du legacy, non corrigés ici :
2752
+ * - le `Form` de dépôt et ses réponses **survivent** : un ampli créé en mode A puis supprimé
2753
+ * laisse son formulaire derrière lui ;
2754
+ * - l'action réécrit `costum.app` et le `buttonList` du menu à partir du costum **résolu en
2755
+ * cache** (`Costum::init`), pas du sous-document en base. Pour un costum dont la config vient
2756
+ * d'un fichier JSON, la suppression matérialise donc cette config dans le document de l'hôte.
2757
+ *
2758
+ * @param ampliId - La CLÉ de l'entrée, lue dans `costum.ampli` ou renvoyée par `createAmpli` — pas
2759
+ * un ObjectId, et jamais un slug recalculé depuis le nom : les entrées anciennes ont une clé
2760
+ * d'une autre forme (`idées-d'été`), que `ampliSlug` ne reproduit pas.
2761
+ * @throws {ApiError} 404 entité non enregistrée ; 400 slug manquant ou hôte de type impossible.
2762
+ * @throws {ApiResponseError} `Ampli not found`, `ampliId is required`, ou refus de droits.
2763
+ */
2764
+ removeAmpli(ampliId: string): Promise<RemoveAmpliResult>;
2695
2765
  /**
2696
2766
  * @param data
2697
2767
  * Paramètres de recherche (partiels — les valeurs manquantes sont complétées
@@ -1,5 +1,5 @@
1
1
  import type ApiClient from "../ApiClient.js";
2
- import type { DocumentListData, PersonRegisterData, AuthenticateUrlData, RefreshTokenUrlData, PasswordRecoveryData, PasswordResetData, ServerExchangeTokenData, ChangePasswordData, DeleteAccountData, UpdateSettingsData, UpdateBlockDescriptionData, UpdateBlockInfoData, UpdateBlockSocialData, UpdateBlockLocalityData, UpdateBlockSlugData, CheckData, ProfilImageData, ProfilBannerData, GetElementsAboutData, MulticonnectData, RelaunchInvitationData, ContactSendData, GetNewsData, GetNewsByIdData, AddNewsData, AddImageNewsData, AddFileNewsData, DeleteNewsData, UpdateNewsData, ShareNewsData, GetCommentsData, AddCommentsData, DeleteCommentsData, UpdateCommentsData, SearchTagsData, ShowVoteData, GlobalAutocompleteData, CityAutocompleteData, CityAutocompleteByCountryData, SuggestionInputData, GetProjectsNoAdminData, GetProjectsAdminData, GetPoisNoAdminData, GetPoisAdminData, GlobalAutocompleteAdminCostumData, GetOrganizationsNoAdminData, GetOrganizationsAdminData, GetUserEligiblePlacesData, GetMembersNoAdminData, GetMembersAdminData, GetFriendsAdminData, GetSubscriptionsData, GetSubscriptionsAdminData, GetSubscribersData, GetSubscribersAdminData, GetContributorsNoAdminData, GetContributorsAdminData, GetBadgesData, GetBadgesFiltersData, ConnectData, LinkSetRolesData, CreateInvitationLinkData, ConnectByRefData, DisconnectData, GetElementsKeyData, GetFavorisData, DeleteFavorisData, AddFavorisData, AddOrganizationData, AddProjectData, AddPoiData, AddEventData, DeleteElementData, AddImageElementData, LinkValidateData, SearchMemberAutocompleteData, GetNotificationsData, GetNotificationsCountData, NotificationUpdateData, MarkNotificationAsReadData, ActivitypubSearchData, ActivitypubLinkData, ActivitypubGetCommunityData, GetBadgeData, AddBadgesData, AssignBadgesData, GetEventsData, SearchEventsCostumData, ShareEventsData, InviteMembersData, FollowData, GetCostumJsonData, GlobalAutocompleteCostumData, NavigatorGettlData, NavigatorGetRessourceTlData, CostumEventRequestActorsData, CostumEventRequestSubeventsData, CostumEventRequestElementEventData, CostumEventRequestCategoriesData, CostumEventRequestDatesData, CostumEventRequestEventData, CostumEventRequestLinkTlToEventData, CostumEventRequestLoadContextTagData, AgendaGetPdfData, GetGalleryData, GetAttendeesNoAdminData, GetAttendeesAdminData, CoformAnswersSearchData, CoformAnswersByIdData, GetCoformByIdData, CoformUploadAnswerFileData, DeleteCoformAnswerFileData, CoformGetAnswerFilesData, GetCoformCatalogsData, SaveCoformAnswerData, GetCoformAnswerHistoryData, GetCoformMultievalDataData, GetCoformCommontableContributorsData, AddVoteData, AddReportAbuseData, UpdatePathValueData, DeleteDocumentByContextData, DeleteDocumentByIdData, DemoteAdminData, CostumFilterCoformData, CostumFilterCoformByPathData, GetCountriesData, SearchZonesData, CoformAnswersByFormsData, CostumToolsCatalogData, CostumToolUsersData, CostumCommunInfoData, CostumSaveToolEnrichmentData, CostumCommunListData, GenerateAnswerFromFormData, GenerateProjectFromAnswerData, GenerateMilestoneFromDepenseData, FundingEnvelopeData, CoremuOperationData, CoremuAddFinancerData, CoremuPayFinancerData, CoremuValidateFinancerPaymentData, CoremuDeleteFinancerData, CostumProjectActionRequestNewData, CostumProjectActionRequestSetStatusData, CostumProjectActionRequestSetDateData, CostumProjectActionRequestSetContributorsData, CostumProjectActionRequestCancelData, CostumProjectActionRequestArchiveData, LinkDiscourseAccountData, UnlinkDiscourseAccountData, DiscourseProfileData, DiscourseCheckEmailData, DiscourseDismissLinkData, LinkMediawikiAccountData, UnlinkMediawikiAccountData, GetMediawikiContributionsData, AddClassifiedData, PersonActivateData, PersonValidateInvitationData, ValidateInvitationByMailData, ImportPreviewData, ExportElementsData, ImportElementsData, GeocodageData, ValidateGroupData, SetSourceData, TransferSourceCheckData, TransferSourceApplyData, TransferSourceRollbackData, TransferSourceHistoryData, ModerateData, NewsModerateData, CommentModerateData, UploadDocumentData, ZoneGetShapeData, ZoneGetZonirisData, CostumListValuesData, CostumResolvedData, DirectoryProposalData, DirectoryProposalCountData, DirectoryProposalNewCounterData } from "./EndpointApi.types.js";
2
+ import type { DocumentListData, PersonRegisterData, AuthenticateUrlData, RefreshTokenUrlData, PasswordRecoveryData, PasswordResetData, ServerExchangeTokenData, ChangePasswordData, DeleteAccountData, UpdateSettingsData, UpdateBlockDescriptionData, UpdateBlockInfoData, UpdateBlockSocialData, UpdateBlockLocalityData, UpdateBlockSlugData, CheckData, ProfilImageData, ProfilBannerData, GetElementsAboutData, MulticonnectData, RelaunchInvitationData, ContactSendData, GetNewsData, GetNewsByIdData, AddNewsData, AddImageNewsData, AddFileNewsData, DeleteNewsData, UpdateNewsData, ShareNewsData, GetCommentsData, AddCommentsData, DeleteCommentsData, UpdateCommentsData, SearchTagsData, ShowVoteData, GlobalAutocompleteData, CityAutocompleteData, CityAutocompleteByCountryData, SuggestionInputData, GetProjectsNoAdminData, GetProjectsAdminData, GetPoisNoAdminData, GetPoisAdminData, GlobalAutocompleteAdminCostumData, GetOrganizationsNoAdminData, GetOrganizationsAdminData, GetUserEligiblePlacesData, GetMembersNoAdminData, GetMembersAdminData, GetFriendsAdminData, GetSubscriptionsData, GetSubscriptionsAdminData, GetSubscribersData, GetSubscribersAdminData, GetContributorsNoAdminData, GetContributorsAdminData, GetBadgesData, GetBadgesFiltersData, ConnectData, LinkSetRolesData, CreateInvitationLinkData, ConnectByRefData, DisconnectData, GetElementsKeyData, GetFavorisData, DeleteFavorisData, AddFavorisData, AddOrganizationData, AddProjectData, AddPoiData, AddEventData, DeleteElementData, AddImageElementData, LinkValidateData, SearchMemberAutocompleteData, GetNotificationsData, GetNotificationsCountData, NotificationUpdateData, MarkNotificationAsReadData, ActivitypubSearchData, ActivitypubLinkData, ActivitypubGetCommunityData, GetBadgeData, AddBadgesData, AssignBadgesData, GetEventsData, SearchEventsCostumData, ShareEventsData, InviteMembersData, FollowData, GetCostumJsonData, GlobalAutocompleteCostumData, NavigatorGettlData, NavigatorGetRessourceTlData, CostumEventRequestActorsData, CostumEventRequestSubeventsData, CostumEventRequestElementEventData, CostumEventRequestCategoriesData, CostumEventRequestDatesData, CostumEventRequestEventData, CostumEventRequestLinkTlToEventData, CostumEventRequestLoadContextTagData, AgendaGetPdfData, GetGalleryData, GetAttendeesNoAdminData, GetAttendeesAdminData, CoformAnswersSearchData, CoformAnswersByIdData, GetCoformByIdData, CoformUploadAnswerFileData, DeleteCoformAnswerFileData, CoformGetAnswerFilesData, GetCoformCatalogsData, SaveCoformAnswerData, GetCoformAnswerHistoryData, GetCoformMultievalDataData, GetCoformCommontableContributorsData, AddVoteData, AddReportAbuseData, UpdatePathValueData, DeleteDocumentByContextData, DeleteDocumentByIdData, DemoteAdminData, CostumFilterCoformData, CostumFilterCoformByPathData, GetCountriesData, SearchZonesData, CoformAnswersByFormsData, CostumToolsCatalogData, CostumToolUsersData, CostumCommunInfoData, CostumSaveToolEnrichmentData, CostumCommunListData, GenerateAnswerFromFormData, GenerateProjectFromAnswerData, GenerateMilestoneFromDepenseData, FundingEnvelopeData, CoremuOperationData, CoremuAddFinancerData, CoremuPayFinancerData, CoremuValidateFinancerPaymentData, CoremuDeleteFinancerData, CostumProjectActionRequestNewData, CostumProjectActionRequestSetStatusData, CostumProjectActionRequestSetDateData, CostumProjectActionRequestSetContributorsData, CostumProjectActionRequestCancelData, CostumProjectActionRequestArchiveData, LinkDiscourseAccountData, UnlinkDiscourseAccountData, DiscourseProfileData, DiscourseCheckEmailData, DiscourseDismissLinkData, LinkMediawikiAccountData, UnlinkMediawikiAccountData, GetMediawikiContributionsData, AddClassifiedData, PersonActivateData, PersonValidateInvitationData, ValidateInvitationByMailData, ImportPreviewData, ExportElementsData, ImportElementsData, GeocodageData, ValidateGroupData, SetSourceData, TransferSourceCheckData, TransferSourceApplyData, TransferSourceRollbackData, TransferSourceHistoryData, ModerateData, NewsModerateData, CommentModerateData, UploadDocumentData, ZoneGetShapeData, ZoneGetZonirisData, CostumListValuesData, CostumResolvedData, DirectoryProposalData, DirectoryProposalCountData, DirectoryProposalNewCounterData, CostumCreateAmpliData, CostumRemoveAmpliData } from "./EndpointApi.types.js";
3
3
  /**
4
4
  * Classe EndpointApi générée automatiquement depuis endpoints-copie.json
5
5
  */
@@ -395,7 +395,7 @@ export declare class EndpointApi {
395
395
  */
396
396
  searchTags(data: SearchTagsData): Promise<any>;
397
397
  /**
398
- * Afficher les votes d'une actualité/commentaire : Récupère la liste des votes (like, love, etc.) sur une actualité/commentaire.
398
+ * Afficher les votes d'une actualité, d'un commentaire ou d'une réponse de formulaire : Récupère la liste des votes (like, love, etc.) sur une actualité, un commentaire ou une réponse de formulaire (coform).
399
399
  * Constant : SHOW_VOTE
400
400
  * @param data - Données envoyées à l'API
401
401
  * @returns Les données de réponse.
@@ -1201,7 +1201,7 @@ export declare class EndpointApi {
1201
1201
  */
1202
1202
  getCoformCommontableContributors(data: GetCoformCommontableContributorsData): Promise<any>;
1203
1203
  /**
1204
- * Voter sur un élément (commentaire ou news) : Permet de voter sur un commentaire ou une news en spécifiant un statut de vote
1204
+ * Voter sur un élément (commentaire, news ou réponse de formulaire) : Permet de voter sur un commentaire, une news ou une réponse de formulaire (coform) en spécifiant un statut de vote. Re-poster le MÊME statut retire le vote (bascule) : la réponse porte alors removedVoteStatus et inc:-1.
1205
1205
  * Constant : ADD_VOTE
1206
1206
  * @param data - Données envoyées à l'API
1207
1207
  * @returns Les données de réponse.
@@ -1816,5 +1816,25 @@ export declare class EndpointApi {
1816
1816
  * @throws {Error} - En cas d'erreur inattendue.
1817
1817
  */
1818
1818
  directoryProposalNewCounter(data: DirectoryProposalNewCounterData): Promise<any>;
1819
+ /**
1820
+ * Créer un ampli : Crée une entrée dans costum.ampli de l'élément porteur du costum. Avec source=site-json aucune page CMS, aucun bloc cms ni bouton de menu n'est écrit. Gate isInterfaceAdmin, résolu par costumSlug (refus en HTTP 200 result:false). Le cache costum est réinitialisé après écriture : element/about renvoie le nouvel ampli immédiatement.
1821
+ * Constant : COSTUM_CREATE_AMPLI
1822
+ * @param data - Données envoyées à l'API
1823
+ * @returns Les données de réponse.
1824
+ * @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
1825
+ * @throws {ApiAuthenticationError} - En cas d'erreur d'authentification.
1826
+ * @throws {Error} - En cas d'erreur inattendue.
1827
+ */
1828
+ costumCreateAmpli(data: CostumCreateAmpliData): Promise<any>;
1829
+ /**
1830
+ * Supprimer un ampli : Retire une entrée de costum.ampli, ses pages CMS et son bouton de menu s'il en a. Ne supprime NI le Form NI ses réponses. Gate isInterfaceAdmin (refus en HTTP 200 result:false).
1831
+ * Constant : COSTUM_REMOVE_AMPLI
1832
+ * @param data - Données envoyées à l'API
1833
+ * @returns Les données de réponse.
1834
+ * @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
1835
+ * @throws {ApiAuthenticationError} - En cas d'erreur d'authentification.
1836
+ * @throws {Error} - En cas d'erreur inattendue.
1837
+ */
1838
+ costumRemoveAmpli(data: CostumRemoveAmpliData): Promise<any>;
1819
1839
  }
1820
1840
  export default EndpointApi;
@@ -1118,9 +1118,9 @@ export interface SearchTagsData {
1118
1118
  export interface ShowVoteData {
1119
1119
  pathParams?: {
1120
1120
  /**
1121
- * Type de l'élément
1121
+ * Type de l'élément (collection Mongo)
1122
1122
  */
1123
- type: "news" | "comments";
1123
+ type: "news" | "comments" | "answers";
1124
1124
  /**
1125
1125
  * ID de l'élément dont on veut récupérer les votes
1126
1126
  */
@@ -6203,20 +6203,20 @@ export interface GetCoformCommontableContributorsData {
6203
6203
  }
6204
6204
  export interface AddVoteData {
6205
6205
  /**
6206
- * ID de l'élément (commentaire ou news) sur lequel voter
6206
+ * ID de l'élément (commentaire, news ou réponse de formulaire) sur lequel voter
6207
6207
  */
6208
6208
  id: string;
6209
6209
  /**
6210
- * Type de collection concernée
6210
+ * Type de collection concernée. `answers` = réponse de formulaire coform (Action.php lit la collection sans liste blanche : seule l'action est restreinte).
6211
6211
  */
6212
- collection: "comments" | "news";
6212
+ collection: "comments" | "news" | "answers";
6213
6213
  /**
6214
6214
  * Type d'action à effectuer (vote)
6215
6215
  */
6216
6216
  action: "vote";
6217
6217
  details: {
6218
6218
  /**
6219
- * Statut du vote (ex: 'like', 'dislike', etc.)
6219
+ * Statut du vote (ex: 'like', 'dislike', etc.). Non vide : il devient un nom de champ (voteCount.<status>), un nom vide fait échouer l'écriture Mongo (legacy comme Node).
6220
6220
  */
6221
6221
  status: string;
6222
6222
  };
@@ -8123,3 +8123,89 @@ export interface DirectoryProposalNewCounterData {
8123
8123
  };
8124
8124
  [k: string]: unknown;
8125
8125
  }
8126
+ export interface CostumCreateAmpliData {
8127
+ /**
8128
+ * Origine de l'appel, matérialisée par AJV (useDefaults) : l'appelant n'a pas à la poser. Seules 'co' (interface Communecter) et 'site-json' sont acceptées serveur ; 'co' n'est PAS au contrat car elle génère les pages CMS du parcours Co.
8129
+ */
8130
+ source: "site-json";
8131
+ /**
8132
+ * Nom affiché. Le serveur en dérive la CLÉ de l'entrée (InflectorHelper::slugifyLikeJS : accents retirés, non-alphanumériques en tirets, minuscules). Un nom qui ne produit aucun slug exploitable ('' ou 'n-a') est refusé. ATTENTION : un slug déjà pris ÉCRASE l'entrée existante, aucune garde serveur.
8133
+ */
8134
+ name: string;
8135
+ /**
8136
+ * Markdown, stocké tel quel.
8137
+ */
8138
+ description?: string;
8139
+ /**
8140
+ * Sérialisé tags[]=a&tags[]=b, relu en tableau par PHP. Vides et doublons retirés côté serveur.
8141
+ */
8142
+ tags?: string[];
8143
+ /**
8144
+ * ObjectId de l'élément porteur du costum.
8145
+ */
8146
+ parentId: string;
8147
+ /**
8148
+ * Collection de l'élément porteur du costum.
8149
+ */
8150
+ parentType: "organizations" | "projects" | "citoyens" | "events";
8151
+ /**
8152
+ * Slug de l'élément porteur : préfixe des identifiants du formulaire généré en MODE A, et nom du parent du Form créé.
8153
+ */
8154
+ parentName: string;
8155
+ /**
8156
+ * Slug de l'élément porteur du costum. REQUIS pour le gate : isInterfaceAdmin() est appelé sans id ni type, il n'accepte qu'un super-admin ou un admin du costum RÉSOLU — et beforeAction → costumCacheParams() ne résout le costum que si $_POST[costumSlug] est présent. Sans lui, un admin de costum ordinaire reçoit « You don't have the right to access this feature ».
8157
+ */
8158
+ costumSlug: string;
8159
+ /**
8160
+ * MODE A : le serveur crée le Form et son sous-formulaire (titre, description, adresse, mots-clés, image) et renvoie les chemins obtenus. Exclusif de coform/*Path. Durci serveur par filter_var(FILTER_VALIDATE_BOOLEAN) : la chaîne 'false' du fil form-urlencoded est bien lue comme faux.
8161
+ */
8162
+ new?: boolean;
8163
+ /**
8164
+ * MODE B : ObjectId du Form existant à rattacher. Exige namePath et addressPath non vides.
8165
+ */
8166
+ coform?: string;
8167
+ /**
8168
+ * MODE B, requis : chemin <idSousFormulaire>.<idQuestion> (SANS le préfixe answers.) de la question titre.
8169
+ */
8170
+ namePath?: string;
8171
+ /**
8172
+ * MODE B : chemin de la question description.
8173
+ */
8174
+ descriptionPath?: string;
8175
+ /**
8176
+ * MODE B, requis : chemin de la question adresse.
8177
+ */
8178
+ addressPath?: string;
8179
+ /**
8180
+ * MODE B : chemin de la question mots-clés.
8181
+ */
8182
+ tagsPath?: string;
8183
+ /**
8184
+ * MODE B : chemin de la question image.
8185
+ */
8186
+ imagePath?: string;
8187
+ /**
8188
+ * MODE B : chemin du finder. Toujours '' en MODE A.
8189
+ */
8190
+ finderPath?: string;
8191
+ [k: string]: unknown;
8192
+ }
8193
+ export interface CostumRemoveAmpliData {
8194
+ /**
8195
+ * CLÉ de l'entrée dans costum.ampli, c'est-à-dire le slug renvoyé à la création (PAS un ObjectId).
8196
+ */
8197
+ ampliId: string;
8198
+ /**
8199
+ * ObjectId de l'élément porteur du costum.
8200
+ */
8201
+ parentId: string;
8202
+ /**
8203
+ * Collection de l'élément porteur du costum.
8204
+ */
8205
+ parentType: "organizations" | "projects" | "citoyens" | "events";
8206
+ /**
8207
+ * Slug de l'élément porteur. REQUIS, et pas décoratif : l'action appelle CacheHelper::getCostum($parentType, $parentId) alors que la signature est ($id, $type, $slug) — arguments inversés — et la résolution retombe en pratique sur $_POST[costumSlug]. L'interface Co l'envoie sans le savoir (ajaxPost l'injecte dans tout POST du module costum) ; un client externe doit le fournir explicitement. Inversion non corrigée : antérieure, et elle touche l'appelant Co.
8208
+ */
8209
+ costumSlug: string;
8210
+ [k: string]: unknown;
8211
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Types de l'**ampli** — l'espace de propositions d'un costum.
3
+ *
4
+ * Source de vérité : les actions legacy du module costum
5
+ * `controllers/actions/ampli/{CreateAmpliAction,RemoveAmpliAction}.php`, routées par
6
+ * `CostumizeController` sur `/costum/costumize/{createampli,removeampli}`.
7
+ *
8
+ * Un ampli n'est **pas une entité** : c'est une entrée de la carte `costum.ampli`, portée par
9
+ * l'élément hôte du costum (organisation, projet, citoyen ou événement) et indexée par son
10
+ * **slug**. D'où le placement des deux méthodes sur `BaseEntity` plutôt qu'une classe dédiée :
11
+ * elles s'appliquent à l'hôte, exactement comme `saveToolEnrichment`.
12
+ */
13
+ /** Collections pouvant porter un costum, donc un ampli (`parentType` des deux actions). */
14
+ export declare const AMPLI_PARENT_TYPES: readonly ["organizations", "projects", "citoyens", "events"];
15
+ export type AmpliParentType = (typeof AMPLI_PARENT_TYPES)[number];
16
+ /**
17
+ * Chemins des questions du formulaire de dépôt, forme `<idSousFormulaire>.<idQuestion>`
18
+ * (**sans** le préfixe `answers.`). Chaîne vide quand la question n'existe pas — `finder` l'est
19
+ * toujours pour un formulaire généré par le serveur.
20
+ */
21
+ export interface AmpliPaths {
22
+ name: string;
23
+ description: string;
24
+ address: string;
25
+ tags: string;
26
+ image: string;
27
+ finder: string;
28
+ }
29
+ /**
30
+ * Une entrée de `costum.ampli`, telle que relue via `element/about` — quelle que soit son époque.
31
+ *
32
+ * Deux formes coexistent en base :
33
+ * - les entrées écrites par `CreateAmpliAction` AVANT modules/costum@3ef97ef28 n'ont que
34
+ * `{ name, description, tags, pages, home }`, et leur clé vient de `strtolower` + espace → tiret
35
+ * (« Idées d'été » → `idées-d'été`) ;
36
+ * - les entrées écrites depuis portent en plus `slug`, `coform` et `path` ({@link CreatedAmpliEntry}).
37
+ *
38
+ * La CLÉ de la carte `costum.ampli` reste la seule référence fiable d'un ampli existant.
39
+ */
40
+ export interface AmpliEntry {
41
+ name: string;
42
+ /** Markdown, `""` si non fourni. */
43
+ description: string;
44
+ /** `null` sur une entrée ancienne créée avec des tags en tableau (`explode` d'un tableau). */
45
+ tags: string[] | null;
46
+ /** Pages Co de l'ampli (`#<page>`). Toujours vide pour une création depuis site-json. */
47
+ pages: string[];
48
+ /** Ancre de la page d'accueil Co. Toujours vide pour une création depuis site-json. */
49
+ home: string;
50
+ /** Clé de l'entrée dans `costum.ampli` — absente des entrées anciennes. */
51
+ slug?: string;
52
+ /** ObjectId du `Form` de dépôt — absent des entrées anciennes. */
53
+ coform?: string;
54
+ /** Chemins des questions du formulaire de dépôt — absents des entrées anciennes. */
55
+ path?: AmpliPaths;
56
+ }
57
+ /**
58
+ * L'entrée que {@link BaseEntity#createAmpli} vient d'écrire : la forme actuelle, complète.
59
+ */
60
+ export interface CreatedAmpliEntry extends AmpliEntry {
61
+ slug: string;
62
+ tags: string[];
63
+ coform: string;
64
+ path: AmpliPaths;
65
+ }
66
+ /** Champs communs aux deux modes de {@link BaseEntity#createAmpli}. */
67
+ interface CreateAmpliInputCommon {
68
+ /**
69
+ * Nom affiché. Le serveur en dérive la **clé** de l'entrée (`ampliSlug`) : « Idées d'été » donne
70
+ * `idees-d-ete`. Un nom qui ne produit aucun slug exploitable est refusé.
71
+ */
72
+ name: string;
73
+ /** Markdown, stocké tel quel. */
74
+ description?: string;
75
+ /** Vides et doublons sont retirés côté serveur. */
76
+ tags?: string[];
77
+ }
78
+ /**
79
+ * Mode A (défaut) — le **serveur crée le formulaire** : un `Form` et son sous-formulaire à cinq
80
+ * questions (titre, description, adresse, mots-clés, image), dont les chemins reviennent dans
81
+ * {@link CreatedAmpliEntry.path}. C'est le mode du parcours de création depuis site-json.
82
+ */
83
+ export type CreateAmpliInputGeneratedForm = CreateAmpliInputCommon;
84
+ /**
85
+ * Mode B — **rattachement à un formulaire existant** : `coform` désigne le `Form`, `namePath` et
86
+ * `addressPath` sont exigés par le serveur, les autres chemins sont facultatifs.
87
+ */
88
+ export interface CreateAmpliInputExistingForm extends CreateAmpliInputCommon {
89
+ /** ObjectId du `Form` à rattacher. Sa présence bascule l'appel en mode B. */
90
+ coform: string;
91
+ namePath: string;
92
+ addressPath: string;
93
+ descriptionPath?: string;
94
+ tagsPath?: string;
95
+ imagePath?: string;
96
+ finderPath?: string;
97
+ }
98
+ /** Entrée de {@link BaseEntity#createAmpli} — le mode se lit à la présence de `coform`. */
99
+ export type CreateAmpliInput = CreateAmpliInputGeneratedForm | CreateAmpliInputExistingForm;
100
+ /**
101
+ * Retour de {@link BaseEntity#createAmpli}.
102
+ *
103
+ * `data`, `app` et `blockCms` ne servent qu'à l'interface Co (boutons de menu, carte des pages,
104
+ * blocs CMS) et arrivent **vides** pour un appel site-json. Ils restent au contrat pour garder une
105
+ * seule forme de réponse ; un appelant site-json les ignore.
106
+ */
107
+ export interface CreateAmpliResult {
108
+ result: true;
109
+ /** Clé de l'entrée : permet de naviguer vers `/ampli/<slug>` sans attendre un rechargement. */
110
+ slug: string;
111
+ ampli: CreatedAmpliEntry;
112
+ data: unknown[];
113
+ app: unknown[];
114
+ blockCms: unknown[];
115
+ }
116
+ /** Retour de {@link BaseEntity#removeAmpli} — `msg` vaut `"Ampli removed"`. */
117
+ export interface RemoveAmpliResult {
118
+ result: true;
119
+ msg: string;
120
+ }
121
+ export {};