@umbraco-cms/backoffice 14.0.0-8a5fc0ad → 14.0.0-9986c334

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 (44) hide show
  1. package/dist-cms/mocks/data/partial-views.data.d.ts +19 -3
  2. package/dist-cms/mocks/data/partial-views.data.js +277 -10
  3. package/dist-cms/mocks/data/utils.d.ts +2 -1
  4. package/dist-cms/mocks/data/utils.js +5 -0
  5. package/dist-cms/mocks/handlers/partial-views.handlers.d.ts +2 -1
  6. package/dist-cms/mocks/handlers/partial-views.handlers.js +37 -5
  7. package/dist-cms/packages/core/entity-action/common/create-folder/create-folder.action.d.ts +8 -0
  8. package/dist-cms/packages/core/entity-action/common/create-folder/create-folder.action.js +21 -0
  9. package/dist-cms/packages/core/entity-action/common/index.d.ts +1 -0
  10. package/dist-cms/packages/core/entity-action/common/index.js +1 -0
  11. package/dist-cms/packages/core/modal/common/folder/folder-modal.element.js +4 -1
  12. package/dist-cms/packages/core/modal/token/folder-modal.token.d.ts +1 -0
  13. package/dist-cms/packages/core/tree/file-system-tree-item/file-system-tree-item.context.d.ts +1 -0
  14. package/dist-cms/packages/core/tree/file-system-tree-item/file-system-tree-item.context.js +12 -0
  15. package/dist-cms/packages/core/tree/file-system-tree-item/file-system-tree-item.element.js +1 -0
  16. package/dist-cms/packages/core/workspace/workspace-action/workspace-action.element.js +12 -4
  17. package/dist-cms/packages/templating/manifests.d.ts +6 -1
  18. package/dist-cms/packages/templating/partial-views/config.d.ts +3 -4
  19. package/dist-cms/packages/templating/partial-views/config.js +1 -0
  20. package/dist-cms/packages/templating/partial-views/entity-actions/create/create-empty.action.js +1 -1
  21. package/dist-cms/packages/templating/partial-views/entity-actions/create/create-from-snippet.action.d.ts +10 -1
  22. package/dist-cms/packages/templating/partial-views/entity-actions/create/create-from-snippet.action.js +16 -1
  23. package/dist-cms/packages/templating/partial-views/entity-actions/create/create-from-snippet.modal.d.ts +16 -0
  24. package/dist-cms/packages/templating/partial-views/entity-actions/create/create-from-snippet.modal.js +73 -0
  25. package/dist-cms/packages/templating/partial-views/entity-actions/manifests.d.ts +6 -1
  26. package/dist-cms/packages/templating/partial-views/entity-actions/manifests.js +43 -5
  27. package/dist-cms/packages/templating/partial-views/manifests.d.ts +6 -1
  28. package/dist-cms/packages/templating/partial-views/repository/partial-views.repository.d.ts +39 -23
  29. package/dist-cms/packages/templating/partial-views/repository/partial-views.repository.js +66 -19
  30. package/dist-cms/packages/templating/partial-views/repository/sources/partial-views.detail.server.data.d.ts +48 -13
  31. package/dist-cms/packages/templating/partial-views/repository/sources/partial-views.detail.server.data.js +56 -17
  32. package/dist-cms/packages/templating/partial-views/repository/sources/partial-views.folder.server.data.d.ts +17 -0
  33. package/dist-cms/packages/templating/partial-views/repository/sources/partial-views.folder.server.data.js +23 -0
  34. package/dist-cms/packages/templating/partial-views/workspace/partial-views-workspace-edit.element.d.ts +6 -1
  35. package/dist-cms/packages/templating/partial-views/workspace/partial-views-workspace-edit.element.js +123 -27
  36. package/dist-cms/packages/templating/partial-views/workspace/partial-views-workspace.context.d.ts +8 -6
  37. package/dist-cms/packages/templating/partial-views/workspace/partial-views-workspace.context.js +47 -6
  38. package/dist-cms/packages/templating/partial-views/workspace/partial-views-workspace.element.d.ts +1 -0
  39. package/dist-cms/packages/templating/partial-views/workspace/partial-views-workspace.element.js +7 -3
  40. package/dist-cms/shared/repository/data-source/data-source.interface.d.ts +2 -2
  41. package/dist-cms/shared/repository/detail-repository.interface.d.ts +2 -2
  42. package/dist-cms/tsconfig.tsbuildinfo +1 -1
  43. package/dist-cms/vscode-html-custom-data.json +1 -1
  44. package/package.json +1 -1
@@ -1,11 +1,27 @@
1
1
  import { UmbEntityData } from './entity.data.js';
