@webiny/webhooks 6.4.0-beta.3 → 6.4.0-beta.4
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/admin/WebhookRoutes.js +13 -2
- package/admin/WebhookRoutes.js.map +1 -1
- package/admin/Webhooks.js +0 -3
- package/admin/Webhooks.js.map +1 -1
- package/admin/features/getWebhookSettings/GetWebhookSettingsGateway.js +1 -0
- package/admin/features/getWebhookSettings/GetWebhookSettingsGateway.js.map +1 -1
- package/admin/features/listWebhookDeliveries/ListWebhookDeliveriesGateway.js +1 -1
- package/admin/features/listWebhookDeliveries/ListWebhookDeliveriesGateway.js.map +1 -1
- package/admin/features/listWebhookDeliveries/abstractions.d.ts +6 -1
- package/admin/features/listWebhookDeliveries/abstractions.js.map +1 -1
- package/admin/features/updateWebhookSettings/UpdateWebhookSettingsGateway.js +1 -0
- package/admin/features/updateWebhookSettings/UpdateWebhookSettingsGateway.js.map +1 -1
- package/admin/features/updateWebhookSettings/abstractions.d.ts +1 -0
- package/admin/features/updateWebhookSettings/abstractions.js.map +1 -1
- package/admin/presentation/{WebhookDeliveries → WebhookDeliveriesPage}/WebhookDeliveriesDataSource.d.ts +1 -2
- package/admin/presentation/{WebhookDeliveries → WebhookDeliveriesPage}/WebhookDeliveriesDataSource.js +5 -7
- package/admin/presentation/WebhookDeliveriesPage/WebhookDeliveriesDataSource.js.map +1 -0
- package/admin/presentation/WebhookDeliveriesPage/WebhookDeliveriesPagePresenter.d.ts +41 -0
- package/admin/presentation/WebhookDeliveriesPage/WebhookDeliveriesPagePresenter.js +223 -0
- package/admin/presentation/WebhookDeliveriesPage/WebhookDeliveriesPagePresenter.js.map +1 -0
- package/admin/presentation/WebhookDeliveriesPage/abstractions.d.ts +42 -0
- package/admin/presentation/WebhookDeliveriesPage/abstractions.js +5 -0
- package/admin/presentation/WebhookDeliveriesPage/abstractions.js.map +1 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryAccordionRow.d.ts +11 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryAccordionRow.js +36 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryAccordionRow.js.map +1 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryBottomInfoBar.d.ts +9 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryBottomInfoBar.js +43 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryBottomInfoBar.js.map +1 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryDetailContent.d.ts +7 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryDetailContent.js +76 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryDetailContent.js.map +1 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryFilters.d.ts +9 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryFilters.js +85 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryFilters.js.map +1 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryList.d.ts +9 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryList.js +61 -0
- package/admin/presentation/WebhookDeliveriesPage/components/DeliveryList.js.map +1 -0
- package/admin/presentation/WebhookDeliveriesPage/components/WebhookDefinitionsButton.d.ts +2 -0
- package/admin/presentation/WebhookDeliveriesPage/components/WebhookDefinitionsButton.js +16 -0
- package/admin/presentation/WebhookDeliveriesPage/components/WebhookDefinitionsButton.js.map +1 -0
- package/admin/presentation/WebhookDeliveriesPage/components/WebhookDeliveriesPage.d.ts +2 -0
- package/admin/presentation/WebhookDeliveriesPage/components/WebhookDeliveriesPage.js +73 -0
- package/admin/presentation/WebhookDeliveriesPage/components/WebhookDeliveriesPage.js.map +1 -0
- package/admin/presentation/WebhookDeliveriesPage/components/statusVariant.d.ts +1 -0
- package/admin/presentation/WebhookDeliveriesPage/components/statusVariant.js +13 -0
- package/admin/presentation/WebhookDeliveriesPage/components/statusVariant.js.map +1 -0
- package/admin/presentation/WebhookDeliveriesPage/feature.d.ts +3 -0
- package/admin/presentation/WebhookDeliveriesPage/feature.js +17 -0
- package/admin/presentation/WebhookDeliveriesPage/feature.js.map +1 -0
- package/admin/presentation/WebhookDeliveriesPage/index.d.ts +5 -0
- package/admin/presentation/WebhookDeliveriesPage/index.js +1 -0
- package/admin/presentation/WebhookForm/WebhookFormPresenter.d.ts +6 -6
- package/admin/presentation/WebhookForm/WebhookFormPresenter.js +83 -72
- package/admin/presentation/WebhookForm/WebhookFormPresenter.js.map +1 -1
- package/admin/presentation/WebhookForm/abstractions.d.ts +2 -9
- package/admin/presentation/WebhookForm/abstractions.js.map +1 -1
- package/admin/presentation/WebhookForm/components/SigningSecret.d.ts +5 -2
- package/admin/presentation/WebhookForm/components/SigningSecret.js +7 -3
- package/admin/presentation/WebhookForm/components/SigningSecret.js.map +1 -1
- package/admin/presentation/WebhookForm/components/WebhookFormView.js +49 -35
- package/admin/presentation/WebhookForm/components/WebhookFormView.js.map +1 -1
- package/admin/presentation/WebhookList/WebhookListPresenter.d.ts +26 -2
- package/admin/presentation/WebhookList/WebhookListPresenter.js +36 -34
- package/admin/presentation/WebhookList/WebhookListPresenter.js.map +1 -1
- package/admin/presentation/WebhookList/abstractions.d.ts +25 -7
- package/admin/presentation/WebhookList/abstractions.js.map +1 -1
- package/admin/presentation/WebhookList/components/CreateWebhookButton.d.ts +2 -0
- package/admin/presentation/WebhookList/components/CreateWebhookButton.js +22 -0
- package/admin/presentation/WebhookList/components/CreateWebhookButton.js.map +1 -0
- package/admin/presentation/WebhookList/components/WebhookDeliveriesButton.d.ts +2 -0
- package/admin/presentation/WebhookList/components/WebhookDeliveriesButton.js +16 -0
- package/admin/presentation/WebhookList/components/WebhookDeliveriesButton.js.map +1 -0
- package/admin/presentation/WebhookList/components/WebhookListContent.d.ts +9 -0
- package/admin/presentation/WebhookList/components/WebhookListContent.js +170 -0
- package/admin/presentation/WebhookList/components/WebhookListContent.js.map +1 -0
- package/admin/presentation/WebhookList/components/WebhookListView.js +10 -140
- package/admin/presentation/WebhookList/components/WebhookListView.js.map +1 -1
- package/admin/presentation/WebhookSettings/WebhookSettingsPresenter.js +14 -6
- package/admin/presentation/WebhookSettings/WebhookSettingsPresenter.js.map +1 -1
- package/admin/routes.d.ts +4 -1
- package/admin/routes.js +11 -4
- package/admin/routes.js.map +1 -1
- package/admin/shared/types.d.ts +1 -0
- package/api/domain/WebhookDelivery.d.ts +0 -1
- package/api/domain/WebhookSettings.d.ts +1 -0
- package/api/domain/constants.d.ts +1 -1
- package/api/domain/constants.js +2 -2
- package/api/domain/constants.js.map +1 -1
- package/api/features/CreateWebhookDelivery/CreateWebhookDeliveryRepository.d.ts +1 -1
- package/api/features/CreateWebhookDelivery/CreateWebhookDeliveryRepository.js +3 -1
- package/api/features/CreateWebhookDelivery/CreateWebhookDeliveryRepository.js.map +1 -1
- package/api/features/CreateWebhookDelivery/abstractions.d.ts +1 -1
- package/api/features/CreateWebhookDelivery/abstractions.js.map +1 -1
- package/api/features/GetWebhookSettings/GetWebhookSettingsRepository.js +4 -2
- package/api/features/GetWebhookSettings/GetWebhookSettingsRepository.js.map +1 -1
- package/api/features/ResendWebhookDelivery/ResendWebhookDeliveryUseCase.d.ts +3 -1
- package/api/features/ResendWebhookDelivery/ResendWebhookDeliveryUseCase.js +9 -4
- package/api/features/ResendWebhookDelivery/ResendWebhookDeliveryUseCase.js.map +1 -1
- package/api/features/SendWebhookTask/SendWebhookTask.d.ts +1 -1
- package/api/features/SendWebhookTask/SendWebhookTask.js +1 -1
- package/api/features/SendWebhookTask/SendWebhookTask.js.map +1 -1
- package/api/features/TriggerWebhook/TriggerWebhookUseCase.d.ts +3 -1
- package/api/features/TriggerWebhook/TriggerWebhookUseCase.js +9 -4
- package/api/features/TriggerWebhook/TriggerWebhookUseCase.js.map +1 -1
- package/api/features/UpdateWebhookSettings/UpdateWebhookSettingsRepository.js +4 -2
- package/api/features/UpdateWebhookSettings/UpdateWebhookSettingsRepository.js.map +1 -1
- package/api/features/UpdateWebhookSettings/abstractions.d.ts +1 -0
- package/api/features/UpdateWebhookSettings/abstractions.js.map +1 -1
- package/api/features/UpdateWebhookSettings/schema.d.ts +1 -0
- package/api/features/UpdateWebhookSettings/schema.js +3 -1
- package/api/features/UpdateWebhookSettings/schema.js.map +1 -1
- package/api/features/WebhookDispatcher/WebhookDispatcher.d.ts +3 -1
- package/api/features/WebhookDispatcher/WebhookDispatcher.js +9 -4
- package/api/features/WebhookDispatcher/WebhookDispatcher.js.map +1 -1
- package/api/graphql/WebhookDeliverySchema.js +12 -8
- package/api/graphql/WebhookDeliverySchema.js.map +1 -1
- package/api/graphql/WebhookEventSchema.js +1 -0
- package/api/graphql/WebhookEventSchema.js.map +1 -1
- package/api/graphql/WebhookSettingsSchema.js +2 -0
- package/api/graphql/WebhookSettingsSchema.js.map +1 -1
- package/api/models/WebhookSettingsModel.js +3 -2
- package/api/models/WebhookSettingsModel.js.map +1 -1
- package/package.json +24 -22
- package/admin/presentation/WebhookDeliveries/WebhookDeliveriesDataSource.js.map +0 -1
- package/admin/presentation/WebhookDeliveries/WebhookDeliveriesPresenter.d.ts +0 -19
- package/admin/presentation/WebhookDeliveries/WebhookDeliveriesPresenter.js +0 -77
- package/admin/presentation/WebhookDeliveries/WebhookDeliveriesPresenter.js.map +0 -1
- package/admin/presentation/WebhookDeliveries/abstractions.d.ts +0 -22
- package/admin/presentation/WebhookDeliveries/abstractions.js +0 -5
- package/admin/presentation/WebhookDeliveries/abstractions.js.map +0 -1
- package/admin/presentation/WebhookDeliveries/components/DeliveryDetail.d.ts +0 -11
- package/admin/presentation/WebhookDeliveries/components/DeliveryDetail.js +0 -73
- package/admin/presentation/WebhookDeliveries/components/DeliveryDetail.js.map +0 -1
- package/admin/presentation/WebhookDeliveries/components/WebhookDeliveriesDrawer.d.ts +0 -8
- package/admin/presentation/WebhookDeliveries/components/WebhookDeliveriesDrawer.js +0 -119
- package/admin/presentation/WebhookDeliveries/components/WebhookDeliveriesDrawer.js.map +0 -1
- package/admin/presentation/WebhookDeliveries/feature.d.ts +0 -3
- package/admin/presentation/WebhookDeliveries/feature.js +0 -17
- package/admin/presentation/WebhookDeliveries/feature.js.map +0 -1
- package/admin/presentation/WebhookDeliveries/index.d.ts +0 -2
- package/admin/presentation/WebhookDeliveries/index.js +0 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/admin";
|
|
2
|
+
import { WebhookDeliveriesPagePresenter } from "./abstractions.js";
|
|
3
|
+
import { WebhookDeliveriesPagePresenter as external_WebhookDeliveriesPagePresenter_js_WebhookDeliveriesPagePresenter } from "./WebhookDeliveriesPagePresenter.js";
|
|
4
|
+
const WebhookDeliveriesPagePresenterFeature = createFeature({
|
|
5
|
+
name: "Webhooks/WebhookDeliveriesPagePresenter",
|
|
6
|
+
register (container) {
|
|
7
|
+
container.register(external_WebhookDeliveriesPagePresenter_js_WebhookDeliveriesPagePresenter).inSingletonScope();
|
|
8
|
+
},
|
|
9
|
+
resolve (container) {
|
|
10
|
+
return {
|
|
11
|
+
presenter: container.resolve(WebhookDeliveriesPagePresenter)
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
export { WebhookDeliveriesPagePresenterFeature };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin/presentation/WebhookDeliveriesPage/feature.js","sources":["../../../../src/admin/presentation/WebhookDeliveriesPage/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/admin\";\nimport { WebhookDeliveriesPagePresenter as PresenterAbstraction } from \"./abstractions.js\";\nimport { WebhookDeliveriesPagePresenter } from \"./WebhookDeliveriesPagePresenter.js\";\n\nexport const WebhookDeliveriesPagePresenterFeature = createFeature({\n name: \"Webhooks/WebhookDeliveriesPagePresenter\",\n register(container) {\n container.register(WebhookDeliveriesPagePresenter).inSingletonScope();\n },\n resolve(container) {\n return { presenter: container.resolve(PresenterAbstraction) };\n }\n});\n"],"names":["WebhookDeliveriesPagePresenterFeature","createFeature","container","WebhookDeliveriesPagePresenter","PresenterAbstraction"],"mappings":";;;AAIO,MAAMA,wCAAwCC,cAAc;IAC/D,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC,2EAAgC,gBAAgB;IACvE;IACA,SAAQD,SAAS;QACb,OAAO;YAAE,WAAWA,UAAU,OAAO,CAACE;QAAsB;IAChE;AACJ"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { WebhookDeliveriesPagePresenterFeature } from "./feature.js";
|
|
2
|
+
export type { IWebhookDeliveriesPagePresenter } from "./abstractions.js";
|
|
3
|
+
export type { IWebhookDeliveriesPageViewModel } from "./abstractions.js";
|
|
4
|
+
export type { IDeliveryPageFilters } from "./abstractions.js";
|
|
5
|
+
export type { IDeliveryFilterOption } from "./abstractions.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { WebhookDeliveriesPagePresenterFeature } from "./feature.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type IWebhookFormPresenter, type IWebhookFormViewModel
|
|
1
|
+
import { type IWebhookFormPresenter, type IWebhookFormViewModel } from "./abstractions.js";
|
|
2
2
|
import { GetWebhookUseCase } from "../../../admin/features/getWebhook/abstractions.js";
|
|
3
3
|
import { CreateWebhookUseCase } from "../../../admin/features/createWebhook/abstractions.js";
|
|
4
4
|
import { UpdateWebhookUseCase } from "../../../admin/features/updateWebhook/abstractions.js";
|
|
@@ -18,19 +18,19 @@ declare class WebhookFormPresenterImpl implements IWebhookFormPresenter {
|
|
|
18
18
|
private _saving;
|
|
19
19
|
private _isNew;
|
|
20
20
|
private _webhook;
|
|
21
|
-
private _showDeliveries;
|
|
22
21
|
private _webhookId;
|
|
23
22
|
private _form;
|
|
24
|
-
private
|
|
25
|
-
private
|
|
23
|
+
private _entityFieldNames;
|
|
24
|
+
private _entityGroups;
|
|
26
25
|
get vm(): IWebhookFormViewModel;
|
|
27
26
|
constructor(formModelFactory: FormModelFactory.Interface, getWebhookUseCase: GetWebhookUseCase.Interface, createWebhookUseCase: CreateWebhookUseCase.Interface, updateWebhookUseCase: UpdateWebhookUseCase.Interface, deleteWebhookUseCase: DeleteWebhookUseCase.Interface, listAvailableEventsUseCase: ListAvailableEventsUseCase.Interface, permissions: WebhookPermissions.Interface);
|
|
28
27
|
private buildForm;
|
|
29
|
-
private
|
|
28
|
+
private entityFieldName;
|
|
30
29
|
private addEventFields;
|
|
31
30
|
private collectEvents;
|
|
32
31
|
private distributeEvents;
|
|
33
|
-
|
|
32
|
+
save(): Promise<boolean>;
|
|
33
|
+
deleteWebhook(): Promise<void>;
|
|
34
34
|
init(id: string): Promise<void>;
|
|
35
35
|
}
|
|
36
36
|
export declare const WebhookFormPresenter: typeof WebhookFormPresenterImpl & {
|
|
@@ -14,7 +14,6 @@ class WebhookFormPresenterImpl {
|
|
|
14
14
|
saving: this._saving,
|
|
15
15
|
isNew: this._isNew,
|
|
16
16
|
webhook: this._webhook,
|
|
17
|
-
showDeliveries: this._showDeliveries,
|
|
18
17
|
permissions: {
|
|
19
18
|
canEdit: this.permissions.canEdit("webhook"),
|
|
20
19
|
canDelete: this.permissions.canDelete("webhook")
|
|
@@ -34,55 +33,9 @@ class WebhookFormPresenterImpl {
|
|
|
34
33
|
this._saving = false;
|
|
35
34
|
this._isNew = false;
|
|
36
35
|
this._webhook = null;
|
|
37
|
-
this._showDeliveries = false;
|
|
38
36
|
this._webhookId = null;
|
|
39
|
-
this.
|
|
40
|
-
this.
|
|
41
|
-
this.actions = {
|
|
42
|
-
save: async ()=>{
|
|
43
|
-
const data = await this._form.submit();
|
|
44
|
-
if (false === data) return;
|
|
45
|
-
this._saving = true;
|
|
46
|
-
try {
|
|
47
|
-
const merged = {
|
|
48
|
-
name: data.name,
|
|
49
|
-
slug: data.slug,
|
|
50
|
-
endpointUrl: data.endpointUrl,
|
|
51
|
-
description: data.description || void 0,
|
|
52
|
-
enabled: data.enabled,
|
|
53
|
-
events: this.collectEvents()
|
|
54
|
-
};
|
|
55
|
-
if (this._isNew) {
|
|
56
|
-
const created = await this.createWebhookUseCase.execute(merged);
|
|
57
|
-
runInAction(()=>{
|
|
58
|
-
this._webhook = created;
|
|
59
|
-
this._webhookId = created.id;
|
|
60
|
-
this._isNew = false;
|
|
61
|
-
this._form.field("slug").setDisabled(true);
|
|
62
|
-
});
|
|
63
|
-
} else {
|
|
64
|
-
const updated = await this.updateWebhookUseCase.execute(this._webhookId, merged);
|
|
65
|
-
runInAction(()=>{
|
|
66
|
-
this._webhook = updated;
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
} finally{
|
|
70
|
-
runInAction(()=>{
|
|
71
|
-
this._saving = false;
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
deleteWebhook: async ()=>{
|
|
76
|
-
if (!this._webhookId || this._isNew) return;
|
|
77
|
-
await this.deleteWebhookUseCase.execute(this._webhookId);
|
|
78
|
-
},
|
|
79
|
-
openDeliveries: ()=>{
|
|
80
|
-
this._showDeliveries = true;
|
|
81
|
-
},
|
|
82
|
-
closeDeliveries: ()=>{
|
|
83
|
-
this._showDeliveries = false;
|
|
84
|
-
}
|
|
85
|
-
};
|
|
37
|
+
this._entityFieldNames = [];
|
|
38
|
+
this._entityGroups = new Map();
|
|
86
39
|
this._form = this.buildForm();
|
|
87
40
|
makeAutoObservable(this, {
|
|
88
41
|
vm: computed
|
|
@@ -108,26 +61,33 @@ class WebhookFormPresenterImpl {
|
|
|
108
61
|
]
|
|
109
62
|
});
|
|
110
63
|
}
|
|
111
|
-
|
|
112
|
-
const slug =
|
|
64
|
+
entityFieldName(appLabel, entityLabel) {
|
|
65
|
+
const slug = `${appLabel}_${entityLabel}`.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
|
|
113
66
|
return `events_${slug}`;
|
|
114
67
|
}
|
|
115
68
|
addEventFields(events) {
|
|
116
69
|
const grouped = new Map();
|
|
117
70
|
for (const event of events){
|
|
118
|
-
|
|
71
|
+
let appMap = grouped.get(event.appLabel);
|
|
72
|
+
if (!appMap) {
|
|
73
|
+
appMap = new Map();
|
|
74
|
+
grouped.set(event.appLabel, appMap);
|
|
75
|
+
}
|
|
76
|
+
const existing = appMap.get(event.entityLabel) ?? [];
|
|
119
77
|
existing.push(event);
|
|
120
|
-
|
|
78
|
+
appMap.set(event.entityLabel, existing);
|
|
121
79
|
}
|
|
122
|
-
this.
|
|
123
|
-
this.
|
|
80
|
+
this._entityGroups = grouped;
|
|
81
|
+
this._entityFieldNames = [];
|
|
124
82
|
this._form.fields((fields)=>{
|
|
125
83
|
const result = {};
|
|
126
|
-
for (const [
|
|
127
|
-
const fieldName = this.
|
|
128
|
-
this.
|
|
129
|
-
result[fieldName] = fields.object().label(
|
|
130
|
-
|
|
84
|
+
for (const [appLabel, entities] of grouped)for (const [entityLabel, entityEvents] of entities){
|
|
85
|
+
const fieldName = this.entityFieldName(appLabel, entityLabel);
|
|
86
|
+
this._entityFieldNames.push(fieldName);
|
|
87
|
+
result[fieldName] = fields.object().label(entityLabel).renderer("objectAccordionSingle", {
|
|
88
|
+
open: false
|
|
89
|
+
}).fields((f)=>({
|
|
90
|
+
selected: f.text().list().options(entityEvents.map((e)=>({
|
|
131
91
|
label: e.label,
|
|
132
92
|
value: e.eventName
|
|
133
93
|
}))).renderer("checkboxes")
|
|
@@ -135,19 +95,30 @@ class WebhookFormPresenterImpl {
|
|
|
135
95
|
}
|
|
136
96
|
return result;
|
|
137
97
|
});
|
|
138
|
-
this._form.setLayout((layout)=>
|
|
98
|
+
this._form.setLayout((layout)=>{
|
|
99
|
+
const rows = [
|
|
139
100
|
layout.row("name", "slug"),
|
|
140
101
|
layout.row("endpointUrl"),
|
|
141
102
|
layout.row("description"),
|
|
142
|
-
layout.row("enabled")
|
|
143
|
-
|
|
144
|
-
|
|
103
|
+
layout.row("enabled")
|
|
104
|
+
];
|
|
105
|
+
for (const [appLabel, entities] of grouped){
|
|
106
|
+
rows.push(layout.separator());
|
|
107
|
+
rows.push(layout.element("sectionHeading", {
|
|
108
|
+
label: appLabel
|
|
109
|
+
}));
|
|
110
|
+
for (const [entityLabel] of entities){
|
|
111
|
+
const fieldName = this.entityFieldName(appLabel, entityLabel);
|
|
112
|
+
rows.push(layout.object(fieldName, (inner)=>[
|
|
145
113
|
inner.row("selected")
|
|
146
|
-
]))
|
|
147
|
-
|
|
114
|
+
]));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return rows;
|
|
118
|
+
});
|
|
148
119
|
this._form.addRule((form)=>{
|
|
149
|
-
if (0 === this.
|
|
150
|
-
for (const fieldName of this.
|
|
120
|
+
if (0 === this._entityFieldNames.length) return [];
|
|
121
|
+
for (const fieldName of this._entityFieldNames){
|
|
151
122
|
const objectField = form.field(fieldName).as("object");
|
|
152
123
|
const selectedField = objectField.children.get("selected");
|
|
153
124
|
if (!selectedField) continue;
|
|
@@ -164,7 +135,7 @@ class WebhookFormPresenterImpl {
|
|
|
164
135
|
}
|
|
165
136
|
collectEvents() {
|
|
166
137
|
const allEvents = [];
|
|
167
|
-
for (const fieldName of this.
|
|
138
|
+
for (const fieldName of this._entityFieldNames){
|
|
168
139
|
const objectField = this._form.field(fieldName).as("object");
|
|
169
140
|
const selectedField = objectField.children.get("selected");
|
|
170
141
|
if (!selectedField) continue;
|
|
@@ -175,15 +146,55 @@ class WebhookFormPresenterImpl {
|
|
|
175
146
|
}
|
|
176
147
|
distributeEvents(webhookEvents) {
|
|
177
148
|
const eventSet = new Set(webhookEvents);
|
|
178
|
-
for (const [
|
|
179
|
-
const fieldName = this.
|
|
149
|
+
for (const [appLabel, entities] of this._entityGroups)for (const [entityLabel, entityEvents] of entities){
|
|
150
|
+
const fieldName = this.entityFieldName(appLabel, entityLabel);
|
|
180
151
|
const objectField = this._form.field(fieldName).as("object");
|
|
181
152
|
const selectedField = objectField.children.get("selected");
|
|
182
153
|
if (!selectedField) continue;
|
|
183
|
-
const selected =
|
|
154
|
+
const selected = entityEvents.filter((e)=>eventSet.has(e.eventName)).map((e)=>e.eventName);
|
|
184
155
|
selectedField.setValue(selected);
|
|
185
156
|
}
|
|
186
157
|
}
|
|
158
|
+
async save() {
|
|
159
|
+
const data = await this._form.submit();
|
|
160
|
+
if (false === data) return false;
|
|
161
|
+
runInAction(()=>{
|
|
162
|
+
this._saving = true;
|
|
163
|
+
});
|
|
164
|
+
try {
|
|
165
|
+
const merged = {
|
|
166
|
+
name: data.name,
|
|
167
|
+
slug: data.slug,
|
|
168
|
+
endpointUrl: data.endpointUrl,
|
|
169
|
+
description: data.description || void 0,
|
|
170
|
+
enabled: data.enabled,
|
|
171
|
+
events: this.collectEvents()
|
|
172
|
+
};
|
|
173
|
+
if (this._isNew) {
|
|
174
|
+
const created = await this.createWebhookUseCase.execute(merged);
|
|
175
|
+
runInAction(()=>{
|
|
176
|
+
this._webhook = created;
|
|
177
|
+
this._webhookId = created.id;
|
|
178
|
+
this._isNew = false;
|
|
179
|
+
this._form.field("slug").setDisabled(true);
|
|
180
|
+
});
|
|
181
|
+
} else {
|
|
182
|
+
const updated = await this.updateWebhookUseCase.execute(this._webhookId, merged);
|
|
183
|
+
runInAction(()=>{
|
|
184
|
+
this._webhook = updated;
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
} finally{
|
|
188
|
+
runInAction(()=>{
|
|
189
|
+
this._saving = false;
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
async deleteWebhook() {
|
|
195
|
+
if (!this._webhookId || this._isNew) return;
|
|
196
|
+
await this.deleteWebhookUseCase.execute(this._webhookId);
|
|
197
|
+
}
|
|
187
198
|
async init(id) {
|
|
188
199
|
this._loading = true;
|
|
189
200
|
this._isNew = "new" === id;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin/presentation/WebhookForm/WebhookFormPresenter.js","sources":["../../../../src/admin/presentation/WebhookForm/WebhookFormPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, runInAction } from \"mobx\";\nimport type { Webhook } from \"~/admin/shared/types.js\";\nimport type { WebhookEvent } from \"~/admin/shared/types.js\";\nimport {\n WebhookFormPresenter as Abstraction,\n type IWebhookFormPresenter,\n type IWebhookFormViewModel,\n type IWebhookFormActions\n} from \"./abstractions.js\";\nimport { GetWebhookUseCase } from \"~/admin/features/getWebhook/abstractions.js\";\nimport { CreateWebhookUseCase } from \"~/admin/features/createWebhook/abstractions.js\";\nimport { UpdateWebhookUseCase } from \"~/admin/features/updateWebhook/abstractions.js\";\nimport { DeleteWebhookUseCase } from \"~/admin/features/deleteWebhook/abstractions.js\";\nimport { ListAvailableEventsUseCase } from \"~/admin/features/listAvailableEvents/abstractions.js\";\nimport { WebhookPermissions } from \"~/admin/features/permissions/abstractions.js\";\nimport {\n FormModelFactory,\n type IFormModel\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\n\nclass WebhookFormPresenterImpl implements IWebhookFormPresenter {\n private _loading = false;\n private _saving = false;\n private _isNew = false;\n private _webhook: Webhook | null = null;\n private _showDeliveries = false;\n private _webhookId: string | null = null;\n private _form: IFormModel;\n private _eventFieldNames: string[] = [];\n private _eventGroups: Map<string, WebhookEvent[]> = new Map();\n\n public get vm(): IWebhookFormViewModel {\n return {\n loading: this._loading,\n saving: this._saving,\n isNew: this._isNew,\n webhook: this._webhook,\n showDeliveries: this._showDeliveries,\n permissions: {\n canEdit: this.permissions.canEdit(\"webhook\"),\n canDelete: this.permissions.canDelete(\"webhook\")\n },\n form: this._form.vm\n };\n }\n\n public constructor(\n private readonly formModelFactory: FormModelFactory.Interface,\n private readonly getWebhookUseCase: GetWebhookUseCase.Interface,\n private readonly createWebhookUseCase: CreateWebhookUseCase.Interface,\n private readonly updateWebhookUseCase: UpdateWebhookUseCase.Interface,\n private readonly deleteWebhookUseCase: DeleteWebhookUseCase.Interface,\n private readonly listAvailableEventsUseCase: ListAvailableEventsUseCase.Interface,\n private readonly permissions: WebhookPermissions.Interface\n ) {\n this._form = this.buildForm();\n\n makeAutoObservable(this, { vm: computed });\n }\n\n private buildForm(): IFormModel {\n return this.formModelFactory.create({\n fields: fields => ({\n name: fields.text().label(\"Name\").required(\"Name is required\"),\n slug: fields\n .text()\n .label(\"Slug\")\n .required(\"Slug is required\")\n .computedUntilDirty(form => {\n const name = String(form.field(\"name\").getValue() ?? \"\");\n return name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\");\n }),\n endpointUrl: fields\n .text()\n .label(\"Endpoint URL\")\n .required(\"Endpoint URL is required\")\n .placeholder(\"https://\"),\n description: fields.text().label(\"Description\").renderer(\"textarea\"),\n enabled: fields.boolean().label(\"Enabled\").defaultValue(false)\n }),\n layout: layout => [\n layout.row(\"name\", \"slug\"),\n layout.row(\"endpointUrl\"),\n layout.row(\"description\"),\n layout.row(\"enabled\")\n ]\n });\n }\n\n private eventFieldName(app: string): string {\n const slug = app\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_|_$/g, \"\");\n return `events_${slug}`;\n }\n\n private addEventFields(events: WebhookEvent[]): void {\n const grouped = new Map<string, WebhookEvent[]>();\n for (const event of events) {\n const existing = grouped.get(event.appLabel) ?? [];\n existing.push(event);\n grouped.set(event.appLabel, existing);\n }\n\n this._eventGroups = grouped;\n this._eventFieldNames = [];\n\n this._form.fields(fields => {\n const result: Record<string, ReturnType<typeof fields.object>> = {};\n\n for (const [app, appEvents] of grouped) {\n const fieldName = this.eventFieldName(app);\n this._eventFieldNames.push(fieldName);\n\n result[fieldName] = fields\n .object()\n .label(app)\n .renderer(\"objectAccordionSingle\")\n .fields(f => {\n return {\n selected: f\n .text()\n .list()\n .options(\n appEvents.map(e => ({\n label: e.label,\n value: e.eventName\n }))\n )\n .renderer(\"checkboxes\")\n };\n });\n }\n\n return result;\n });\n\n this._form.setLayout(layout => [\n layout.row(\"name\", \"slug\"),\n layout.row(\"endpointUrl\"),\n layout.row(\"description\"),\n layout.row(\"enabled\"),\n layout.separator(),\n ...this._eventFieldNames.map(name =>\n layout.object(name, inner => [inner.row(\"selected\")])\n )\n ]);\n\n this._form.addRule(form => {\n if (this._eventFieldNames.length === 0) {\n return [];\n }\n for (const fieldName of this._eventFieldNames) {\n const objectField = form.field(fieldName).as(\"object\");\n const selectedField = objectField.children.get(\"selected\");\n if (!selectedField) {\n continue;\n }\n const values = selectedField.getValue<string[]>();\n if (values && values.length > 0) {\n return [];\n }\n }\n\n return [{ path: \"Events\", message: \"At least one event must be selected.\" }];\n });\n }\n\n private collectEvents(): string[] {\n const allEvents: string[] = [];\n\n for (const fieldName of this._eventFieldNames) {\n const objectField = this._form.field(fieldName).as(\"object\");\n const selectedField = objectField.children.get(\"selected\");\n if (!selectedField) {\n continue;\n }\n const values = selectedField.getValue<string[]>();\n if (values && values.length > 0) {\n allEvents.push(...values);\n }\n }\n\n return allEvents;\n }\n\n private distributeEvents(webhookEvents: string[]): void {\n const eventSet = new Set(webhookEvents);\n\n for (const [app, appEvents] of this._eventGroups) {\n const fieldName = this.eventFieldName(app);\n const objectField = this._form.field(fieldName).as(\"object\");\n const selectedField = objectField.children.get(\"selected\");\n if (!selectedField) {\n continue;\n }\n\n const selected = appEvents.filter(e => eventSet.has(e.eventName)).map(e => e.eventName);\n selectedField.setValue(selected);\n }\n }\n\n public actions: IWebhookFormActions = {\n save: async () => {\n const data = await this._form.submit<Record<string, unknown>>();\n if (data === false) {\n return;\n }\n\n this._saving = true;\n\n try {\n const merged = {\n name: data.name as string,\n slug: data.slug as string,\n endpointUrl: data.endpointUrl as string,\n description: (data.description as string) || undefined,\n enabled: data.enabled as boolean,\n events: this.collectEvents()\n };\n\n if (this._isNew) {\n const created = await this.createWebhookUseCase.execute(merged);\n\n runInAction(() => {\n this._webhook = created;\n this._webhookId = created.id;\n this._isNew = false;\n this._form.field(\"slug\").setDisabled(true);\n });\n } else {\n const updated = await this.updateWebhookUseCase.execute(\n this._webhookId!,\n merged\n );\n\n runInAction(() => {\n this._webhook = updated;\n });\n }\n } finally {\n runInAction(() => {\n this._saving = false;\n });\n }\n },\n deleteWebhook: async () => {\n if (!this._webhookId || this._isNew) {\n return;\n }\n await this.deleteWebhookUseCase.execute(this._webhookId);\n },\n openDeliveries: () => {\n this._showDeliveries = true;\n },\n closeDeliveries: () => {\n this._showDeliveries = false;\n }\n };\n\n public async init(id: string): Promise<void> {\n this._loading = true;\n this._isNew = id === \"new\";\n this._webhookId = id === \"new\" ? null : id;\n\n const eventsPromise = this.listAvailableEventsUseCase.execute();\n\n if (!this._isNew) {\n const [webhook, events] = await Promise.all([\n this.getWebhookUseCase.execute(id),\n eventsPromise\n ]);\n\n runInAction(() => {\n this._webhook = webhook;\n this._form = this.buildForm();\n this.addEventFields(events);\n this._form.setData({\n name: webhook.name,\n slug: webhook.slug,\n endpointUrl: webhook.endpointUrl,\n description: webhook.description ?? \"\",\n enabled: webhook.enabled\n });\n this._form.field(\"slug\").setDisabled(true);\n this.distributeEvents(webhook.events);\n this._loading = false;\n });\n } else {\n const events = await eventsPromise;\n\n runInAction(() => {\n this._form = this.buildForm();\n this.addEventFields(events);\n this._loading = false;\n });\n }\n }\n}\n\nexport const WebhookFormPresenter = Abstraction.createImplementation({\n implementation: WebhookFormPresenterImpl,\n dependencies: [\n FormModelFactory,\n GetWebhookUseCase,\n CreateWebhookUseCase,\n UpdateWebhookUseCase,\n DeleteWebhookUseCase,\n ListAvailableEventsUseCase,\n WebhookPermissions\n ]\n});\n"],"names":["WebhookFormPresenterImpl","formModelFactory","getWebhookUseCase","createWebhookUseCase","updateWebhookUseCase","deleteWebhookUseCase","listAvailableEventsUseCase","permissions","Map","data","merged","undefined","created","runInAction","updated","makeAutoObservable","computed","fields","form","name","String","layout","app","slug","events","grouped","event","existing","result","appEvents","fieldName","f","e","inner","objectField","selectedField","values","allEvents","webhookEvents","eventSet","Set","selected","id","eventsPromise","webhook","Promise","WebhookFormPresenter","Abstraction","FormModelFactory","GetWebhookUseCase","CreateWebhookUseCase","UpdateWebhookUseCase","DeleteWebhookUseCase","ListAvailableEventsUseCase","WebhookPermissions"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"admin/presentation/WebhookForm/WebhookFormPresenter.js","sources":["../../../../src/admin/presentation/WebhookForm/WebhookFormPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, runInAction } from \"mobx\";\nimport type { Webhook } from \"~/admin/shared/types.js\";\nimport type { WebhookEvent } from \"~/admin/shared/types.js\";\nimport {\n WebhookFormPresenter as Abstraction,\n type IWebhookFormPresenter,\n type IWebhookFormViewModel\n} from \"./abstractions.js\";\nimport { GetWebhookUseCase } from \"~/admin/features/getWebhook/abstractions.js\";\nimport { CreateWebhookUseCase } from \"~/admin/features/createWebhook/abstractions.js\";\nimport { UpdateWebhookUseCase } from \"~/admin/features/updateWebhook/abstractions.js\";\nimport { DeleteWebhookUseCase } from \"~/admin/features/deleteWebhook/abstractions.js\";\nimport { ListAvailableEventsUseCase } from \"~/admin/features/listAvailableEvents/abstractions.js\";\nimport { WebhookPermissions } from \"~/admin/features/permissions/abstractions.js\";\nimport {\n FormModelFactory,\n type IFormModel,\n type ILayoutNodeBuilder\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\n\nclass WebhookFormPresenterImpl implements IWebhookFormPresenter {\n private _loading = false;\n private _saving = false;\n private _isNew = false;\n private _webhook: Webhook | null = null;\n private _webhookId: string | null = null;\n private _form: IFormModel;\n private _entityFieldNames: string[] = [];\n private _entityGroups: Map<string, Map<string, WebhookEvent[]>> = new Map();\n\n public get vm(): IWebhookFormViewModel {\n return {\n loading: this._loading,\n saving: this._saving,\n isNew: this._isNew,\n webhook: this._webhook,\n permissions: {\n canEdit: this.permissions.canEdit(\"webhook\"),\n canDelete: this.permissions.canDelete(\"webhook\")\n },\n form: this._form.vm\n };\n }\n\n public constructor(\n private readonly formModelFactory: FormModelFactory.Interface,\n private readonly getWebhookUseCase: GetWebhookUseCase.Interface,\n private readonly createWebhookUseCase: CreateWebhookUseCase.Interface,\n private readonly updateWebhookUseCase: UpdateWebhookUseCase.Interface,\n private readonly deleteWebhookUseCase: DeleteWebhookUseCase.Interface,\n private readonly listAvailableEventsUseCase: ListAvailableEventsUseCase.Interface,\n private readonly permissions: WebhookPermissions.Interface\n ) {\n this._form = this.buildForm();\n\n makeAutoObservable(this, { vm: computed });\n }\n\n private buildForm(): IFormModel {\n return this.formModelFactory.create({\n fields: fields => ({\n name: fields.text().label(\"Name\").required(\"Name is required\"),\n slug: fields\n .text()\n .label(\"Slug\")\n .required(\"Slug is required\")\n .computedUntilDirty(form => {\n const name = String(form.field(\"name\").getValue() ?? \"\");\n return name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\");\n }),\n endpointUrl: fields\n .text()\n .label(\"Endpoint URL\")\n .required(\"Endpoint URL is required\")\n .placeholder(\"https://\"),\n description: fields.text().label(\"Description\").renderer(\"textarea\"),\n enabled: fields.boolean().label(\"Enabled\").defaultValue(false)\n }),\n layout: layout => [\n layout.row(\"name\", \"slug\"),\n layout.row(\"endpointUrl\"),\n layout.row(\"description\"),\n layout.row(\"enabled\")\n ]\n });\n }\n\n private entityFieldName(appLabel: string, entityLabel: string): string {\n const slug = `${appLabel}_${entityLabel}`\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_|_$/g, \"\");\n return `events_${slug}`;\n }\n\n private addEventFields(events: WebhookEvent[]): void {\n const grouped = new Map<string, Map<string, WebhookEvent[]>>();\n for (const event of events) {\n let appMap = grouped.get(event.appLabel);\n if (!appMap) {\n appMap = new Map();\n grouped.set(event.appLabel, appMap);\n }\n const existing = appMap.get(event.entityLabel) ?? [];\n existing.push(event);\n appMap.set(event.entityLabel, existing);\n }\n\n this._entityGroups = grouped;\n this._entityFieldNames = [];\n\n this._form.fields(fields => {\n const result: Record<string, ReturnType<typeof fields.object>> = {};\n\n for (const [appLabel, entities] of grouped) {\n for (const [entityLabel, entityEvents] of entities) {\n const fieldName = this.entityFieldName(appLabel, entityLabel);\n this._entityFieldNames.push(fieldName);\n\n result[fieldName] = fields\n .object()\n .label(entityLabel)\n .renderer(\"objectAccordionSingle\", { open: false })\n .fields(f => {\n return {\n selected: f\n .text()\n .list()\n .options(\n entityEvents.map(e => ({\n label: e.label,\n value: e.eventName\n }))\n )\n .renderer(\"checkboxes\")\n };\n });\n }\n }\n\n return result;\n });\n\n this._form.setLayout(layout => {\n const rows: ILayoutNodeBuilder[] = [\n layout.row(\"name\", \"slug\"),\n layout.row(\"endpointUrl\"),\n layout.row(\"description\"),\n layout.row(\"enabled\")\n ];\n\n for (const [appLabel, entities] of grouped) {\n rows.push(layout.separator());\n rows.push(layout.element(\"sectionHeading\", { label: appLabel }));\n\n for (const [entityLabel] of entities) {\n const fieldName = this.entityFieldName(appLabel, entityLabel);\n rows.push(layout.object(fieldName, inner => [inner.row(\"selected\")]));\n }\n }\n\n return rows;\n });\n\n this._form.addRule(form => {\n if (this._entityFieldNames.length === 0) {\n return [];\n }\n for (const fieldName of this._entityFieldNames) {\n const objectField = form.field(fieldName).as(\"object\");\n const selectedField = objectField.children.get(\"selected\");\n if (!selectedField) {\n continue;\n }\n const values = selectedField.getValue<string[]>();\n if (values && values.length > 0) {\n return [];\n }\n }\n\n return [{ path: \"Events\", message: \"At least one event must be selected.\" }];\n });\n }\n\n private collectEvents(): string[] {\n const allEvents: string[] = [];\n\n for (const fieldName of this._entityFieldNames) {\n const objectField = this._form.field(fieldName).as(\"object\");\n const selectedField = objectField.children.get(\"selected\");\n if (!selectedField) {\n continue;\n }\n const values = selectedField.getValue<string[]>();\n if (values && values.length > 0) {\n allEvents.push(...values);\n }\n }\n\n return allEvents;\n }\n\n private distributeEvents(webhookEvents: string[]): void {\n const eventSet = new Set(webhookEvents);\n\n for (const [appLabel, entities] of this._entityGroups) {\n for (const [entityLabel, entityEvents] of entities) {\n const fieldName = this.entityFieldName(appLabel, entityLabel);\n const objectField = this._form.field(fieldName).as(\"object\");\n const selectedField = objectField.children.get(\"selected\");\n if (!selectedField) {\n continue;\n }\n\n const selected = entityEvents\n .filter(e => eventSet.has(e.eventName))\n .map(e => e.eventName);\n selectedField.setValue(selected);\n }\n }\n }\n\n public async save(): Promise<boolean> {\n const data = await this._form.submit<Record<string, unknown>>();\n if (data === false) {\n return false;\n }\n\n runInAction(() => {\n this._saving = true;\n });\n\n try {\n const merged = {\n name: data.name as string,\n slug: data.slug as string,\n endpointUrl: data.endpointUrl as string,\n description: (data.description as string) || undefined,\n enabled: data.enabled as boolean,\n events: this.collectEvents()\n };\n\n if (this._isNew) {\n const created = await this.createWebhookUseCase.execute(merged);\n\n runInAction(() => {\n this._webhook = created;\n this._webhookId = created.id;\n this._isNew = false;\n this._form.field(\"slug\").setDisabled(true);\n });\n } else {\n const updated = await this.updateWebhookUseCase.execute(this._webhookId!, merged);\n\n runInAction(() => {\n this._webhook = updated;\n });\n }\n } finally {\n runInAction(() => {\n this._saving = false;\n });\n }\n\n return true;\n }\n\n public async deleteWebhook(): Promise<void> {\n if (!this._webhookId || this._isNew) {\n return;\n }\n await this.deleteWebhookUseCase.execute(this._webhookId);\n }\n\n public async init(id: string): Promise<void> {\n this._loading = true;\n this._isNew = id === \"new\";\n this._webhookId = id === \"new\" ? null : id;\n\n const eventsPromise = this.listAvailableEventsUseCase.execute();\n\n if (!this._isNew) {\n const [webhook, events] = await Promise.all([\n this.getWebhookUseCase.execute(id),\n eventsPromise\n ]);\n\n runInAction(() => {\n this._webhook = webhook;\n this._form = this.buildForm();\n this.addEventFields(events);\n this._form.setData({\n name: webhook.name,\n slug: webhook.slug,\n endpointUrl: webhook.endpointUrl,\n description: webhook.description ?? \"\",\n enabled: webhook.enabled\n });\n this._form.field(\"slug\").setDisabled(true);\n this.distributeEvents(webhook.events);\n this._loading = false;\n });\n } else {\n const events = await eventsPromise;\n\n runInAction(() => {\n this._form = this.buildForm();\n this.addEventFields(events);\n this._loading = false;\n });\n }\n }\n}\n\nexport const WebhookFormPresenter = Abstraction.createImplementation({\n implementation: WebhookFormPresenterImpl,\n dependencies: [\n FormModelFactory,\n GetWebhookUseCase,\n CreateWebhookUseCase,\n UpdateWebhookUseCase,\n DeleteWebhookUseCase,\n ListAvailableEventsUseCase,\n WebhookPermissions\n ]\n});\n"],"names":["WebhookFormPresenterImpl","formModelFactory","getWebhookUseCase","createWebhookUseCase","updateWebhookUseCase","deleteWebhookUseCase","listAvailableEventsUseCase","permissions","Map","makeAutoObservable","computed","fields","form","name","String","layout","appLabel","entityLabel","slug","events","grouped","event","appMap","existing","result","entities","entityEvents","fieldName","f","e","rows","inner","objectField","selectedField","values","allEvents","webhookEvents","eventSet","Set","selected","data","runInAction","merged","undefined","created","updated","id","eventsPromise","webhook","Promise","WebhookFormPresenter","Abstraction","FormModelFactory","GetWebhookUseCase","CreateWebhookUseCase","UpdateWebhookUseCase","DeleteWebhookUseCase","ListAvailableEventsUseCase","WebhookPermissions"],"mappings":"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"}
|
|
@@ -5,27 +5,20 @@ export interface IWebhookFormViewModel {
|
|
|
5
5
|
saving: boolean;
|
|
6
6
|
isNew: boolean;
|
|
7
7
|
webhook: Webhook | null;
|
|
8
|
-
showDeliveries: boolean;
|
|
9
8
|
permissions: {
|
|
10
9
|
canEdit: boolean;
|
|
11
10
|
canDelete: boolean;
|
|
12
11
|
};
|
|
13
12
|
form: IFormVM;
|
|
14
13
|
}
|
|
15
|
-
export interface IWebhookFormActions {
|
|
16
|
-
save(): Promise<void>;
|
|
17
|
-
deleteWebhook(): Promise<void>;
|
|
18
|
-
openDeliveries(): void;
|
|
19
|
-
closeDeliveries(): void;
|
|
20
|
-
}
|
|
21
14
|
export interface IWebhookFormPresenter {
|
|
22
15
|
vm: IWebhookFormViewModel;
|
|
23
|
-
actions: IWebhookFormActions;
|
|
24
16
|
init(id: string): void;
|
|
17
|
+
save(): Promise<boolean>;
|
|
18
|
+
deleteWebhook(): Promise<void>;
|
|
25
19
|
}
|
|
26
20
|
export declare const WebhookFormPresenter: import("@webiny/di").Abstraction<IWebhookFormPresenter>;
|
|
27
21
|
export declare namespace WebhookFormPresenter {
|
|
28
22
|
type Interface = IWebhookFormPresenter;
|
|
29
23
|
type ViewModel = IWebhookFormViewModel;
|
|
30
|
-
type Actions = IWebhookFormActions;
|
|
31
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin/presentation/WebhookForm/abstractions.js","sources":["../../../../src/admin/presentation/WebhookForm/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\nimport type { Webhook } from \"~/admin/shared/types.js\";\nimport type { IFormVM } from \"@webiny/app-admin/features/formModel/abstractions.js\";\n\nexport interface IWebhookFormViewModel {\n loading: boolean;\n saving: boolean;\n isNew: boolean;\n webhook: Webhook | null;\n
|
|
1
|
+
{"version":3,"file":"admin/presentation/WebhookForm/abstractions.js","sources":["../../../../src/admin/presentation/WebhookForm/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\nimport type { Webhook } from \"~/admin/shared/types.js\";\nimport type { IFormVM } from \"@webiny/app-admin/features/formModel/abstractions.js\";\n\nexport interface IWebhookFormViewModel {\n loading: boolean;\n saving: boolean;\n isNew: boolean;\n webhook: Webhook | null;\n permissions: {\n canEdit: boolean;\n canDelete: boolean;\n };\n form: IFormVM;\n}\n\nexport interface IWebhookFormPresenter {\n vm: IWebhookFormViewModel;\n init(id: string): void;\n save(): Promise<boolean>;\n deleteWebhook(): Promise<void>;\n}\n\nexport const WebhookFormPresenter =\n createAbstraction<IWebhookFormPresenter>(\"WebhookFormPresenter\");\n\nexport namespace WebhookFormPresenter {\n export type Interface = IWebhookFormPresenter;\n export type ViewModel = IWebhookFormViewModel;\n}\n"],"names":["WebhookFormPresenter","createAbstraction"],"mappings":";AAuBO,MAAMA,uBACTC,kBAAyC"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import type { IWebhookFormPresenter } from "../abstractions.js";
|
|
2
3
|
interface SigningSecretProps {
|
|
3
|
-
|
|
4
|
+
presenter: IWebhookFormPresenter;
|
|
4
5
|
}
|
|
5
|
-
export declare const SigningSecret: ({
|
|
6
|
+
export declare const SigningSecret: (({ presenter }: SigningSecretProps) => React.JSX.Element | null) & {
|
|
7
|
+
displayName: string;
|
|
8
|
+
};
|
|
6
9
|
export {};
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import react, { useCallback, useState } from "react";
|
|
2
|
+
import { observer } from "mobx-react-lite";
|
|
2
3
|
import { IconButton, Text } from "@webiny/admin-ui";
|
|
3
4
|
import { useSnackbar } from "@webiny/app-admin/hooks/index.js";
|
|
4
5
|
import { ReactComponent } from "@webiny/icons/visibility.svg";
|
|
5
6
|
import { ReactComponent as visibility_off_svg_ReactComponent } from "@webiny/icons/visibility_off.svg";
|
|
6
7
|
import { ReactComponent as content_copy_svg_ReactComponent } from "@webiny/icons/content_copy.svg";
|
|
7
|
-
const
|
|
8
|
+
const SigningSecret_SigningSecret = observer(function({ presenter }) {
|
|
9
|
+
const { vm } = presenter;
|
|
8
10
|
const [revealed, setRevealed] = useState(false);
|
|
9
11
|
const { showSnackbar } = useSnackbar();
|
|
12
|
+
if (vm.isNew || !vm.webhook?.signingSecret) return null;
|
|
13
|
+
const secret = vm.webhook.signingSecret;
|
|
10
14
|
const handleCopy = useCallback(async ()=>{
|
|
11
15
|
await navigator.clipboard.writeText(secret);
|
|
12
16
|
showSnackbar("Signing secret copied to clipboard.");
|
|
@@ -37,7 +41,7 @@ const SigningSecret = ({ secret })=>{
|
|
|
37
41
|
onClick: ()=>void handleCopy(),
|
|
38
42
|
"aria-label": "Copy secret"
|
|
39
43
|
})));
|
|
40
|
-
};
|
|
41
|
-
export { SigningSecret };
|
|
44
|
+
});
|
|
45
|
+
export { SigningSecret_SigningSecret as SigningSecret };
|
|
42
46
|
|
|
43
47
|
//# sourceMappingURL=SigningSecret.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin/presentation/WebhookForm/components/SigningSecret.js","sources":["../../../../../src/admin/presentation/WebhookForm/components/SigningSecret.tsx"],"sourcesContent":["import React, { useState, useCallback } from \"react\";\nimport { IconButton, Text } from \"@webiny/admin-ui\";\nimport { useSnackbar } from \"@webiny/app-admin/hooks/index.js\";\nimport { ReactComponent as VisibilityIcon } from \"@webiny/icons/visibility.svg\";\nimport { ReactComponent as VisibilityOffIcon } from \"@webiny/icons/visibility_off.svg\";\nimport { ReactComponent as CopyIcon } from \"@webiny/icons/content_copy.svg\";\n\ninterface SigningSecretProps {\n
|
|
1
|
+
{"version":3,"file":"admin/presentation/WebhookForm/components/SigningSecret.js","sources":["../../../../../src/admin/presentation/WebhookForm/components/SigningSecret.tsx"],"sourcesContent":["import React, { useState, useCallback } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { IconButton, Text } from \"@webiny/admin-ui\";\nimport { useSnackbar } from \"@webiny/app-admin/hooks/index.js\";\nimport { ReactComponent as VisibilityIcon } from \"@webiny/icons/visibility.svg\";\nimport { ReactComponent as VisibilityOffIcon } from \"@webiny/icons/visibility_off.svg\";\nimport { ReactComponent as CopyIcon } from \"@webiny/icons/content_copy.svg\";\nimport type { IWebhookFormPresenter } from \"../abstractions.js\";\n\ninterface SigningSecretProps {\n presenter: IWebhookFormPresenter;\n}\n\nexport const SigningSecret = observer(function SigningSecret({ presenter }: SigningSecretProps) {\n const { vm } = presenter;\n const [revealed, setRevealed] = useState(false);\n const { showSnackbar } = useSnackbar();\n\n if (vm.isNew || !vm.webhook?.signingSecret) {\n return null;\n }\n\n const secret = vm.webhook.signingSecret;\n\n const handleCopy = useCallback(async () => {\n await navigator.clipboard.writeText(secret);\n showSnackbar(\"Signing secret copied to clipboard.\");\n }, [secret, showSnackbar]);\n\n return (\n <div className=\"flex flex-col gap-xs\">\n <Text size=\"sm\" className=\"text-neutral-strong\">\n Signing Secret\n </Text>\n <div className=\"flex items-center gap-sm rounded-sm border-sm border-neutral-muted px-sm py-xs\">\n <Text size=\"sm\" className=\"flex-1 font-mono select-all\">\n {revealed ? secret : \"•\".repeat(24)}\n </Text>\n <IconButton\n icon={revealed ? <VisibilityOffIcon /> : <VisibilityIcon />}\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => setRevealed(prev => !prev)}\n aria-label={revealed ? \"Hide secret\" : \"Reveal secret\"}\n />\n <IconButton\n icon={<CopyIcon />}\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => void handleCopy()}\n aria-label=\"Copy secret\"\n />\n </div>\n </div>\n );\n});\n"],"names":["SigningSecret","observer","presenter","vm","revealed","setRevealed","useState","showSnackbar","useSnackbar","secret","handleCopy","useCallback","navigator","Text","IconButton","VisibilityOffIcon","VisibilityIcon","prev","CopyIcon"],"mappings":";;;;;;;AAaO,MAAMA,8BAAgBC,SAAS,SAAuB,EAAEC,SAAS,EAAsB;IAC1F,MAAM,EAAEC,EAAE,EAAE,GAAGD;IACf,MAAM,CAACE,UAAUC,YAAY,GAAGC,SAAS;IACzC,MAAM,EAAEC,YAAY,EAAE,GAAGC;IAEzB,IAAIL,GAAG,KAAK,IAAI,CAACA,GAAG,OAAO,EAAE,eACzB,OAAO;IAGX,MAAMM,SAASN,GAAG,OAAO,CAAC,aAAa;IAEvC,MAAMO,aAAaC,YAAY;QAC3B,MAAMC,UAAU,SAAS,CAAC,SAAS,CAACH;QACpCF,aAAa;IACjB,GAAG;QAACE;QAAQF;KAAa;IAEzB,OAAO,WAAP,GACI,oBAAC;QAAI,WAAU;qBACX,oBAACM,MAAIA;QAAC,MAAK;QAAK,WAAU;OAAsB,iCAGhD,oBAAC;QAAI,WAAU;qBACX,oBAACA,MAAIA;QAAC,MAAK;QAAK,WAAU;OACrBT,WAAWK,SAAS,IAAI,MAAM,CAAC,oBAEpC,oBAACK,YAAUA;QACP,MAAMV,WAAW,WAAXA,GAAW,oBAACW,mCAAiBA,QAAAA,WAAAA,GAAM,oBAACC,gBAAcA;QACxD,SAAQ;QACR,MAAK;QACL,SAAS,IAAMX,YAAYY,CAAAA,OAAQ,CAACA;QACpC,cAAYb,WAAW,gBAAgB;sBAE3C,oBAACU,YAAUA;QACP,oBAAM,oBAACI,iCAAQA;QACf,SAAQ;QACR,MAAK;QACL,SAAS,IAAM,KAAKR;QACpB,cAAW;;AAK/B"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import react, { useEffect, useMemo } from "react";
|
|
1
|
+
import react, { useCallback, useEffect, useMemo } from "react";
|
|
2
2
|
import { observer } from "mobx-react-lite";
|
|
3
3
|
import { DiContainerProvider, useContainer, useFeature, useRoute } from "@webiny/app";
|
|
4
|
-
import { FormErrors, useRouter } from "@webiny/app-admin";
|
|
5
|
-
import { Button,
|
|
6
|
-
import { FormView } from "@webiny/app-admin/features/formModel/FormView.js";
|
|
4
|
+
import { FormErrors, FormView, SimpleForm, SimpleFormContent, SimpleFormFooter, SimpleFormHeader, useFieldRenderers, useRouter } from "@webiny/app-admin";
|
|
5
|
+
import { Button, OverlayLoader, useToast } from "@webiny/admin-ui";
|
|
7
6
|
import { WebhookFormPresenterFeature } from "../feature.js";
|
|
8
7
|
import { GetWebhookFeature } from "../../../features/getWebhook/feature.js";
|
|
9
8
|
import { CreateWebhookFeature } from "../../../features/createWebhook/feature.js";
|
|
@@ -13,52 +12,67 @@ import { ListAvailableEventsFeature } from "../../../features/listAvailableEvent
|
|
|
13
12
|
import { WebhookPermissionsFeature } from "../../../features/permissions/feature.js";
|
|
14
13
|
import { Routes } from "../../../routes.js";
|
|
15
14
|
import { SigningSecret } from "./SigningSecret.js";
|
|
16
|
-
import {
|
|
15
|
+
import { HasPermission } from "../../security/HasPermission.js";
|
|
16
|
+
const SectionHeading = ({ field })=>/*#__PURE__*/ react.createElement("span", {
|
|
17
|
+
className: "text-md font-semibold"
|
|
18
|
+
}, String(field.label ?? ""));
|
|
17
19
|
const WebhookFormView_WebhookFormViewInner = observer(function() {
|
|
18
20
|
const { presenter } = useFeature(WebhookFormPresenterFeature);
|
|
19
21
|
const { goToRoute } = useRouter();
|
|
20
22
|
const { route } = useRoute(Routes.Form);
|
|
23
|
+
const toast = useToast();
|
|
21
24
|
const id = route.params.id;
|
|
25
|
+
const defaultRenderers = useFieldRenderers();
|
|
26
|
+
const renderers = useMemo(()=>({
|
|
27
|
+
...defaultRenderers,
|
|
28
|
+
"element:sectionHeading": SectionHeading
|
|
29
|
+
}), [
|
|
30
|
+
defaultRenderers
|
|
31
|
+
]);
|
|
22
32
|
useEffect(()=>{
|
|
23
33
|
presenter.init(id);
|
|
24
34
|
}, [
|
|
25
35
|
presenter,
|
|
26
36
|
id
|
|
27
37
|
]);
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
38
|
+
const saveForm = useCallback(async ()=>{
|
|
39
|
+
const res = await presenter.save();
|
|
40
|
+
if (res) toast.showSuccessToast({
|
|
41
|
+
title: "Webhook saved successfully!"
|
|
42
|
+
});
|
|
43
|
+
}, [
|
|
44
|
+
presenter
|
|
45
|
+
]);
|
|
46
|
+
const { vm } = presenter;
|
|
47
|
+
return /*#__PURE__*/ react.createElement(SimpleForm, null, vm.loading ? /*#__PURE__*/ react.createElement(OverlayLoader, {
|
|
48
|
+
text: "Loading..."
|
|
49
|
+
}) : null, vm.saving ? /*#__PURE__*/ react.createElement(OverlayLoader, {
|
|
50
|
+
text: "Saving..."
|
|
51
|
+
}) : null, vm.form.errors.length > 0 ? /*#__PURE__*/ react.createElement("div", {
|
|
52
|
+
className: "mb-lg"
|
|
53
|
+
}, /*#__PURE__*/ react.createElement(FormErrors, {
|
|
54
|
+
form: vm.form
|
|
55
|
+
})) : null, /*#__PURE__*/ react.createElement(SimpleFormHeader, {
|
|
56
|
+
title: vm.isNew ? "Create Webhook" : vm.webhook?.name ?? "Edit Webhook"
|
|
57
|
+
}), /*#__PURE__*/ react.createElement(SimpleFormContent, null, /*#__PURE__*/ react.createElement(FormView, {
|
|
58
|
+
name: "Webhook",
|
|
59
|
+
form: vm.form,
|
|
60
|
+
renderers: renderers
|
|
61
|
+
}), /*#__PURE__*/ react.createElement(SigningSecret, {
|
|
62
|
+
presenter: presenter
|
|
63
|
+
})), /*#__PURE__*/ react.createElement(SimpleFormFooter, {
|
|
64
|
+
className: "border-t-sm border-t-neutral-dimmed pt-lg"
|
|
65
|
+
}, /*#__PURE__*/ react.createElement(Button, {
|
|
42
66
|
variant: "secondary",
|
|
43
67
|
onClick: ()=>goToRoute(Routes.List)
|
|
44
|
-
}, "Cancel"),
|
|
68
|
+
}, "Cancel"), /*#__PURE__*/ react.createElement(HasPermission, {
|
|
69
|
+
entity: "webhook",
|
|
70
|
+
action: "edit"
|
|
71
|
+
}, /*#__PURE__*/ react.createElement(Button, {
|
|
45
72
|
variant: "primary",
|
|
46
|
-
onClick:
|
|
73
|
+
onClick: saveForm,
|
|
47
74
|
disabled: vm.saving
|
|
48
|
-
}, vm.saving ? "Saving..." : "Save")))
|
|
49
|
-
className: "p-lg"
|
|
50
|
-
}, /*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(FormErrors, {
|
|
51
|
-
form: vm.form
|
|
52
|
-
}), /*#__PURE__*/ react.createElement(FormView, {
|
|
53
|
-
name: "Webhook",
|
|
54
|
-
form: vm.form
|
|
55
|
-
}), !vm.isNew && vm.webhook?.signingSecret && /*#__PURE__*/ react.createElement(SigningSecret, {
|
|
56
|
-
secret: vm.webhook.signingSecret
|
|
57
|
-
})))), vm.showDeliveries && vm.webhook && /*#__PURE__*/ react.createElement(WebhookDeliveriesDrawer, {
|
|
58
|
-
webhookId: vm.webhook.id,
|
|
59
|
-
open: vm.showDeliveries,
|
|
60
|
-
onClose: ()=>actions.closeDeliveries()
|
|
61
|
-
}));
|
|
75
|
+
}, vm.saving ? "Saving..." : "Save"))));
|
|
62
76
|
});
|
|
63
77
|
const WebhookFormView = ()=>{
|
|
64
78
|
const container = useContainer();
|