@jumoo/usync 18.2.0 → 18.3.0

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 (71) hide show
  1. package/LICENCE +372 -372
  2. package/README.md +16 -10
  3. package/dist/api/index.d.ts +2 -2
  4. package/dist/api/index.js +1 -1
  5. package/dist/api/sdk.gen.d.ts +2 -1
  6. package/dist/api/sdk.gen.js +5 -0
  7. package/dist/api/types.gen.d.ts +37 -0
  8. package/dist/components/usync-action-box.js +71 -71
  9. package/dist/components/usync-change-detail.js +409 -409
  10. package/dist/components/usync-change-view.js +49 -49
  11. package/dist/components/usync-content-preview.d.ts +27 -0
  12. package/dist/components/usync-content-preview.js +532 -0
  13. package/dist/components/usync-content-type-preview.d.ts +25 -0
  14. package/dist/components/usync-content-type-preview.js +530 -0
  15. package/dist/components/usync-data-type-preview.d.ts +21 -0
  16. package/dist/components/usync-data-type-preview.js +295 -0
  17. package/dist/components/usync-progress-box.js +113 -113
  18. package/dist/components/usync-result-row.js +65 -65
  19. package/dist/components/usync-results-group-view.js +63 -63
  20. package/dist/components/usync-results-view.js +77 -69
  21. package/dist/components/usync-sync-file-info-view.js +10 -10
  22. package/dist/constants.js +1 -1
  23. package/dist/dialogs/details-modal-element.d.ts +15 -0
  24. package/dist/dialogs/details-modal-element.js +260 -50
  25. package/dist/dialogs/details-modal-token.d.ts +10 -1
  26. package/dist/dialogs/error-modal-element.js +22 -22
  27. package/dist/dialogs/legacy-modal-element.js +22 -22
  28. package/dist/dialogs/single-import-modal.element.js +31 -31
  29. package/dist/exports.d.ts +1 -0
  30. package/dist/exports.js +1 -0
  31. package/dist/icons/svg/logo.js +20 -20
  32. package/dist/lang/files/da-dk.d.ts +37 -0
  33. package/dist/lang/files/da-dk.js +49 -12
  34. package/dist/lang/files/de-de.d.ts +37 -0
  35. package/dist/lang/files/de-de.js +49 -12
  36. package/dist/lang/files/en-us.d.ts +50 -0
  37. package/dist/lang/files/en-us.js +62 -12
  38. package/dist/lang/files/es-es.d.ts +37 -0
  39. package/dist/lang/files/es-es.js +49 -12
  40. package/dist/lang/files/fr-fr.d.ts +37 -0
  41. package/dist/lang/files/fr-fr.js +49 -12
  42. package/dist/lang/files/nl-nl.d.ts +37 -0
  43. package/dist/lang/files/nl-nl.js +49 -12
  44. package/dist/manifests.js +2 -0
  45. package/dist/preview/index.d.ts +1 -0
  46. package/dist/preview/index.js +1 -0
  47. package/dist/preview/manifest.d.ts +2 -0
  48. package/dist/preview/manifest.js +22 -0
  49. package/dist/preview/types.d.ts +72 -0
  50. package/dist/preview/types.js +2 -0
  51. package/dist/repository/SyncAction.respositoy.d.ts +13 -0
  52. package/dist/repository/SyncAction.respositoy.js +6 -0
  53. package/dist/repository/sources/SyncAction.source.d.ts +10 -0
  54. package/dist/repository/sources/SyncAction.source.js +6 -1
  55. package/dist/signalr/signalr.context.js +73 -26
  56. package/dist/tree/usync.menu-element.js +8 -8
  57. package/dist/utils/preview/content-type-diff.d.ts +18 -0
  58. package/dist/utils/preview/content-type-diff.js +72 -0
  59. package/dist/utils/preview/content-type-layout.d.ts +39 -0
  60. package/dist/utils/preview/content-type-layout.js +100 -0
  61. package/dist/workspace/components/usync-action-button.js +53 -53
  62. package/dist/workspace/components/usync-file-picker.element.js +33 -33
  63. package/dist/workspace/components/usync-file-upload.element.js +25 -25
  64. package/dist/workspace/dialogs/import-modal.element.js +22 -22
  65. package/dist/workspace/views/addons/addons.element.js +97 -97
  66. package/dist/workspace/views/default/default.element.js +186 -186
  67. package/dist/workspace/views/legacy/legacy.element.js +81 -81
  68. package/dist/workspace/views/settings/components/usyncSettingItem.element.js +38 -38
  69. package/dist/workspace/views/settings/settings.element.js +124 -124
  70. package/dist/workspace/workspace.element.js +16 -16
  71. package/package.json +77 -77
