@jumoo/usync 17.5.1 → 17.5.2-prerelease.15

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 (39) hide show
  1. package/dist/api/index.d.ts +1 -1
  2. package/dist/api/index.js +1 -1
  3. package/dist/api/sdk.gen.d.ts +2 -1
  4. package/dist/api/sdk.gen.js +7 -0
  5. package/dist/api/types.gen.d.ts +361 -0
  6. package/dist/api/types.gen.js +13 -0
  7. package/dist/components/index.d.ts +3 -0
  8. package/dist/components/index.js +3 -0
  9. package/dist/components/usync-content-preview.d.ts +27 -0
  10. package/dist/components/usync-content-preview.js +540 -0
  11. package/dist/components/usync-content-type-preview.d.ts +25 -0
  12. package/dist/components/usync-content-type-preview.js +548 -0
  13. package/dist/components/usync-data-type-preview.d.ts +21 -0
  14. package/dist/components/usync-data-type-preview.js +293 -0
  15. package/dist/components/usync-results-view.js +13 -5
  16. package/dist/dialogs/details-modal-element.d.ts +12 -1
  17. package/dist/dialogs/details-modal-element.js +139 -9
  18. package/dist/dialogs/details-modal-token.d.ts +10 -1
  19. package/dist/lang/files/da-dk.d.ts +37 -0
  20. package/dist/lang/files/da-dk.js +37 -0
  21. package/dist/lang/files/de-de.d.ts +37 -0
  22. package/dist/lang/files/de-de.js +37 -0
  23. package/dist/lang/files/en-us.d.ts +37 -0
  24. package/dist/lang/files/en-us.js +37 -0
  25. package/dist/lang/files/es-es.d.ts +37 -0
  26. package/dist/lang/files/es-es.js +37 -0
  27. package/dist/lang/files/fr-fr.d.ts +37 -0
  28. package/dist/lang/files/fr-fr.js +37 -0
  29. package/dist/lang/files/nl-nl.d.ts +37 -0
  30. package/dist/lang/files/nl-nl.js +37 -0
  31. package/dist/repository/SyncAction.respositoy.d.ts +8 -0
  32. package/dist/repository/SyncAction.respositoy.js +6 -0
  33. package/dist/repository/sources/SyncAction.source.d.ts +5 -0
  34. package/dist/repository/sources/SyncAction.source.js +5 -0
  35. package/dist/utils/preview/content-type-diff.d.ts +18 -0
  36. package/dist/utils/preview/content-type-diff.js +72 -0
  37. package/dist/utils/preview/content-type-layout.d.ts +39 -0
  38. package/dist/utils/preview/content-type-layout.js +100 -0
  39. package/package.json +1 -1
