@cakemail-org/ui-components-v2 2.2.102 → 2.2.103

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.
Files changed (31) hide show
  1. package/dist/cjs/components/index.d.ts +1 -0
  2. package/dist/cjs/components/scopePicker/index.d.ts +8 -0
  3. package/dist/cjs/components/scopePicker/scopeGroups.d.ts +21 -0
  4. package/dist/cjs/components/scopePicker/types.d.ts +1 -0
  5. package/dist/cjs/factories/index.d.ts +1 -0
  6. package/dist/cjs/factories/personalAccessTokens/index.d.ts +22 -0
  7. package/dist/cjs/factories/personalAccessTokens/types.d.ts +1 -0
  8. package/dist/cjs/index.js +435 -0
  9. package/dist/cjs/models/index.d.ts +1 -0
  10. package/dist/cjs/models/personalAccessToken/index.d.ts +21 -0
  11. package/dist/cjs/models/personalAccessToken/types.d.ts +10 -0
  12. package/dist/cjs/services/index.d.ts +1 -0
  13. package/dist/cjs/services/personalAccessTokens/index.d.ts +24 -0
  14. package/dist/cjs/services/personalAccessTokens/types.d.ts +1 -0
  15. package/dist/cjs/utils/posthog.d.ts +5 -1
  16. package/dist/esm/components/index.d.ts +1 -0
  17. package/dist/esm/components/scopePicker/index.d.ts +8 -0
  18. package/dist/esm/components/scopePicker/scopeGroups.d.ts +21 -0
  19. package/dist/esm/components/scopePicker/types.d.ts +1 -0
  20. package/dist/esm/factories/index.d.ts +1 -0
  21. package/dist/esm/factories/personalAccessTokens/index.d.ts +22 -0
  22. package/dist/esm/factories/personalAccessTokens/types.d.ts +1 -0
  23. package/dist/esm/index.js +429 -2
  24. package/dist/esm/models/index.d.ts +1 -0
  25. package/dist/esm/models/personalAccessToken/index.d.ts +21 -0
  26. package/dist/esm/models/personalAccessToken/types.d.ts +10 -0
  27. package/dist/esm/services/index.d.ts +1 -0
  28. package/dist/esm/services/personalAccessTokens/index.d.ts +24 -0
  29. package/dist/esm/services/personalAccessTokens/types.d.ts +1 -0
  30. package/dist/esm/utils/posthog.d.ts +5 -1
  31. package/package.json +1 -1
@@ -37,6 +37,7 @@ export * from "./modal";
37
37
  export * from "./overlay";
38
38
  export * from "./radio";
39
39
  export * from "./resourceEdit";
40
+ export * from "./scopePicker";
40
41
  export * from "./search";
41
42
  export * from "./sideMenu";
42
43
  export * from "./sideMenu/sideMenuContainer";
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ export type TScopePicker = {
3
+ value: string[];
4
+ onChange: (scopes: string[]) => void;
5
+ isPartner?: boolean;
6
+ disabled?: boolean;
7
+ };
8
+ export declare function ScopePicker({ value, onChange, isPartner, disabled }: TScopePicker): React.JSX.Element;
@@ -0,0 +1,21 @@
1
+ export type TScopeAction = "read" | "write" | "delete" | "send" | "import" | "export" | "admin";
2
+ export type TScopeResource = {
3
+ resource: string;
4
+ label: string;
5
+ actions: TScopeAction[];
6
+ };
7
+ export type TScopeCategory = {
8
+ id: string;
9
+ label: string;
10
+ adminOnly: boolean;
11
+ resources: TScopeResource[];
12
+ };
13
+ export declare const SCOPE_IMPLICATIONS: Record<string, string[]>;
14
+ export declare const SCOPE_CATEGORIES: TScopeCategory[];
15
+ export type TScopePreset = {
16
+ id: string;
17
+ label: string;
18
+ scopes: string[];
19
+ };
20
+ export declare function getCategoryScopes(categoryId: string): string[];
21
+ export declare const SCOPE_PRESETS: TScopePreset[];
@@ -0,0 +1 @@
1
+ export { TScopePicker } from ".";
@@ -9,6 +9,7 @@ export * from "./emailAPI";
9
9
  export * from "./forms";
10
10
  export * from "./lists";
11
11
  export * from "./pages";
12
+ export * from "./personalAccessTokens";
12
13
  export * from "./popups";
13
14
  export * from "./senders";
14
15
  export * from "./suppressedEmails";
@@ -0,0 +1,22 @@
1
+ import { PersonalAccessTokenModel } from "../../models/personalAccessToken";
2
+ import { TGenericListReturn } from "../../types";
3
+ export declare class PersonalAccessTokensFactory {
4
+ static list({ page, perPage, status }?: {
5
+ page?: number;
6
+ perPage?: number;
7
+ status?: string;
8
+ }): Promise<TGenericListReturn<PersonalAccessTokenModel>>;
9
+ static get({ keyPrefix }: {
10
+ keyPrefix: string;
11
+ }): Promise<PersonalAccessTokenModel>;
12
+ static create({ name, scopes, expiresAt, allowedAccountIds }: {
13
+ name: string;
14
+ scopes: string[];
15
+ expiresAt?: number | null;
16
+ allowedAccountIds?: string[] | null;
17
+ }): Promise<{
18
+ pat: PersonalAccessTokenModel;
19
+ plaintext: string;
20
+ }>;
21
+ }
22
+ export * from "./types";
@@ -0,0 +1 @@
1
+ export {};
package/dist/cjs/index.js CHANGED
@@ -3895,6 +3895,10 @@ exports.EEvents = void 0;
3895
3895
  EEvents["CUSTOM_DOMAIN_CREATED"] = "CustomDomain.Created";
3896
3896
  EEvents["CUSTOM_DOMAIN_VERIFIED"] = "CustomDomain.Verified";