@@ -24,6 +24,43 @@ export default {
24
24
  showAll: 'Afficher tous les éléments',
25
25
  detailHeadline: 'Modifications détectées',
26
26
  detailHeader: 'Ce qui est différent',
27
+ detailPosition: '%0% sur %1%',
28
+ changesTab: 'Modifications',
29
+ diffTab: 'Diff',
30
+ previewCurrent: 'Actuel (ce site)',
31
+ previewIncoming: 'Entrant (fichiers uSync)',
32
+ previewNotInSite: "Cet élément n'existe pas encore sur le site",
33
+ previewDeleted: "Cet élément sera supprimé ou renommé par l'import",
34
+ previewFailed: "L'élément entrant n'a pas pu être construit pour l'aperçu",
35
+ previewEditor: "Aperçu de l'éditeur",
36
+ previewEditorDesc: 'Comment ce type de données apparaît aux éditeurs',
37
+ previewConfiguration: 'Configuration',
38
+ previewNoConfiguration: 'Aucune configuration',
39
+ previewPropertyEditor: 'Éditeur de propriété',
40
+ previewPropertyEditorUi: "UI de l'éditeur de propriété",
41
+ previewDocumentType: 'Type de document',
42
+ previewMediaType: 'Type de média',
43
+ previewMemberType: 'Type de membre',
44
+ previewElementType: "Type d'élément",
45
+ previewAllowedAtRoot: 'Autorisé à la racine',
46
+ previewVariesByCulture: 'Varie selon la culture',
47
+ previewVariesBySegment: 'Varie selon le segment',
48
+ previewCompositions: 'Compositions',
49
+ previewGenericTab: 'Général',
50
+ previewNoProperties: 'Aucune propriété',
51
+ previewMissingDataType: "le type de données de cette propriété n'existe pas encore sur le site",
52
+ previewNewDataType: 'nouveau type de données',
53
+ previewNew: 'nouveau',
54
+ previewParent: 'Parent',
55
+ previewRoot: '(racine)',
56
+ previewSortOrder: 'Ordre de tri',
57
+ previewTemplate: 'Modèle',
58
+ previewPublished: 'Publié',
59
+ previewNotPublished: 'Non publié',
60
+ previewTrashed: 'Dans la corbeille',
61
+ previewCulture: 'Langue',
62
+ previewOnlyChanges: 'Afficher uniquement les modifications',
63
+ previewNoValueChanges: 'Aucune valeur ne change',
27
64
  runningInBackground: 'uSync exécute ce processus en arrière-plan. Si vous quittez cette page, il continuera de fonctionner.',
28
65
  connectionLost: 'La connexion au serveur a été perdue. Le processus continuera de s\'exécuter en arrière-plan, mais vous ne verrez pas les mises à jour ici.',
29
66
  importSingle: 'Importer',
@@ -46,21 +83,21 @@ export default {
46
83
  changeHeading: 'Résultats',
47
84
  changeCount: '{1}/{0} modifications',
48
85
  noChangeCount: '0/{0} modifications',
49
- legacyInfo: `<p>uSync a trouvé un dossier uSync hérité à <strong>%0%</strong>.<br />
86
+ legacyInfo: `<p>uSync a trouvé un dossier uSync hérité à <strong>%0%</strong>.<br />
50
87
  Il est probable que son contenu devra être converti d'une façon ou d'une autre</p>`,
51
- legacyObsolete: `<h4>Types de données obsolètes</h4>
52
- <ul>%0%</ul>
53
- <p>Vous pouvez convertir ces types de données en utilisant
54
- <a href="https://github.com/Jumoo/uSyncMigrations" target="_blank">uSync.Migrations</a><br />
88
+ legacyObsolete: `<h4>Types de données obsolètes</h4>
89
+ <ul>%0%</ul>
90
+ <p>Vous pouvez convertir ces types de données en utilisant
91
+ <a href="https://github.com/Jumoo/uSyncMigrations" target="_blank">uSync.Migrations</a><br />
55
92
  <em>(Dans la version complète d'uSync, la conversion se fera ici.)</em></p>`,
56
- legacyCopy: `<h4>Copier vers uSync/v14</h4>
57
- <p>Vous pouvez copier votre dossier %0% vers le dossier ~/uSync/v14<br />et exécuter une importation.</p>
58
- <p>Si rien ne nécessite de conversion, tout devrait s'importer correctement.</p>
93
+ legacyCopy: `<h4>Copier vers uSync/v14</h4>
94
+ <p>Vous pouvez copier votre dossier %0% vers le dossier ~/uSync/v14<br />et exécuter une importation.</p>
95
+ <p>Si rien ne nécessite de conversion, tout devrait s'importer correctement.</p>
59
96
  <p><strong>Supprimez ou renommez le dossier %0% pour éviter cette popup</strong></p>`,
60
- hmacMismatch: `<h4>Incompatibilité HMAC <uui-icon name="alert"></uui-icon></h4>
61
- <p>Il semble que le paramètre <code>Imaging:HMAC</code> utilisé pour générer les fichiers dans le dossier uSync ne corresponde pas au paramètre actuel de ce site.</p>
62
- <p>Les images dans les contrôles RTE auront la valeur HMAC ajoutée à l'URL, et sans configuration supplémentaire, ces images pourraient ne pas s'afficher correctement.</p>
63
- <ul><li>Vous pouvez activer le "mappage HMAC" dans uSync,</li>
97
+ hmacMismatch: `<h4>Incompatibilité HMAC <uui-icon name="alert"></uui-icon></h4>
98
+ <p>Il semble que le paramètre <code>Imaging:HMAC</code> utilisé pour générer les fichiers dans le dossier uSync ne corresponde pas au paramètre actuel de ce site.</p>
99
+ <p>Les images dans les contrôles RTE auront la valeur HMAC ajoutée à l'URL, et sans configuration supplémentaire, ces images pourraient ne pas s'afficher correctement.</p>
100
+ <ul><li>Vous pouvez activer le "mappage HMAC" dans uSync,</li>
64
101
  <li>ou vous pouvez vous assurer que la valeur HMAC dans le paramètre <code>Imaging:HMAC</code> correspond à la valeur utilisée pour générer les fichiers dans le dossier uSync</li></ul>`,
65
102
  formatMismatch: 'La version du format du fichier de synchronisation ne correspond pas à la version attendue. Cela peut indiquer un problème de compatibilité potentiel.',
66
103
  legacyBanner: 'Ce site contient des fichiers d\'une version précédente d\'uSync. Consultez les détails dans l\'onglet Héritage.',
@@ -24,6 +24,43 @@ declare const _default: {
24
24
  showAll: string;
25
25
  detailHeadline: string;
26
26
  detailHeader: string;
27
+ detailPosition: string;
28
+ changesTab: string;
29
+ diffTab: 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: 'Alle items weergeven',
25
25
  detailHeadline: 'Gedetecteerde wijzigingen',
26
26
  detailHeader: 'Wat er anders is',
27
+ detailPosition: '%0% van %1%',
28
+ changesTab: 'Wijzigingen',
29
+ diffTab: 'Diff',
30
+ previewCurrent: 'Huidig (deze site)',
31
+ previewIncoming: 'Inkomend (uSync-bestanden)',
32
+ previewNotInSite: 'Dit item bestaat nog niet op de site',
33
+ previewDeleted: 'Dit item wordt door de import verwijderd of hernoemd',
34
+ previewFailed: 'Het inkomende item kon niet worden opgebouwd voor het voorbeeld',
35
+ previewEditor: 'Editor-voorbeeld',
36
+ previewEditorDesc: 'Zo ziet dit datatype eruit voor redacteuren',
37
+ previewConfiguration: 'Configuratie',
38
+ previewNoConfiguration: 'Geen configuratie',
39
+ previewPropertyEditor: 'Property editor',
40
+ previewPropertyEditorUi: 'Property editor UI',
41
+ previewDocumentType: 'Documenttype',
42
+ previewMediaType: 'Mediatype',
43
+ previewMemberType: 'Ledentype',
44
+ previewElementType: 'Elementtype',
45
+ previewAllowedAtRoot: 'Toegestaan in de root',
46
+ previewVariesByCulture: 'Varieert per cultuur',
47
+ previewVariesBySegment: 'Varieert per segment',
48
+ previewCompositions: 'Composities',
49
+ previewGenericTab: 'Algemeen',
50
+ previewNoProperties: 'Geen eigenschappen',
51
+ previewMissingDataType: 'het datatype voor deze eigenschap bestaat nog niet op de site',
52
+ previewNewDataType: 'nieuw datatype',
53
+ previewNew: 'nieuw',
54
+ previewParent: 'Bovenliggend',
55
+ previewRoot: '(root)',
56
+ previewSortOrder: 'Sorteervolgorde',
57
+ previewTemplate: 'Sjabloon',
58
+ previewPublished: 'Gepubliceerd',
59
+ previewNotPublished: 'Niet gepubliceerd',
60
+ previewTrashed: 'In de prullenbak',
61
+ previewCulture: 'Taal',
62
+ previewOnlyChanges: 'Alleen wijzigingen tonen',
63
+ previewNoValueChanges: 'Geen waarden veranderen',
27
64
  runningInBackground: 'uSync voert dit proces op de achtergrond uit. Als u van deze pagina navigeert, blijft het doorlopen.',
28
65
  connectionLost: 'De verbinding met de server is verbroken. Het proces blijft op de achtergrond draaien, maar u ziet hier geen updates.',
29
66
  importSingle: 'Importeren',
@@ -46,21 +83,21 @@ export default {
46
83
  changeHeading: 'Resultaten',
47
84
  changeCount: '{1}/{0} wijzigingen',
48
85
  noChangeCount: '0/{0} wijzigingen',
49
- legacyInfo: `<p>uSync heeft een verouderde uSync-map gevonden op <strong>%0%</strong>.<br />
86
+ legacyInfo: `<p>uSync heeft een verouderde uSync-map gevonden op <strong>%0%</strong>.<br />
50
87
  Het is waarschijnlijk dat de inhoud op de een of andere manier geconverteerd moet worden</p>`,
51
- legacyObsolete: `<h4>Verouderde gegevenstypen</h4>
52
- <ul>%0%</ul>
53
- <p>U kunt deze gegevenstypen converteren met
54
- <a href="https://github.com/Jumoo/uSyncMigrations" target="_blank">uSync.Migrations</a><br />
88
+ legacyObsolete: `<h4>Verouderde gegevenstypen</h4>
89
+ <ul>%0%</ul>
90
+ <p>U kunt deze gegevenstypen converteren met
91
+ <a href="https://github.com/Jumoo/uSyncMigrations" target="_blank">uSync.Migrations</a><br />
55
92
  <em>(In de volledige uSync-release zal de conversie hier plaatsvinden.)</em></p>`,
56
- legacyCopy: `<h4>Kopiëren naar uSync/v14</h4>
57
- <p>U kunt uw %0%-map kopiëren naar de ~/uSync/v14-map<br />en een import uitvoeren.</p>
58
- <p>Als er niets geconverteerd hoeft te worden, zou alles correct moeten importeren.</p>
93
+ legacyCopy: `<h4>Kopiëren naar uSync/v14</h4>
94
+ <p>U kunt uw %0%-map kopiëren naar de ~/uSync/v14-map<br />en een import uitvoeren.</p>
95
+ <p>Als er niets geconverteerd hoeft te worden, zou alles correct moeten importeren.</p>
59
96
  <p><strong>Verwijder of hernoem de %0%-map om deze popup te voorkomen</strong></p>`,
60
- hmacMismatch: `<h4>HMAC-mismatch <uui-icon name="alert"></uui-icon></h4>
61
- <p>Het lijkt erop dat de <code>Imaging:HMAC</code>-instelling die werd gebruikt om de bestanden in de uSync-map te genereren, niet overeenkomt met de huidige instelling voor deze site.</p>
62
- <p>Afbeeldingen in RTE-besturingselementen hebben de HMAC-waarde toegevoegd aan de URL-waarde, en zonder aanvullende configuratie worden deze afbeeldingen mogelijk niet correct weergegeven.</p>
63
- <ul><li>U kunt "HMAC-mapping" inschakelen in uSync,</li>
97
+ hmacMismatch: `<h4>HMAC-mismatch <uui-icon name="alert"></uui-icon></h4>
98
+ <p>Het lijkt erop dat de <code>Imaging:HMAC</code>-instelling die werd gebruikt om de bestanden in de uSync-map te genereren, niet overeenkomt met de huidige instelling voor deze site.</p>
99
+ <p>Afbeeldingen in RTE-besturingselementen hebben de HMAC-waarde toegevoegd aan de URL-waarde, en zonder aanvullende configuratie worden deze afbeeldingen mogelijk niet correct weergegeven.</p>
100
+ <ul><li>U kunt "HMAC-mapping" inschakelen in uSync,</li>
64
101
  <li>of u kunt ervoor zorgen dat de HMAC-waarde in de <code>Imaging:HMAC</code>-instelling overeenkomt met de waarde die werd gebruikt om de bestanden in de uSync-map te genereren</li></ul>`,
65
102
  formatMismatch: 'De versie van het synchronisatiebestandsformaat komt niet overeen met de verwachte versie. Dit kan wijzen op een mogelijk compatibiliteitsprobleem.',
66
103
  legacyBanner: 'Deze site bevat bestanden van een eerdere versie van uSync. Bekijk de details op het tabblad Verouderd.',
package/dist/manifests.js CHANGED
@@ -4,6 +4,7 @@ import { manifests as localization } from './lang/manifest.js';
4
4
  import { manifests as dialogs } from './dialogs/manifest.js';
5
5
  import { manifests as conditions } from './conditions/manifest.js';
6
6
  import { manifests as icons } from './icons/manifest.js';
7
+ import { manifests as previews } from './preview/manifest.js';
7
8
  export const manifests = [
8
9
  ...localization,
9
10
  ...trees,
@@ -11,4 +12,5 @@ export const manifests = [
11
12
  ...dialogs,
12
13
  ...conditions,
13
14
  ...icons,
15
+ ...previews,
14
16
  ];
@@ -0,0 +1 @@
1
+ export * from './types.js';
@@ -0,0 +1 @@
1
+ export * from './types.js';
@@ -0,0 +1,2 @@
1
+ import type { ManifestuSyncItemPreview } from './types.js';
2
+ export declare const manifests: ManifestuSyncItemPreview[];
@@ -0,0 +1,22 @@
1
+ const dataTypePreview = {
2
+ type: 'usync-item-preview',
3
+ alias: 'usync.item-preview.data-type',
4
+ name: 'uSync data type preview',
5
+ element: () => import('../components/usync-data-type-preview.js'),
6
+ forEntityTypes: ['data-type'],
7
+ };
8
+ const contentTypePreview = {
9
+ type: 'usync-item-preview',
10
+ alias: 'usync.item-preview.content-type',
11
+ name: 'uSync content type preview',
12
+ element: () => import('../components/usync-content-type-preview.js'),
13
+ forEntityTypes: ['document-type', 'media-type', 'member-type'],
14
+ };
15
+ const contentPreview = {
16
+ type: 'usync-item-preview',
17
+ alias: 'usync.item-preview.content',
18
+ name: 'uSync content preview',
19
+ element: () => import('../components/usync-content-preview.js'),
20
+ forEntityTypes: ['document', 'media'],
21
+ };
22
+ export const manifests = [dataTypePreview, contentTypePreview, contentPreview];
@@ -0,0 +1,72 @@
1
+ import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
2
+ import type { DataTypeResponseModel, DocumentResponseModel, DocumentTypeResponseModel, MediaResponseModel, MediaTypeResponseModel, MemberTypeResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
3
+ import type { SyncItemPreviewResponse } from '../api';
4
+ /**
5
+ * An element that shows the preview of an import for one or more entity types.
6
+ */
7
+ export interface uSyncItemPreviewElement extends HTMLElement {
8
+ preview?: SyncItemPreviewResponse;
9
+ }
10
+ /**
11
+ * Shows the preview for items of the given entity types in the details dialog.
12
+ *
13
+ * The entity types match the `EntityType` of the server side preview mapper,
14
+ * and `preview.preview` is the model that mapper built.
15
+ */
16
+ export interface ManifestuSyncItemPreview extends ManifestElement<uSyncItemPreviewElement> {
17
+ type: 'usync-item-preview';
18
+ forEntityTypes: Array<string>;
19
+ }
20
+ declare global {
21
+ interface UmbExtensionManifestMap {
22
+ ManifestuSyncItemPreview: ManifestuSyncItemPreview;
23
+ }
24
+ }
25
+ /** the model a preview mapper built, as the type the element expects. */
26
+ export declare const getPreviewModel: <T>(preview?: SyncItemPreviewResponse) => T | undefined;
27
+ export type uSyncPreviewContentTypeModel = DocumentTypeResponseModel | MediaTypeResponseModel | MemberTypeResponseModel;
28
+ /** preview model for a data type (entity type data-type) */
29
+ export interface SyncDataTypePreview {
30
+ current?: DataTypeResponseModel | null;
31
+ incoming?: DataTypeResponseModel | null;
32
+ }
33
+ /** what the preview needs to lay out the properties of an item */
34
+ export interface SyncPropertiesPreview<TTypeModel> {
35
+ /** the content types either side is composed of (as they are in the site) */
36
+ compositions: Array<TTypeModel>;
37
+ /** the data types used by the properties on either side */
38
+ dataTypes: Array<DataTypeResponseModel>;
39
+ /** keys of the data types that aren't in the site yet */
40
+ newDataTypes: Array<string>;
41
+ /** keys of the compositions that aren't in the site yet */
42
+ newCompositions: Array<string>;
43
+ }
44
+ /** preview model for a document, media or member type */
45
+ export interface SyncContentTypePreview<TTypeModel extends uSyncPreviewContentTypeModel = uSyncPreviewContentTypeModel> extends SyncPropertiesPreview<TTypeModel> {
46
+ current?: TTypeModel | null;
47
+ incoming?: TTypeModel | null;
48
+ }
49
+ export interface SyncContentPreviewCulture {
50
+ culture: string;
51
+ published: boolean;
52
+ }
53
+ /** the settings of a content or media item that aren't property values */
54
+ export interface SyncContentPreviewInfo {
55
+ /** name of the parent item (null when the item is at the root) */
56
+ parent?: string | null;
57
+ sortOrder: number;
58
+ trashed: boolean;
59
+ /** alias of the template (content only) */
60
+ template?: string | null;
61
+ /** published state for each culture (an empty culture for invariant content) */
62
+ published: Array<SyncContentPreviewCulture>;
63
+ }
64
+ /** preview model for a document or media item */
65
+ export interface SyncContentPreview<TModel extends DocumentResponseModel | MediaResponseModel = DocumentResponseModel | MediaResponseModel, TTypeModel extends DocumentTypeResponseModel | MediaTypeResponseModel = DocumentTypeResponseModel | MediaTypeResponseModel> extends SyncPropertiesPreview<TTypeModel> {
66
+ current?: TModel | null;
67
+ incoming?: TModel | null;
68
+ currentInfo?: SyncContentPreviewInfo | null;
69
+ incomingInfo?: SyncContentPreviewInfo | null;
70
+ /** the document (or media) type of the item, as it is in the site */
71
+ contentType?: TTypeModel | null;
72
+ }
@@ -0,0 +1,2 @@
1
+ /** the model a preview mapper built, as the type the element expects. */
2
+ export const getPreviewModel = (preview) => preview?.preview;
@@ -118,4 +118,17 @@ export declare class uSyncActionRepository extends UmbControllerBase {
118
118
  request?: Request;
119
119
  response?: Response;
120
120
  }>>;
121
+ /**
122
+ * gets the current and incoming versions of an item, when its handler supports previews.
123
+ */
124
+ getPreview(handler: string, key: string): Promise<import("@umbraco-cms/backoffice/resources").UmbApiResponse<({
125
+ data: import("@jumoo/uSync").SyncItemPreviewResponse;
126
+ error: undefined;
127
+ } | {
128
+ data: undefined;
129
+ error: unknown;
130
+ }) & {
131
+ request?: Request;
132
+ response?: Response;
133
+ }>>;
121
134
  }
@@ -121,5 +121,11 @@ export class uSyncActionRepository extends UmbControllerBase {
121
121
  async getSyncFileInfo() {
122
122
  return await __classPrivateFieldGet(this, _uSyncActionRepository_actionDataSource, "f").getSyncFileInfo();
123
123
  }
124
+ /**
125
+ * gets the current and incoming versions of an item, when its handler supports previews.
126
+ */
127
+ async getPreview(handler, key) {
128
+ return await __classPrivateFieldGet(this, _uSyncActionRepository_actionDataSource, "f").getPreview(handler, key);
129
+ }
124
130
  }
125
131
  _uSyncActionRepository_actionDataSource = new WeakMap(), _uSyncActionRepository_settingsDataSource = new WeakMap(), _uSyncActionRepository_migrartionDataSource = new WeakMap();
@@ -54,4 +54,14 @@ export declare class uSyncActionDataSource implements SyncActionDataSource {
54
54
  request?: Request;
55
55
  response?: Response;
56
56
  }>>;
57
+ getPreview(handler: string, key: string): Promise<import("@umbraco-cms/backoffice/resources").UmbApiResponse<({
58
+ data: import("@jumoo/uSync").SyncItemPreviewResponse;
59
+ error: undefined;
60
+ } | {
61
+ data: undefined;
62
+ error: unknown;
63
+ }) & {
64
+ request?: Request;
65
+ response?: Response;
66
+ }>>;
57
67
  }
@@ -11,7 +11,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
11
11
  };
12
12
  var _uSyncActionDataSource_host;
13
13
  import { tryExecute } from '@umbraco-cms/backoffice/resources';
14
- import { getActionsBySet, getRunning, getStatus, getSyncFileInfo, postDownload, postImport, postPerform, postProcessUpload, } from '@jumoo/uSync';
14
+ import { getActionsBySet, getPreview, getRunning, getStatus, getSyncFileInfo, postDownload, postImport, postPerform, postProcessUpload, } from '@jumoo/uSync';
15
15
  export class uSyncActionDataSource {
16
16
  constructor(host) {
17
17
  _uSyncActionDataSource_host.set(this, void 0);
@@ -53,5 +53,10 @@ export class uSyncActionDataSource {
53
53
  body: view,
54
54
  }));
55
55
  }
56
+ async getPreview(handler, key) {
57
+ return await tryExecute(__classPrivateFieldGet(this, _uSyncActionDataSource_host, "f"), getPreview({
58
+ query: { handler, key },
59
+ }), { disableNotifications: true });
60
+ }
56
61
  }
57
62
  _uSyncActionDataSource_host = new WeakMap();
@@ -1,19 +1,20 @@
1
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
- 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");
4
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
- };
6
1
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
7
2
  if (kind === "m") throw new TypeError("Private method is not writable");