@@ -0,0 +1,293 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _uSyncDataTypePreviewElement_instances, _uSyncDataTypePreviewElement_renderSide, _uSyncDataTypePreviewElement_renderMissing, _uSyncDataTypePreviewElement_renderInfo, _uSyncDataTypePreviewElement_renderEditor, _uSyncDataTypePreviewElement_renderConfig;
13
+ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
14
+ import { classMap, css, customElement, html, nothing, property, } from '@umbraco-cms/backoffice/external/lit';
15
+ import '@umbraco-cms/backoffice/components';
16
+ import { deepEqual, prettyJson } from '../utils/diff/index.js';
17
+ /**
18
+ * Shows the current and incoming versions of a data type side by side,
19
+ * rendered with the real property editor, so you can see what an import
20
+ * will do before running it.
21
+ */
22
+ let uSyncDataTypePreviewElement = class uSyncDataTypePreviewElement extends UmbLitElement {
23
+ constructor() {
24
+ super(...arguments);
25
+ _uSyncDataTypePreviewElement_instances.add(this);
26
+ }
27
+ render() {
28
+ if (!this.preview)
29
+ return nothing;
30
+ const current = this.preview.currentDataType ?? undefined;
31
+ const incoming = this.preview.incomingDataType ?? undefined;
32
+ return html `
33
+ <div class="sides">
34
+ ${__classPrivateFieldGet(this, _uSyncDataTypePreviewElement_instances, "m", _uSyncDataTypePreviewElement_renderSide).call(this, 'current', current, incoming)}
35
+ ${__classPrivateFieldGet(this, _uSyncDataTypePreviewElement_instances, "m", _uSyncDataTypePreviewElement_renderSide).call(this, 'incoming', incoming, current)}
36
+ </div>
37
+ `;
38
+ }
39
+ };
40
+ _uSyncDataTypePreviewElement_instances = new WeakSet();
41
+ _uSyncDataTypePreviewElement_renderSide = function _uSyncDataTypePreviewElement_renderSide(side, dataType, other) {
42
+ const headline = side === 'current'
43
+ ? this.localize.termOrDefault('uSync_previewCurrent', 'Current (this site)')
44
+ : this.localize.termOrDefault('uSync_previewIncoming', 'Incoming (uSync files)');
45
+ return html `
46
+ <div class="side">
47
+ <h4 class="side-headline">${headline}</h4>
48
+ ${dataType
49
+ ? html `
50
+ ${__classPrivateFieldGet(this, _uSyncDataTypePreviewElement_instances, "m", _uSyncDataTypePreviewElement_renderInfo).call(this, dataType, other)} ${__classPrivateFieldGet(this, _uSyncDataTypePreviewElement_instances, "m", _uSyncDataTypePreviewElement_renderEditor).call(this, dataType)}
51
+ ${__classPrivateFieldGet(this, _uSyncDataTypePreviewElement_instances, "m", _uSyncDataTypePreviewElement_renderConfig).call(this, dataType, other, side)}
52
+ `
53
+ : __classPrivateFieldGet(this, _uSyncDataTypePreviewElement_instances, "m", _uSyncDataTypePreviewElement_renderMissing).call(this, side)}
54
+ </div>
55
+ `;
56
+ };
57
+ _uSyncDataTypePreviewElement_renderMissing = function _uSyncDataTypePreviewElement_renderMissing(side) {
58
+ const message = side === 'current'
59
+ ? this.localize.termOrDefault('uSync_previewNotInSite', 'This item does not exist in the site yet')
60
+ : this.preview?.isDelete
61
+ ? this.localize.termOrDefault('uSync_previewDeleted', 'This item will be deleted or renamed by the import')
62
+ : this.localize.termOrDefault('uSync_previewFailed', 'The incoming item could not be built for the preview');
63
+ return html `<uui-box class="info"><p class="empty">${message}</p></uui-box>`;
64
+ };
65
+ _uSyncDataTypePreviewElement_renderInfo = function _uSyncDataTypePreviewElement_renderInfo(dataType, other) {
66
+ const changed = (field) => other !== undefined && other[field] !== dataType[field];
67
+ return html `
68
+ <uui-box class="info">
69
+ <div slot="headline" class="headline">
70
+ <umb-icon name="icon-autofill"></umb-icon>
71
+ <span class=${classMap({ changed: changed('name') })}>${dataType.name}</span>
72
+ </div>
73
+ <dl class="meta">
74
+ <dt>
75
+ ${this.localize.termOrDefault('uSync_previewPropertyEditor', 'Property editor')}
76
+ </dt>
77
+ <dd class=${classMap({ changed: changed('editorAlias') })}>
78
+ <code>${dataType.editorAlias}</code>
79
+ </dd>
80
+ <dt>
81
+ ${this.localize.termOrDefault('uSync_previewPropertyEditorUi', 'Property editor UI')}
82
+ </dt>
83
+ <dd class=${classMap({ changed: changed('editorUiAlias') })}>
84
+ <code>${dataType.editorUiAlias}</code>
85
+ </dd>
86
+ </dl>
87
+ </uui-box>
88
+ `;
89
+ };
90
+ _uSyncDataTypePreviewElement_renderEditor = function _uSyncDataTypePreviewElement_renderEditor(dataType) {
91
+ return html `
92
+ <uui-box
93
+ .headline=${this.localize.termOrDefault('uSync_previewEditor', 'Editor preview')}>
94
+ <!-- inert rather than readonly: most editors render only their value when
95
+ readonly, which is empty here, so you wouldn't see the editor at all. -->
96
+ <umb-property-dataset .value=${[]} inert>
97
+ <umb-property
98
+ alias="usyncPreview"
99
+ .label=${dataType.name}
100
+ .description=${this.localize.termOrDefault('uSync_previewEditorDesc', 'How this data type looks to editors')}
101
+ .propertyEditorUiAlias=${dataType.editorUiAlias}
102
+ .config=${dataType.values}></umb-property>
103
+ </umb-property-dataset>
104
+ </uui-box>
105
+ `;
106
+ };
107
+ _uSyncDataTypePreviewElement_renderConfig = function _uSyncDataTypePreviewElement_renderConfig(dataType, other, side) {
108
+ const values = [...dataType.values].sort((a, b) => a.alias.localeCompare(b.alias));
109
+ return html `
110
+ <uui-box
111
+ .headline=${this.localize.termOrDefault('uSync_previewConfiguration', 'Configuration')}>
112
+ ${values.length === 0
113
+ ? html `<p class="empty">
114
+ ${this.localize.termOrDefault('uSync_previewNoConfiguration', 'No configuration')}
115
+ </p>`
116
+ : html `<table>
117
+ ${values.map((value) => {
118
+ const status = configStatus(value.alias, value.value, other, side);
119
+ return html `<tr class="row-${status}">
120
+ <th><code>${value.alias}</code></th>
121
+ <td><pre>${formatConfigValue(value.value)}</pre></td>
122
+ </tr>`;
123
+ })}
124
+ </table>`}
125
+ </uui-box>
126
+ `;
127
+ };
128
+ uSyncDataTypePreviewElement.styles = css `
129
+ :host {
130
+ display: block;
131
+ container-type: inline-size;
132
+ }
133
+
134
+ /* the two sides share rows (headline, info, editor, config), so the
135
+ boxes line up across the sides. */
136
+ .sides {
137
+ display: grid;
138
+ grid-template-columns: 1fr 1fr;
139
+ grid-template-rows: auto auto auto 1fr;
140
+ gap: var(--uui-size-space-4) var(--uui-size-space-5);
141
+ }
142
+
143
+ .side {
144
+ display: grid;
145
+ grid-row: span 4;
146
+ grid-template-rows: subgrid;
147
+ min-width: 0;
148
+ }
149
+
150
+ .side > :last-child {
151
+ align-self: start;
152
+ }
153
+
154
+ @container (max-width: 760px) {
155
+ .sides {
156
+ grid-template-columns: 1fr;
157
+ grid-template-rows: none;
158
+ row-gap: var(--uui-size-layout-1);
159
+ }
160
+
161
+ .side {
162
+ display: flex;
163
+ flex-direction: column;
164
+ gap: var(--uui-size-space-4);
165
+ grid-row: auto;
166
+ }
167
+ }
168
+
169
+ .side-headline {
170
+ margin: 0;
171
+ font-size: var(--uui-type-small-size);
172
+ text-transform: uppercase;
173
+ letter-spacing: 0.04em;
174
+ color: var(--uui-color-text-alt);
175
+ }
176
+
177
+ .headline {
178
+ display: flex;
179
+ align-items: center;
180
+ gap: var(--uui-size-space-3);
181
+ }
182
+
183
+ .meta {
184
+ display: grid;
185
+ grid-template-columns: max-content 1fr;
186
+ align-items: baseline;
187
+ gap: var(--uui-size-space-3) var(--uui-size-space-5);
188
+ margin: 0;
189
+ }
190
+
191
+ .meta dt {
192
+ font-weight: 700;
193
+ }
194
+
195
+ .meta dd {
196
+ margin: 0;
197
+ overflow-wrap: anywhere;
198
+ }
199
+
200
+ /* a changed field gets a soft highlight, spread with a shadow so the text doesn't move. */
201
+ .changed {
202
+ background: color-mix(in srgb, var(--uui-color-warning) 35%, transparent);
203
+ border-radius: var(--uui-border-radius);
204
+ box-shadow: 0 0 0 var(--uui-size-space-1)
205
+ color-mix(in srgb, var(--uui-color-warning) 35%, transparent);
206
+ }
207
+
208
+ /* umb-property pads itself for a full workspace, tighten it up here. */
209
+ umb-property {
210
+ --uui-size-layout-1: var(--uui-size-space-2);
211
+ }
212
+
213
+ table {
214
+ width: 100%;
215
+ border-collapse: collapse;
216
+ margin: calc(-1 * var(--uui-size-space-2)) 0;
217
+ }
218
+
219
+ tr + tr {
220
+ border-top: 1px solid var(--uui-color-divider);
221
+ }
222
+
223
+ th,
224
+ td {
225
+ text-align: left;
226
+ vertical-align: baseline;
227
+ padding: var(--uui-size-space-3) var(--uui-size-space-3);
228
+ }
229
+
230
+ /* the alias column is as wide as the longest alias (up to 40%), so values sit beside their names. */
231
+ th {
232
+ width: 1%;
233
+ max-width: 40%;
234
+ white-space: nowrap;
235
+ font-weight: 700;
236
+ }
237
+
238
+ th code,
239
+ td pre {
240
+ font-size: var(--uui-type-small-size);
241
+ }
242
+
243
+ td pre {
244
+ margin: 0;
245
+ white-space: pre-wrap;
246
+ word-break: break-word;
247
+ }
248
+
249
+ /* marked with an inset bar rather than a border, so the content doesn't shift. */
250
+ tr.row-changed {
251
+ box-shadow: inset 3px 0 0 var(--uui-color-warning);
252
+ background: color-mix(in srgb, var(--uui-color-warning) 10%, transparent);
253
+ }
254
+
255
+ tr.row-added {
256
+ box-shadow: inset 3px 0 0 var(--uui-color-positive);
257
+ background: color-mix(in srgb, var(--uui-color-positive) 6%, transparent);
258
+ }
259
+
260
+ tr.row-removed {
261
+ box-shadow: inset 3px 0 0 var(--uui-color-danger);
262
+ background: color-mix(in srgb, var(--uui-color-danger) 6%, transparent);
263
+ }
264
+
265
+ .empty {
266
+ margin: 0;
267
+ color: var(--uui-color-text-alt);
268
+ }
269
+ `;
270
+ __decorate([
271
+ property({ type: Object })
272
+ ], uSyncDataTypePreviewElement.prototype, "preview", void 0);
273
+ uSyncDataTypePreviewElement = __decorate([
274
+ customElement('usync-data-type-preview')
275
+ ], uSyncDataTypePreviewElement);
276
+ export { uSyncDataTypePreviewElement };
277
+ /**
278
+ * how a config value on this side compares to the other side. an alias
279
+ * missing from the current side is being added, one missing from the
280
+ * incoming side is being removed.
281
+ */
282
+ function configStatus(alias, value, other, side) {
283
+ if (!other)
284
+ return 'unchanged';
285
+ const match = other.values.find((v) => v.alias === alias);
286
+ if (!match)
287
+ return side === 'incoming' ? 'added' : 'removed';
288
+ return deepEqual(value, match.value) ? 'unchanged' : 'changed';
289
+ }
290
+ function formatConfigValue(value) {
291
+ return typeof value === 'string' ? value : prettyJson(value);
292
+ }
293
+ export default uSyncDataTypePreviewElement;
@@ -15,7 +15,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
15
15
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
16
16
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
17
17
  };