2
- import { FileSystemTreeItemPresentationModel, PagedFileSystemTreeItemPresentationModel } from '../../external/backend-api/index.js';
3
- export declare const data: Array<FileSystemTreeItemPresentationModel>;
4
- declare class UmbPartialViewsData extends UmbEntityData<FileSystemTreeItemPresentationModel> {
2
+ import { CreateTextFileViewModelBaseModel, FileSystemTreeItemPresentationModel, PagedFileSystemTreeItemPresentationModel, PartialViewResponseModel, PartialViewSnippetResponseModel, SnippetItemResponseModel } from '../../external/backend-api/index.js';
3
+ type PartialViewsDataItem = PartialViewResponseModel & FileSystemTreeItemPresentationModel & {
4
+ id: string;
5
+ };
6
+ export declare const treeData: Array<PartialViewsDataItem>;
7
+ declare class UmbPartialViewsTreeData extends UmbEntityData<FileSystemTreeItemPresentationModel> {
5
8
  constructor();
6
9
  getTreeRoot(): PagedFileSystemTreeItemPresentationModel;
7
10
  getTreeItemChildren(parentPath: string): PagedFileSystemTreeItemPresentationModel;
8
11
  getTreeItem(paths: Array<string>): Array<FileSystemTreeItemPresentationModel>;
9
12
  }
13
+ export declare const umbPartialViewsTreeData: UmbPartialViewsTreeData;
14
+ export declare const snippets: Array<PartialViewSnippetResponseModel>;
15
+ declare class UmbPartialViewSnippetsData extends UmbEntityData<SnippetItemResponseModel> {
16
+ constructor();
17
+ getSnippets(): Array<SnippetItemResponseModel>;
18
+ getSnippetByName(name: string): SnippetItemResponseModel | undefined;
19
+ }
20
+ declare class UmbPartialViewsData extends UmbEntityData<PartialViewResponseModel> {
21
+ constructor();
22
+ getPartialView(path: string): PartialViewResponseModel | undefined;
23
+ insertPartialView(item: CreateTextFileViewModelBaseModel): PartialViewsDataItem;
24
+ }
25
+ export declare const umbPartialViewSnippetsData: UmbPartialViewSnippetsData;
10
26
  export declare const umbPartialViewsData: UmbPartialViewsData;
11
27
  export {};
@@ -1,7 +1,8 @@
1
1
  import { UmbEntityData } from './entity.data.js';
2
- import { createFileSystemTreeItem } from './utils.js';
3
- export const data = [
2
+ import { createFileSystemTreeItem, createTextFileItem } from './utils.js';
3
+ export const treeData = [
4
4
  {
5
+ id: 'blockgrid',
5
6
  path: 'blockgrid',
6
7
  isFolder: true,
7
8
  name: 'blockgrid',
@@ -9,6 +10,7 @@ export const data = [
9
10
  hasChildren: true,
10
11
  },
11
12
  {
13
+ id: 'blocklist',
12
14
  path: 'blocklist',
13
15
  isFolder: true,
14
16
  name: 'blocklist',
@@ -16,6 +18,7 @@ export const data = [
16
18
  hasChildren: true,
17
19
  },
18
20
  {
21
+ id: 'grid',
19
22
  path: 'grid',
20
23
  isFolder: true,
21
24
  name: 'grid',
@@ -23,48 +26,86 @@ export const data = [
23
26
  hasChildren: true,
24
27
  },
25
28
  {
29
+ id: 'blockgrid/area.cshtml',
26
30
  path: 'blockgrid/area.cshtml',
27
31
  isFolder: false,
28
32
  name: 'area.cshtml',
29
33
  type: 'partial-view',
30
34
  hasChildren: false,
35
+ content: `@using Umbraco.Extensions
36
+ @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<Umbraco.Cms.Core.Models.Blocks.BlockGridArea>
37
+
38
+ <div class="umb-block-grid__area"
39
+ data-area-col-span="@Model.ColumnSpan"
40
+ data-area-row-span="@Model.RowSpan"
41
+ data-area-alias="@Model.Alias"
42
+ style="--umb-block-grid--grid-columns: @Model.ColumnSpan;--umb-block-grid--area-column-span: @Model.ColumnSpan; --umb-block-grid--area-row-span: @Model.RowSpan;">
43
+ @await Html.GetBlockGridItemsHtmlAsync(Model)
44
+ </div>
45
+ `,
31
46
  },
32
47
  {
48
+ id: 'blockgrid/items.cshtml',
33
49
  path: 'blockgrid/items.cshtml',
34
50
  isFolder: false,
35
51
  name: 'items.cshtml',
36
52
  type: 'partial-view',
37
53
  hasChildren: false,
54
+ content: '@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage',
38
55
  },
39
56
  {
57
+ id: 'blocklist/default.cshtml',
40
58
  path: 'blocklist/default.cshtml',
41
59
  isFolder: false,
42
60
  name: 'default.cshtml',
43
61
  type: 'partial-view',
44
62
  hasChildren: false,
63
+ content: `@using Umbraco.Extensions
64
+ @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<Umbraco.Cms.Core.Models.Blocks.BlockGridModel>
65
+ @{
66
+ if (Model?.Any() != true) { return; }
67
+ }
68
+
69
+ <div class="umb-block-grid"
70
+ data-grid-columns="@(Model.GridColumns?.ToString() ?? "12");"
71
+ style="--umb-block-grid--grid-columns: @(Model.GridColumns?.ToString() ?? "12");">
72
+ @await Html.GetBlockGridItemsHtmlAsync(Model)
73
+ </div>
74
+ `,
45
75
  },
46
76
  {
47
- path: 'grid/editors',
77
+ id: 'grid/embed.cshtm',
78
+ path: 'grid/embed.cshtm',
48
79
  isFolder: false,
49
- name: 'editors',
80
+ name: 'embed.cshtml',
50
81
  type: 'partial-view',
51
82
  hasChildren: false,
83
+ content: `@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<dynamic>
84
+
85
+ @if (Model is not null)
86
+ {
87
+ string embedValue = Convert.ToString(Model.value);
88
+ embedValue = embedValue.DetectIsJson() ? Model.value.preview : Model.value;
89
+
90
+ <div class="video-wrapper">
91
+ @Html.Raw(embedValue)
92
+ </div>
93
+ }
94
+ `,
52
95
  },
53
96
  {
97
+ id: 'grid/default.cshtml',
54
98
  path: 'grid/default.cshtml',
55
99
  isFolder: false,
56
100
  name: 'items.cshtml',
57
101
  type: 'partial-view',
58
102
  hasChildren: false,
103
+ content: '@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage',
59
104
  },
60
105
  ];
61
- // Temp mocked database
62
- // TODO: all properties are optional in the server schema. I don't think this is correct.
63
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
64
- // @ts-ignore
65
- class UmbPartialViewsData extends UmbEntityData {
106
+ class UmbPartialViewsTreeData extends UmbEntityData {
66
107
  constructor() {
67
- super(data);
108
+ super(treeData);
68
109
  }
69
110
  getTreeRoot() {
70
111
  const items = this.data.filter((item) => item.path?.includes('/') === false);
@@ -83,4 +124,230 @@ class UmbPartialViewsData extends UmbEntityData {
83
124
  return items.map((item) => createFileSystemTreeItem(item));
84
125
  }
85
126
  }
127
+ export const umbPartialViewsTreeData = new UmbPartialViewsTreeData();
128
+ export const snippets = [
129
+ {
130
+ name: 'Empty',
131
+ content: '@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage',
132
+ },
133
+ {
134
+ name: 'Breadcrumb',
135
+ content: `@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
136
+ @using Umbraco.Cms.Core.Routing
137
+ @using Umbraco.Extensions
138
+
139
+ @inject IPublishedUrlProvider PublishedUrlProvider
140
+ @*
141
+ This snippet makes a breadcrumb of parents using an unordered HTML list.
142
+
143
+ How it works:
144
+ - It uses the Ancestors() method to get all parents and then generates links so the visitor can go back
145
+ - Finally it outputs the name of the current page (without a link)
146
+ *@
147
+
148
+ @{ var selection = Model.Ancestors().ToArray(); }
149
+
150
+ @if (selection?.Length > 0)
151
+ {
152
+ <ul class="breadcrumb">
153
+ @* For each page in the ancestors collection which have been ordered by Level (so we start with the highest top node first) *@
154
+ @foreach (var item in selection.OrderBy(x => x.Level))
155
+ {
156
+ <li><a href="@item.Url(PublishedUrlProvider)">@item.Name</a> <span class="divider">/</span></li>
157
+ }
158
+
159
+ @* Display the current page as the last item in the list *@
160
+ <li class="active">@Model.Name</li>
161
+ </ul>
162
+ }`,
163
+ },
164
+ {
165
+ name: 'EditProfile',
166
+ content: `@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
167
+
168
+ @using Umbraco.Cms.Core.Services
169
+ @using Umbraco.Cms.Web.Common.Security
170
+ @using Umbraco.Cms.Web.Website.Controllers
171
+ @using Umbraco.Cms.Web.Website.Models
172
+ @using Umbraco.Extensions
173
+ @inject MemberModelBuilderFactory memberModelBuilderFactory;
174
+ @inject IMemberExternalLoginProviders memberExternalLoginProviders
175
+ @inject IExternalLoginWithKeyService externalLoginWithKeyService
176
+ @{
177
+
178
+ // Build a profile model to edit
179
+ var profileModel = await memberModelBuilderFactory
180
+ .CreateProfileModel()
181
+ // If null or not set, this will redirect to the current page
182
+ .WithRedirectUrl(null)
183
+ // Include editable custom properties on the form
184
+ .WithCustomProperties(true)
185
+ .BuildForCurrentMemberAsync();
186
+
187
+ var success = TempData["FormSuccess"] != null;
188
+
189
+ var loginProviders = await memberExternalLoginProviders.GetMemberProvidersAsync();
190
+ var externalSignInError = ViewData.GetExternalSignInProviderErrors();
191
+
192
+ var currentExternalLogin = profileModel is null
193
+ ? new Dictionary<string, string>()
194
+ : externalLoginWithKeyService.GetExternalLogins(profileModel.Key).ToDictionary(x=>x.LoginProvider, x=>x.ProviderKey);
195
+ }
196
+
197
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
198
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.min.js"></script>
199
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>
200
+
201
+ @if (profileModel != null)
202
+ {
203
+ if (success)
204
+ {
205
+ @* This message will show if profileModel.RedirectUrl is not defined (default) *@
206
+ <p class="text-success">Profile updated</p>
207
+ }
208
+
209
+ using (Html.BeginUmbracoForm<UmbProfileController>("HandleUpdateProfile", new { RedirectUrl = profileModel.RedirectUrl }))
210
+ {
211
+ <h2>Update your account.</h2>
212
+ <hr />
213
+ <div asp-validation-summary="All" class="text-danger"></div>
214
+ <div class="mb-3">
215
+ <label asp-for="@profileModel.Name" class="form-label"></label>
216
+ <input asp-for="@profileModel.Name" class="form-control" aria-required="true" />
217
+ <span asp-validation-for="@profileModel.Name" class="form-text text-danger"></span>
218
+ </div>
219
+ <div class="mb-3">
220
+ <label asp-for="@profileModel.Email" class="form-label"></label>
221
+ <input asp-for="@profileModel.Email" class="form-control" autocomplete="username" aria-required="true" />
222
+ <span asp-validation-for="@profileModel.Email" class="form-text text-danger"></span>
223
+ </div>
224
+
225
+ @if (!string.IsNullOrWhiteSpace(profileModel.UserName))
226
+ {
227
+ <div class="mb-3">
228
+ <label asp-for="@profileModel.UserName" class="form-label"></label>
229
+ <input asp-for="@profileModel.UserName" class="form-control" autocomplete="username" aria-required="true" />
230
+ <span asp-validation-for="@profileModel.UserName" class="form-text text-danger"></span>
231
+ </div>
232
+ }
233
+
234
+ @if (profileModel.MemberProperties != null)
235
+ {
236
+ for (var i = 0; i < profileModel.MemberProperties.Count; i++)
237
+ {
238
+ <div class="mb-3">
239
+ @Html.LabelFor(m => profileModel.MemberProperties[i].Value, profileModel.MemberProperties[i].Name)
240
+ <input asp-for="@profileModel.MemberProperties[i].Value" class="form-control" />
241
+ @Html.HiddenFor(m => profileModel.MemberProperties[i].Alias)
242
+ <span asp-validation-for="@profileModel.MemberProperties[i].Value" class="form-text text-danger"></span>
243
+ </div>
244
+ }
245
+ }
246
+
247
+ <button type="submit" class="btn btn-primary">Update</button>
248
+
249
+ if (loginProviders.Any())
250
+ {
251
+ <hr/>
252
+ <h4>Link external accounts</h4>
253
+
254
+ if (externalSignInError?.AuthenticationType is null && externalSignInError?.Errors.Any() == true)
255
+ {
256
+ @Html.DisplayFor(x => externalSignInError.Errors);
257
+ }
258
+
259
+ @foreach (var login in loginProviders)
260
+ {
261
+ if (currentExternalLogin.TryGetValue(login.ExternalLoginProvider.AuthenticationType, out var providerKey))
262
+ {
263
+ @using (Html.BeginUmbracoForm<UmbExternalLoginController>(nameof(UmbExternalLoginController.Disassociate)))
264
+ {
265
+ <input type="hidden" name="providerKey" value="@providerKey"/>
266
+ <button type="submit" name="provider" value="@login.ExternalLoginProvider.AuthenticationType">
267
+ Un-Link your @login.AuthenticationScheme.DisplayName account
268
+ </button>
269
+
270
+ if (externalSignInError?.AuthenticationType == login.ExternalLoginProvider.AuthenticationType)
271
+ {
272
+ @Html.DisplayFor(x => externalSignInError.Errors);
273
+ }
274
+ }
275
+ }
276
+ else
277
+ {
278
+ @using (Html.BeginUmbracoForm<UmbExternalLoginController>(nameof(UmbExternalLoginController.LinkLogin)))
279
+ {
280
+ <button type="submit" name="provider" value="@login.ExternalLoginProvider.AuthenticationType">
281
+ Link your @login.AuthenticationScheme.DisplayName account
282
+ </button>
283
+
284
+ if (externalSignInError?.AuthenticationType == login.ExternalLoginProvider.AuthenticationType)
285
+ {
286
+ @Html.DisplayFor(x => externalSignInError.Errors);
287
+ }
288
+ }
289
+ }
290
+
291
+ }
292
+ }
293
+ }
294
+ }`,
295
+ },
296
+ {
297
+ name: 'Login',
298
+ content: 'login',
299
+ },
300
+ {
301
+ name: 'LoginStatus',
302
+ content: 'loginStatus',
303
+ },
304
+ {
305
+ name: 'MultinodeTree-picker',
306
+ content: 'MultinodeTree-picker',
307
+ },
308
+ {
309
+ name: 'Navigation',
310
+ content: 'Navigation',
311
+ },
312
+ {
313
+ name: 'RegisterMember',
314
+ content: 'RegisterMember',
315
+ },
316
+ {
317
+ name: 'SiteMap',
318
+ content: 'SiteMap',
319
+ },
320
+ ];
321
+ class UmbPartialViewSnippetsData extends UmbEntityData {
322
+ constructor() {
323
+ super(snippets);
324
+ }
325
+ getSnippets() {
326
+ return this.data;
327
+ }
328
+ getSnippetByName(name) {
329
+ return this.data.find((item) => item.name === name);
330
+ }
331
+ }
332
+ class UmbPartialViewsData extends UmbEntityData {
333
+ constructor() {
334
+ super(treeData);
335
+ }
336
+ getPartialView(path) {
337
+ return createTextFileItem(this.data.find((item) => item.path === path));
338
+ }
339
+ insertPartialView(item) {
340
+ const newItem = {
341
+ ...item,
342
+ path: `${item.parentPath}/${item.name}.cshtml}`,
343
+ id: `${item.parentPath}/${item.name}.cshtml}`,
344
+ isFolder: false,
345
+ hasChildren: false,
346
+ type: 'partial-view',
347
+ };
348
+ this.insert(newItem);
349
+ return newItem;
350
+ }
351
+ }
352
+ export const umbPartialViewSnippetsData = new UmbPartialViewSnippetsData();
86
353
  export const umbPartialViewsData = new UmbPartialViewsData();
@@ -1,4 +1,4 @@
1
- import type { ContentTreeItemResponseModel, DocumentTreeItemResponseModel, DocumentTypeTreeItemResponseModel, EntityTreeItemResponseModel, FolderTreeItemResponseModel, DocumentTypeResponseModel, FileSystemTreeItemPresentationModel, DocumentResponseModel } from '../../external/backend-api/index.js';
1
+ import type { ContentTreeItemResponseModel, DocumentTreeItemResponseModel, DocumentTypeTreeItemResponseModel, EntityTreeItemResponseModel, FolderTreeItemResponseModel, DocumentTypeResponseModel, FileSystemTreeItemPresentationModel, DocumentResponseModel, TextFileResponseModelBaseModel } from '../../external/backend-api/index.js';
2
2
  export declare const createEntityTreeItem: (item: any) => EntityTreeItemResponseModel;
3
3
  export declare const createFolderTreeItem: (item: any) => FolderTreeItemResponseModel;
4
4
  export declare const createContentTreeItem: (item: any) => ContentTreeItemResponseModel & {
@@ -9,3 +9,4 @@ export declare const createDocumentTreeItem: (item: DocumentResponseModel) => Do
9
9
  };
10
10
  export declare const createDocumentTypeTreeItem: (item: DocumentTypeResponseModel) => DocumentTypeTreeItemResponseModel;
11
11
  export declare const createFileSystemTreeItem: (item: any) => FileSystemTreeItemPresentationModel;
12
+ export declare const createTextFileItem: (item: any) => TextFileResponseModelBaseModel;
@@ -55,3 +55,8 @@ export const createFileSystemTreeItem = (item) => {
55
55
  isFolder: item.isFolder,
56
56
  };
57
57
  };
58
+ export const createTextFileItem = (item) => ({
59
+ path: item.path,
60
+ name: item.name,
61
+ content: item.content,
62
+ });
@@ -1 +1,2 @@
1
- export declare const handlers: import("msw").RestHandler<import("msw/lib/glossary-de6278a9.js").M<import("msw/lib/glossary-de6278a9.js").h>>[];
1
+ import { RestHandler, MockedRequest, DefaultBodyType } from 'msw';
2
+ export declare const handlers: RestHandler<MockedRequest<DefaultBodyType>>[];
@@ -1,23 +1,55 @@
1
1
  const { rest } = window.MockServiceWorker;
2
- import { umbPartialViewsData } from '../data/partial-views.data.js';
2
+ import { umbPartialViewsData, umbPartialViewsTreeData } from '../data/partial-views.data.js';
3
3
  import { umbracoPath } from '../../shared/utils/index.js';
4
- export const handlers = [
4
+ const treeHandlers = [
5
5
  rest.get(umbracoPath('/tree/partial-view/root'), (req, res, ctx) => {
6
- const response = umbPartialViewsData.getTreeRoot();
6
+ const response = umbPartialViewsTreeData.getTreeRoot();
7
7
  return res(ctx.status(200), ctx.json(response));
8
8
  }),
9
9
  rest.get(umbracoPath('/tree/partial-view/children'), (req, res, ctx) => {
10
10
  const path = req.url.searchParams.get('path');
11
11
  if (!path)
12
12
  return;
13
- const response = umbPartialViewsData.getTreeItemChildren(path);
13
+ const response = umbPartialViewsTreeData.getTreeItemChildren(path);
14
14
  return res(ctx.status(200), ctx.json(response));
15
15
  }),
16
16
  rest.get(umbracoPath('/tree/partial-view/item'), (req, res, ctx) => {
17
17
  const paths = req.url.searchParams.getAll('paths');
18
18
  if (!paths)
19
19
  return;
20
- const items = umbPartialViewsData.getTreeItem(paths);
20
+ const items = umbPartialViewsTreeData.getTreeItem(paths);
21
21
  return res(ctx.status(200), ctx.json(items));
22
22
  }),
23
23
  ];
24
+ const detailHandlers = [
25
+ rest.get(umbracoPath('/partial-view'), (req, res, ctx) => {
26
+ const path = decodeURIComponent(req.url.searchParams.get('path') ?? '').replace('-cshtml', '.cshtml');
27
+ if (!path)
28
+ return res(ctx.status(400));
29
+ const response = umbPartialViewsData.getPartialView(path);
30
+ return res(ctx.status(200), ctx.json(response));
31
+ }),
32
+ rest.post(umbracoPath('/partial-view'), (req, res, ctx) => {
33
+ const requestBody = req.json();
34
+ if (!requestBody)
35
+ return res(ctx.status(400, 'no body found'));
36
+ const response = umbPartialViewsData.insertPartialView(requestBody);
37
+ return res(ctx.status(200), ctx.json(response));
38
+ }),
39
+ rest.delete(umbracoPath('/partial-view'), (req, res, ctx) => {
40
+ const path = req.url.searchParams.get('path');
41
+ if (!path)
42
+ return res(ctx.status(400));
43
+ const response = umbPartialViewsData.delete([path]);
44
+ return res(ctx.status(200), ctx.json(response));
45
+ }),
46
+ rest.put(umbracoPath('/partial-view'), (req, res, ctx) => {
47
+ const requestBody = req.json();
48
+ if (!requestBody)
49
+ return res(ctx.status(400, 'no body found'));
50
+ const response = umbPartialViewsData.updateData(requestBody);
51
+ return res(ctx.status(200));
52
+ }),
53
+ ];
54
+ const folderHandlers = [];
55
+ export const handlers = [...treeHandlers, ...detailHandlers, ...folderHandlers];
@@ -0,0 +1,8 @@
1
+ import { UmbEntityActionBase } from '../../entity-action.js';
2
+ import { UmbControllerHostElement } from '../../../../../libs/controller-api/index.js';
3
+ import { UmbFolderRepository } from '../../../../../shared/repository/index.js';
4
+ export declare class UmbCreateFolderEntityAction<T extends UmbFolderRepository> extends UmbEntityActionBase<T> {
5
+ #private;
6
+ constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string);
7
+ execute(): Promise<void>;
8
+ }
@@ -0,0 +1,21 @@
1
+ import { UmbEntityActionBase } from '../../entity-action.js';
2
+ import { UmbContextConsumerController } from '../../../../../libs/context-api/index.js';
3
+ import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UMB_FOLDER_MODAL, } from '../../../modal/index.js';
4
+ export class UmbCreateFolderEntityAction extends UmbEntityActionBase {
5
+ #modalContext;
6
+ constructor(host, repositoryAlias, unique) {
7
+ super(host, repositoryAlias, unique);
8
+ new UmbContextConsumerController(this.host, UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => {
9
+ this.#modalContext = instance;
10
+ });
11
+ }
12
+ async execute() {
13
+ if (!this.repository || !this.#modalContext)
14
+ return;
15
+ const modalContext = this.#modalContext.open(UMB_FOLDER_MODAL, {
16
+ repositoryAlias: this.repositoryAlias,
17
+ parentUnique: this.unique ?? null,
18
+ });
19
+ await modalContext.onSubmit();
20
+ }
21
+ }
@@ -5,3 +5,4 @@ export * from './folder-update/folder-update.action.js';
5
5
  export * from './move/move.action.js';
6
6
  export * from './sort-children-of/sort-children-of.action.js';
7
7
  export * from './trash/trash.action.js';
8
+ export * from './create-folder/create-folder.action.js';
@@ -5,3 +5,4 @@ export * from './folder-update/folder-update.action.js';
5
5
  export * from './move/move.action.js';
6
6
  export * from './sort-children-of/sort-children-of.action.js';
7
7
  export * from './trash/trash.action.js';
8
+ export * from './create-folder/create-folder.action.js';
@@ -13,6 +13,7 @@ export let UmbFolderModalElement = class UmbFolderModalElement extends UmbLitEle
13
13
  constructor() {
14
14
  super(...arguments);
15
15
  this.#unique = null;
16
+ this.#parentUnique = null;
16
17
  this._isNew = false;
17
18
  }
18
19
  get data() {
@@ -21,11 +22,13 @@ export let UmbFolderModalElement = class UmbFolderModalElement extends UmbLitEle
21
22
  set data(value) {
22
23
  this._data = value;
23
24
  this.#unique = value?.unique || null;
25
+ this.#parentUnique = value?.parentUnique || null;
24
26
  this.#repositoryAlias = value?.repositoryAlias;
25
27
  this.#observeRepository();
26
28
  }
27
29
  #repositoryAlias;
28
30
  #unique;
31
+ #parentUnique;
29
32
  #repository;
30
33
  #repositoryObserver;
31
34
  #observeRepository() {
@@ -58,7 +61,7 @@ export let UmbFolderModalElement = class UmbFolderModalElement extends UmbLitEle
58
61
  async #create() {
59
62
  if (!this.#repository)
60
63
  throw new Error('Repository is required to create folder');
61
- const { data } = await this.#repository.createFolderScaffold(this.#unique);
64
+ const { data } = await this.#repository.createFolderScaffold(this.#parentUnique);
62
65
  this._folder = data;
63
66
  this._isNew = true;
64
67
  }
@@ -3,6 +3,7 @@ import { FolderReponseModel } from '../../../../external/backend-api/index.js';
3
3
  export interface UmbFolderModalData {
4
4
  repositoryAlias: string;
5
5
  unique?: string;
6
+ parentUnique?: string | null;
6
7
  }
7
8
  export interface UmbFolderModalResult {
8
9
  folder: FolderReponseModel;
@@ -10,5 +10,6 @@ import { FileSystemTreeItemPresentationModel } from '../../../../external/backen
10
10
  */
11
11
  export declare class UmbFileSystemTreeItemContext extends UmbTreeItemContextBase<FileSystemTreeItemPresentationModel> {
12
12
  constructor(host: UmbControllerHostElement);
13
+ checkIfIsFolder(): void;
13
14
  constructPath(pathname: string, entityType: string, path: string): string;
14
15
  }
@@ -10,6 +10,18 @@ export class UmbFileSystemTreeItemContext extends UmbTreeItemContextBase {
10
10
  constructor(host) {
11
11
  super(host, (x) => x.path);
12
12
  }
13
+ //TODO: this is not a nice solution! There should be a better way to distinguish in the tree between folders and files. Additionally we need to be able to register an action only on empty folder.
14
+ checkIfIsFolder() {
15
+ const treeItem = this.getTreeItem();
16
+ if (treeItem?.isFolder) {
17
+ if (treeItem.hasChildren) {
18
+ this.type = `${this.getTreeItem()?.type}-folder`;
19
+ }
20
+ else {
21
+ this.type = `${this.getTreeItem()?.type}-folder-empty`;
22
+ }
23
+ }
24
+ }
13
25
  constructPath(pathname, entityType, path) {
14
26
  return `section/${pathname}/workspace/${entityType}/edit/${encodeURIComponent(path).replace('.', '-')}`;
15
27
  }
@@ -36,6 +36,7 @@ export let UmbFileSystemTreeItemElement = class UmbFileSystemTreeItemElement ext
36
36
  set item(value) {
37
37
  this._item = value;
38
38
  this.#context.setTreeItem(value);
39
+ this.#context.checkIfIsFolder();
39
40
  }
40
41
  #context = new UmbFileSystemTreeItemContext(this);
41
42
  render() {
@@ -29,19 +29,27 @@ export let UmbWorkspaceActionElement = class UmbWorkspaceActionElement extends U
29
29
  }
30
30
  #api;
31
31
  async _onClick() {
32
- if (!this.#api)
33
- return;
34
- await this.#api.execute();
32
+ this._buttonState = 'waiting';
33
+ try {
34
+ if (!this.#api)
35
+ throw new Error('No api defined');
36
+ await this.#api.execute();
37
+ this._buttonState = 'success';
38
+ }
39
+ catch (error) {
40
+ this._buttonState = 'failed';
41
+ }
35
42
  this.dispatchEvent(new UmbExecutedEvent());
36
43
  }
37
44
  render() {
38
45
  return html `
39
46
  <uui-button
47
+ id="action-button"
40
48
  @click=${this._onClick}
41
49
  look=${this.manifest?.meta.look || 'default'}
42
50
  color=${this.manifest?.meta.color || 'default'}
43
51
  label=${this.manifest?.meta.label || ''}
44
- .state="${this._buttonState}"></uui-button>
52
+ .state=${this._buttonState}></uui-button>
45
53
  `;
46
54
  }
47
55
  static { this.styles = [UUITextStyles, css ``]; }
@@ -1 +1,6 @@
1
- export declare const manifests: (import("../core/index.js").ManifestEntityAction | import("../core/index.js").ManifestMenu | import("../core/index.js").ManifestMenuItemTreeKind | import("../core/index.js").ManifestModal | import("../core/index.js").ManifestRepository | import("../core/index.js").ManifestSectionSidebarApp | import("../core/index.js").ManifestStore | import("../core/index.js").ManifestTreeStore | import("../core/index.js").ManifestItemStore | import("../core/index.js").ManifestTree | import("../core/index.js").ManifestTreeItem | import("../core/index.js").ManifestWorkspace | import("../core/index.js").ManifestWorkspaceAction | import("../core/index.js").ManifestWorkspaceEditorView)[];
1
+ export declare const manifests: (import("../core/index.js").ManifestEntityAction | import("../core/index.js").ManifestMenu | import("../core/index.js").ManifestMenuItemTreeKind | import("../core/index.js").ManifestModal | import("../core/index.js").ManifestRepository | import("../core/index.js").ManifestSectionSidebarApp | import("../core/index.js").ManifestStore | import("../core/index.js").ManifestTreeStore | import("../core/index.js").ManifestItemStore | import("../core/index.js").ManifestTree | import("../core/index.js").ManifestTreeItem | import("../core/index.js").ManifestWorkspace | import("../core/index.js").ManifestWorkspaceAction | import("../core/index.js").ManifestWorkspaceEditorView | {
2
+ type: string;
3
+ alias: string;
4
+ name: string;
5
+ loader: () => Promise<typeof import("./partial-views/entity-actions/create/create-from-snippet.modal.js")>;
6
+ })[];
@@ -1,10 +1,9 @@
1
- import { FileSystemTreeItemPresentationModel } from '../../../external/backend-api/index.js';
2
- export interface PartialViewDetails extends FileSystemTreeItemPresentationModel {
3
- content: string;
4
- }
1
+ import { PartialViewResponseModel } from '../../../external/backend-api/index.js';
2
+ export type PartialViewDetails = PartialViewResponseModel;
5
3
  export declare const PARTIAL_VIEW_ENTITY_TYPE = "partial-view";
6
4
  export declare const PARTIAL_VIEW_ROOT_ENTITY_TYPE = "partial-view-root";
7
5
  export declare const PARTIAL_VIEW_FOLDER_ENTITY_TYPE = "partial-view-folder";
6
+ export declare const PARTIAL_VIEW_FOLDER_EMPTY_ENTITY_TYPE = "partial-view-folder-empty";
8
7
  export declare const PARTIAL_VIEW_REPOSITORY_ALIAS = "Umb.Repository.PartialViews";
9
8
  export declare const PARTIAL_VIEW_TREE_ALIAS = "Umb.Tree.PartialViews";
10
9
  export declare const UMB_PARTIAL_VIEW_TREE_STORE_CONTEXT_TOKEN_ALIAS = "Umb.Store.PartialViews.Tree";
@@ -1,6 +1,7 @@
1
1
  export const PARTIAL_VIEW_ENTITY_TYPE = 'partial-view';
2
2
  export const PARTIAL_VIEW_ROOT_ENTITY_TYPE = 'partial-view-root';
3
3
  export const PARTIAL_VIEW_FOLDER_ENTITY_TYPE = 'partial-view-folder';
4
+ export const PARTIAL_VIEW_FOLDER_EMPTY_ENTITY_TYPE = 'partial-view-folder-empty';
4
5
  export const PARTIAL_VIEW_REPOSITORY_ALIAS = 'Umb.Repository.PartialViews';
5
6
  export const PARTIAL_VIEW_TREE_ALIAS = 'Umb.Tree.PartialViews';
6
7
  export const UMB_PARTIAL_VIEW_TREE_STORE_CONTEXT_TOKEN_ALIAS = 'Umb.Store.PartialViews.Tree';