8
3
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
9
4
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
5
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
6
  };
12
- var _uSyncSignalRContext_instances, _uSyncSignalRContext_connection, _uSyncSignalRContext_connected, _uSyncSignalRContext_update, _uSyncSignalRContext_add, _uSyncSignalRContext_complete, _uSyncSignalRContext_setupConnection;
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 _uSyncSignalRContext_instances, _uSyncSignalRContext_connection, _uSyncSignalRContext_auth, _uSyncSignalRContext_server, _uSyncSignalRContext_connect, _uSyncSignalRContext_clientId, _uSyncSignalRContext_connected, _uSyncSignalRContext_update, _uSyncSignalRContext_add, _uSyncSignalRContext_complete, _uSyncSignalRContext_setupConnection;
13
13
  import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
14
14
  import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
15
15
  import { USYNC_SIGNALR_CONTEXT_TOKEN, } from '@jumoo/uSync';
16
16
  import { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth';
17
+ import { UMB_SERVER_CONTEXT } from '@umbraco-cms/backoffice/server';
17
18
  import * as signalR from '@jumoo/uSync/external/signalr';
18
19
  import { uSyncSignalRReconnectPolicy } from './signalr-reconnect-policy.js';
19
20
  export class uSyncSignalRContext extends UmbControllerBase {
@@ -21,6 +22,9 @@ export class uSyncSignalRContext extends UmbControllerBase {
21
22
  super(host);
22
23
  _uSyncSignalRContext_instances.add(this);
23
24
  _uSyncSignalRContext_connection.set(this, void 0);
25
+ _uSyncSignalRContext_auth.set(this, void 0);
26
+ _uSyncSignalRContext_server.set(this, void 0);
27
+ _uSyncSignalRContext_clientId.set(this, null);
24
28
  _uSyncSignalRContext_connected.set(this, new UmbObjectState(false));
25
29
  this.connected = __classPrivateFieldGet(this, _uSyncSignalRContext_connected, "f").asObservable();
26
30
  _uSyncSignalRContext_update.set(this, new UmbObjectState(undefined));
@@ -31,12 +35,12 @@ export class uSyncSignalRContext extends UmbControllerBase {
31
35
  this.complete = __classPrivateFieldGet(this, _uSyncSignalRContext_complete, "f").asObservable();
32
36
  this.provideContext(USYNC_SIGNALR_CONTEXT_TOKEN, this);
33
37
  this.consumeContext(UMB_AUTH_CONTEXT, (auth) => {
34
- if (!auth)
35
- return;
36
- const authConfig = auth?.getOpenApiConfiguration();
37
- if (!authConfig)
38
- return;
39
- __classPrivateFieldGet(this, _uSyncSignalRContext_instances, "m", _uSyncSignalRContext_setupConnection).call(this, '/umbraco/SyncHub', auth);
38
+ __classPrivateFieldSet(this, _uSyncSignalRContext_auth, auth, "f");
39
+ __classPrivateFieldGet(this, _uSyncSignalRContext_instances, "m", _uSyncSignalRContext_connect).call(this);
40
+ });
41
+ this.consumeContext(UMB_SERVER_CONTEXT, (server) => {
42
+ __classPrivateFieldSet(this, _uSyncSignalRContext_server, server, "f");
43
+ __classPrivateFieldGet(this, _uSyncSignalRContext_instances, "m", _uSyncSignalRContext_connect).call(this);
40
44
  });
41
45
  }
42
46
  hostConnected() {
@@ -49,7 +53,7 @@ export class uSyncSignalRContext extends UmbControllerBase {
49
53
  });
50
54
  }
51
55
  getClientId() {
52
- return __classPrivateFieldGet(this, _uSyncSignalRContext_connection, "f")?.connectionId ?? null;
56
+ return __classPrivateFieldGet(this, _uSyncSignalRContext_clientId, "f");
53
57
  }
54
58
  /**
55
59
  * Synchronous read of the current connection state - used by callers
@@ -75,11 +79,34 @@ export class uSyncSignalRContext extends UmbControllerBase {
75
79
  __classPrivateFieldGet(this, _uSyncSignalRContext_update, "f").setValue({ message, count: 0, total: 1 });
76
80
  }
77
81
  }
78
- _uSyncSignalRContext_connection = new WeakMap(), _uSyncSignalRContext_connected = new WeakMap(), _uSyncSignalRContext_update = new WeakMap(), _uSyncSignalRContext_add = new WeakMap(), _uSyncSignalRContext_complete = new WeakMap(), _uSyncSignalRContext_instances = new WeakSet(), _uSyncSignalRContext_setupConnection = function _uSyncSignalRContext_setupConnection(url, auth) {
82
+ _uSyncSignalRContext_connection = new WeakMap(), _uSyncSignalRContext_auth = new WeakMap(), _uSyncSignalRContext_server = new WeakMap(), _uSyncSignalRContext_clientId = new WeakMap(), _uSyncSignalRContext_connected = new WeakMap(), _uSyncSignalRContext_update = new WeakMap(), _uSyncSignalRContext_add = new WeakMap(), _uSyncSignalRContext_complete = new WeakMap(), _uSyncSignalRContext_instances = new WeakSet(), _uSyncSignalRContext_connect = function _uSyncSignalRContext_connect() {
83
+ // either context being re-provided replaces the connection, so
84
+ // stop the old one rather than leave it running alongside.
85
+ if (__classPrivateFieldGet(this, _uSyncSignalRContext_connection, "f")) {
86
+ __classPrivateFieldGet(this, _uSyncSignalRContext_connection, "f").stop();
87
+ __classPrivateFieldSet(this, _uSyncSignalRContext_connection, undefined, "f");
88
+ __classPrivateFieldSet(this, _uSyncSignalRContext_clientId, null, "f");
89
+ __classPrivateFieldGet(this, _uSyncSignalRContext_connected, "f").setValue(false);
90
+ }
91
+ if (!__classPrivateFieldGet(this, _uSyncSignalRContext_auth, "f") || !__classPrivateFieldGet(this, _uSyncSignalRContext_server, "f"))
92
+ return;
93
+ if (!__classPrivateFieldGet(this, _uSyncSignalRContext_auth, "f").getOpenApiConfiguration())
94
+ return;
95
+ const connection = __classPrivateFieldGet(this, _uSyncSignalRContext_server, "f").getServerConnection();
96
+ // Older Umbraco versions do not expose this setting.
97
+ const skipNegotiation = 'getSignalRSkipNegotiation' in connection &&
98
+ typeof connection.getSignalRSkipNegotiation === 'function' &&
99
+ connection.getSignalRSkipNegotiation() === true;
100
+ __classPrivateFieldGet(this, _uSyncSignalRContext_instances, "m", _uSyncSignalRContext_setupConnection).call(this, '/umbraco/SyncHub', __classPrivateFieldGet(this, _uSyncSignalRContext_auth, "f"), skipNegotiation);
101
+ }, _uSyncSignalRContext_setupConnection = function _uSyncSignalRContext_setupConnection(url, auth, skipNegotiation) {
79
102
  // the token is fetched on every (re)connect, so a reconnect after
80
103
  // the original token has expired still authenticates.
81
104
  __classPrivateFieldSet(this, _uSyncSignalRContext_connection, new signalR.HubConnectionBuilder()
82
- .withUrl(url, { accessTokenFactory: () => auth.getLatestToken() })
105
+ .withUrl(url, {
106
+ accessTokenFactory: () => auth.getLatestToken(),
107
+ skipNegotiation,
108
+ transport: skipNegotiation ? signalR.HttpTransportType.WebSockets : undefined,
109
+ })
83
110
  .withAutomaticReconnect(new uSyncSignalRReconnectPolicy())
84
111
  .configureLogging(signalR.LogLevel.Warning)
85
112
  .build(), "f");
@@ -92,19 +119,39 @@ _uSyncSignalRContext_connection = new WeakMap(), _uSyncSignalRContext_connected
92
119
  __classPrivateFieldGet(this, _uSyncSignalRContext_connection, "f").on('complete', (data) => {
93
120
  __classPrivateFieldGet(this, _uSyncSignalRContext_complete, "f").setValue(data);
94
121
  });
95
- __classPrivateFieldGet(this, _uSyncSignalRContext_connection, "f").start().then(() => {
96
- __classPrivateFieldGet(this, _uSyncSignalRContext_connected, "f").setValue(true);
122
+ const connection = __classPrivateFieldGet(this, _uSyncSignalRContext_connection, "f");
123
+ // a stopped connection can still report state while it winds down,
124
+ // only the current one may update connected.
125
+ const setConnected = (connected) => {
126
+ if (__classPrivateFieldGet(this, _uSyncSignalRContext_connection, "f") !== connection)
127
+ return;
128
+ if (!connected)
129
+ __classPrivateFieldSet(this, _uSyncSignalRContext_clientId, null, "f");
130
+ __classPrivateFieldGet(this, _uSyncSignalRContext_connected, "f").setValue(connected);
131
+ };
132
+ // the connection id comes from the negotiate response, so when
133
+ // negotiation is skipped we have to ask the hub for it.
134
+ const onConnected = async () => {
135
+ const clientId = connection.connectionId ??
136
+ (await connection.invoke('GetConnectionId').catch(() => null));
137
+ if (__classPrivateFieldGet(this, _uSyncSignalRContext_connection, "f") !== connection)
138
+ return;
139
+ __classPrivateFieldSet(this, _uSyncSignalRContext_clientId, clientId, "f");
140
+ setConnected(true);
141
+ };
142
+ connection
143
+ .start()
144
+ .then(onConnected)
145
+ .catch((error) => {
146
+ // with negotiation skipped there is no transport fallback, so a
147
+ // blocked WebSocket ends here; status polling covers progress.
148
+ console.warn('uSync: SignalR connection failed', error);
149
+ setConnected(false);
97
150
  });
98
151
  // the client id changes on reconnect, requests made after this
99
152
  // pick up the new one via getClientId().
100
- __classPrivateFieldGet(this, _uSyncSignalRContext_connection, "f").onreconnecting(() => {
101
- __classPrivateFieldGet(this, _uSyncSignalRContext_connected, "f").setValue(false);
102
- });
103
- __classPrivateFieldGet(this, _uSyncSignalRContext_connection, "f").onreconnected(() => {
104
- __classPrivateFieldGet(this, _uSyncSignalRContext_connected, "f").setValue(true);
105
- });
106
- __classPrivateFieldGet(this, _uSyncSignalRContext_connection, "f").onclose(() => {
107
- __classPrivateFieldGet(this, _uSyncSignalRContext_connected, "f").setValue(false);
108
- });
153
+ connection.onreconnecting(() => setConnected(false));
154
+ connection.onreconnected(onConnected);
155
+ connection.onclose(() => setConnected(false));
109
156
  };
110
157
  export default uSyncSignalRContext;
@@ -37,17 +37,17 @@ let uSyncMenuElement = class uSyncMenuElement extends UmbElementMixin(LitElement
37
37
  });
38
38
  }
39
39
  render() {
40
- return html `<umb-menu-item-layout
41
- label=${this.manifest.meta.label ?? this.manifest.name}
42
- icon-name=${this.manifest.meta.icon ?? 'icon-bug'}
43
- .href=${this.itemPath}
44
- ?has-Children=${this.hasChildren}
45
- >${this.renderChildren()}
40
+ return html `<umb-menu-item-layout
41
+ label=${this.manifest.meta.label ?? this.manifest.name}
42
+ icon-name=${this.manifest.meta.icon ?? 'icon-bug'}
43
+ .href=${this.itemPath}
44
+ ?has-Children=${this.hasChildren}
45
+ >${this.renderChildren()}
46
46
  </umb-menu-item-layout>`;
47
47
  }
48
48
  renderChildren() {
49
- return html `<umb-extension-slot
50
- type="usync-menuItem"
49
+ return html `<umb-extension-slot
50
+ type="usync-menuItem"
51
51
  default-element="umb-menu-item-default"></umb-extension-slot>`;
52
52
  }
53
53
  };
@@ -0,0 +1,18 @@
1
+ import { type USyncPreviewContentType } from './content-type-layout.js';
2
+ export type USyncPreviewStatus = 'added' | 'removed' | 'changed';
3
+ export interface USyncPreviewItemChange {
4
+ status: USyncPreviewStatus;
5
+ /** the fields that differ (for a changed item) */
6
+ fields: string[];
7
+ }
8
+ export interface USyncContentTypeDiff {
9
+ /** top level fields (name, icon, compositions...) that differ */
10
+ fields: Set<string>;
11
+ properties: Map<string, USyncPreviewItemChange>;
12
+ containers: Map<string, USyncPreviewItemChange>;
13
+ }
14
+ /**
15
+ * compare two versions of a content type by key. Items only in the current
16
+ * version are being removed, items only in the incoming version are being added.
17
+ */
18
+ export declare function diffContentTypes(current: USyncPreviewContentType | undefined, incoming: USyncPreviewContentType | undefined): USyncContentTypeDiff;