3897
3897
  EEvents["CUSTOM_DOMAIN_DELETED"] = "CustomDomain.Deleted";
3898
+ EEvents["PAT_CREATED"] = "PAT.Created";
3899
+ EEvents["PAT_UPDATED"] = "PAT.Updated";
3900
+ EEvents["PAT_REVOKED"] = "PAT.Revoked";
3901
+ EEvents["PAT_TOKEN_COPIED"] = "PAT.Token.Copied";
3898
3902
  })(exports.EEvents || (exports.EEvents = {}));
3899
3903
  function eventCondition(type, disabledEvents) {
3900
3904
  if (disabledEvents === void 0) { disabledEvents = []; }
@@ -11711,6 +11715,57 @@ function renderPage(_a) {
11711
11715
  });
11712
11716
  }
11713
11717
 
11718
+ var BASE_URL = function () { return uiKitConfig.GATEWAY_PROXY + "/pats"; };
11719
+ function listPats(_a) {
11720
+ var page = _a.page, perPage = _a.perPage, status = _a.status;
11721
+ return callApi({
11722
+ url: BASE_URL(),
11723
+ query: camelCase({ page: page, per_page: perPage, status: status }),
11724
+ fetchOptions: { method: exports.EMethods.get }
11725
+ });
11726
+ }
11727
+ function getPat(_a) {
11728
+ var keyPrefix = _a.keyPrefix;
11729
+ return callApi({
11730
+ url: "".concat(BASE_URL(), "/").concat(keyPrefix),
11731
+ fetchOptions: { method: exports.EMethods.get }
11732
+ });
11733
+ }
11734
+ function createPat(_a) {
11735
+ var name = _a.name, scopes = _a.scopes, expiresAt = _a.expiresAt, allowedAccountIds = _a.allowedAccountIds;
11736
+ return callApi({
11737
+ url: BASE_URL(),
11738
+ fetchOptions: {
11739
+ method: exports.EMethods.post,
11740
+ body: { name: name, scopes: scopes, expires_at: expiresAt !== null && expiresAt !== void 0 ? expiresAt : null, allowed_account_ids: allowedAccountIds !== null && allowedAccountIds !== void 0 ? allowedAccountIds : null }
11741
+ }
11742
+ });
11743
+ }
11744
+ function updatePat(_a) {
11745
+ var keyPrefix = _a.keyPrefix, name = _a.name, scopes = _a.scopes, allowedAccountIds = _a.allowedAccountIds;
11746
+ var body = {};
11747
+ if (name !== undefined)
11748
+ body.name = name;
11749
+ if (scopes !== undefined)
11750
+ body.scopes = scopes;
11751
+ if (allowedAccountIds !== undefined)
11752
+ body.allowed_account_ids = allowedAccountIds;
11753
+ return callApi({
11754
+ url: "".concat(BASE_URL(), "/").concat(keyPrefix),
11755
+ fetchOptions: {
11756
+ method: exports.EMethods.patch,
11757
+ body: body
11758
+ }
11759
+ });
11760
+ }
11761
+ function revokePat(_a) {
11762
+ var keyPrefix = _a.keyPrefix;
11763
+ return callApi({
11764
+ url: "".concat(BASE_URL(), "/").concat(keyPrefix),
11765
+ fetchOptions: { method: exports.EMethods.delete }
11766
+ });
11767
+ }
11768
+
11714
11769
  function listPopups(_a) {
11715
11770
  return __awaiter(this, void 0, void 0, function () {
11716
11771
  var options = __rest(_a, []);
@@ -12812,6 +12867,47 @@ var PageModel = /** @class */ (function (_super) {
12812
12867
  return PageModel;
12813
12868
  }(ListPageModel));
12814
12869
 
12870
+ var PersonalAccessTokenModel = /** @class */ (function () {
12871
+ function PersonalAccessTokenModel(params) {
12872
+ this.key_prefix = params.key_prefix;
12873
+ this.name = params.name;
12874
+ this.status = params.status;
12875
+ this.scopes = params.scopes;
12876
+ this.allowed_account_ids = params.allowed_account_ids;
12877
+ this.created_at = params.created_at;
12878
+ this.expires_at = params.expires_at;
12879
+ this.revoked_at = params.revoked_at;
12880
+ }
12881
+ PersonalAccessTokenModel.prototype.toJson = function () { return modelToJson(this); };
12882
+ PersonalAccessTokenModel.prototype.set = function (property, value) { modelSet(this, property, value); };
12883
+ PersonalAccessTokenModel.prototype.update = function (_a) {
12884
+ return __awaiter(this, arguments, void 0, function (_b) {
12885
+ var _this = this;
12886
+ var name = _b.name, scopes = _b.scopes, allowedAccountIds = _b.allowedAccountIds;
12887
+ return __generator(this, function (_c) {
12888
+ return [2 /*return*/, updatePat({ keyPrefix: this.key_prefix, name: name, scopes: scopes, allowedAccountIds: allowedAccountIds })
12889
+ .then(function (data) {
12890
+ trackEvent(exports.EEvents.PAT_UPDATED, { key_prefix: _this.key_prefix });
12891
+ return new PersonalAccessTokenModel(data.data);
12892
+ })];
12893
+ });
12894
+ });
12895
+ };
12896
+ PersonalAccessTokenModel.prototype.revoke = function () {
12897
+ return __awaiter(this, void 0, void 0, function () {
12898
+ var _this = this;
12899
+ return __generator(this, function (_a) {
12900
+ return [2 /*return*/, revokePat({ keyPrefix: this.key_prefix })
12901
+ .then(function (data) {
12902
+ trackEvent(exports.EEvents.PAT_REVOKED, { key_prefix: _this.key_prefix });
12903
+ return new PersonalAccessTokenModel(data.data);
12904
+ })];
12905
+ });
12906
+ });
12907
+ };
12908
+ return PersonalAccessTokenModel;
12909
+ }());
12910
+
12815
12911
  exports.EPopupTriggerType = void 0;
12816
12912
  (function (EPopupTriggerType) {
12817
12913
  EPopupTriggerType["on_page_load"] = "on_page_load";
@@ -18908,6 +19004,298 @@ function ResourceEdit(_a) {
18908
19004
  support && React.createElement(material.Box, { className: "resource-support ".concat(!open ? "open" : "hidden") }, support));
18909
19005
  }
18910
19006
 
19007
+ // Scope implication rules
19008
+ var SCOPE_IMPLICATIONS = {
19009
+ "write": ["read"],
19010
+ "delete": ["read"],
19011
+ "send": ["read"],
19012
+ "import": ["read", "write"],
19013
+ "export": ["read"],
19014
+ "admin": ["read", "write", "delete"],
19015
+ };
19016
+ var SCOPE_CATEGORIES = [
19017
+ {
19018
+ id: "audience",
19019
+ label: "Audience",
19020
+ adminOnly: false,
19021
+ resources: [
19022
+ { resource: "lists", label: "Lists", actions: ["read", "write", "delete"] },
19023
+ { resource: "contacts", label: "Contacts", actions: ["read", "write", "delete", "import", "export"] },
19024
+ { resource: "segments", label: "Segments", actions: ["read", "write", "delete"] },
19025
+ { resource: "tags", label: "Tags", actions: ["read", "write", "delete"] },
19026
+ { resource: "custom_attributes", label: "Custom Attributes", actions: ["read", "write", "delete"] },
19027
+ { resource: "interests", label: "Interests", actions: ["read", "write", "delete"] },
19028
+ ]
19029
+ },
19030
+ {
19031
+ id: "suppressions",
19032
+ label: "Suppressions",
19033
+ adminOnly: false,
19034
+ resources: [
19035
+ { resource: "suppressions", label: "Suppressions", actions: ["read", "write", "delete"] },
19036
+ ]
19037
+ },
19038
+ {
19039
+ id: "campaigns",
19040
+ label: "Campaigns",
19041
+ adminOnly: false,
19042
+ resources: [
19043
+ { resource: "campaigns", label: "Campaigns", actions: ["read", "write", "delete", "send"] },
19044
+ { resource: "campaign_blueprints", label: "Campaign Blueprints", actions: ["read", "write", "delete"] },
19045
+ ]
19046
+ },
19047
+ {
19048
+ id: "templates",
19049
+ label: "Templates",
19050
+ adminOnly: false,
19051
+ resources: [
19052
+ { resource: "templates", label: "Templates", actions: ["read", "write", "delete"] },
19053
+ ]
19054
+ },
19055
+ {
19056
+ id: "emailapi",
19057
+ label: "Email API",
19058
+ adminOnly: false,
19059
+ resources: [
19060
+ { resource: "email_api", label: "Email API", actions: ["read", "send"] },
19061
+ ]
19062
+ },
19063
+ {
19064
+ id: "forms",
19065
+ label: "Forms",
19066
+ adminOnly: false,
19067
+ resources: [
19068
+ { resource: "forms", label: "Forms", actions: ["read", "write", "delete"] },
19069
+ { resource: "preference_centers", label: "Preference Centers", actions: ["read", "write", "delete"] },
19070
+ ]
19071
+ },
19072
+ {
19073
+ id: "deliverability",
19074
+ label: "Deliverability",
19075
+ adminOnly: false,
19076
+ resources: [
19077
+ { resource: "senders", label: "Senders", actions: ["read", "write", "delete"] },
19078
+ { resource: "dkim", label: "DKIM", actions: ["read", "write", "delete"] },
19079
+ { resource: "domains", label: "Domains", actions: ["read", "write", "delete"] },
19080
+ { resource: "logos", label: "Logos", actions: ["read", "write", "delete"] },
19081
+ ]
19082
+ },
19083
+ {
19084
+ id: "webhooks",
19085
+ label: "Webhooks",
19086
+ adminOnly: false,
19087
+ resources: [
19088
+ { resource: "webhooks", label: "Webhooks", actions: ["read", "write", "delete"] },
19089
+ ]
19090
+ },
19091
+ {
19092
+ id: "analytics",
19093
+ label: "Analytics",
19094
+ adminOnly: false,
19095
+ resources: [
19096
+ { resource: "reports", label: "Reports", actions: ["read", "export"] },
19097
+ { resource: "logs", label: "Logs", actions: ["read", "export"] },
19098
+ { resource: "links", label: "Links", actions: ["read"] },
19099
+ { resource: "tasks", label: "Tasks", actions: ["read"] },
19100
+ ]
19101
+ },
19102
+ {
19103
+ id: "account",
19104
+ label: "Account",
19105
+ adminOnly: false,
19106
+ resources: [
19107
+ { resource: "account", label: "Account", actions: ["read", "write"] },
19108
+ ]
19109
+ },
19110
+ {
19111
+ id: "users_admin",
19112
+ label: "Users (Admin)",
19113
+ adminOnly: true,
19114
+ resources: [
19115
+ { resource: "users", label: "Users", actions: ["read", "write", "admin"] },
19116
+ ]
19117
+ },
19118
+ {
19119
+ id: "subaccounts_admin",
19120
+ label: "Sub-accounts (Admin)",
19121
+ adminOnly: true,
19122
+ resources: [
19123
+ { resource: "sub_accounts", label: "Sub-accounts", actions: ["read", "write", "admin"] },
19124
+ ]
19125
+ },
19126
+ {
19127
+ id: "tokens_admin",
19128
+ label: "Tokens (Admin)",
19129
+ adminOnly: true,
19130
+ resources: [
19131
+ { resource: "tokens", label: "Access Tokens", actions: ["read", "admin"] },
19132
+ ]
19133
+ },
19134
+ ];
19135
+ // Helper to get all scopes for a category
19136
+ function getCategoryScopes(categoryId) {
19137
+ var cat = SCOPE_CATEGORIES.find(function (c) { return c.id === categoryId; });
19138
+ if (!cat)
19139
+ return [];
19140
+ return cat.resources.flatMap(function (r) { return r.actions.map(function (a) { return "".concat(r.resource, ":").concat(a); }); });
19141
+ }
19142
+ var SCOPE_PRESETS = [
19143
+ {
19144
+ id: "readonly",
19145
+ label: "Read-only (all)",
19146
+ scopes: SCOPE_CATEGORIES
19147
+ .filter(function (c) { return !c.adminOnly; })
19148
+ .flatMap(function (c) { return c.resources.map(function (r) { return "".concat(r.resource, ":read"); }); })
19149
+ },
19150
+ {
19151
+ id: "full",
19152
+ label: "Full access",
19153
+ scopes: SCOPE_CATEGORIES
19154
+ .filter(function (c) { return !c.adminOnly; })
19155
+ .flatMap(function (c) { return c.resources.flatMap(function (r) { return r.actions.map(function (a) { return "".concat(r.resource, ":").concat(a); }); }); })
19156
+ },
19157
+ {
19158
+ id: "campaigns",
19159
+ label: "Campaigns manager",
19160
+ scopes: __spreadArray(__spreadArray(__spreadArray([], getCategoryScopes("campaigns"), true), getCategoryScopes("templates"), true), [
19161
+ "senders:read",
19162
+ "reports:read",
19163
+ ], false)
19164
+ },
19165
+ {
19166
+ id: "contacts",
19167
+ label: "Contact manager",
19168
+ scopes: __spreadArray(__spreadArray([], getCategoryScopes("audience"), true), getCategoryScopes("suppressions"), true)
19169
+ },
19170
+ {
19171
+ id: "developer",
19172
+ label: "Developer",
19173
+ scopes: __spreadArray(__spreadArray(__spreadArray([], getCategoryScopes("emailapi"), true), getCategoryScopes("webhooks"), true), [
19174
+ "reports:read", "logs:read",
19175
+ ], false)
19176
+ },
19177
+ ];
19178
+
19179
+ function getImpliedScopes(scope) {
19180
+ var _a = scope.split(":"), resource = _a[0], action = _a[1];
19181
+ var implied = SCOPE_IMPLICATIONS[action] || [];
19182
+ return implied.map(function (a) { return "".concat(resource, ":").concat(a); });
19183
+ }
19184
+ function ScopePicker(_a) {
19185
+ var value = _a.value, onChange = _a.onChange, _b = _a.isPartner, isPartner = _b === void 0 ? false : _b, _c = _a.disabled, disabled = _c === void 0 ? false : _c;
19186
+ var _d = React.useState(new Set()), expandedCategories = _d[0], setExpandedCategories = _d[1];
19187
+ var selectedSet = React.useMemo(function () { return new Set(value); }, [value]);
19188
+ var visibleCategories = React.useMemo(function () { return SCOPE_CATEGORIES.filter(function (c) { return !c.adminOnly || isPartner; }); }, [isPartner]);
19189
+ var toggleCategory = React.useCallback(function (categoryId) {
19190
+ setExpandedCategories(function (prev) {
19191
+ var next = new Set(prev);
19192
+ if (next.has(categoryId))
19193
+ next.delete(categoryId);
19194
+ else
19195
+ next.add(categoryId);
19196
+ return next;
19197
+ });
19198
+ }, []);
19199
+ var handleScopeToggle = React.useCallback(function (scope, checked) {
19200
+ if (disabled)
19201
+ return;
19202
+ var next = new Set(selectedSet);
19203
+ if (checked) {
19204
+ next.add(scope);
19205
+ // Add implied scopes
19206
+ getImpliedScopes(scope).forEach(function (s) { return next.add(s); });
19207
+ }
19208
+ else {
19209
+ next.delete(scope);
19210
+ }
19211
+ onChange(Array.from(next));
19212
+ }, [selectedSet, onChange, disabled]);
19213
+ var handleCategorySelectAll = React.useCallback(function (categoryId, checked) {
19214
+ if (disabled)
19215
+ return;
19216
+ var cat = SCOPE_CATEGORIES.find(function (c) { return c.id === categoryId; });
19217
+ if (!cat)
19218
+ return;
19219
+ var next = new Set(selectedSet);
19220
+ cat.resources.forEach(function (r) {
19221
+ r.actions.forEach(function (a) {
19222
+ var scope = "".concat(r.resource, ":").concat(a);
19223
+ if (checked) {
19224
+ next.add(scope);
19225
+ getImpliedScopes(scope).forEach(function (s) { return next.add(s); });
19226
+ }
19227
+ else {
19228
+ next.delete(scope);
19229
+ }
19230
+ });
19231
+ });
19232
+ onChange(Array.from(next));
19233
+ }, [selectedSet, onChange, disabled]);
19234
+ var handlePreset = React.useCallback(function (presetId) {
19235
+ if (disabled)
19236
+ return;
19237
+ var preset = SCOPE_PRESETS.find(function (p) { return p.id === presetId; });
19238
+ if (!preset)
19239
+ return;
19240
+ // Expand all implied scopes
19241
+ var expanded = new Set();
19242
+ preset.scopes.forEach(function (s) {
19243
+ expanded.add(s);
19244
+ getImpliedScopes(s).forEach(function (implied) { return expanded.add(implied); });
19245
+ });
19246
+ onChange(Array.from(expanded));
19247
+ }, [onChange, disabled]);
19248
+ var isCategoryAllSelected = React.useCallback(function (categoryId) {
19249
+ var cat = SCOPE_CATEGORIES.find(function (c) { return c.id === categoryId; });
19250
+ if (!cat)
19251
+ return false;
19252
+ return cat.resources.every(function (r) { return r.actions.every(function (a) { return selectedSet.has("".concat(r.resource, ":").concat(a)); }); });
19253
+ }, [selectedSet]);
19254
+ var isImplied = React.useCallback(function (scope) {
19255
+ // Scope is implied (auto-selected due to another scope) if removing it wouldn't break anything
19256
+ var _a = scope.split(":"), resource = _a[0], action = _a[1];
19257
+ // Check if any other selected scope implies this one
19258
+ return Array.from(selectedSet).some(function (s) {
19259
+ if (s === scope)
19260
+ return false;
19261
+ var _a = s.split(":"), r = _a[0], a = _a[1];
19262
+ if (r !== resource)
19263
+ return false;
19264
+ return (SCOPE_IMPLICATIONS[a] || []).includes(action);
19265
+ });
19266
+ }, [selectedSet]);
19267
+ return (React.createElement("div", { className: "scopePicker", "aria-label": "Permission scope picker" },
19268
+ React.createElement("div", { className: "scopePicker__presets" },
19269
+ React.createElement("span", { className: "scopePicker__presetsLabel" }, "Quick presets:"),
19270
+ React.createElement("div", { className: "scopePicker__presetButtons" }, SCOPE_PRESETS.map(function (preset) { return (React.createElement("button", { key: preset.id, type: "button", className: "scopePicker__presetBtn", onClick: function () { return handlePreset(preset.id); }, disabled: disabled }, preset.label)); }))),
19271
+ React.createElement("div", { className: "scopePicker__categories" }, visibleCategories.map(function (category) {
19272
+ var isExpanded = expandedCategories.has(category.id);
19273
+ var allSelected = isCategoryAllSelected(category.id);
19274
+ return (React.createElement("div", { key: category.id, className: "scopePicker__category ".concat(category.adminOnly ? "scopePicker__category--admin" : "") },
19275
+ React.createElement("div", { className: "scopePicker__categoryHeader" },
19276
+ React.createElement("label", { className: "scopePicker__categorySelect" },
19277
+ React.createElement("input", { type: "checkbox", checked: allSelected, onChange: function (e) { return handleCategorySelectAll(category.id, e.target.checked); }, disabled: disabled, "aria-label": "Select all ".concat(category.label, " scopes") }),
19278
+ React.createElement("span", { className: "scopePicker__categoryLabel" }, category.label)),
19279
+ React.createElement("button", { type: "button", className: "scopePicker__categoryToggle", onClick: function () { return toggleCategory(category.id); }, "aria-expanded": isExpanded, "aria-label": "".concat(isExpanded ? "Collapse" : "Expand", " ").concat(category.label) }, isExpanded ? "▲" : "▼")),
19280
+ isExpanded && (React.createElement("div", { className: "scopePicker__categoryBody" }, category.resources.map(function (resource) { return (React.createElement("div", { key: resource.resource, className: "scopePicker__resource" },
19281
+ React.createElement("span", { className: "scopePicker__resourceLabel" }, resource.label),
19282
+ React.createElement("div", { className: "scopePicker__actions" }, resource.actions.map(function (action) {
19283
+ var scope = "".concat(resource.resource, ":").concat(action);
19284
+ var checked = selectedSet.has(scope);
19285
+ var implied = isImplied(scope);
19286
+ return (React.createElement("label", { key: action, className: "scopePicker__action ".concat(implied ? "scopePicker__action--implied" : ""), title: implied ? "Automatically included by another selected permission" : undefined },
19287
+ React.createElement("input", { type: "checkbox", checked: checked, onChange: function (e) { return handleScopeToggle(scope, e.target.checked); }, disabled: disabled || implied, "aria-label": "".concat(resource.label, " ").concat(action) }),
19288
+ React.createElement("span", null, action)));
19289
+ })))); })))));
19290
+ })),
19291
+ value.length > 0 && (React.createElement("details", { className: "scopePicker__summary" },
19292
+ React.createElement("summary", null,
19293
+ "Selected permissions (",
19294
+ value.length,
19295
+ ")"),
19296
+ React.createElement("div", { className: "scopePicker__summaryList" }, value.sort().map(function (scope) { return (React.createElement("span", { key: scope, className: "scopePicker__summaryChip" }, scope)); }))))));
19297
+ }
19298
+
18911
19299
  var css_248z$2 = ".sideMenu-component-v2 {\n z-index: 8000;\n width: -moz-fit-content;\n width: fit-content;\n}\n.sideMenu-component-v2 .sideMenu-spacer {\n display: none;\n}\n.sideMenu-component-v2.minified:hover .sideMenu-spacer {\n display: block;\n}\n.sideMenu-component-v2 .sideMenu-wrapper {\n z-index: 8000;\n display: flex;\n height: 100%;\n flex-direction: column;\n width: 20rem;\n min-width: 20rem;\n max-width: 20rem;\n padding: 1rem;\n background: var(--shade100, #F3F2F2);\n position: relative;\n box-sizing: border-box;\n}\n.sideMenu-component-v2 .sideMenu-wrapper::-webkit-scrollbar {\n display: block;\n}\n.sideMenu-component-v2 .sideMenu-wrapper::-webkit-scrollbar-track:horizontal {\n position: absolute;\n bottom: -20px;\n}\n.sideMenu-component-v2 .sideMenu-wrapper::-webkit-scrollbar-track:vertical {\n border-bottom-left-radius: 0 !important;\n border-bottom-right-radius: 8px !important;\n border-top-right-radius: 8px !important;\n}\n.sideMenu-component-v2 .sideMenu-wrapper::-webkit-scrollbar-track {\n height: 2.5rem;\n width: 2.5rem;\n padding: 2rem;\n background-clip: content-box;\n border-bottom-left-radius: 8px;\n}\n.sideMenu-component-v2 .sideMenu-wrapper::-webkit-scrollbar-thumb {\n background: var(--body-font-color-2, var(--silver, #9B9B9B));\n border-radius: 24px;\n border-top: 5px solid var(--background-color-1, var(--white, #FFFFFF));\n border-bottom: 5px solid var(--background-color-1, var(--white, #FFFFFF));\n border-right: 5px solid var(--background-color-1, var(--white, #FFFFFF));\n border-left: 5px solid var(--background-color-1, var(--white, #FFFFFF));\n}\n.sideMenu-component-v2 .sideMenu-wrapper.minified:hover {\n box-shadow: 0px 0px 32px 0px rgba(0, 0, 0, 0.15);\n position: absolute !important;\n}\n.sideMenu-component-v2 .sideMenu-wrapper.minified:not(:hover) {\n gap: 1rem;\n max-width: 73px;\n min-width: 73px;\n}\n.sideMenu-component-v2 .sideMenu-wrapper.minified:not(:hover) .sideMenuHeader {\n display: none;\n}\n.sideMenu-component-v2 .sideMenu-wrapper.minified:not(:hover) .subNav-component-v2 button {\n padding: 0.75rem;\n margin-right: 0;\n}\n.sideMenu-component-v2 .sideMenu-wrapper.minified:not(:hover) .subNav-component-v2 button:not(.selected) {\n display: none;\n}\n.sideMenu-component-v2 .sideMenu-wrapper.minified:not(:hover) .sideMenuContainer-component-v2 .menuItemRow .sideMenuItem-component-v2.subItem,\n.sideMenu-component-v2 .sideMenu-wrapper.minified:not(:hover) .sideMenuContainer-component-v2 .menuItemRow .sideMenuItem-component-v2 .chevron {\n display: none;\n}\n.sideMenu-component-v2 .sideMenu-wrapper.minified:not(:hover) .sideMenuContainer-component-v2 .menuItemRow .sideMenuItem-component-v2 a {\n justify-content: center;\n}\n.sideMenu-component-v2 .sideMenu-wrapper.minified:not(:hover) .sideMenuContainer-component-v2 .menuItemRow .sideMenuItem-component-v2 a .MuiStack-root {\n display: none;\n}\n.sideMenu-component-v2 .sideMenu-wrapper.minified:not(:hover) .footer > .avatar-component-v2 {\n display: block;\n}\n.sideMenu-component-v2 .sideMenu-wrapper.minified:not(:hover) .footer button {\n display: none;\n}\n.sideMenu-component-v2 .sideMenu-wrapper .sideMenuHeader {\n margin-bottom: 1.5rem;\n}\n.sideMenu-component-v2 .sideMenu-wrapper .sideMenuHeader .minifyIcon {\n cursor: pointer;\n}\n.sideMenu-component-v2 .sideMenu-wrapper .search-component-v2 {\n margin-top: 1.5rem;\n position: relative;\n}\n.sideMenu-component-v2 .sideMenu-wrapper .search-component-v2 .inputContainer {\n padding: 0.75rem 1rem;\n box-shadow: unset;\n border-radius: 8px;\n border: 1px solid var(--shade200, #DBDADA);\n}\n.sideMenu-component-v2 .sideMenu-wrapper .search-component-v2:after {\n position: absolute;\n left: 0;\n bottom: -1.5rem;\n content: \"\";\n display: block;\n width: 100%;\n height: 1.5rem;\n background: linear-gradient(var(--shade100, #F3F2F2) 0%, transparent 100%);\n}\n.sideMenu-component-v2 .sideMenu-wrapper .subNav-component-v2 {\n width: 100%;\n position: relative;\n justify-content: space-between;\n}\n.sideMenu-component-v2 .sideMenu-wrapper .subNav-component-v2:after {\n position: absolute;\n left: 0;\n bottom: -1.5rem;\n content: \"\";\n display: block;\n width: 100%;\n height: 1.5rem;\n background: linear-gradient(var(--shade100, #F3F2F2) 0%, transparent 100%);\n}\n.sideMenu-component-v2 .sideMenu-wrapper .subNav-component-v2 button {\n flex: 1;\n}\n.sideMenu-component-v2 .sideMenu-wrapper .subNav-component-v2 button:not(.selected):not(:hover) {\n background: none;\n}\n.sideMenu-component-v2 .sideMenu-wrapper .subNav-component-v2 button:not(.selected):not(:hover) svg path:not(.noFill),\n.sideMenu-component-v2 .sideMenu-wrapper .subNav-component-v2 button:not(.selected):not(:hover) svg rect:not(.noFill) {\n fill: var(--secondary-brand-color, var(--teal, #0ABDAE));\n}\n.sideMenu-component-v2 .sideMenu-wrapper .subNav-component-v2 button:not(.selected):not(:hover) svg path.noFill,\n.sideMenu-component-v2 .sideMenu-wrapper .subNav-component-v2 button:not(.selected):not(:hover) svg rect.noFill {\n stroke: var(--secondary-brand-color, var(--teal, #0ABDAE));\n}\n.sideMenu-component-v2 .sideMenu-wrapper .sideMenuContainer-component-v2 {\n padding-top: 1.5rem;\n padding-bottom: 1.5rem;\n}\n.sideMenu-component-v2 .sideMenu-wrapper .footer {\n position: relative;\n justify-self: flex-end;\n}\n.sideMenu-component-v2 .sideMenu-wrapper .footer:before {\n position: absolute;\n left: 0;\n top: -1.5rem;\n content: \"\";\n display: block;\n width: 100%;\n height: 1.5rem;\n background: linear-gradient(transparent 0, var(--shade100, #F3F2F2) 100%);\n}\n.sideMenu-component-v2 .sideMenu-wrapper .footer > .avatar-component-v2 {\n display: none;\n}\n\n.sideMenuContainer-component-v2 {\n flex: 1;\n overflow-y: auto;\n}\n.sideMenuContainer-component-v2 .menuItemsContainer > .menuItemRow.divider {\n margin-top: 1rem;\n margin-bottom: 1rem;\n}\n.sideMenuContainer-component-v2 .menuItemsContainer > .menuItemRow.withSubItems.openedSubMenu .sideMenuItem-component-v2:nth-child(2) {\n margin-top: calc(0.5rem - 1px);\n}\n.sideMenuContainer-component-v2 .menuItemsContainer > .menuItemRow.withSubItems.openedSubMenu .sideMenuItem-component-v2:last-child {\n margin-bottom: calc(0.5rem - 1px);\n}\n.sideMenuContainer-component-v2 .menuItemsContainer > .menuItemRow.subSection {\n margin-top: 1rem;\n}\n.sideMenuContainer-component-v2 .menuItemsContainer > .menuItemRow:first-child {\n margin-top: 0;\n}\n.sideMenuContainer-component-v2 .menuItemsContainer .sideMenuItem-component-v2.subItem {\n margin-left: 2.75rem;\n}\n.sideMenuContainer-component-v2 .menuItemsContainer .sideMenuItem-component-v2.subItem > a,\n.sideMenuContainer-component-v2 .menuItemsContainer .sideMenuItem-component-v2.subItem > a > div > span {\n font-size: 0.875rem;\n}\n.sideMenuContainer-component-v2 .menuItemsContainer .sideMenuItem-component-v2.rotate .chevron {\n rotate: 180deg;\n}\n.sideMenuContainer-component-v2 .menuItemsContainer .sideMenuItem-component-v2.hasLocationSelected:hover a {\n cursor: default;\n background: unset !important;\n}\n\n.sideMenuItem-component-v2 {\n box-sizing: border-box;\n}\n.sideMenuItem-component-v2:hover a, .sideMenuItem-component-v2.selected a {\n background: var(--shade200, #DBDADA);\n}\n.sideMenuItem-component-v2.hasSubItemSelected > .MuiTypography-root .chevron {\n rotate: -90deg;\n}\n.sideMenuItem-component-v2 .avatar-component-v2 .MuiAvatar-root {\n border-color: var(--shade200, #DBDADA);\n background: var(--white, #FFFFFF);\n}\n.sideMenuItem-component-v2 .chevron {\n margin-left: 1rem;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.sideMenuItem-component-v2 a {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0.75rem;\n border-radius: 8px;\n text-decoration: none !important;\n gap: 1rem;\n}\n.sideMenuItem-component-v2 a > .MuiStack-root {\n flex: 1;\n}\n.sideMenuItem-component-v2 a img {\n max-width: 80px;\n}\n.sideMenuItem-component-v2.soloItem a {\n border-radius: 16px;\n padding: 1.5rem;\n border: 1px solid var(--shade200, #DBDADA);\n}\n.sideMenuItem-component-v2.soloItem a:hover {\n border-color: var(--wild-sand, #dddddd);\n}\n.sideMenuItem-component-v2.soloItem .chevron {\n rotate: -90deg;\n}\n.sideMenuItem-component-v2.subSection {\n padding: 0.5rem 0.75rem 0.5rem 0.75rem;\n}";
18912
19300
  styleInject(css_248z$2);
18913
19301
 
@@ -19765,6 +20153,45 @@ var PagesFactory = /** @class */ (function () {
19765
20153
  return PagesFactory;
19766
20154
  }());
19767
20155
 
20156
+ var PersonalAccessTokensFactory = /** @class */ (function () {
20157
+ function PersonalAccessTokensFactory() {
20158
+ }
20159
+ PersonalAccessTokensFactory.list = function () {
20160
+ return __awaiter(this, arguments, void 0, function (_a) {
20161
+ var _b = _a === void 0 ? {} : _a, page = _b.page, perPage = _b.perPage, status = _b.status;
20162
+ return __generator(this, function (_c) {
20163
+ return [2 /*return*/, listPats({ page: page, perPage: perPage, status: status }).then(function (data) {
20164
+ data.data = data.data.map(function (pat) { return new PersonalAccessTokenModel(pat); });
20165
+ return data;
20166
+ })];
20167
+ });
20168
+ });
20169
+ };
20170
+ PersonalAccessTokensFactory.get = function (_a) {
20171
+ return __awaiter(this, arguments, void 0, function (_b) {
20172
+ var keyPrefix = _b.keyPrefix;
20173
+ return __generator(this, function (_c) {
20174
+ return [2 /*return*/, getPat({ keyPrefix: keyPrefix }).then(function (data) {
20175
+ return new PersonalAccessTokenModel(data.data);
20176
+ })];
20177
+ });
20178
+ });
20179
+ };
20180
+ PersonalAccessTokensFactory.create = function (_a) {
20181
+ return __awaiter(this, arguments, void 0, function (_b) {
20182
+ var name = _b.name, scopes = _b.scopes, expiresAt = _b.expiresAt, allowedAccountIds = _b.allowedAccountIds;
20183
+ return __generator(this, function (_c) {
20184
+ return [2 /*return*/, createPat({ name: name, scopes: scopes, expiresAt: expiresAt, allowedAccountIds: allowedAccountIds }).then(function (data) {
20185
+ var _a = data.data, plaintext = _a.plaintext, patData = __rest(_a, ["plaintext"]);
20186
+ trackEvent(exports.EEvents.PAT_CREATED, { name: name, scopes: scopes });
20187
+ return { pat: new PersonalAccessTokenModel(patData), plaintext: plaintext };
20188
+ })];
20189
+ });
20190
+ });
20191
+ };
20192
+ return PersonalAccessTokensFactory;
20193
+ }());
20194
+
19768
20195
  var PopupsFactory = /** @class */ (function () {
19769
20196
  function PopupsFactory() {
19770
20197
  }
@@ -20233,11 +20660,14 @@ exports.OverlayHandler = OverlayHandler;
20233
20660
  exports.OverlayHeading = OverlayHeading;
20234
20661
  exports.PageModel = PageModel;
20235
20662
  exports.PagesFactory = PagesFactory;
20663
+ exports.PersonalAccessTokenModel = PersonalAccessTokenModel;
20664
+ exports.PersonalAccessTokensFactory = PersonalAccessTokensFactory;
20236
20665
  exports.PhoneTextField = PhoneTextField;
20237
20666
  exports.PopupModel = PopupModel;
20238
20667
  exports.PopupsFactory = PopupsFactory;
20239
20668
  exports.Radio = Radio;
20240
20669
  exports.ResourceEdit = ResourceEdit;
20670
+ exports.ScopePicker = ScopePicker;
20241
20671
  exports.Search = Search;
20242
20672
  exports.SenderModel = SenderModel;
20243
20673
  exports.SendersFactory = SendersFactory;
@@ -20289,6 +20719,7 @@ exports.createContactsExport = createContactsExport;
20289
20719
  exports.createCustomDomain = createCustomDomain;
20290
20720
  exports.createForm = createForm;
20291
20721
  exports.createPage = createPage;
20722
+ exports.createPat = createPat;
20292
20723
  exports.createPopup = createPopup;
20293
20724
  exports.createSender = createSender;
20294
20725
  exports.createSuppressedEmailExport = createSuppressedEmailExport;
@@ -20381,6 +20812,7 @@ exports.getListLogs = getListLogs;
20381
20812
  exports.getListReport = getListReport;
20382
20813
  exports.getNestedProperty = getNestedProperty;
20383
20814
  exports.getPage = getPage;
20815
+ exports.getPat = getPat;
20384
20816
  exports.getPopup = getPopup;
20385
20817
  exports.getPropertyValue = getPropertyValue;
20386
20818
  exports.getSender = getSender;
@@ -20420,6 +20852,7 @@ exports.listList = listList;
20420
20852
  exports.listListAttributes = listListAttributes;
20421
20853
  exports.listListInterests = listListInterests;
20422
20854
  exports.listPages = listPages;
20855
+ exports.listPats = listPats;
20423
20856
  exports.listPopups = listPopups;
20424
20857
  exports.listSenders = listSenders;
20425
20858
  exports.listSuppressedEmails = listSuppressedEmails;
@@ -20457,6 +20890,7 @@ exports.requestSupportService = requestSupportService;
20457
20890
  exports.resendEmail = resendEmail;
20458
20891
  exports.resendVerificationEmail = resendVerificationEmail;
20459
20892
  exports.resumeCampaign = resumeCampaign;
20893
+ exports.revokePat = revokePat;
20460
20894
  exports.saveList = saveList;
20461
20895
  exports.scheduleCampaign = scheduleCampaign;
20462
20896
  exports.searchCustomerProfiles = searchCustomerProfiles;
@@ -20489,6 +20923,7 @@ exports.updateAnyAutomation = updateAnyAutomation;
20489
20923
  exports.updateAutomation = updateAutomation;
20490
20924
  exports.updateCampaign = updateCampaign;
20491
20925
  exports.updatePage = updatePage;
20926
+ exports.updatePat = updatePat;
20492
20927
  exports.updatePopup = updatePopup;
20493
20928
  exports.updateSystemEmails = updateSystemEmails;
20494
20929
  exports.updateTemplate = updateTemplate;
@@ -8,6 +8,7 @@ export * from "./emailAPI";
8
8
  export * from "./form";
9
9
  export * from "./list";
10
10
  export * from "./pages";
11
+ export * from "./personalAccessToken";
11
12
  export * from "./popups";
12
13
  export * from "./sender";
13
14
  export * from "./systemEmails";
@@ -0,0 +1,21 @@
1
+ import { TPatModel } from "./types";
2
+ export declare class PersonalAccessTokenModel {
3
+ readonly key_prefix: string;
4
+ name: string;
5
+ status: "active" | "revoked" | "expired";
6
+ scopes: string[];
7
+ allowed_account_ids: string[] | null;
8
+ readonly created_at: number;
9
+ readonly expires_at: number | null;
10
+ readonly revoked_at: number | null;
11
+ constructor(params: TPatModel);
12
+ toJson(): any;
13
+ set<T extends keyof this>(property: T, value: this[T]): void;
14
+ update({ name, scopes, allowedAccountIds }: {
15
+ name?: string;
16
+ scopes?: string[];
17
+ allowedAccountIds?: string[] | null;
18
+ }): Promise<PersonalAccessTokenModel>;
19
+ revoke(): Promise<PersonalAccessTokenModel>;
20
+ }
21
+ export * from "./types";
@@ -0,0 +1,10 @@
1
+ export type TPatModel = {
2
+ key_prefix: string;
3
+ name: string;
4
+ status: "active" | "revoked" | "expired";
5
+ scopes: string[];
6
+ allowed_account_ids: string[] | null;
7
+ created_at: number;
8
+ expires_at: number | null;
9
+ revoked_at: number | null;
10
+ };
@@ -12,6 +12,7 @@ export * from "./forms";
12
12
  export * from "./hidden";
13
13
  export * from "./lists";
14
14
  export * from "./pages";
15
+ export * from "./personalAccessTokens";
15
16
  export * from "./popups";
16
17
  export * from "./senders";
17
18
  export * from "./suppressedEmails";