18
- var _uSyncResultsView_instances, _uSyncResultsView_modalContext, _uSyncResultsView_toggleShowAll, _uSyncResultsView_showDetail;
18
+ var _uSyncResultsView_instances, _uSyncResultsView_modalContext, _uSyncResultsView_toggleShowAll, _uSyncResultsView_showDetail, _uSyncResultsView_visibleItems;
19
19
  import { LitElement, html, customElement, property, css, state, nothing, } from '@umbraco-cms/backoffice/external/lit';
20
20
  import { ChangeType } from '@jumoo/uSync';
21
21
  import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
@@ -98,10 +98,11 @@ _uSyncResultsView_showDetail = async function _uSyncResultsView_showDetail(e) {
98
98
  const detailsModal = __classPrivateFieldGet(this, _uSyncResultsView_modalContext, "f")?.open(this, USYNC_DETAILS_MODAL, {
99
99
  data: {
100
100
  item: e.action,
101
- showActions: !this.hideActions &&
102
- (e.action.change == ChangeType.CREATE ||
103
- e.action.change == ChangeType.UPDATE ||
104
- e.action.change == ChangeType.IMPORT),
101
+ items: __classPrivateFieldGet(this, _uSyncResultsView_instances, "m", _uSyncResultsView_visibleItems).call(this),
102
+ showActions: (item) => !this.hideActions &&
103
+ (item.change == ChangeType.CREATE ||
104
+ item.change == ChangeType.UPDATE ||
105
+ item.change == ChangeType.IMPORT),
105
106
  },
106
107
  });
107
108
  const data = await detailsModal?.onSubmit().catch(() => {
@@ -110,6 +111,13 @@ _uSyncResultsView_showDetail = async function _uSyncResultsView_showDetail(e) {
110
111
  if (!data)
111
112
  return;
112
113
  };
114
+ _uSyncResultsView_visibleItems = function _uSyncResultsView_visibleItems() {
115
+ const groups = this.groupBy(this.results || [], (result) => result.itemType);
116
+ return Object.values(groups)
117
+ .flat()
118
+ .filter((r) => r.change !== ChangeType.EXPORT &&
119
+ (this.showAll || r.change !== ChangeType.NO_CHANGE));
120
+ };
113
121
  uSyncResultsView.styles = css `
114
122
  :host {
115
123
  display: block;
@@ -1,12 +1,23 @@
1
1
  import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
2
2
  import { nothing } from '@umbraco-cms/backoffice/external/lit';
3
- import { uSyncDetailsModalData, uSyncDetailsModalValue } from '@jumoo/uSync';
3
+ import { uSyncDetailsModalData, uSyncDetailsModalValue, type SyncItemPreviewResponse } from '@jumoo/uSync';
4
4
  import { UUIButtonState } from '@umbraco-cms/backoffice/external/uui';
5
+ import '../components/usync-data-type-preview.js';
6
+ import '../components/usync-content-type-preview.js';
7
+ import '../components/usync-content-preview.js';
5
8
  export declare class uSyncDetailsModalElement extends UmbModalBaseElement<uSyncDetailsModalData, uSyncDetailsModalValue> {
6
9
  #private;
7
10
  importState: UUIButtonState;
11
+ private _preview?;
12
+ private _tab;
13
+ private _item?;
14
+ private _index;
8
15
  constructor();
16
+ connectedCallback(): void;
9
17
  render(): import("lit-html").TemplateResult<1>;
18
+ renderNavigation(): typeof nothing | import("lit-html").TemplateResult<1>;
19
+ renderTabs(): typeof nothing | import("lit-html").TemplateResult<1>;
20
+ renderPreview(preview: SyncItemPreviewResponse): typeof nothing | import("lit-html").TemplateResult<1>;
10
21
  renderActions(): typeof nothing | import("lit-html").TemplateResult<1>;
11
22
  static styles: import("lit").CSSResult;
12
23
  }
@@ -9,22 +9,34 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _uSyncDetailsModalElement_instances, _uSyncDetailsModalElement_onImport, _uSyncDetailsModalElement_onClose;
12
+ var _uSyncDetailsModalElement_instances, _uSyncDetailsModalElement_repository, _uSyncDetailsModalElement_moveTo, _uSyncDetailsModalElement_loadPreview, _uSyncDetailsModalElement_showActions, _uSyncDetailsModalElement_onImport, _uSyncDetailsModalElement_onClose;
13
13
  import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement, } from '@umbraco-cms/backoffice/modal';
14
14
  import { css, customElement, html, nothing, state, } from '@umbraco-cms/backoffice/external/lit';
15
- import { USYNC_IMPORT_SINGLE_MODAL, } from '@jumoo/uSync';
15
+ import { USYNC_IMPORT_SINGLE_MODAL, uSyncActionRepository, } from '@jumoo/uSync';
16
+ import '../components/usync-data-type-preview.js';
17
+ import '../components/usync-content-type-preview.js';
18
+ import '../components/usync-content-preview.js';
16
19
  let uSyncDetailsModalElement = class uSyncDetailsModalElement extends UmbModalBaseElement {
17
20
  constructor() {
18
21
  super();
19
22
  _uSyncDetailsModalElement_instances.add(this);
23
+ this._tab = 'changes';
24
+ this._index = -1;
25
+ _uSyncDetailsModalElement_repository.set(this, new uSyncActionRepository(this));
20
26
  // this.consumeContext(USYNC_CORE_CONTEXT_TOKEN, (_instance) => {
21
27
  // if (!_instance) return;
22
28
  // this.#actionContext = _instance;
23
29
  // });
24
30
  }
31
+ connectedCallback() {
32
+ super.connectedCallback();
33
+ this._item = this.data?.item;
34
+ this._index = this.data?.items?.indexOf(this.data.item) ?? -1;
35
+ __classPrivateFieldGet(this, _uSyncDetailsModalElement_instances, "m", _uSyncDetailsModalElement_loadPreview).call(this);
36
+ }
25
37
  render() {
26
38
  return html `
27
- <umb-body-layout headline="Changes : ${this.data?.item.name ?? ''}">
39
+ <umb-body-layout headline="Changes : ${this._item?.name ?? ''}">
28
40
  <div class="layout">
29
41
  <uui-box style="--uui-box-default-padding: 0;">
30
42
  <div slot="header" id="header">
@@ -33,10 +45,14 @@ let uSyncDetailsModalElement = class uSyncDetailsModalElement extends UmbModalBa
33
45
  </div>
34
46
  <div slot="header-actions">${this.renderActions()}</div>
35
47
  </uui-box>
36
- <uui-box style="--uui-box-default-padding: 0;">
37
- <usync-change-view .item=${this.data?.item}></usync-change-view>
38
- </uui-box>
48
+ ${this.renderTabs()}
49
+ ${this._tab === 'preview' && this._preview
50
+ ? this.renderPreview(this._preview)
51
+ : html `<uui-box style="--uui-box-default-padding: 0;">
52
+ <usync-change-view .item=${this._item}></usync-change-view>
53
+ </uui-box>`}
39
54
  </div>
55
+ ${this.renderNavigation()}
40
56
  <div slot="actions">
41
57
  <uui-button
42
58
  id="cancel"
@@ -46,8 +62,66 @@ let uSyncDetailsModalElement = class uSyncDetailsModalElement extends UmbModalBa
46
62
  </umb-body-layout>
47
63
  `;
48
64
  }
65
+ renderNavigation() {
66
+ const count = this.data?.items?.length ?? 0;
67
+ if (count < 2 || this._index < 0)
68
+ return nothing;
69
+ return html `<div slot="footer-info" id="navigation">
70
+ <uui-button
71
+ compact
72
+ look="secondary"
73
+ .label=${this.localize.term('general_previous')}
74
+ ?disabled=${this._index === 0}
75
+ @click=${() => __classPrivateFieldGet(this, _uSyncDetailsModalElement_instances, "m", _uSyncDetailsModalElement_moveTo).call(this, this._index - 1)}>
76
+ <uui-icon name="icon-arrow-left"></uui-icon>
77
+ </uui-button>
78
+ <span>
79
+ ${this.localize.termOrDefault('uSync_detailPosition', `${this._index + 1} of ${count}`, this.localize.number(this._index + 1), this.localize.number(count))}
80
+ </span>
81
+ <uui-button
82
+ compact
83
+ look="secondary"
84
+ .label=${this.localize.term('general_next')}
85
+ ?disabled=${this._index === count - 1}
86
+ @click=${() => __classPrivateFieldGet(this, _uSyncDetailsModalElement_instances, "m", _uSyncDetailsModalElement_moveTo).call(this, this._index + 1)}>
87
+ <uui-icon name="icon-arrow-right"></uui-icon>
88
+ </uui-button>
89
+ </div>`;
90
+ }
91
+ renderTabs() {
92
+ if (!this._preview)
93
+ return nothing;
94
+ return html `<uui-tab-group>
95
+ <uui-tab
96
+ .label=${this.localize.termOrDefault('uSync_changesTab', 'Changes')}
97
+ ?active=${this._tab === 'changes'}
98
+ @click=${() => (this._tab = 'changes')}></uui-tab>
99
+ <uui-tab
100
+ .label=${this.localize.termOrDefault('uSync_previewTab', 'Preview')}
101
+ ?active=${this._tab === 'preview'}
102
+ @click=${() => (this._tab = 'preview')}></uui-tab>
103
+ </uui-tab-group>`;
104
+ }
105
+ renderPreview(preview) {
106
+ switch (preview.entityType) {
107
+ case 'data-type':
108
+ return html `<usync-data-type-preview
109
+ .preview=${preview}></usync-data-type-preview>`;
110
+ case 'document-type':
111
+ case 'media-type':
112
+ case 'member-type':
113
+ return html `<usync-content-type-preview
114
+ .preview=${preview}></usync-content-type-preview>`;
115
+ case 'document':
116
+ case 'media':
117
+ return html `<usync-content-preview
118
+ .preview=${preview}></usync-content-preview>`;
119
+ default:
120
+ return nothing;
121
+ }
122
+ }
49
123
  renderActions() {
50
- if (!this.data?.showActions)
124
+ if (!__classPrivateFieldGet(this, _uSyncDetailsModalElement_instances, "m", _uSyncDetailsModalElement_showActions).call(this))
51
125
  return nothing;
52
126
  return html ` <uui-button
53
127
  id="import"
@@ -58,16 +132,53 @@ let uSyncDetailsModalElement = class uSyncDetailsModalElement extends UmbModalBa
58
132
  @click="${__classPrivateFieldGet(this, _uSyncDetailsModalElement_instances, "m", _uSyncDetailsModalElement_onImport)}"></uui-button>`;
59
133
  }
60
134
  };
135
+ _uSyncDetailsModalElement_repository = new WeakMap();
61
136
  _uSyncDetailsModalElement_instances = new WeakSet();
137
+ _uSyncDetailsModalElement_moveTo = function _uSyncDetailsModalElement_moveTo(index) {
138
+ const item = this.data?.items?.[index];
139
+ if (!item)
140
+ return;
141
+ this._index = index;
142
+ this._item = item;
143
+ this._preview = undefined;
144
+ __classPrivateFieldGet(this, _uSyncDetailsModalElement_instances, "m", _uSyncDetailsModalElement_loadPreview).call(this);
145
+ };
146
+ _uSyncDetailsModalElement_loadPreview = async function _uSyncDetailsModalElement_loadPreview() {
147
+ const item = this._item;
148
+ if (!item?.handler || !item.key) {
149
+ this._tab = 'changes';
150
+ return;
151
+ }
152
+ // only some handlers support previews, the rest return a 404
153
+ // and the modal stays as it was (just the changes list).
154
+ const { data } = await __classPrivateFieldGet(this, _uSyncDetailsModalElement_repository, "f").getPreview(item.handler, item.key);
155
+ // moving through the list quickly can return previews out of order,
156
+ // so drop anything that isn't for the item we are now showing.
157
+ if (item !== this._item)
158
+ return;
159
+ if (data?.entityType) {
160
+ this._preview = data;
161
+ }
162
+ else {
163
+ this._tab = 'changes';
164
+ }
165
+ };
166
+ _uSyncDetailsModalElement_showActions = function _uSyncDetailsModalElement_showActions() {
167
+ const showActions = this.data?.showActions;
168
+ if (typeof showActions === 'function') {
169
+ return this._item ? showActions(this._item) : false;
170
+ }
171
+ return showActions ?? false;
172
+ };
62
173
  _uSyncDetailsModalElement_onImport = async function _uSyncDetailsModalElement_onImport(e) {
63
174
  e.stopPropagation();
64
- if (!this.data?.item)
175
+ if (!this._item)
65
176
  return;
66
177
  const modalContext = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
67
178
  if (!modalContext)
68
179
  return;
69
180
  const modal = modalContext.open(this, USYNC_IMPORT_SINGLE_MODAL, {
70
- data: { action: this.data?.item },
181
+ data: { action: this._item },
71
182
  });
72
183
  const data = await modal?.onSubmit().catch(() => {
73
184
  return;
@@ -87,10 +198,29 @@ uSyncDetailsModalElement.styles = css `
87
198
  #header h3 {
88
199
  margin: 0;
89
200
  }
201
+
202
+ #navigation {
203
+ display: flex;
204
+ align-items: center;
205
+ gap: var(--uui-size-space-3);
206
+ padding-left: var(--uui-size-space-4);
207
+ }
90
208
  `;
91
209
  __decorate([
92
210
  state()
93
211
  ], uSyncDetailsModalElement.prototype, "importState", void 0);
212
+ __decorate([
213
+ state()
214
+ ], uSyncDetailsModalElement.prototype, "_preview", void 0);
215
+ __decorate([
216
+ state()
217
+ ], uSyncDetailsModalElement.prototype, "_tab", void 0);
218
+ __decorate([
219
+ state()
220
+ ], uSyncDetailsModalElement.prototype, "_item", void 0);
221
+ __decorate([
222
+ state()
223
+ ], uSyncDetailsModalElement.prototype, "_index", void 0);
94
224
  uSyncDetailsModalElement = __decorate([
95
225
  customElement('usync-details-modal')
96
226
  ], uSyncDetailsModalElement);
@@ -2,7 +2,16 @@ import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
2
2
  import { USyncActionView } from '@jumoo/uSync';
3
3
  export interface uSyncDetailsModalData {
4
4
  item: USyncActionView;
5
- showActions?: boolean;
5
+ /**
6
+ * show the import button, either for every item or decided per item
7
+ * (when moving through `items` the answer can change from item to item).
8
+ */
9
+ showActions?: boolean | ((item: USyncActionView) => boolean);
10
+ /**
11
+ * the full list the item came from, when set the dialog can move
12
+ * to the previous / next item in the list.
13
+ */
14
+ items?: Array<USyncActionView>;
6
15
  }
7
16
  export interface uSyncDetailsModalValue {
8
17
  result: boolean;
@@ -24,6 +24,43 @@ declare const _default: {
24
24
  showAll: string;
25
25
  detailHeadline: string;
26
26
  detailHeader: string;
27
+ detailPosition: string;
28
+ previewTab: string;
29
+ changesTab: string;
30
+ previewCurrent: string;
31
+ previewIncoming: string;
32
+ previewNotInSite: string;
33
+ previewDeleted: string;
34
+ previewFailed: string;
35
+ previewEditor: string;
36
+ previewEditorDesc: string;
37
+ previewConfiguration: string;
38
+ previewNoConfiguration: string;
39
+ previewPropertyEditor: string;
40
+ previewPropertyEditorUi: string;
41
+ previewDocumentType: string;
42
+ previewMediaType: string;
43
+ previewMemberType: string;
44
+ previewElementType: string;
45
+ previewAllowedAtRoot: string;
46
+ previewVariesByCulture: string;
47
+ previewVariesBySegment: string;
48
+ previewCompositions: string;
49
+ previewGenericTab: string;
50
+ previewNoProperties: string;
51
+ previewMissingDataType: string;
52
+ previewNewDataType: string;
53
+ previewNew: string;
54
+ previewParent: string;
55
+ previewRoot: string;
56
+ previewSortOrder: string;
57
+ previewTemplate: string;
58
+ previewPublished: string;
59
+ previewNotPublished: string;
60
+ previewTrashed: string;
61
+ previewCulture: string;
62
+ previewOnlyChanges: string;
63
+ previewNoValueChanges: string;
27
64
  runningInBackground: string;
28
65
  connectionLost: string;
29
66
  importSingle: string;
@@ -24,6 +24,43 @@ export default {
24
24
  showAll: 'Vis alle elementer',
25
25
  detailHeadline: 'Registrerede ændringer',
26
26
  detailHeader: 'Ting der er anderledes',
27
+ detailPosition: '%0% af %1%',
28
+ previewTab: 'Visuel',
29
+ changesTab: 'Ændringer',
30
+ previewCurrent: 'Nuværende (dette site)',
31
+ previewIncoming: 'Indkommende (uSync-filer)',
32
+ previewNotInSite: 'Dette element findes ikke på sitet endnu',
33
+ previewDeleted: 'Dette element bliver slettet eller omdøbt af importen',
34
+ previewFailed: 'Det indkommende element kunne ikke bygges til forhåndsvisningen',
35
+ previewEditor: 'Editor-forhåndsvisning',
36
+ previewEditorDesc: 'Sådan ser denne datatype ud for redaktører',
37
+ previewConfiguration: 'Konfiguration',
38
+ previewNoConfiguration: 'Ingen konfiguration',
39
+ previewPropertyEditor: 'Property editor',
40
+ previewPropertyEditorUi: 'Property editor UI',
41
+ previewDocumentType: 'Dokumenttype',
42
+ previewMediaType: 'Medietype',
43
+ previewMemberType: 'Medlemstype',
44
+ previewElementType: 'Elementtype',
45
+ previewAllowedAtRoot: 'Tilladt i roden',
46
+ previewVariesByCulture: 'Varierer efter kultur',
47
+ previewVariesBySegment: 'Varierer efter segment',
48
+ previewCompositions: 'Kompositioner',
49
+ previewGenericTab: 'Generelt',
50
+ previewNoProperties: 'Ingen egenskaber',
51
+ previewMissingDataType: 'datatypen for denne egenskab findes ikke på sitet endnu',
52
+ previewNewDataType: 'ny datatype',
53
+ previewNew: 'ny',
54
+ previewParent: 'Overordnet',
55
+ previewRoot: '(roden)',
56
+ previewSortOrder: 'Sorteringsrækkefølge',
57
+ previewTemplate: 'Skabelon',
58
+ previewPublished: 'Udgivet',
59
+ previewNotPublished: 'Ikke udgivet',
60
+ previewTrashed: 'I papirkurven',
61
+ previewCulture: 'Sprog',
62
+ previewOnlyChanges: 'Vis kun ændringer',
63
+ previewNoValueChanges: 'Ingen værdier ændres',
27
64
  runningInBackground: 'uSync kører denne proces i baggrunden. Hvis du navigerer væk fra denne side, vil den fortsætte med at køre.',
28
65
  connectionLost: 'Forbindelsen til serveren er gået tabt. Processen vil fortsætte med at køre i baggrunden, men du vil ikke se opdateringer her.',
29
66
  importSingle: 'Importer',