diff --git a/Directory.Build.props b/Directory.Build.props index e3b99ff..1a9d506 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -32,8 +32,8 @@ - false - 12.0.0 + true + 16.0.0 true true diff --git a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/package-lock.json b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/package-lock.json index 6e1f7f8..82541cb 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/package-lock.json +++ b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/package-lock.json @@ -1,17 +1,17 @@ { "name": "umbraco-commerce-product-feeds", - "version": "15.0.0", + "version": "16.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "umbraco-commerce-product-feeds", - "version": "15.0.0", + "version": "16.0.0", "license": "ISC", "dependencies": { "@hey-api/client-axios": "^0.8.0", - "@umbraco-cms/backoffice": "^16.0.0-rc3", - "@umbraco-commerce/backoffice": "^16.0.0-rc1", + "@umbraco-cms/backoffice": "^16.0.0", + "@umbraco-commerce/backoffice": "^16.0.0", "nanoid": "^5.1.5" }, "devDependencies": { @@ -610,6 +610,20 @@ "axios": ">= 1.0.0 < 2" } }, + "node_modules/@hey-api/client-fetch": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@hey-api/client-fetch/-/client-fetch-0.10.2.tgz", + "integrity": "sha512-AGiFYDx+y8VT1wlQ3EbzzZtfU8EfV+hLLRTtr8Y/tjYZaxIECwJagVZf24YzNbtEBXONFV50bwcU1wLVGXe1ow==", + "deprecated": "Starting with v0.73.0, this package is bundled directly inside @hey-api/openapi-ts.", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/hey-api" + }, + "peerDependencies": { + "@hey-api/openapi-ts": "< 2" + } + }, "node_modules/@hey-api/json-schema-ref-parser": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@hey-api/json-schema-ref-parser/-/json-schema-ref-parser-1.0.6.tgz", @@ -790,20 +804,20 @@ "license": "MIT" }, "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.3.0.tgz", - "integrity": "sha512-nQIWonJ6eFAvUUrSlwyHDm/aE8PBDu5kRpL0vHMg6K8fK3Diq1xdPjTnsJSwxABhaZ+5eBi1btQB5ShUTKo4nQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.4.0.tgz", + "integrity": "sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==", "license": "BSD-3-Clause", "peer": true }, "node_modules/@lit/reactive-element": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.0.tgz", - "integrity": "sha512-L2qyoZSQClcBmq0qajBVbhYEcG6iK0XfLn66ifLe/RfC0/ihpc+pl0Wdn8bJ8o+hj38cG0fGXRgSS20MuXn7qA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.1.tgz", + "integrity": "sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==", "license": "BSD-3-Clause", "peer": true, "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.2.0" + "@lit-labs/ssr-dom-shim": "^1.4.0" } }, "node_modules/@nodelib/fs.scandir": { @@ -1642,6 +1656,13 @@ "url": "https://github.com/sponsors/ueberdosis" } }, + "node_modules/@types/diff": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/diff/-/diff-7.0.2.tgz", + "integrity": "sha512-JSWRMozjFKsGlEjiiKajUjIJVKuKdE3oVy2DNtK+fUo8q82nhFZ2CPQwicAIkXrofahDXrWJ7mjelvZphMS98Q==", + "license": "MIT", + "peer": true + }, "node_modules/@types/eslint__js": { "version": "9.14.0", "resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-9.14.0.tgz", @@ -1972,18 +1993,16 @@ } }, "node_modules/@umbraco-cms/backoffice": { - "version": "16.0.0-rc3", - "resolved": "https://registry.npmjs.org/@umbraco-cms/backoffice/-/backoffice-16.0.0-rc3.tgz", - "integrity": "sha512-2R339fA/HOep19e7AqzpbILRwcqLJQgX36PSAfOB6ZpXSPp9/Ap5g6Ao3GUd3PwwN46Lwh8YIRmvnq0AzBHYQg==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@umbraco-cms/backoffice/-/backoffice-16.0.0.tgz", + "integrity": "sha512-d8YvcCu4Bddps4agKHZoBgmhPhJhffoEEHUFD18iiRx+6ccRighO/qaE/5X8SeZzusSuyFnbeyJRo/5tyu0FRA==", "license": "MIT", - "workspaces": [ - "./src/packages/*" - ], "engines": { "node": ">=22", "npm": ">=10.9" }, "peerDependencies": { + "@hey-api/client-fetch": "^0.10.0", "@tiptap/core": "2.11.7", "@tiptap/extension-character-count": "2.11.7", "@tiptap/extension-image": "2.11.7", @@ -1999,166 +2018,169 @@ "@tiptap/extension-underline": "2.11.7", "@tiptap/pm": "2.11.7", "@tiptap/starter-kit": "2.11.7", - "@umbraco-ui/uui": "^1.13.0", - "@umbraco-ui/uui-css": "^1.13.0", + "@types/diff": "^7.0.2", + "@umbraco-ui/uui": "1.14.0", + "@umbraco-ui/uui-css": "1.14.0", + "diff": "^7.0.0", "dompurify": "^3.2.5", "element-internals-polyfill": "^3.0.2", "lit": "^3.3.0", "marked": "^15.0.9", "monaco-editor": "^0.52.2", - "rxjs": "^7.8.2" + "rxjs": "^7.8.2", + "uuid": "^11.1.0" } }, "node_modules/@umbraco-commerce/backoffice": { - "version": "16.0.0-rc1", - "resolved": "https://registry.npmjs.org/@umbraco-commerce/backoffice/-/backoffice-16.0.0-rc1.tgz", - "integrity": "sha512-KN+33D6gHO82tDmiWxLjodTT7R+5PhZcMaVURl0yjxW187JVNZWkCJR6XoYFEWUT7hf7v1UAIj8JQ/rz90XPdA==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@umbraco-commerce/backoffice/-/backoffice-16.2.1.tgz", + "integrity": "sha512-2Oc8moHohUsGiopCY8VEE5ffQ8/R+hibMCgzuNBb/o2he50EfLpONwLfzBF4Tx5gmERzeqOhgc2SJ6aO4bBoEg==", "engines": { "node": ">=22 <23", "npm": ">=10.9 < 11" }, "peerDependencies": { - "@umbraco-cms/backoffice": "^16.0.0-rc3" + "@umbraco-cms/backoffice": "^16.0.0" } }, "node_modules/@umbraco-ui/uui": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui/-/uui-1.13.0.tgz", - "integrity": "sha512-O/RvFeW+Mjn24ckmWJeTzMZKYbVrnaHscl9zKGKkMSva3j3mnJs/Q9N6BfihQy3qdZP5ED+2lGomezxfoLjZ7g==", - "license": "MIT", - "peer": true, - "dependencies": { - "@umbraco-ui/uui-action-bar": "1.13.0", - "@umbraco-ui/uui-avatar": "1.13.0", - "@umbraco-ui/uui-avatar-group": "1.13.0", - "@umbraco-ui/uui-badge": "1.13.0", - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-boolean-input": "1.13.0", - "@umbraco-ui/uui-box": "1.13.0", - "@umbraco-ui/uui-breadcrumbs": "1.13.0", - "@umbraco-ui/uui-button": "1.13.0", - "@umbraco-ui/uui-button-copy-text": "1.13.0", - "@umbraco-ui/uui-button-group": "1.13.0", - "@umbraco-ui/uui-button-inline-create": "1.13.0", - "@umbraco-ui/uui-card": "1.13.0", - "@umbraco-ui/uui-card-block-type": "1.13.0", - "@umbraco-ui/uui-card-content-node": "1.13.0", - "@umbraco-ui/uui-card-media": "1.13.0", - "@umbraco-ui/uui-card-user": "1.13.0", - "@umbraco-ui/uui-caret": "1.13.0", - "@umbraco-ui/uui-checkbox": "1.13.0", - "@umbraco-ui/uui-color-area": "1.13.0", - "@umbraco-ui/uui-color-picker": "1.13.0", - "@umbraco-ui/uui-color-slider": "1.13.0", - "@umbraco-ui/uui-color-swatch": "1.13.0", - "@umbraco-ui/uui-color-swatches": "1.13.0", - "@umbraco-ui/uui-combobox": "1.13.0", - "@umbraco-ui/uui-combobox-list": "1.13.0", - "@umbraco-ui/uui-css": "1.13.0", - "@umbraco-ui/uui-dialog": "1.13.0", - "@umbraco-ui/uui-dialog-layout": "1.13.0", - "@umbraco-ui/uui-file-dropzone": "1.13.0", - "@umbraco-ui/uui-file-preview": "1.13.0", - "@umbraco-ui/uui-form": "1.13.0", - "@umbraco-ui/uui-form-layout-item": "1.13.0", - "@umbraco-ui/uui-form-validation-message": "1.13.0", - "@umbraco-ui/uui-icon": "1.13.0", - "@umbraco-ui/uui-icon-registry": "1.13.0", - "@umbraco-ui/uui-icon-registry-essential": "1.13.0", - "@umbraco-ui/uui-input": "1.13.0", - "@umbraco-ui/uui-input-file": "1.13.0", - "@umbraco-ui/uui-input-lock": "1.13.0", - "@umbraco-ui/uui-input-password": "1.13.0", - "@umbraco-ui/uui-keyboard-shortcut": "1.13.0", - "@umbraco-ui/uui-label": "1.13.0", - "@umbraco-ui/uui-loader": "1.13.0", - "@umbraco-ui/uui-loader-bar": "1.13.0", - "@umbraco-ui/uui-loader-circle": "1.13.0", - "@umbraco-ui/uui-menu-item": "1.13.0", - "@umbraco-ui/uui-modal": "1.13.0", - "@umbraco-ui/uui-pagination": "1.13.0", - "@umbraco-ui/uui-popover": "1.13.0", - "@umbraco-ui/uui-popover-container": "1.13.0", - "@umbraco-ui/uui-progress-bar": "1.13.0", - "@umbraco-ui/uui-radio": "1.13.0", - "@umbraco-ui/uui-range-slider": "1.13.0", - "@umbraco-ui/uui-ref": "1.13.0", - "@umbraco-ui/uui-ref-list": "1.13.0", - "@umbraco-ui/uui-ref-node": "1.13.0", - "@umbraco-ui/uui-ref-node-data-type": "1.13.0", - "@umbraco-ui/uui-ref-node-document-type": "1.13.0", - "@umbraco-ui/uui-ref-node-form": "1.13.0", - "@umbraco-ui/uui-ref-node-member": "1.13.0", - "@umbraco-ui/uui-ref-node-package": "1.13.0", - "@umbraco-ui/uui-ref-node-user": "1.13.0", - "@umbraco-ui/uui-scroll-container": "1.13.0", - "@umbraco-ui/uui-select": "1.13.0", - "@umbraco-ui/uui-slider": "1.13.0", - "@umbraco-ui/uui-symbol-expand": "1.13.0", - "@umbraco-ui/uui-symbol-file": "1.13.0", - "@umbraco-ui/uui-symbol-file-dropzone": "1.13.0", - "@umbraco-ui/uui-symbol-file-thumbnail": "1.13.0", - "@umbraco-ui/uui-symbol-folder": "1.13.0", - "@umbraco-ui/uui-symbol-lock": "1.13.0", - "@umbraco-ui/uui-symbol-more": "1.13.0", - "@umbraco-ui/uui-symbol-sort": "1.13.0", - "@umbraco-ui/uui-table": "1.13.0", - "@umbraco-ui/uui-tabs": "1.13.0", - "@umbraco-ui/uui-tag": "1.13.0", - "@umbraco-ui/uui-textarea": "1.13.0", - "@umbraco-ui/uui-toast-notification": "1.13.0", - "@umbraco-ui/uui-toast-notification-container": "1.13.0", - "@umbraco-ui/uui-toast-notification-layout": "1.13.0", - "@umbraco-ui/uui-toggle": "1.13.0", - "@umbraco-ui/uui-visually-hidden": "1.13.0" + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui/-/uui-1.14.0.tgz", + "integrity": "sha512-et9xGGEcFyIBaMzSbPFt81SDyPdGyV8qyZzLePbs4vDTJiqjtefl0ICZib3Cwm8X4TjCXOcbVMU84wV2RCcIsQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@umbraco-ui/uui-action-bar": "1.14.0", + "@umbraco-ui/uui-avatar": "1.14.0", + "@umbraco-ui/uui-avatar-group": "1.14.0", + "@umbraco-ui/uui-badge": "1.14.0", + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-boolean-input": "1.14.0", + "@umbraco-ui/uui-box": "1.14.0", + "@umbraco-ui/uui-breadcrumbs": "1.14.0", + "@umbraco-ui/uui-button": "1.14.0", + "@umbraco-ui/uui-button-copy-text": "1.14.0", + "@umbraco-ui/uui-button-group": "1.14.0", + "@umbraco-ui/uui-button-inline-create": "1.14.0", + "@umbraco-ui/uui-card": "1.14.0", + "@umbraco-ui/uui-card-block-type": "1.14.0", + "@umbraco-ui/uui-card-content-node": "1.14.0", + "@umbraco-ui/uui-card-media": "1.14.0", + "@umbraco-ui/uui-card-user": "1.14.0", + "@umbraco-ui/uui-caret": "1.14.0", + "@umbraco-ui/uui-checkbox": "1.14.0", + "@umbraco-ui/uui-color-area": "1.14.0", + "@umbraco-ui/uui-color-picker": "1.14.0", + "@umbraco-ui/uui-color-slider": "1.14.0", + "@umbraco-ui/uui-color-swatch": "1.14.0", + "@umbraco-ui/uui-color-swatches": "1.14.0", + "@umbraco-ui/uui-combobox": "1.14.0", + "@umbraco-ui/uui-combobox-list": "1.14.0", + "@umbraco-ui/uui-css": "1.14.0", + "@umbraco-ui/uui-dialog": "1.14.0", + "@umbraco-ui/uui-dialog-layout": "1.14.0", + "@umbraco-ui/uui-file-dropzone": "1.14.0", + "@umbraco-ui/uui-file-preview": "1.14.0", + "@umbraco-ui/uui-form": "1.14.0", + "@umbraco-ui/uui-form-layout-item": "1.14.0", + "@umbraco-ui/uui-form-validation-message": "1.14.0", + "@umbraco-ui/uui-icon": "1.14.0", + "@umbraco-ui/uui-icon-registry": "1.14.0", + "@umbraco-ui/uui-icon-registry-essential": "1.14.0", + "@umbraco-ui/uui-input": "1.14.0", + "@umbraco-ui/uui-input-file": "1.14.0", + "@umbraco-ui/uui-input-lock": "1.14.0", + "@umbraco-ui/uui-input-password": "1.14.0", + "@umbraco-ui/uui-keyboard-shortcut": "1.14.0", + "@umbraco-ui/uui-label": "1.14.0", + "@umbraco-ui/uui-loader": "1.14.0", + "@umbraco-ui/uui-loader-bar": "1.14.0", + "@umbraco-ui/uui-loader-circle": "1.14.0", + "@umbraco-ui/uui-menu-item": "1.14.0", + "@umbraco-ui/uui-modal": "1.14.0", + "@umbraco-ui/uui-pagination": "1.14.0", + "@umbraco-ui/uui-popover": "1.14.0", + "@umbraco-ui/uui-popover-container": "1.14.0", + "@umbraco-ui/uui-progress-bar": "1.14.0", + "@umbraco-ui/uui-radio": "1.14.0", + "@umbraco-ui/uui-range-slider": "1.14.0", + "@umbraco-ui/uui-ref": "1.14.0", + "@umbraco-ui/uui-ref-list": "1.14.0", + "@umbraco-ui/uui-ref-node": "1.14.0", + "@umbraco-ui/uui-ref-node-data-type": "1.14.0", + "@umbraco-ui/uui-ref-node-document-type": "1.14.0", + "@umbraco-ui/uui-ref-node-form": "1.14.0", + "@umbraco-ui/uui-ref-node-member": "1.14.0", + "@umbraco-ui/uui-ref-node-package": "1.14.0", + "@umbraco-ui/uui-ref-node-user": "1.14.0", + "@umbraco-ui/uui-scroll-container": "1.14.0", + "@umbraco-ui/uui-select": "1.14.0", + "@umbraco-ui/uui-slider": "1.14.0", + "@umbraco-ui/uui-symbol-expand": "1.14.0", + "@umbraco-ui/uui-symbol-file": "1.14.0", + "@umbraco-ui/uui-symbol-file-dropzone": "1.14.0", + "@umbraco-ui/uui-symbol-file-thumbnail": "1.14.0", + "@umbraco-ui/uui-symbol-folder": "1.14.0", + "@umbraco-ui/uui-symbol-lock": "1.14.0", + "@umbraco-ui/uui-symbol-more": "1.14.0", + "@umbraco-ui/uui-symbol-sort": "1.14.0", + "@umbraco-ui/uui-table": "1.14.0", + "@umbraco-ui/uui-tabs": "1.14.0", + "@umbraco-ui/uui-tag": "1.14.0", + "@umbraco-ui/uui-textarea": "1.14.0", + "@umbraco-ui/uui-toast-notification": "1.14.0", + "@umbraco-ui/uui-toast-notification-container": "1.14.0", + "@umbraco-ui/uui-toast-notification-layout": "1.14.0", + "@umbraco-ui/uui-toggle": "1.14.0", + "@umbraco-ui/uui-visually-hidden": "1.14.0" } }, "node_modules/@umbraco-ui/uui-action-bar": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-action-bar/-/uui-action-bar-1.13.0.tgz", - "integrity": "sha512-0AGQ1zsUZT1wHKx+01JkRKLNtpjCS/SqEy/NVHUyYIGPimr6NQDM9Ok00LZKpZVwxcvArdy38XaAz6SijlaTqg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-action-bar/-/uui-action-bar-1.14.0.tgz", + "integrity": "sha512-cTX0TvVxNC7EFMtEqMGMBFC8E5O8bedmJ1Hkddvp4lAzrbLGrFTPcwOG/kISaSXzFrnMzyQNdi3s23orcL5VRA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-button-group": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-button-group": "1.14.0" } }, "node_modules/@umbraco-ui/uui-avatar": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-avatar/-/uui-avatar-1.13.0.tgz", - "integrity": "sha512-w+DwB9PUcnR0y0CzeNQA2638PjF2Dswiyuoxa2ryggcy38ihypj0Fj8FpzRSe5rax2JMtpJnuoDPwUpqVwGfOQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-avatar/-/uui-avatar-1.14.0.tgz", + "integrity": "sha512-ykYlbHV4K+zW7viv+oqfsGcL0ZII4vQy3YnPusFiz6bS3ceDDpY9MpRtuDTv4z+PXW4Wo1FjB2iMHrza55/RUw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-avatar-group": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-avatar-group/-/uui-avatar-group-1.13.0.tgz", - "integrity": "sha512-G8lIknUuhy+swW9Xz7qN3fp0L5Xhx4d5C2Q9WbW316GeseLYCm2eRhXDLpiEzIMxoVYtA9P0gbkuxLFDkznc+Q==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-avatar-group/-/uui-avatar-group-1.14.0.tgz", + "integrity": "sha512-8pLxQvtW1yuaReuSy0wq6kYZXPSiZjKv8ecmciLgWr9aKGR++CwYrwWKA3c+jZTarb8dz4MGMnQpqHCTqlQbpQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-avatar": "1.13.0", - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-avatar": "1.14.0", + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-badge": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-badge/-/uui-badge-1.13.0.tgz", - "integrity": "sha512-z7Z5IZwcfFJDFIPnBDfuCv+YkBHafn15oi4rNmNVynaM/iFJ+W3NAE7EmdWMDZzuDeQngbFpoRx1Ub7I4mqsng==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-badge/-/uui-badge-1.14.0.tgz", + "integrity": "sha512-iUosWuf7XngJBdwmvx8BZkzsollH4146Gt2CQBGltFZRCZ7uUkB2zCYb2E1ys4BEWuKHK4ZLiOcYtpPtoNeZJQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-base": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-base/-/uui-base-1.13.0.tgz", - "integrity": "sha512-VG0xlVzuq74qKaWn+eaTcTblR6HCi9YyrNohLLhHVAJuelmcgoPwHdNzkjoaWXlq16XKnB5Kmb6BgEtVmSQZ5w==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-base/-/uui-base-1.14.0.tgz", + "integrity": "sha512-m/BQYeKL9XmHPfHfCfSwTjcmUmJxynI0m4yqLTmQqQ3x1hiRqqfYyLSrpi3uW1H/HCxttUkxEwkhAdYogMDIpQ==", "license": "MIT", "peer": true, "peerDependencies": { @@ -2166,244 +2188,244 @@ } }, "node_modules/@umbraco-ui/uui-boolean-input": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-boolean-input/-/uui-boolean-input-1.13.0.tgz", - "integrity": "sha512-WsP+W5/4Fcp9sg0gFlfh8FyIzaczRC4kc2LxT3haljflgQTMVwV4MGGadOYg89hVpD0C4dZaqp69sskLWc6fWQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-boolean-input/-/uui-boolean-input-1.14.0.tgz", + "integrity": "sha512-O+/GzpF2mNLdhXXNAfxI0k5VaR7CUnUxDDxYPhMgmuLOBwdjiq9iScJM4MUl+l7hihF5ue7os6I8DY2CnG7LJQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-box": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-box/-/uui-box-1.13.0.tgz", - "integrity": "sha512-msIz5NerPKx7bnTyEyMjihnfxSTlslU+FyE4DsUUwZT6vtFxT2Dt74UbO8cg0ut9GoBjR1wpn4qNTW3xRxfdiA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-box/-/uui-box-1.14.0.tgz", + "integrity": "sha512-VjD6MtEnJuHOYarFtLvn/Dyz2MRJ0sPXSDTZ3HWsF0G5fdAUB487ErOGb8CL1JtmUYgZOy6N3CqPlFyWHD+DIA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-css": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-css": "1.14.0" } }, "node_modules/@umbraco-ui/uui-breadcrumbs": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-breadcrumbs/-/uui-breadcrumbs-1.13.0.tgz", - "integrity": "sha512-DG/m4bZ3bPTryrN6mDQMmabXPmvKcVlsfjuhJ/UDazq6T/4DVfB6YrXk6q+4N6X4njg88CO/V6ObnyB7RE+flQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-breadcrumbs/-/uui-breadcrumbs-1.14.0.tgz", + "integrity": "sha512-IxHPUnIaGyvo54oDdcJf4AfzkYF1Nf727SCLHD28WqMh4QCKQQsyBGa5xhFjcQ4RSediNwvAnY7dNVVYu9OrzQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-button": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button/-/uui-button-1.13.0.tgz", - "integrity": "sha512-dJWr9fKQFB4CRMJ23oRmkuzN45ESuxDn1nwgLw0TLhJrAWo5uoyTL1k/IuNdg0C3+BqNIzC5B8m5YC2S+BpPlA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button/-/uui-button-1.14.0.tgz", + "integrity": "sha512-TVCPLVcXR4wGjtLtrTYOjoAdvwQPiCep1GiHAbozD0QKNgOqjZ2fE3CapwEwoaSNGcgw/37t0KMhUqfmZgYo2g==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-icon-registry-essential": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-icon-registry-essential": "1.14.0" } }, "node_modules/@umbraco-ui/uui-button-copy-text": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button-copy-text/-/uui-button-copy-text-1.13.0.tgz", - "integrity": "sha512-/4j4PnxNRAyeD2LYA+dyyCZurOPnGioQfl2iFIE/B2znBvJR2JHrnCLwcAqawI+YhHxGgyKNck7BCKihYQxkow==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button-copy-text/-/uui-button-copy-text-1.14.0.tgz", + "integrity": "sha512-cE3ZjSaWzzdgYdNtGv1SzIClMoCxqL86+QPz9zMYvN//yA8YQmkv7y2eUyT+lKFNJXXHMgzVKMhoSn8aUzvQrA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-button": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-button": "1.14.0" } }, "node_modules/@umbraco-ui/uui-button-group": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button-group/-/uui-button-group-1.13.0.tgz", - "integrity": "sha512-Pksx35rtKriOUO9IP1ETnQDoBnoiRzwheM8fmqeo44jSPsr7emaQrI3BOwqeOuD7KfPRIVnzwLdm14K4Zw6tZA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button-group/-/uui-button-group-1.14.0.tgz", + "integrity": "sha512-W4Jf671PqtnBnYKWNyyB6rgq88qyT0IWhqUR3ilJS45znIiht/ec5xDhTFoyhLWP9+zQn/3e8EqZbmnJUj2HAA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-button-inline-create": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button-inline-create/-/uui-button-inline-create-1.13.0.tgz", - "integrity": "sha512-6XtJ/nZpVDkYFiWEqbr5uz5CJ2Yqled4W7zAsh53QuCCYFgyU6yU9AFtrhPRwC9I27XzmBTQRZgCkQFWuEuL5A==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button-inline-create/-/uui-button-inline-create-1.14.0.tgz", + "integrity": "sha512-vDOZJEfjQDqIKymdpxD3h/uvBacXu/yD/xnHMrxADeMQYinvNn0AFjTFBakgfusymRLjXQubrJ63MWqidTRsQQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-card": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card/-/uui-card-1.13.0.tgz", - "integrity": "sha512-fBskLWqFoquKfgFK6bJ4lM0V30XZCZcJjjwTUmSjRFvklyF3csL7W9bKB9hs+aFu0/GDQlVqOBa5tA4RLpcj0w==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card/-/uui-card-1.14.0.tgz", + "integrity": "sha512-9A44pCbx9nyBtbvFE26FiP+rLE2rUg177vgoMTuURuszYoiEgfU8ixVhWCbDD14LpxET0/Yg9RNiMYF8K1bDvw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-card-block-type": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-block-type/-/uui-card-block-type-1.13.0.tgz", - "integrity": "sha512-YBDHZ+76oz27+P9v8YSr3OwWs3eftqy2d3Gg/sxh3Y6n9gI2TdXtJgev9GVL2FpifZXM2A1ySzh8MscC2HLJIA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-block-type/-/uui-card-block-type-1.14.0.tgz", + "integrity": "sha512-FQAInMb4AKj11Jy3TQTc6iz80h0ulmlraw3CtFbnOpwHIRP/aqUVGCW0Zb+Yykz1DGmmGvFE1u1epK/jH//6aQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-card": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-card": "1.14.0" } }, "node_modules/@umbraco-ui/uui-card-content-node": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-content-node/-/uui-card-content-node-1.13.0.tgz", - "integrity": "sha512-IYe/AUaJ7Pspd+zSQlJMRIUzzF7+dLnq6ApezC9b93mEEhB4WwX+BbzfHbbhyNxMv9Za9gBKZljIH3RluPWnog==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-content-node/-/uui-card-content-node-1.14.0.tgz", + "integrity": "sha512-KcXiUfG0ulgvXWuqOGu3LTcRVoGru+Q4sj4q0bV9H/d3ZfY1idPqhkbM7v6TO56gzCng0DJ/kTL0/H5IWd8IcA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-card": "1.13.0", - "@umbraco-ui/uui-icon": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-card": "1.14.0", + "@umbraco-ui/uui-icon": "1.14.0" } }, "node_modules/@umbraco-ui/uui-card-media": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-media/-/uui-card-media-1.13.0.tgz", - "integrity": "sha512-ohRFE1FqmYNJ7VXKjzMqjhCfzfabL9bLOpJet0+VXCMHUomHZv9UHQTI1ibp71BMp934vWT3kqGgco6RYqujSQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-media/-/uui-card-media-1.14.0.tgz", + "integrity": "sha512-Lnr8Y1bxj6QoleSMCj8GDsyJu1N5Rm105/nHYdnPO3+JcNNv3ThodKdHXYo/slSLrcVOoPJHNAQodZG66mIqsg==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-card": "1.13.0", - "@umbraco-ui/uui-symbol-file": "1.13.0", - "@umbraco-ui/uui-symbol-folder": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-card": "1.14.0", + "@umbraco-ui/uui-symbol-file": "1.14.0", + "@umbraco-ui/uui-symbol-folder": "1.14.0" } }, "node_modules/@umbraco-ui/uui-card-user": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-user/-/uui-card-user-1.13.0.tgz", - "integrity": "sha512-lAB2IuXvNK8l/n+D9s9cNNUUvBdZE2Uy3UDc0QJla3qo2RLsyM4pSgVeS0Ve+GOI1A4vyK8Sfx68cDptW04Vaw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-user/-/uui-card-user-1.14.0.tgz", + "integrity": "sha512-ZBFWO2109+A9SkkznqNHUiul6G6zab/D318yz0wMTW6m2R0E8QE9mljIw8Entd720HeZlvOKpvK3ElSTNlxnJg==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-avatar": "1.13.0", - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-card": "1.13.0" + "@umbraco-ui/uui-avatar": "1.14.0", + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-card": "1.14.0" } }, "node_modules/@umbraco-ui/uui-caret": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-caret/-/uui-caret-1.13.0.tgz", - "integrity": "sha512-OCrJISFcRvB6V1+xPS+AjGEp+ue3vyegTRJsLEOVbyCHbrzFwNUKLc2EFYz2rxOGjcFs7Z9M8I6eoLUuMxDQAQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-caret/-/uui-caret-1.14.0.tgz", + "integrity": "sha512-c+71esCgWn7V6Z8gr9fZkfw9BQgewZi5pbJ8R1G6HLEzz0NN11zAn5BAVebdxF5OUi/ajFqvxnAYOSSiWel5tg==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-checkbox": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-checkbox/-/uui-checkbox-1.13.0.tgz", - "integrity": "sha512-9ywXUZgC8kMLEgsx1JFH0iftSeI8zzVDVECYq36+dVuz0iWtXfUjb5ygSoUX0guiACVY5gNba/H+t9R+3FbUgw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-checkbox/-/uui-checkbox-1.14.0.tgz", + "integrity": "sha512-qD/O8H7pcPnJkaf5iWjDKg89LgQKZeuBiRmrXqVePDk0HHjdZ+8TJlDaANRyBq5JePezrj6UpHPVabYDqXIJYQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-boolean-input": "1.13.0", - "@umbraco-ui/uui-icon-registry-essential": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-boolean-input": "1.14.0", + "@umbraco-ui/uui-icon-registry-essential": "1.14.0" } }, "node_modules/@umbraco-ui/uui-color-area": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-area/-/uui-color-area-1.13.0.tgz", - "integrity": "sha512-X7CyxicQYE5VR5iXSY0IsPym0pSYWFLQ9KDgzVIDM3fvoM+KpiGYrDhGTgrHrTpJ3EE8JO06fPrx/mJ2NyxOyQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-area/-/uui-color-area-1.14.0.tgz", + "integrity": "sha512-ijja8REx/1OhG2ZA1yK98Q8IhSeDf+GIjfCvkR1ptzzFkz1Wiv1mvxkh9eExByidp90SgsTF3kdUxR8x6V570A==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", + "@umbraco-ui/uui-base": "1.14.0", "colord": "^2.9.3" } }, "node_modules/@umbraco-ui/uui-color-picker": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-picker/-/uui-color-picker-1.13.0.tgz", - "integrity": "sha512-ROkz+5+ecZ9GbctpaynL9CeMdXhamY2wPfwjVHyp/QERLXsvhlXIojD0n11Fp4i9FzQsiHb328T5aTnBZ3tqcw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-picker/-/uui-color-picker-1.14.0.tgz", + "integrity": "sha512-WG7I2mYDjW3W27V3LDRpUrZfkjnnuHPo8+X4ZBnY6xRXnQ83hxbdqXkaKYI6VY1dMhhqGa82wrbb4NBHGkKBiQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-popover-container": "1.13.0", + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-popover-container": "1.14.0", "colord": "^2.9.3" } }, "node_modules/@umbraco-ui/uui-color-slider": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-slider/-/uui-color-slider-1.13.0.tgz", - "integrity": "sha512-om/OwXDVDNsy0HZIuIv6VXoi5aFBU7KtHfiq7/OLnnWtO5MQREwBCTVthhSFfe7LaZSZnFhFn89hrmw7hfhljQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-slider/-/uui-color-slider-1.14.0.tgz", + "integrity": "sha512-8eNA+7GJNVl68amAJIbCWMe/8usWanZ1fKXPf3ZJ54K65K2cDYd2hS7DEVEwSXo+AV9iMeBYgbHIRBqVPZ89jw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-color-swatch": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-swatch/-/uui-color-swatch-1.13.0.tgz", - "integrity": "sha512-tiT274ldYjDMFeBQBx3yGu7HgYaNrxjNIrcktlsddfWxxjJ3UNu08YdoP4DqJOi6limQhadBllCBa9oyz4iOig==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-swatch/-/uui-color-swatch-1.14.0.tgz", + "integrity": "sha512-1c2bNmEqL5J1ZW24adzSsGDwnYFQOyjsI29M+UQdlTZW16s3zh9O97414KIN9ivE+SkgbE7c9lZhNEKyi2IJpw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-icon-registry-essential": "1.13.0", + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-icon-registry-essential": "1.14.0", "colord": "^2.9.3" } }, "node_modules/@umbraco-ui/uui-color-swatches": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-swatches/-/uui-color-swatches-1.13.0.tgz", - "integrity": "sha512-DAZ9cAxIp+kGFeGteDCgt+Om0vcuacmjtT98N1meP/EkPgJf6y21o3y4oySeQMAhWXznr3DBxyHHKN1Jt3do8Q==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-swatches/-/uui-color-swatches-1.14.0.tgz", + "integrity": "sha512-UIQysF89CZH0CKwhzbd+1BZAXxUlnCmHoWDGot+Mb4sGZL5esrEB0QQmhJOVO/ehMP+GoFUnh4fWLXUCzRPdvw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-color-swatch": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-color-swatch": "1.14.0" } }, "node_modules/@umbraco-ui/uui-combobox": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-combobox/-/uui-combobox-1.13.0.tgz", - "integrity": "sha512-8lKmqQMQkh+yMA4iFonDLwpNf6EZ+pYXhJ2Xcum14WT6UI6BgiQvuM2nmRrkWhqA7Wx0tTAAdP5ILPAl5lENRQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-combobox/-/uui-combobox-1.14.0.tgz", + "integrity": "sha512-ZKa0KF0ADSX//hm116QdEDjQgyZK1ahY+hzOtdU7EDlJBQdTq3cHtwn6B8JdhPoVlS0Yd3XB+oQ7UXjYn7rGQQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-button": "1.13.0", - "@umbraco-ui/uui-combobox-list": "1.13.0", - "@umbraco-ui/uui-icon": "1.13.0", - "@umbraco-ui/uui-popover-container": "1.13.0", - "@umbraco-ui/uui-scroll-container": "1.13.0", - "@umbraco-ui/uui-symbol-expand": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-button": "1.14.0", + "@umbraco-ui/uui-combobox-list": "1.14.0", + "@umbraco-ui/uui-icon": "1.14.0", + "@umbraco-ui/uui-popover-container": "1.14.0", + "@umbraco-ui/uui-scroll-container": "1.14.0", + "@umbraco-ui/uui-symbol-expand": "1.14.0" } }, "node_modules/@umbraco-ui/uui-combobox-list": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-combobox-list/-/uui-combobox-list-1.13.0.tgz", - "integrity": "sha512-ZVRouGMb7VH5wD8a0kE1t71oUMD1gUvFdACPWTjunpgM0ZXk1wOGGtS3vsEaTAkbQ8gABPpsYnCaWBt0MR+RpA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-combobox-list/-/uui-combobox-list-1.14.0.tgz", + "integrity": "sha512-CRsRycwyb9CeyNINQ1KztGAHTRhQcphVEl/bLVr3jTtuqSWWxKsGQVDe69iKNAfHuiU3o7MlsUH0+ea296x/8w==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-css": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-css/-/uui-css-1.13.0.tgz", - "integrity": "sha512-6crDukueGm9t5CBU+d/icouGELQQIQsfi/qT7J6qISRZTvBjoT0FxUxUtpXsIQs1H0qgULhwx8PTKnfQ/AMZFA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-css/-/uui-css-1.14.0.tgz", + "integrity": "sha512-M0zmrjBpDzrb3r+l1qMNGEhJbJSHNeR7PDtpHoMaO96ozaZSL/87XzpwsBklwTR9xyfm+VgDFNTqQXqYnS2e/A==", "license": "MIT", "peer": true, "peerDependencies": { @@ -2411,603 +2433,603 @@ } }, "node_modules/@umbraco-ui/uui-dialog": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-dialog/-/uui-dialog-1.13.0.tgz", - "integrity": "sha512-RzePOwJrhBEYBZAwgvNkIro+cVirLxgaIGNFUgnvoWIovHJNOuSso65MtcGON3nvuQ4JxE8SIOTE/hwT04R7Ag==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-dialog/-/uui-dialog-1.14.0.tgz", + "integrity": "sha512-eZdmNLkSW5OAETTZlvUKByQbXv/4/tYznNHCHyWxxGrYuHVHh5sNj+3ZUbZp+VjIy1zd42slKh/KDmYV6pBarQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-css": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-css": "1.14.0" } }, "node_modules/@umbraco-ui/uui-dialog-layout": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-dialog-layout/-/uui-dialog-layout-1.13.0.tgz", - "integrity": "sha512-m8eoCEz0dugWmqrmRw2vHae3k7oYjr53JiOkb8viCMh7veQo4EM0zqZgdCwADs1wES8woOX5zdttp9JtqYenRw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-dialog-layout/-/uui-dialog-layout-1.14.0.tgz", + "integrity": "sha512-rYlwHk5zsX+eBZLBxI/68W6Q1vb7G/NuZoasquQXZ7jgxRhaRw199YQojtUCWtIowWn2uqqbD2a0RYPs9n3FIg==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-file-dropzone": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-file-dropzone/-/uui-file-dropzone-1.13.0.tgz", - "integrity": "sha512-1TFkyeNB3qWWhgc7NYudxXOc3v0cBRuRpVYPA3xocfVkqCG2PgEc7ePW18CtUuuGntGwv0E0Oni2bfSLrqVmuQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-file-dropzone/-/uui-file-dropzone-1.14.0.tgz", + "integrity": "sha512-GSy0mlR5KsyC9oF3CMB2qwuGiT5P3moVFxanRAO7u8qimRAO2jLS0/8u1QCh120AGRQZzDhw/TJ9XF7NXTWJtA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-symbol-file-dropzone": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-symbol-file-dropzone": "1.14.0" } }, "node_modules/@umbraco-ui/uui-file-preview": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-file-preview/-/uui-file-preview-1.13.0.tgz", - "integrity": "sha512-ZEW2q6If0+3WWHnQp9UPdL+rcI4zUKlyvELDU1JDzx/IVDFJb8f7fI5qhzQjl4kXCVI54Ch4WkBie6RDpNSqVg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-file-preview/-/uui-file-preview-1.14.0.tgz", + "integrity": "sha512-UGxlpKoCVjFYbkNfXcMi0kCSjcocnHlTHH1fyk/Mg5jZ1OZCmV8dnQQKCB139X9FdHZhL0QeZA3KZUYA28iqaQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-symbol-file": "1.13.0", - "@umbraco-ui/uui-symbol-file-thumbnail": "1.13.0", - "@umbraco-ui/uui-symbol-folder": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-symbol-file": "1.14.0", + "@umbraco-ui/uui-symbol-file-thumbnail": "1.14.0", + "@umbraco-ui/uui-symbol-folder": "1.14.0" } }, "node_modules/@umbraco-ui/uui-form": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-form/-/uui-form-1.13.0.tgz", - "integrity": "sha512-Y5Wgl3AcixLbPHJJK2yqdga5NMHx5Jv3YvG69+AdPkgzyNmCtdbDitV8ex2ysNYMO3WbBRdYIjbI5pYRl3xn5Q==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-form/-/uui-form-1.14.0.tgz", + "integrity": "sha512-UoEP62nCNTa4ILDNFX2ASNN95XfUugPhGmtUdKmvTUH6F3NSai2iiLIp/dM+GBC4PJXmt8rzq6NdLqYonkMK+w==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-form-layout-item": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-form-layout-item/-/uui-form-layout-item-1.13.0.tgz", - "integrity": "sha512-GKNjsvUBbl2ba9e7b88Vk7HuMO9exnGDRpmQ94PSH/rOUF44ri4mPTPFU2k9DCvIkSs7lxDvotXE7kQ5IPQYBw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-form-layout-item/-/uui-form-layout-item-1.14.0.tgz", + "integrity": "sha512-1ahnmF9Ciw0RC/pRAS3FJ2vVmnpQ6O20bwqJrCTYvJQeqJXV3bzSxYmMY/s6Z5tsoNDzkfYcTHfnti/MmyuFJw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-form-validation-message": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-form-validation-message": "1.14.0" } }, "node_modules/@umbraco-ui/uui-form-validation-message": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-form-validation-message/-/uui-form-validation-message-1.13.0.tgz", - "integrity": "sha512-x1E84q6L8DbpBkoS+ykdvmoEUcObXYhym6nhh2lK2TAn7vZu+XD+Osd5rgy5ycZ4YtYnCqetlaPwQwAFqFiSHA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-form-validation-message/-/uui-form-validation-message-1.14.0.tgz", + "integrity": "sha512-rv+mId8htw/8V3rle5bOjgWK8X+3IX7B+PAvFAfy+lc89OUV+OT04RGy0sg3hhncoPsIT8EhQ2MYunIyh3MwnA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-icon": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-icon/-/uui-icon-1.13.0.tgz", - "integrity": "sha512-TKmQi4n8ZV6v228U6zi9f38g/Nu4ok1cbvoIiSfSvmSYNXD1weuWK5y7Ph7EGr6jL5T5vKbDhjcZUIjzBOVWAA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-icon/-/uui-icon-1.14.0.tgz", + "integrity": "sha512-IdBRPC8xc9leIBRaHmTVoGhxRkz8CNeYjgJLNBauFox5uSkWuE7OE9BUYBJKdZz4k8yHLHHrWHVkcaHvgF+QUw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-icon-registry": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-icon-registry/-/uui-icon-registry-1.13.0.tgz", - "integrity": "sha512-/w7EN7Exi7ST0olPuxFLFm8rw3Mt2QhZsqQWQXXYnb4hTC+ot27IDahQmlLOx85+h/KH3Qz+Tn2NgM3BEdQQ5w==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-icon-registry/-/uui-icon-registry-1.14.0.tgz", + "integrity": "sha512-N9cXDF6B3R+h2TCaCHkOJUTSsD10Wei8NrldvYL2fhBqG8FgaquqBI/715NGoRtwp9KKz74N/Z6EIn2MBiMaMQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-icon": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-icon": "1.14.0" } }, "node_modules/@umbraco-ui/uui-icon-registry-essential": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-icon-registry-essential/-/uui-icon-registry-essential-1.13.0.tgz", - "integrity": "sha512-CcuBNg06ewGM6OhwjXCQKm5QDYXySCcc7TQajJ14kfMXtdcO8ls6eI2D8t+Hkc4YN7TQaUeGgzMF746f4TiiNQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-icon-registry-essential/-/uui-icon-registry-essential-1.14.0.tgz", + "integrity": "sha512-NjkNmQpMHLcyGakqGlASyPOr8Vnr8+KCdExfkbDdg07iDFlzyGyNmCkTdzY2tNXsIq5bD1c4nzHYmE76FszorQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-icon-registry": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-icon-registry": "1.14.0" } }, "node_modules/@umbraco-ui/uui-input": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input/-/uui-input-1.13.0.tgz", - "integrity": "sha512-2GwLio1SDBofYLZjds47X6Fxq29ORgQBZaD9xwowFaoWCsG+WIFsE7VaE4KgPASUOQYoMMzFZX3F2TdvbjPEAg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input/-/uui-input-1.14.0.tgz", + "integrity": "sha512-FeYiTUzCcZdNtury6B8ZMl66mW/fGfgXMB5HvIVDFp0ik+WpC8vLcQqHgJ/qFxWGF32H0qIsVqLnzcwkAwvRxw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-input-file": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-file/-/uui-input-file-1.13.0.tgz", - "integrity": "sha512-wKmFAzThstZPeCOtNtdAX8SZ09T0mJQEA1g+l6EaCV5ikPLSO0kiqmv3P0p0IDf6WSX29+UhcSp2hOVzR+cELg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-file/-/uui-input-file-1.14.0.tgz", + "integrity": "sha512-l4RcQWf+0OLM9i9NWvnMkQtzzNcALBRmtiTBLdz6ROFm2Z+S3MuT8vzl0QiduJNWK5gzANu/FFuTL70fIh/BDw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-action-bar": "1.13.0", - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-button": "1.13.0", - "@umbraco-ui/uui-file-dropzone": "1.13.0", - "@umbraco-ui/uui-icon": "1.13.0", - "@umbraco-ui/uui-icon-registry-essential": "1.13.0" + "@umbraco-ui/uui-action-bar": "1.14.0", + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-button": "1.14.0", + "@umbraco-ui/uui-file-dropzone": "1.14.0", + "@umbraco-ui/uui-icon": "1.14.0", + "@umbraco-ui/uui-icon-registry-essential": "1.14.0" } }, "node_modules/@umbraco-ui/uui-input-lock": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-lock/-/uui-input-lock-1.13.0.tgz", - "integrity": "sha512-qChhwO5NsA8es9X41HJ73sXtmvKUF90WBBL8PYgESLkL7zQdvhe9wfJhVjZ1WMJkOc6F7uTAJbawuEVXSX0uKA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-lock/-/uui-input-lock-1.14.0.tgz", + "integrity": "sha512-wt/VL43EpHJcvf9GEnXSuHG/iW7yI7vD3wEWI+wgCKv9SdTzE/M4aPon/pxnQsVCvGvWhWvdFeGdlfwhXSurLQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-button": "1.13.0", - "@umbraco-ui/uui-icon": "1.13.0", - "@umbraco-ui/uui-input": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-button": "1.14.0", + "@umbraco-ui/uui-icon": "1.14.0", + "@umbraco-ui/uui-input": "1.14.0" } }, "node_modules/@umbraco-ui/uui-input-password": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-password/-/uui-input-password-1.13.0.tgz", - "integrity": "sha512-1ljgXM1Ux2J73J2mNd01Xh1Bk7Por0MXk6fQ4TP/qp4A5ohF6CmiBVNWSBkWLfEY7TNHfvOIIIiDGfc0Ko0UFw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-password/-/uui-input-password-1.14.0.tgz", + "integrity": "sha512-XCc/0QJH2w9PZJPouhbJbMR+w0QKUusut1MWW9NsfzRheHkcDuzc3Vf69OLFGGww/FjYjkxwT9as/2aLXxotjw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-icon-registry-essential": "1.13.0", - "@umbraco-ui/uui-input": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-icon-registry-essential": "1.14.0", + "@umbraco-ui/uui-input": "1.14.0" } }, "node_modules/@umbraco-ui/uui-keyboard-shortcut": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-keyboard-shortcut/-/uui-keyboard-shortcut-1.13.0.tgz", - "integrity": "sha512-zKh674a19swyaZiLI/vCws56H4P+lUCIQxu+/U3280zGQqp35vCj0RhvbU2zA4QCCvTEWSrOOQwyu019zEEz5w==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-keyboard-shortcut/-/uui-keyboard-shortcut-1.14.0.tgz", + "integrity": "sha512-G3LCdfP5uPe00bg8kKBMZhLan8gH7QbSRMX7aMsT+Fc6nAyWWTwJ/Qt4qJjk/fbeHts1OWD+sbHdRtXK+DotRA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-label": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-label/-/uui-label-1.13.0.tgz", - "integrity": "sha512-BcfvqdFybY0Vb7TVinfHDLrAyhmtayz5ZGXwnTZpwyg7IP+pPZrFunrhcPPTPIrvJEw/j7qgpfC2AKMsiaZq7A==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-label/-/uui-label-1.14.0.tgz", + "integrity": "sha512-a22p01O0CqnNTxQxmjPwCFBFXi5KKzhpno4DXjSDVTmeJc85IxiR5ODAELKHJf6XwZMkOv+QG+AZuIJFVEZ13Q==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-loader": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-loader/-/uui-loader-1.13.0.tgz", - "integrity": "sha512-AmNcIX7XNtW9dc29TdlMgTcTJBxU7MCae9iivNLLfFrg3VblltCPeeCOcLx77rw/k9o/IWrhLOsN81Q0HPfs7g==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-loader/-/uui-loader-1.14.0.tgz", + "integrity": "sha512-2/HNDk0AZQ992hHYQk+VP5GetofSKxCsLf77/wiswyz48kM9eJ9wkieovxzLK1IuOQs0A+cCe2NnU/z5fZnvvw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-loader-bar": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-loader-bar/-/uui-loader-bar-1.13.0.tgz", - "integrity": "sha512-wRJl2n6VesXV5z7EOz3W8DKDo2XLbpb4a9HZHauDtnGl9aNQggcFYBXTrLAvqg2Nuir2g52kQT9mDcQiTDxJLQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-loader-bar/-/uui-loader-bar-1.14.0.tgz", + "integrity": "sha512-hAviuSx29RPWpYIqmWiGmW31r3nj8A1VGobmdVwR0BJHfdxee57ZrNGsEZhK6pzuHSvshGTITNwLk03E1UA/Nw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-loader-circle": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-loader-circle/-/uui-loader-circle-1.13.0.tgz", - "integrity": "sha512-efDzwo7uC7bs60boAvJNtqI7CFTe/4R5xdyi9khSF9w/0WnMRgIsY9h7xQLWCycjC/Nvoe/UwBZQ6P5khkdfaw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-loader-circle/-/uui-loader-circle-1.14.0.tgz", + "integrity": "sha512-I+rcgwbxwKGxLzVCGZ3qT4e/sK8CofTPzdCmh1BpNlKrWpuJ9NGgysrGs7V1IleJJxIXuzD+BBlIoGxuCwBJQg==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-menu-item": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-menu-item/-/uui-menu-item-1.13.0.tgz", - "integrity": "sha512-Rl3y+gXyN4ZLdzhhmCW1dWWC53erFVnVV1OTm2paYk1w13du/T4S+X7J0uyobrc1E3iFTjAFNh0UuvHxRsxtcQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-menu-item/-/uui-menu-item-1.14.0.tgz", + "integrity": "sha512-8Pc68dJLwl7GrbGIRD7MpyMSBkuz8/CtzuLhygrFHK608crg5bBPC1+Zdt3VdkqDk7QZRd5rtL+pYgEJm87Q4A==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-loader-bar": "1.13.0", - "@umbraco-ui/uui-symbol-expand": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-loader-bar": "1.14.0", + "@umbraco-ui/uui-symbol-expand": "1.14.0" } }, "node_modules/@umbraco-ui/uui-modal": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-modal/-/uui-modal-1.13.0.tgz", - "integrity": "sha512-uiBmQg4gE3S9lreABkLbr4kSRdZAbkxzavBZ27DTDWjeez5Zn+sqy+FckPGct+HZheTdXgGF+M4YRypZj7gOhg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-modal/-/uui-modal-1.14.0.tgz", + "integrity": "sha512-3Ux1guj029PIcUn4nmPUU29Oqxq1HoRUib3lWoRRIgJ3F8WyGms+GEgCMj4v/LzIdezczqVtxKdOMcLIm2gvcQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-pagination": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-pagination/-/uui-pagination-1.13.0.tgz", - "integrity": "sha512-RtD+szI8P+7y2tKBLLPJyCOlfS504LgQqD4pUOZbxemsQmMe37OZ1CiiqfrNJVEv4TbMHP0WvoRiLFDawICXnw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-pagination/-/uui-pagination-1.14.0.tgz", + "integrity": "sha512-jP906bsiXOBpAdF/ZVi0hlRyR/+HX52ocjItlvMJWc2Xt4Fpzms7W90buYcG4hvz7g0snKy84JgTMup5vxf2iQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-button": "1.13.0", - "@umbraco-ui/uui-button-group": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-button": "1.14.0", + "@umbraco-ui/uui-button-group": "1.14.0" } }, "node_modules/@umbraco-ui/uui-popover": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-popover/-/uui-popover-1.13.0.tgz", - "integrity": "sha512-fpN0x+9p7cxrKiBYzEbpAYuIFYxWlUDrv4jYw3+oEI1ZP2wlS4dKphxhNtLreGrbaYsSUXe8Vgx9wy3eFawfug==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-popover/-/uui-popover-1.14.0.tgz", + "integrity": "sha512-blMgYLRlEUon7vAQ6s1KE0hNBgyuMeI7ugxHCMDAFwgtHIh9VO2YfPAqlKBkofM72R9QZDbkCg1tOUuuF0yX1Q==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-popover-container": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-popover-container/-/uui-popover-container-1.13.0.tgz", - "integrity": "sha512-pNvfRLjFzRY7j8bJ1LDGROBZ1+h4HbKqr7O4bs8z8ZfdrxqHb1k/BssbSNt25JFmoHDSRZbFs3yBL9jhVEr/Xg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-popover-container/-/uui-popover-container-1.14.0.tgz", + "integrity": "sha512-1wG99PbKDdkzvV3W2avF5/zU7XLoxmui125EfKwCdDYuE5fsR1alBZHsdk6PvFXXpcbGaNJ/dWyWg+Ip687HeA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-progress-bar": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-progress-bar/-/uui-progress-bar-1.13.0.tgz", - "integrity": "sha512-QRgydD21AJfmv89WWiim8O/7XR0BTsWP73lga2Tbj3OU/8jjw0vcqmjzf0uhOir5SL1Y0Y1CT/SPUjgxc0VC0g==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-progress-bar/-/uui-progress-bar-1.14.0.tgz", + "integrity": "sha512-ImFS/QWWSZ9oExINb8thaQ6mexFpq62AbvZoVDzdBrje1pf9FErSs4u1XReS9iRtkE1kyGiyY302a4fAoKyMtQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-radio": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-radio/-/uui-radio-1.13.0.tgz", - "integrity": "sha512-SsSqyte7n2KEqEjmtI2ajUX6m0AL6nreSZ53IGViMBim8bTcW4oBq5Wbp3dll+s88WvExppozE2iA1kLgjijOw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-radio/-/uui-radio-1.14.0.tgz", + "integrity": "sha512-PbQ0SloYLJE6YUldwPU5MoBj+/zIQifNhaEYb2Ss2Ka7LFXFAZ9TvXr/INreh4zxI9DSeXirj41k3O+7fbB/Cg==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-range-slider": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-range-slider/-/uui-range-slider-1.13.0.tgz", - "integrity": "sha512-gplKOzASnz2spVVkwgj1kYAPFRqp4KRuDFlWyr2IY5luvTajUZC6JOB4aQDs5+OMbgYvF4G+PKFEapuYnR7gNg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-range-slider/-/uui-range-slider-1.14.0.tgz", + "integrity": "sha512-ha798qXr/J3Kjd++eHBYdfqFSVKvSg9TWd+aAhAVj9rVb0Q8mbuinqUcWN9ZHukTNl7lG0/4HbTfM80Lm5V6TA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-ref": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref/-/uui-ref-1.13.0.tgz", - "integrity": "sha512-jgVgHFa7/5zcg86Rtkecp7XO9FENQUQ7uMZyCAUHYCPur/n0CKNBrVjwQ/PEI0o1VR+eRGUG5iByZgQW1yWTtQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref/-/uui-ref-1.14.0.tgz", + "integrity": "sha512-bjKcCLRxcu6HR+0kRrLpdit449FHhc16x1LZPncTtjAXN+kZYVmBiQ1QL2/W1l734vRm68nmHVuE5LB1Y2RuIw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-ref-list": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-list/-/uui-ref-list-1.13.0.tgz", - "integrity": "sha512-9Nw03JwymtGnkqvnEeRhmSS+F7Xlzp7yef4R/WdZEIYASV42vwCIAj5Wdj2JI+Apc0ZVZ4hCQhbfNVsr+e7ddQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-list/-/uui-ref-list-1.14.0.tgz", + "integrity": "sha512-rVUldYm4FMAM3SJ8cCbvwdTm4LL9iz3LoFeTxXpfuo6STP+Y26kqR5z5hex6rUcX51se5yEp7PpQDO5bHHz5OA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-ref-node": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node/-/uui-ref-node-1.13.0.tgz", - "integrity": "sha512-otjHMgmaekLl3iPwDjLgJ6H7HIWF3QqNLNAiHnGZ1pdShJyLfajvHxnDULeUuI6zRDdjavzz3fhPUnjzyraYpQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node/-/uui-ref-node-1.14.0.tgz", + "integrity": "sha512-d10iNjb5x3klPZzzt4AZqeGJ3xbqbaLc4NJb4lQ6C6+djLL+tsJf1MN1vC17dC/wPJ5B894iSBaha0fa8fVfMQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-icon": "1.13.0", - "@umbraco-ui/uui-ref": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-icon": "1.14.0", + "@umbraco-ui/uui-ref": "1.14.0" } }, "node_modules/@umbraco-ui/uui-ref-node-data-type": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-data-type/-/uui-ref-node-data-type-1.13.0.tgz", - "integrity": "sha512-M5+7ekzpoNJmjD8YvH5TQPb1ENbIwnjyXyUv7IiXV2AtTF/H/g0t4pEU+SYhlrAe61VyW5TedtAMWK+oDKrWUg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-data-type/-/uui-ref-node-data-type-1.14.0.tgz", + "integrity": "sha512-DcwR0qltykP1NHT8aRqbgQ4/PF2h64ehvBUpEeYg7U9/1xgpWlelkHlZ6CREzZUENaOFrpJzmhzbQWxYa7XKWA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-ref-node": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-ref-node": "1.14.0" } }, "node_modules/@umbraco-ui/uui-ref-node-document-type": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-document-type/-/uui-ref-node-document-type-1.13.0.tgz", - "integrity": "sha512-AsTjfuAKak/cdaZaJCjuu19YyYwC2FunPP2fz2PuXPr7ULcmo78oYIZY6YJPUsPlBSMN5PIIr9iox3ob6Dd+Rg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-document-type/-/uui-ref-node-document-type-1.14.0.tgz", + "integrity": "sha512-71A3vJa5SAZd6rTRaa5r/0fV+fr/Am4T5rZu8gdSfEw52ppkVNbg5iHqIwFKN2QDBzKI9GFSrjSVPmRJIsTNTQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-ref-node": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-ref-node": "1.14.0" } }, "node_modules/@umbraco-ui/uui-ref-node-form": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-form/-/uui-ref-node-form-1.13.0.tgz", - "integrity": "sha512-ySHrq0xH4l69NH12pXzfPrrMG9fRnHF7ul+iKSrPvqUdWnsNpEzYakGvt6XXji1x3ogZEKnKMlzAXrHZDL8LoA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-form/-/uui-ref-node-form-1.14.0.tgz", + "integrity": "sha512-hVF6NtGqAZ0GRr28H2q2jOD7T4fTD837sJw7kJTLdzV5Oatu0rqWs4nmV6KpUCJjoUGYFWg+fKc5vvrF+gXXFA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-ref-node": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-ref-node": "1.14.0" } }, "node_modules/@umbraco-ui/uui-ref-node-member": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-member/-/uui-ref-node-member-1.13.0.tgz", - "integrity": "sha512-UiSAxsPjpivbI0Hm1fZ1O7nTgkSjPigi9z5RWT4P0viiYetrc8ggJpZ5cDFEQH2xBe40qfBQQGr8vJ4Gsz3opg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-member/-/uui-ref-node-member-1.14.0.tgz", + "integrity": "sha512-Xy1mCgaPDLWnpXyfU1KgaEX+u04JXKnkbrj92d43k4HB30tbI/8BjwyYEaT3Phvs4fmUC0h4ege41Zu8aYfqDg==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-ref-node": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-ref-node": "1.14.0" } }, "node_modules/@umbraco-ui/uui-ref-node-package": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-package/-/uui-ref-node-package-1.13.0.tgz", - "integrity": "sha512-iANsUZDFjLQdalKVI007LuNDlEsruh88peWiBrDN47HtRZlZ/tLV67Ljd5oRjZhAFZLjjFQ1jl0DOkkD3lKIFw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-package/-/uui-ref-node-package-1.14.0.tgz", + "integrity": "sha512-MNF0n9nlC6W7Ove9fm7+YwhWwEL5+nUmhYZySEb3YAwjOXHDgL9hHS0gmT1YXxu+66RtBXdqUkZbfI2AVKv7qw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-ref-node": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-ref-node": "1.14.0" } }, "node_modules/@umbraco-ui/uui-ref-node-user": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-user/-/uui-ref-node-user-1.13.0.tgz", - "integrity": "sha512-XckwV6nrJjWeeBZX7j28fJdJZlzugyhfXIacp6+AnFHrL5NXjsb3Hi4ZLt00CurcxmhVVta+J5uvmOLSVi7Myw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-user/-/uui-ref-node-user-1.14.0.tgz", + "integrity": "sha512-AFycox1NtGnhVtGgJ3Sg0fCAUlOf38V7S2KPrFubAFmjbxcddWqlMVWzxTcUbUDE2TL5KHnU/JCUxf4BQO1pUw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-ref-node": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-ref-node": "1.14.0" } }, "node_modules/@umbraco-ui/uui-scroll-container": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-scroll-container/-/uui-scroll-container-1.13.0.tgz", - "integrity": "sha512-3Qnl6aGxRs2FYvZzskZYFXnDsej5vBHalu/0b7VKfTPdUMJuAtR+1rz+veLvm9hL5pf9sJbSx4IZe+BubrYmnw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-scroll-container/-/uui-scroll-container-1.14.0.tgz", + "integrity": "sha512-N+jYDLTCmo5vC1Mutv/d/mWMivkbWXI1AWM20i7wDQ3U8R6VsbA4Rr7Ne8V9jSnOrgQY9PHrTE2OI99S0bFrnw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-select": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-select/-/uui-select-1.13.0.tgz", - "integrity": "sha512-JF4Jtgc/H61tdPVD01kkBRkUofWatrUG9diRMuaGPvQsWEVNvbCJKXJ+Fww9pMQts25EidLhhtqG2hX3ZSsgYA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-select/-/uui-select-1.14.0.tgz", + "integrity": "sha512-/hTUiJ38/gpEf4pk7AWauy/i4o+DYkJR9CpdkL8oyjjwjkmJAVL817v4sXUcTvuaYYVrVqBY1M7U3FgEumKHVw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-slider": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-slider/-/uui-slider-1.13.0.tgz", - "integrity": "sha512-r4QE+V0LTyn1NAyHsLBkHAvu1jzqfpQ9mOIzwt7ekpuKUrlbaB+LWVo+lxiX7ShUVHxL+0squ0/1CNrLquz0AA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-slider/-/uui-slider-1.14.0.tgz", + "integrity": "sha512-biiJ7+aJnkfaPcNF4fuIIGfEmvmTXoOmI56BZN4ICRo1+wntVkfY64hjGTQ2gPV/d26eK1FNyUFpRl8leIxjVA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-symbol-expand": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-expand/-/uui-symbol-expand-1.13.0.tgz", - "integrity": "sha512-nR6Ld0ZrWQX0Ijk1y+3sRXMaAh87uaQkhcIHgS9Ziz+F1JbCf5WCygla3Xux5t+zpxhPVy6yvZc3iWJxQMp1TA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-expand/-/uui-symbol-expand-1.14.0.tgz", + "integrity": "sha512-8cXPlHmIoajexztcHKGdTrmbp+NR4O0Le+EtQrRMqf6S8apbw7SNy98h3CeSb6Gq2ZTXdXxzZnCtyo+znxpFHA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-symbol-file": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-file/-/uui-symbol-file-1.13.0.tgz", - "integrity": "sha512-F3+MyQaGDUYr+Z0VyBmZaIirPKSkON2Gu6jrb8kX04UuqVPIRvoxjubGTmu6wU5M0ATRt/NIG5CzYJp33R8bGA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-file/-/uui-symbol-file-1.14.0.tgz", + "integrity": "sha512-vWx6C/0xT+SUk3LTeqrzbS4P6YXPzN0kqqnUH7riHACYNZxmpAgB8EVU0MzlMdW/TpiMcapw0/KHYuMtBZ8Nkw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-symbol-file-dropzone": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-file-dropzone/-/uui-symbol-file-dropzone-1.13.0.tgz", - "integrity": "sha512-ko3+WSdgd3pG3SI5eUPJ/VbOYTW86AW6EmYDrsALAdRdKhQ5Kusbe7M8Uds8BB3EJ9GT9+xcjocLNMCTxV8soA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-file-dropzone/-/uui-symbol-file-dropzone-1.14.0.tgz", + "integrity": "sha512-AAb/Cv/INzjonxc4fDR1n0YMs2hO+O+fYtsW9VyAUxqLHnhxNFufwPU80v1Y0nNnKuaNlSAdGwM/4QJujwhj3w==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-symbol-file-thumbnail": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-file-thumbnail/-/uui-symbol-file-thumbnail-1.13.0.tgz", - "integrity": "sha512-fgdJcecVz39MuFTTneD9yI8K/4KZQkHaARfvcWmc2rvRD8S5HzGcp/a+y0zOmzLIpKi3Sjlwc/4d123nE3V0NQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-file-thumbnail/-/uui-symbol-file-thumbnail-1.14.0.tgz", + "integrity": "sha512-BBQKo03UVTPq6MO6GVDPv40w3Nizy8LRKQ6quNuhB0UcrWkqOAoJEMX/afX17oGtCoONN/Zq54mmXWgHD8yo1Q==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-symbol-folder": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-folder/-/uui-symbol-folder-1.13.0.tgz", - "integrity": "sha512-TIh45JTtvv6l+/7+UtSQxxyvtIyiv9tVv1QC4SKesW19opUkWiaNd5awaKlshi+Iu9CbXvCVwxTJ6TK5z3hsaA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-folder/-/uui-symbol-folder-1.14.0.tgz", + "integrity": "sha512-Z+Kcdk2QyuLf+hKNTacdM6jeNo+wexZ0ktUPbVHJUjYaHuyzqNVV0Du8NJyFBMwyiomV9xLKxQi0YeI/aDg+Cg==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-symbol-lock": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-lock/-/uui-symbol-lock-1.13.0.tgz", - "integrity": "sha512-/39U8n0DfHNI4I2X1WX8dJv6pSOHeJMvpyS1Cla54Q45gtt7RHMU55aNEGBZoF19oPV2W74gl7vfcHGTtnPKNQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-lock/-/uui-symbol-lock-1.14.0.tgz", + "integrity": "sha512-dLcc1TkD541ikC+iOEguJmXsJYphqBwEmt2fqVJEDYddmGUf1ZlUNJSjkamU8vaER6NgNIhmqByU0Lv2SdDrjQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-symbol-more": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-more/-/uui-symbol-more-1.13.0.tgz", - "integrity": "sha512-mEwbSezTZfG77MUdWrFGXkMaSBHpC899lToDONTnQurkvLBxbBRBlT+xhHo54psAzJX7C6NLRvExTMztGU1OeQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-more/-/uui-symbol-more-1.14.0.tgz", + "integrity": "sha512-HgelD3iF2YMRrCumw8YqeVW/OsByGMWF1ILk8aylyS+4faIEKhnKIpLlw0WovFBYJQpWilcm/JtMqBqa6DfMvg==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-symbol-sort": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-sort/-/uui-symbol-sort-1.13.0.tgz", - "integrity": "sha512-BDcvHXrueX3d6sFcQa5jzxlV1C0OdhymN1Q5GzXpby2xLJTjNbeGISdgHGCxjLPsmHUAAZ7XCGR8pqI0F+8Hpg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-sort/-/uui-symbol-sort-1.14.0.tgz", + "integrity": "sha512-cXahfWqCZuu1AOQyrycTmKgZXzBq8v+cqLsEeE929ZokVD35AsTXkLbo6kLN+zVRXAz5kNyaERrfS8yLoZFtWA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-table": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-table/-/uui-table-1.13.0.tgz", - "integrity": "sha512-CKoPIsqURMtR6PwaSs4UvB56LVLMTop93gArI//yN9Ox1/w7awxnnkRN2skpKIbtDHrbEBI//NJE50jPoS82eg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-table/-/uui-table-1.14.0.tgz", + "integrity": "sha512-4ko7jaoH24qLnlwo6jWAuphmkcNL/7RXcDOSgW8aBc0x3nXG2Ufk4PQi0z+k614eDW6+seMZASAsnMx94XhLEQ==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-tabs": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-tabs/-/uui-tabs-1.13.0.tgz", - "integrity": "sha512-b50xJ1Xka8nu51GCR8n2RZtCFjwTYDXV5zQF+s5KXpgC6A8mahCvzmmINHdgGnKm1JNG3c8abhwrueyxxVdI8Q==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-tabs/-/uui-tabs-1.14.0.tgz", + "integrity": "sha512-m7OEIFK9YD2z7PgD78+U0uFacob/9DqN4nlZXxOkaj/tIxcBbWDXCqRnVBkhkxJKocs6NBYaGi2XHBq9F7/S/w==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-button": "1.13.0", - "@umbraco-ui/uui-popover-container": "1.13.0", - "@umbraco-ui/uui-symbol-more": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-button": "1.14.0", + "@umbraco-ui/uui-popover-container": "1.14.0", + "@umbraco-ui/uui-symbol-more": "1.14.0" } }, "node_modules/@umbraco-ui/uui-tag": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-tag/-/uui-tag-1.13.0.tgz", - "integrity": "sha512-SBY9Mi9A89jIag7URKQqXW3omDk5Eczw2LuNF7VnkXmQCuvsiRP6/BzSBCh9m0RrD4QOLSXpYGgSoLSpS7MitA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-tag/-/uui-tag-1.14.0.tgz", + "integrity": "sha512-CphycjqzlUnMA+eEgJCCLKtmsCn5ileGPDn5ei427dc5P5wOEU6aGKqeAGMivP6db4UhUMjh3g0xXfQCKbqEaA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-textarea": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-textarea/-/uui-textarea-1.13.0.tgz", - "integrity": "sha512-H4XChy1m5gq43eySQ3Zp/AsBvh35Gk0VLijFxdhCfV+HHpuyrt0fJsYnjq1W1xoqhyt7h84YRpNIJMyAIm2WHQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-textarea/-/uui-textarea-1.14.0.tgz", + "integrity": "sha512-l/hyV78IQn+Akb4UA0AtOTsdYJgCun7eC+i0vaOeNANXrO/B0Dhr2yembO0/mf/u2RxIFeOSsW8GUYixrIxSPw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@umbraco-ui/uui-toast-notification": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification/-/uui-toast-notification-1.13.0.tgz", - "integrity": "sha512-o45G8hWXgqcfGaJM+nhCTDSpevREJd+gPKT5XhTkD2wA99/kevdedmlYIgKS+9wONLk5A0j8qnsbWntinbb+rw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification/-/uui-toast-notification-1.14.0.tgz", + "integrity": "sha512-5pb4miAkdgoURoTQGvXQZoUHWIR4tgdUe78hPr2et3xSNw+N0Y/LHlDX1Bo9FBOKEvtFT6YHM0nqOIjW9/RpKw==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-button": "1.13.0", - "@umbraco-ui/uui-css": "1.13.0", - "@umbraco-ui/uui-icon": "1.13.0", - "@umbraco-ui/uui-icon-registry-essential": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-button": "1.14.0", + "@umbraco-ui/uui-css": "1.14.0", + "@umbraco-ui/uui-icon": "1.14.0", + "@umbraco-ui/uui-icon-registry-essential": "1.14.0" } }, "node_modules/@umbraco-ui/uui-toast-notification-container": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification-container/-/uui-toast-notification-container-1.13.0.tgz", - "integrity": "sha512-9O0t73v7qkb3+VE8i0pD1vo33tNt1U7t3L6699jNMZZr+7R6a5YOAVrFt+gs+kQcQXWt0HCfQxhKJ8opLoBOyw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification-container/-/uui-toast-notification-container-1.14.0.tgz", + "integrity": "sha512-5ai853OExMOFrKTrAgvx4OkRNJY8gfIA3UmLBQSVE4E065I0xW4F+L9A3foEU4so2z01OIwvJ53RRk7JriohTg==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-toast-notification": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-toast-notification": "1.14.0" } }, "node_modules/@umbraco-ui/uui-toast-notification-layout": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification-layout/-/uui-toast-notification-layout-1.13.0.tgz", - "integrity": "sha512-yhz8msOc1ngA//oBDefrR8pagTbvAenBiyk/fPuEwGQriM43e8bbVCJvhmrsTuAzAL8nn/ilKhAU5lrkn2rAmg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification-layout/-/uui-toast-notification-layout-1.14.0.tgz", + "integrity": "sha512-8WaiSNLB8NoKJMRQCqFh+KkhjOStXcJ+yLJJR/AM6HF6Pc0tYl+R3zM4LY9WJjQQEOXENcTUPMURJSwpJ2fsGA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-css": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-css": "1.14.0" } }, "node_modules/@umbraco-ui/uui-toggle": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toggle/-/uui-toggle-1.13.0.tgz", - "integrity": "sha512-tHzG/Lh9vRLjPu7EhFupaD7jkpVenyEM3iIsA24wBVKmqJGxacpuuuOwpTv6vGGiIYSKfRDXTDk07Q6MHDSy4g==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toggle/-/uui-toggle-1.14.0.tgz", + "integrity": "sha512-s8//Y2LAqDQ3h4C3PA9yJcVXF2H6gnv2NzMZ22KotJQT9+yhhR3UrOlndOZKkWqKtDxwSLEp9EmyITgDdEoT3A==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0", - "@umbraco-ui/uui-boolean-input": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0", + "@umbraco-ui/uui-boolean-input": "1.14.0" } }, "node_modules/@umbraco-ui/uui-visually-hidden": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-visually-hidden/-/uui-visually-hidden-1.13.0.tgz", - "integrity": "sha512-1ayTJylWnpAl0VQE7X2PBJCKLZ15R+xfZ3yy4ygT751k4wML26nvdWscp/tYfl4MteqrHtNJKTRTFoQ1Dn/r/g==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-visually-hidden/-/uui-visually-hidden-1.14.0.tgz", + "integrity": "sha512-wGbMiw+UuMYayMDBau5dD2B3HX2tFPlnOftvD9Z+FNKnGnU5e/V+QInCYy7FlywBQ5fDpfKcXseud/kONGRmsA==", "license": "MIT", "peer": true, "dependencies": { - "@umbraco-ui/uui-base": "1.13.0" + "@umbraco-ui/uui-base": "1.14.0" } }, "node_modules/@webassemblyjs/ast": { @@ -3738,6 +3760,16 @@ "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", "license": "MIT" }, + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dompurify": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.6.tgz", @@ -4631,9 +4663,9 @@ "peer": true }, "node_modules/lit": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.0.tgz", - "integrity": "sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.1.tgz", + "integrity": "sha512-Ksr/8L3PTapbdXJCk+EJVB78jDodUMaP54gD24W186zGRARvwrsPfS60wae/SSCTCNZVPd1chXqio1qHQmu4NA==", "license": "BSD-3-Clause", "peer": true, "dependencies": { @@ -4643,21 +4675,21 @@ } }, "node_modules/lit-element": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.0.tgz", - "integrity": "sha512-MGrXJVAI5x+Bfth/pU9Kst1iWID6GHDLEzFEnyULB/sFiRLgkd8NPK/PeeXxktA3T6EIIaq8U3KcbTU5XFcP2Q==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.1.tgz", + "integrity": "sha512-WGAWRGzirAgyphK2urmYOV72tlvnxw7YfyLDgQ+OZnM9vQQBQnumQ7jUJe6unEzwGU3ahFOjuz1iz1jjrpCPuw==", "license": "BSD-3-Clause", "peer": true, "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.2.0", + "@lit-labs/ssr-dom-shim": "^1.4.0", "@lit/reactive-element": "^2.1.0", "lit-html": "^3.3.0" } }, "node_modules/lit-html": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.0.tgz", - "integrity": "sha512-RHoswrFAxY2d8Cf2mm4OZ1DgzCoBKUKSPvA1fhtSELxUERq2aQQ2h05pO9j81gS1o7RIRJ+CePLogfyahwmynw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.1.tgz", + "integrity": "sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==", "license": "BSD-3-Clause", "peer": true, "dependencies": { @@ -6181,6 +6213,20 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "peer": true, + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/vite": { "version": "6.3.5", "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", diff --git a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/package.json b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/package.json index 18fe156..347d8e0 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/package.json +++ b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/package.json @@ -1,6 +1,6 @@ { "name": "umbraco-commerce-product-feeds", - "version": "15.0.0", + "version": "16.0.0", "description": "A product feeds generator for Umbraco Commerce", "main": "./src/index.ts", "type": "module", @@ -31,8 +31,8 @@ "license": "ISC", "dependencies": { "@hey-api/client-axios": "^0.8.0", - "@umbraco-cms/backoffice": "^16.0.0-rc3", - "@umbraco-commerce/backoffice": "^16.0.0-rc1", + "@umbraco-cms/backoffice": "^16.0.0", + "@umbraco-commerce/backoffice": "^16.0.0", "nanoid": "^5.1.5" } -} +} \ No newline at end of file diff --git a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/generated/apis/client.gen.ts b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/generated/apis/client.gen.ts index 4506429..98b659a 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/generated/apis/client.gen.ts +++ b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/generated/apis/client.gen.ts @@ -14,5 +14,5 @@ import { type Config, type ClientOptions as DefaultClientOptions, createClient, export type CreateClientConfig = (override?: Config) => Config & T>; export const client = createClient(createConfig({ - baseURL: 'https://localhost:44322', + baseURL: 'http://localhost:44321', })); \ No newline at end of file diff --git a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/generated/apis/sdk.gen.ts b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/generated/apis/sdk.gen.ts index d23b4b0..154f11e 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/generated/apis/sdk.gen.ts +++ b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/generated/apis/sdk.gen.ts @@ -1,7 +1,7 @@ // This file is auto-generated by @hey-api/openapi-ts import { type Options as ClientOptions, type TDataShape, type Client, formDataBodySerializer } from '@hey-api/client-axios'; -import type { DeleteData, DeleteResponses, DeleteErrors, GetDocumentTypesData, GetDocumentTypesResponses, GetDocumentTypesErrors, GetFeedTypesData, GetFeedTypesResponses, GetFeedTypesErrors, GetDetailsData, GetDetailsResponses, GetDetailsErrors, GetByStoreData, GetByStoreResponses, GetByStoreErrors, GetPropertyValueExtractorsData, GetPropertyValueExtractorsResponses, GetPropertyValueExtractorsErrors, SaveData, SaveResponses, SaveErrors } from './types.gen'; +import type { DeleteV2Data, DeleteV2Responses, DeleteV2Errors, DeleteData, DeleteResponses, DeleteErrors, GetDocumentTypesData, GetDocumentTypesResponses, GetDocumentTypesErrors, GetDocumentTypesV2Data, GetDocumentTypesV2Responses, GetDocumentTypesV2Errors, GetFeedGeneratorsV2Data, GetFeedGeneratorsV2Responses, GetFeedGeneratorsV2Errors, GetFeedTypesData, GetFeedTypesResponses, GetFeedTypesErrors, GetDetailsData, GetDetailsResponses, GetDetailsErrors, GetDetailsV2Data, GetDetailsV2Responses, GetDetailsV2Errors, GetByStoreData, GetByStoreResponses, GetByStoreErrors, GetByStoreV2Data, GetByStoreV2Responses, GetByStoreV2Errors, GetPropertyValueExtractorsData, GetPropertyValueExtractorsResponses, GetPropertyValueExtractorsErrors, GetPropertyValueExtractorsV2Data, GetPropertyValueExtractorsV2Responses, GetPropertyValueExtractorsV2Errors, SaveData, SaveResponses, SaveErrors, SaveV2Data, SaveV2Responses, SaveV2Errors } from './types.gen'; import { client as _heyApiClient } from './client.gen'; export type Options = ClientOptions & { @@ -18,6 +18,28 @@ export type Options; }; +export const deleteV2 = (options?: Options) => { + return (options?.client ?? _heyApiClient).post({ + ...formDataBodySerializer, + responseType: 'json', + security: [ + { + scheme: 'bearer', + type: 'http', + }, + ], + url: '/umbraco/ucproductfeeds/management/api/v2/setting/delete', + ...options, + headers: { + 'Content-Type': null, + ...options?.headers, + }, + }); +}; + +/** + * @deprecated + */ export const delete_ = (options?: Options) => { return (options?.client ?? _heyApiClient).post({ ...formDataBodySerializer, @@ -37,6 +59,9 @@ export const delete_ = (options?: Options< }); }; +/** + * @deprecated + */ export const getDocumentTypes = (options?: Options) => { return (options?.client ?? _heyApiClient).get({ security: [ @@ -50,6 +75,36 @@ export const getDocumentTypes = (options?: }); }; +export const getDocumentTypesV2 = (options?: Options) => { + return (options?.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http', + }, + ], + url: '/umbraco/ucproductfeeds/management/api/v2/setting/documenttypes', + ...options, + }); +}; + +export const getFeedGeneratorsV2 = (options?: Options) => { + return (options?.client ?? _heyApiClient).get({ + responseType: 'json', + security: [ + { + scheme: 'bearer', + type: 'http', + }, + ], + url: '/umbraco/ucproductfeeds/management/api/v2/setting/feedgenerators', + ...options, + }); +}; + +/** + * @deprecated + */ export const getFeedTypes = (options?: Options) => { return (options?.client ?? _heyApiClient).get({ responseType: 'json', @@ -64,6 +119,9 @@ export const getFeedTypes = (options?: Opt }); }; +/** + * @deprecated + */ export const getDetails = (options: Options) => { return (options.client ?? _heyApiClient).get({ responseType: 'json', @@ -78,6 +136,23 @@ export const getDetails = (options: Option }); }; +export const getDetailsV2 = (options: Options) => { + return (options.client ?? _heyApiClient).get({ + responseType: 'json', + security: [ + { + scheme: 'bearer', + type: 'http', + }, + ], + url: '/umbraco/ucproductfeeds/management/api/v2/setting/get/{id}', + ...options, + }); +}; + +/** + * @deprecated + */ export const getByStore = (options: Options) => { return (options.client ?? _heyApiClient).get({ responseType: 'json', @@ -92,6 +167,23 @@ export const getByStore = (options: Option }); }; +export const getByStoreV2 = (options: Options) => { + return (options.client ?? _heyApiClient).get({ + responseType: 'json', + security: [ + { + scheme: 'bearer', + type: 'http', + }, + ], + url: '/umbraco/ucproductfeeds/management/api/v2/setting/getbystore', + ...options, + }); +}; + +/** + * @deprecated + */ export const getPropertyValueExtractors = (options?: Options) => { return (options?.client ?? _heyApiClient).get({ responseType: 'json', @@ -106,6 +198,23 @@ export const getPropertyValueExtractors = }); }; +export const getPropertyValueExtractorsV2 = (options?: Options) => { + return (options?.client ?? _heyApiClient).get({ + responseType: 'json', + security: [ + { + scheme: 'bearer', + type: 'http', + }, + ], + url: '/umbraco/ucproductfeeds/management/api/v2/setting/propertyvalueextractors', + ...options, + }); +}; + +/** + * @deprecated + */ export const save = (options?: Options) => { return (options?.client ?? _heyApiClient).post({ responseType: 'json', @@ -122,4 +231,22 @@ export const save = (options?: Options(options?: Options) => { + return (options?.client ?? _heyApiClient).post({ + responseType: 'json', + security: [ + { + scheme: 'bearer', + type: 'http', + }, + ], + url: '/umbraco/ucproductfeeds/management/api/v2/setting/save', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + }, + }); }; \ No newline at end of file diff --git a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/generated/apis/types.gen.ts b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/generated/apis/types.gen.ts index c3666b3..8c21f40 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/generated/apis/types.gen.ts +++ b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/generated/apis/types.gen.ts @@ -15,9 +15,13 @@ export type NotificationHeaderModel = { export type ProductFeedSettingReadModelReadable = { id: string; + feedGeneratorId: string; + feedName: string; feedType: ProductFeedType; + /** + * @deprecated + */ readonly feedTypeName: string; - feedName: string; feedDescription: string; storeId: string; productRootId: string; @@ -30,8 +34,9 @@ export type ProductFeedSettingReadModelReadable = { export type ProductFeedSettingReadModelWritable = { id: string; - feedType: ProductFeedType; + feedGeneratorId: string; feedName: string; + feedType: ProductFeedType; feedDescription: string; storeId: string; productRootId: string; @@ -45,8 +50,9 @@ export type ProductFeedSettingReadModelWritable = { export type ProductFeedSettingWriteModel = { id?: string | null; feedRelativePath: string; - feedType: ProductFeedType; + feedGeneratorId: string; feedName: string; + feedType: ProductFeedType; feedDescription: string; storeId: string; productRootId: string; @@ -64,6 +70,39 @@ export type PropertyAndNodeMapItem = { valueExtractorId?: string | null; }; +export type DeleteV2Data = { + body?: { + ids?: Array; + }; + path?: never; + query?: never; + url: '/umbraco/ucproductfeeds/management/api/v2/setting/delete'; +}; + +export type DeleteV2Errors = { + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user does not have access to this resource + */ + 403: unknown; + /** + * Internal Server Error + */ + 500: unknown; +}; + +export type DeleteV2Responses = { + /** + * OK + */ + 200: boolean; +}; + +export type DeleteV2Response = DeleteV2Responses[keyof DeleteV2Responses]; + export type DeleteData = { body?: { ids?: Array; @@ -122,6 +161,58 @@ export type GetDocumentTypesResponses = { 200: unknown; }; +export type GetDocumentTypesV2Data = { + body?: never; + path?: never; + query?: never; + url: '/umbraco/ucproductfeeds/management/api/v2/setting/documenttypes'; +}; + +export type GetDocumentTypesV2Errors = { + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user does not have access to this resource + */ + 403: unknown; +}; + +export type GetDocumentTypesV2Responses = { + /** + * OK + */ + 200: unknown; +}; + +export type GetFeedGeneratorsV2Data = { + body?: never; + path?: never; + query?: never; + url: '/umbraco/ucproductfeeds/management/api/v2/setting/feedgenerators'; +}; + +export type GetFeedGeneratorsV2Errors = { + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user does not have access to this resource + */ + 403: unknown; +}; + +export type GetFeedGeneratorsV2Responses = { + /** + * OK + */ + 200: Array; +}; + +export type GetFeedGeneratorsV2Response = GetFeedGeneratorsV2Responses[keyof GetFeedGeneratorsV2Responses]; + export type GetFeedTypesData = { body?: never; path?: never; @@ -182,6 +273,39 @@ export type GetDetailsResponses = { export type GetDetailsResponse = GetDetailsResponses[keyof GetDetailsResponses]; +export type GetDetailsV2Data = { + body?: never; + path: { + id: string; + }; + query?: never; + url: '/umbraco/ucproductfeeds/management/api/v2/setting/get/{id}'; +}; + +export type GetDetailsV2Errors = { + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user does not have access to this resource + */ + 403: unknown; + /** + * Not Found + */ + 404: unknown; +}; + +export type GetDetailsV2Responses = { + /** + * OK + */ + 200: ProductFeedSettingReadModelReadable; +}; + +export type GetDetailsV2Response = GetDetailsV2Responses[keyof GetDetailsV2Responses]; + export type GetByStoreData = { body?: never; path?: never; @@ -211,6 +335,35 @@ export type GetByStoreResponses = { export type GetByStoreResponse = GetByStoreResponses[keyof GetByStoreResponses]; +export type GetByStoreV2Data = { + body?: never; + path?: never; + query: { + storeId: string; + }; + url: '/umbraco/ucproductfeeds/management/api/v2/setting/getbystore'; +}; + +export type GetByStoreV2Errors = { + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user does not have access to this resource + */ + 403: unknown; +}; + +export type GetByStoreV2Responses = { + /** + * OK + */ + 200: Array; +}; + +export type GetByStoreV2Response = GetByStoreV2Responses[keyof GetByStoreV2Responses]; + export type GetPropertyValueExtractorsData = { body?: never; path?: never; @@ -238,6 +391,33 @@ export type GetPropertyValueExtractorsResponses = { export type GetPropertyValueExtractorsResponse = GetPropertyValueExtractorsResponses[keyof GetPropertyValueExtractorsResponses]; +export type GetPropertyValueExtractorsV2Data = { + body?: never; + path?: never; + query?: never; + url: '/umbraco/ucproductfeeds/management/api/v2/setting/propertyvalueextractors'; +}; + +export type GetPropertyValueExtractorsV2Errors = { + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user does not have access to this resource + */ + 403: unknown; +}; + +export type GetPropertyValueExtractorsV2Responses = { + /** + * OK + */ + 200: Array; +}; + +export type GetPropertyValueExtractorsV2Response = GetPropertyValueExtractorsV2Responses[keyof GetPropertyValueExtractorsV2Responses]; + export type SaveData = { body?: ProductFeedSettingWriteModel; path?: never; @@ -279,6 +459,47 @@ export type SaveResponses = { export type SaveResponse = SaveResponses[keyof SaveResponses]; +export type SaveV2Data = { + body?: ProductFeedSettingWriteModel; + path?: never; + query?: never; + url: '/umbraco/ucproductfeeds/management/api/v2/setting/save'; +}; + +export type SaveV2Errors = { + /** + * Bad Request + */ + 400: string; + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user does not have access to this resource + */ + 403: unknown; + /** + * Internal Server Error + */ + 500: string; +}; + +export type SaveV2Error = SaveV2Errors[keyof SaveV2Errors]; + +export type SaveV2Responses = { + /** + * OK + */ + 200: string; + /** + * Created + */ + 201: string; +}; + +export type SaveV2Response = SaveV2Responses[keyof SaveV2Responses]; + export type ClientOptions = { - baseURL: 'https://localhost:44322' | (string & {}); + baseURL: 'http://localhost:44321' | (string & {}); }; \ No newline at end of file diff --git a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/index.ts b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/index.ts index 05c1f15..34c89a8 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/index.ts +++ b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/index.ts @@ -21,7 +21,7 @@ export const onInit: UmbEntryPointOnInit = (host, extensionRegistry) => { const config = instance?.getOpenApiConfiguration(); apiClient.setConfig({ - baseURL: config?.base ?? "", + baseURL: config?.base ?? '', }); apiClient.instance.interceptors.request.use(async (request) => { diff --git a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/datasource.ts b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/datasource.ts index eedd640..bed6def 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/datasource.ts +++ b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/datasource.ts @@ -1,8 +1,8 @@ import { tryExecute } from '@umbraco-cms/backoffice/resources'; -import { delete_, getByStore, getDetails, getFeedTypes, getPropertyValueExtractors, LookupReadModel, ProductFeedSettingReadModelReadable, ProductFeedSettingWriteModel, save } from '../generated/apis'; import { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbPagedModel, UmbRepositoryResponse } from '@umbraco-cms/backoffice/repository'; import { FeProductFeedSettingWriteModel } from './details/types'; +import { deleteV2, getByStoreV2, getDetailsV2, getFeedGeneratorsV2, getPropertyValueExtractorsV2, LookupReadModel, ProductFeedSettingReadModelReadable, ProductFeedSettingWriteModel, saveV2 } from '../generated/apis'; export class UcpfListDataSource { #host: UmbControllerHost; @@ -12,7 +12,7 @@ export class UcpfListDataSource { } async fetchListAsync(storeId: string): Promise>> { - const { data, error } = await tryExecute(this.#host, getByStore({ + const { data, error } = await tryExecute(this.#host, getByStoreV2({ query: { storeId, }, @@ -30,7 +30,7 @@ export class UcpfListDataSource { } async fetchFeedSettingDetailsAsync(id: string) { - const { data, error } = await getDetails({ + const { data, error } = await getDetailsV2({ path: { id, }, @@ -46,7 +46,7 @@ export class UcpfListDataSource { } async fetchFeedTypesAsync() { - const { data, error } = await getFeedTypes(); + const { data, error } = await getFeedGeneratorsV2(); if (data) { return { data: data as Array }; @@ -58,7 +58,7 @@ export class UcpfListDataSource { } async fetchPropertyValueExtractorsAsync() { - const { data, error } = await getPropertyValueExtractors(); + const { data, error } = await getPropertyValueExtractorsV2(); if (data) { return { data: data as Array }; @@ -70,7 +70,7 @@ export class UcpfListDataSource { } async saveAsync(model: FeProductFeedSettingWriteModel) { - const { data, error } = await save({ + const { data, error } = await saveV2({ body: model as ProductFeedSettingWriteModel, }); @@ -88,7 +88,7 @@ export class UcpfListDataSource { throw 'no id to delete'; } - const { data, error } = await delete_({ + const { data, error } = await deleteV2({ body: { ids }, }); diff --git a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/context.ts b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/context.ts index 33c1734..682979d 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/context.ts +++ b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/context.ts @@ -99,11 +99,15 @@ export class UcpfDetailsWorkspaceContext protected resetState(): void { super.resetState(); + + const availableFeedTypes = this.#feedTypes.getValue(); + this.#unique.setValue(''); this.#model.setValue({ + feedName: '', feedDescription: '', storeId: this.#store!.id, - feedName: '', + feedGeneratorId: availableFeedTypes.length > 0 ? availableFeedTypes[0] : '', feedRelativePath: '', productChildVariantTypeIds: [], productDocumentTypeIds: [], diff --git a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/manifests.ts b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/manifests.ts index d1b7f0a..b856d2e 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/manifests.ts +++ b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/manifests.ts @@ -1,14 +1,9 @@ -import type { - ManifestEntityAction, - ManifestWorkspace, - ManifestWorkspaceAction, - ManifestWorkspaceView, -} from '@umbraco-cms/backoffice/extension-registry'; -import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import { ManifestWorkspace, ManifestWorkspaceAction, ManifestWorkspaceView, UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; import { UcpfDetailsWorkspaceContext } from './context.js'; import UcpfDetailsWorkspaceViewElement from './views/details.element.js'; import { ProductFeedEntityActionDelete } from './actions/entity-action.delete.js'; import { UcpfWorkspaceActionOpenFeed } from './actions/workspace-action.open-feed.js'; +import { ManifestEntityAction } from '@umbraco-cms/backoffice/entity-action'; export const detailsWorkspaceManifest: ManifestWorkspace = { type: 'workspace', diff --git a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/types.ts b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/types.ts index 49ce757..b886f0e 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/types.ts +++ b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/types.ts @@ -3,10 +3,11 @@ import { ProductFeedSettingWriteModel, PropertyAndNodeMapItem } from '../../gene export type FeProductFeedSettingWriteModel = Omit & { id?: string propertyNameMappings: Array - productRootId?: string, - feedType?: 'GoogleMerchantCenter' + productRootId?: string | null, + feedGeneratorId: string, + feedType?: string, } export type FePropertyAndNodeMapDetails = PropertyAndNodeMapItem & { uiId: string -} \ No newline at end of file +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/views/details.element.ts b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/views/details.element.ts index 93d64ab..08cd164 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/views/details.element.ts +++ b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/details/views/details.element.ts @@ -57,11 +57,11 @@ export class UcpfDetailsWorkspaceViewElement this.observe(this.#workspaceContext.model, (model) => { this._model = model; - this._feedTypes = this.#markSelectedOption(this._feedTypes, model!.feedType); + this._feedTypes = this.#markSelectedOption(this._feedTypes, model!.feedGeneratorId); }); this.observe(this.#workspaceContext.feedTypeOptions, (feedTypes) => { - this._feedTypes = this.#markSelectedOption(feedTypes, this._model?.feedType); + this._feedTypes = this.#markSelectedOption(feedTypes, this._model?.feedGeneratorId); }); this.observe(this.#workspaceContext.propertyValueExtractorOptions, (options) => { @@ -188,7 +188,7 @@ export class UcpfDetailsWorkspaceViewElement label=${this.localize.term('ucProductFeeds_propFeedTypeLabel')} placeholder=${`-- ${this.localize.term('ucPlaceholders_selectAnItem')} --`} slot='editor' - name='feedType' + name='feedGeneratorId' .options=${this._feedTypes} @change=${this.#onSelectElementChange}> diff --git a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/list/collections/actions/bulk-action.delete.ts b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/list/collections/actions/bulk-action.delete.ts index 9586264..7180ed7 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/list/collections/actions/bulk-action.delete.ts +++ b/src/Umbraco.Commerce.ProductFeeds.Client/frontend/src/workspaces/list/collections/actions/bulk-action.delete.ts @@ -52,13 +52,13 @@ export class UcpfListBulkDeleteAction extends UmbEntityBulkActionBase + /// This is the general exception class for the package, allowing consumers to catch exceptions thrown specifically by it. + /// + public class UmbracoCommerceProductFeedsGeneralException : Exception + { + public UmbracoCommerceProductFeedsGeneralException() + { + } + + public UmbracoCommerceProductFeedsGeneralException(string message) + : base(message) + { + } + + public UmbracoCommerceProductFeedsGeneralException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Application/FeedFormat.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Application/FeedFormat.cs new file mode 100644 index 0000000..b8a2e04 --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Application/FeedFormat.cs @@ -0,0 +1,9 @@ +namespace Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Application +{ + public enum FeedFormat + { + Unknown, + Xml, + Json + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Application/IProductFeedGeneratorFactory.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Application/IProductFeedGeneratorFactory.cs index a33e82a..aab6877 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Application/IProductFeedGeneratorFactory.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Application/IProductFeedGeneratorFactory.cs @@ -4,6 +4,12 @@ namespace Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Application { public interface IProductFeedGeneratorFactory { - IProductFeedGeneratorService GetGenerator(ProductFeedType feedType); + [Obsolete("Will be removed in v17. Use the overload that takes feedGeneratorId.")] + IProductFeedGeneratorService GetGenerator(ProductFeedType feedType) + => GetGenerator(feedType); + + // TODO - v17: remove the default implementation + IProductFeedGeneratorService GetGenerator(Guid feedGeneratorId) + => throw new NotImplementedException("This method should be implemented in the concrete factory class."); } } diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Application/IProductFeedGeneratorService.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Application/IProductFeedGeneratorService.cs index 361e3c1..2b19aa6 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Application/IProductFeedGeneratorService.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Application/IProductFeedGeneratorService.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using System.Xml; using Umbraco.Commerce.ProductFeeds.Core.Features.FeedSettings.Application; @@ -5,6 +6,26 @@ namespace Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Application { public interface IProductFeedGeneratorService { - Task GenerateFeedAsync(ProductFeedSettingReadModel feedSetting); + /// + /// Returns the feed generator id. Must be unique among the feed generator services. + /// + public Guid Id => throw new NotImplementedException(); // TODO - v17: remove the default implementation. + + /// + /// Returns a user friendly name of the value extractor. + /// + public string DisplayName => throw new NotImplementedException(); // TODO - v17: remove the default implementation. + + /// + /// Returns the feed format that this generator can generate. + /// + public FeedFormat Format { get => FeedFormat.Unknown; } // TODO - v17: remove the default implementation. + + [Obsolete("Will be removed in v17. Use GenerateXmlFeedAsync or GenerateJsonFeedAsync instead.")] + Task GenerateFeedAsync(ProductFeedSettingReadModel feedSetting) => GenerateXmlFeedAsync(feedSetting); + + Task GenerateXmlFeedAsync(ProductFeedSettingReadModel feedSetting) => throw new NotImplementedException("XML feed generation is not implemented."); + + Task GenerateJsonFeedAsync(ProductFeedSettingReadModel feedSetting) => throw new NotImplementedException("JSON feed generation is not implemented."); } } diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/FeedGeneratorCollection.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/FeedGeneratorCollection.cs new file mode 100644 index 0000000..7ffe7fd --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/FeedGeneratorCollection.cs @@ -0,0 +1,12 @@ +using Umbraco.Cms.Core.Composing; +using Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Application; + +namespace Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Implementations +{ + public class FeedGeneratorCollection : BuilderCollectionBase + { + public FeedGeneratorCollection(Func> items) : base(items) + { + } + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/FeedGeneratorCollectionBuilder.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/FeedGeneratorCollectionBuilder.cs new file mode 100644 index 0000000..b7c2446 --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/FeedGeneratorCollectionBuilder.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.Composing; +using Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Application; + +namespace Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Implementations +{ + public class FeedGeneratorCollectionBuilder : OrderedCollectionBuilderBase + { + protected override FeedGeneratorCollectionBuilder This => this; + + protected override ServiceLifetime CollectionLifetime => ServiceLifetime.Scoped; + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/FeedGeneratorServiceBase.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/FeedGeneratorServiceBase.cs new file mode 100644 index 0000000..674d287 --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/FeedGeneratorServiceBase.cs @@ -0,0 +1,33 @@ +using System.Text.Json; +using System.Xml; +using Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Application; +using Umbraco.Commerce.ProductFeeds.Core.Features.FeedSettings.Application; +using Umbraco.Commerce.ProductFeeds.Core.Features.PropertyValueExtractors.Application; + +namespace Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Implementations +{ + public abstract class FeedGeneratorServiceBase : IProductFeedGeneratorService + { + protected FeedGeneratorServiceBase( + ISingleValuePropertyExtractorFactory singleValuePropertyExtractorFactory, + IMultipleValuePropertyExtractorFactory multipleValuePropertyExtractorFactory) + { + SingleValuePropertyExtractorFactory = singleValuePropertyExtractorFactory; + MultipleValuePropertyExtractorFactory = multipleValuePropertyExtractorFactory; + } + + public abstract Guid Id { get; } + public abstract string DisplayName { get; } + public abstract FeedFormat Format { get; } + + protected ISingleValuePropertyExtractorFactory SingleValuePropertyExtractorFactory { get; } + protected IMultipleValuePropertyExtractorFactory MultipleValuePropertyExtractorFactory { get; } + + [Obsolete("Will be removed in v17. Use GenerateXmlFeedAsync or GenerateJsonFeedAsync instead.")] + public virtual Task GenerateFeedAsync(ProductFeedSettingReadModel feedSetting) => GenerateXmlFeedAsync(feedSetting); + + public virtual Task GenerateXmlFeedAsync(ProductFeedSettingReadModel feedSetting) => throw new NotImplementedException("XML feed generation is not implemented."); + + public virtual Task GenerateJsonFeedAsync(ProductFeedSettingReadModel feedSetting) => throw new NotImplementedException("JSON feed generation is not implemented."); + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/GoogleMerchantCenterFeedService.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/GoogleMerchantCenterFeedService.cs index a2f2ef4..2343822 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/GoogleMerchantCenterFeedService.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/GoogleMerchantCenterFeedService.cs @@ -20,7 +20,7 @@ namespace Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Implementat /// /// This is the feed generator that follows Google Merchant Center's standard. /// - public class GoogleMerchantCenterFeedService : IProductFeedGeneratorService + public class GoogleMerchantCenterFeedService : FeedGeneratorServiceBase // TODO - v17: Make internal { private const string GoogleXmlNamespaceUri = "http://base.google.com/ns/1.0"; @@ -33,32 +33,38 @@ public class GoogleMerchantCenterFeedService : IProductFeedGeneratorService private readonly ICurrencyService _currencyService; private readonly IProductQueryService _productQueryService; private readonly IUmbracoCommerceApi _commerceApi; - private readonly ISingleValuePropertyExtractorFactory _singleValuePropertyExtractorFactory; - private readonly IMultipleValuePropertyExtractorFactory _multipleValuePropertyExtractorFactory; + + public override Guid Id => new("101AE565-038F-443E-A29E-4FE0C7146C4A"); + + public override string DisplayName => "Google Merchant Center Feed"; + + public override FeedFormat Format => FeedFormat.Xml; public GoogleMerchantCenterFeedService( ILogger logger, ICurrencyService currencyService, IProductQueryService productQueryService, IUmbracoCommerceApi commerceApi, - ISingleValuePropertyExtractorFactory singleValuePropertyExtractor, + ISingleValuePropertyExtractorFactory singleValuePropertyExtractorFactory, IMultipleValuePropertyExtractorFactory multipleValuePropertyExtractorFactory) + : base(singleValuePropertyExtractorFactory, multipleValuePropertyExtractorFactory) { _logger = logger; _currencyService = currencyService; _productQueryService = productQueryService; _commerceApi = commerceApi; - _singleValuePropertyExtractorFactory = singleValuePropertyExtractor; - _multipleValuePropertyExtractorFactory = multipleValuePropertyExtractorFactory; } + [Obsolete("Will be removed in v17. Use GenerateXmlFeedAsync or GenerateJsonFeedAsync instead.")] + public override Task GenerateFeedAsync(ProductFeedSettingReadModel feedSetting) => GenerateFeedAsync(feedSetting); + /// /// Generate the product feed following the inputted settings. /// /// /// /// - public async Task GenerateFeedAsync(ProductFeedSettingReadModel feedSetting) + public override async Task GenerateXmlFeedAsync(ProductFeedSettingReadModel feedSetting) { ArgumentNullException.ThrowIfNull(feedSetting, nameof(feedSetting)); @@ -157,22 +163,24 @@ private async Task NewItemNodeAsync(ProductFeedSettingReadModel feed // add custom properties foreach (PropertyAndNodeMapItem map in feedSetting.PropertyNameMappings) { - if (_singleValuePropertyExtractorFactory.TryGetExtractor(map.ValueExtractorId, out ISingleValuePropertyExtractor? singleValueExtractor) + if (SingleValuePropertyExtractorFactory.TryGetExtractor(map.ValueExtractorId, out ISingleValuePropertyExtractor? singleValueExtractor) && singleValueExtractor != null) { string propValue = singleValueExtractor.Extract(variant, map.PropertyAlias, mainProduct); itemNode.AddChild(map.NodeName, propValue, GoogleXmlNamespaceUri); } - else if (_multipleValuePropertyExtractorFactory.TryGetExtractor(map.ValueExtractorId!, out IMultipleValuePropertyExtractor? multipleValueExtractor) + else if (MultipleValuePropertyExtractorFactory.TryGetExtractor(map.ValueExtractorId!, out IMultipleValuePropertyExtractor? multipleValueExtractor) && multipleValueExtractor != null) { var values = multipleValueExtractor.Extract(variant, map.PropertyAlias, mainProduct).ToList(); if (map.NodeName.Equals("g:image_link", StringComparison.OrdinalIgnoreCase)) { + // image nodes are special, they can have multiple values, but Google Merchant Center treats them differently AddImageNodes(itemNode, values); } else { + // handle general multiple value properties foreach (string value in values) { itemNode.AddChild(map.NodeName, value, GoogleXmlNamespaceUri); diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/ProductFeedGeneratorFactory.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/ProductFeedGeneratorFactory.cs index d2907c6..0e0a3cb 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/ProductFeedGeneratorFactory.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedGenerators/Implementations/ProductFeedGeneratorFactory.cs @@ -4,26 +4,31 @@ namespace Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Implementations { + // TODO - v17: make internal public class ProductFeedGeneratorFactory : IProductFeedGeneratorFactory { - private readonly IServiceProvider _serviceProvider; + private readonly FeedGeneratorCollection _feedGenerators; + [Obsolete("Will be removed in v17. Use the constructor that takes FeedGeneratorCollection instead.")] public ProductFeedGeneratorFactory(IServiceProvider serviceProvider) + : this(serviceProvider.GetService()) { - _serviceProvider = serviceProvider; } - public IProductFeedGeneratorService GetGenerator(ProductFeedType feedType) + public ProductFeedGeneratorFactory(FeedGeneratorCollection feedGenerators) { - switch (feedType) - { - case ProductFeedType.GoogleMerchantCenter: - return _serviceProvider.GetRequiredService(); - - default: - throw new InvalidOperationException($"Invalid feed type: {feedType}"); - } + _feedGenerators = feedGenerators; + } + public IProductFeedGeneratorService GetGenerator(Guid feedGeneratorId) + { + IProductFeedGeneratorService feedGenerator = _feedGenerators.FirstOrDefault(p => p.Id == feedGeneratorId) + ?? throw new InvalidOperationException($"Feed generator not found. id: {feedGeneratorId}"); + return feedGenerator; } + + [Obsolete("Will be removed in v17. Use feedGeneratorId instead.")] + public IProductFeedGeneratorService GetGenerator(ProductFeedType feedType) + => GetGenerator(new Guid("101AE565-038F-443E-A29E-4FE0C7146C4A")); // Use the Google Merchant Center Feed ID as default } } diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/IProductFeedSettingsService.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/IProductFeedSettingsService.cs index 3c3a7dc..b89dcc7 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/IProductFeedSettingsService.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/IProductFeedSettingsService.cs @@ -2,9 +2,25 @@ namespace Umbraco.Commerce.ProductFeeds.Core.Features.FeedSettings.Application { public interface IProductFeedSettingsService { + /// + /// Delete product feed setting by the given id. + /// + /// + /// Task DeleteSettingAsync(Guid id); + + /// + /// Find product feed setting by the given parameters. + /// + /// + /// Task FindSettingAsync(FindSettingParams findSettingParams); + /// + /// Get list of product feed settings for the given store id. + /// + /// + /// Task> GetListAsync(Guid storeId); /// diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedSettingReadModel.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedSettingReadModel.cs index 6b58a28..5c5a441 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedSettingReadModel.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedSettingReadModel.cs @@ -2,17 +2,20 @@ namespace Umbraco.Commerce.ProductFeeds.Core.Features.FeedSettings.Application { - public class ProductFeedSettingReadModel { public Guid Id { get; set; } + public required Guid FeedGeneratorId { get; set; } + + public required string FeedName { get; set; } + + [Obsolete("Will be removed in 17.")] public ProductFeedType FeedType { get; set; } + [Obsolete("Will be removed in 17.")] public string FeedTypeName => FeedType.GetDescription(); - public required string FeedName { get; set; } - public required string FeedDescription { get; set; } public required Guid StoreId { get; set; } diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedSettingWriteModel.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedSettingWriteModel.cs index 372a791..368a5cb 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedSettingWriteModel.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedSettingWriteModel.cs @@ -6,10 +6,13 @@ public class ProductFeedSettingWriteModel public required string FeedRelativePath { get; set; } - public ProductFeedType? FeedType { get; set; } + public required string FeedGeneratorId { get; set; } public required string FeedName { get; set; } + [Obsolete("Will be removed in v17. Migrate to Feed Generator Id.")] + public ProductFeedType? FeedType { get; set; } + public required string FeedDescription { get; set; } public required Guid StoreId { get; set; } diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedSettingWriteModelValidator.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedSettingWriteModelValidator.cs index 8469b7f..cd38d7d 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedSettingWriteModelValidator.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedSettingWriteModelValidator.cs @@ -11,7 +11,7 @@ public ProductFeedSettingWriteModelValidator() RuleFor(x => x.FeedName).NotEmpty().WithName("Feed Name"); RuleFor(x => x.FeedRelativePath).NotEmpty().WithName("Feed Relative Path"); RuleFor(x => x.FeedDescription).MaximumLength(MaximumStringLength).WithName("Feed Description"); - RuleFor(x => x.FeedType).NotEmpty().WithName("Feed Type"); + RuleFor(x => x.FeedGeneratorId).NotEmpty().WithName("Feed Generator Id"); RuleFor(x => x.StoreId).NotEmpty().WithName("Umbraco Commerce Store"); RuleFor(x => x.ProductRootId).NotEmpty().WithName("Product Root"); RuleFor(x => x.ProductDocumentTypeIds).NotEmpty().WithName("Product Document Types"); diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedType.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedType.cs index 66eb84a..eea2afe 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedType.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/FeedSettings/Application/ProductFeedType.cs @@ -2,6 +2,7 @@ namespace Umbraco.Commerce.ProductFeeds.Core.Features.FeedSettings.Application { + [Obsolete("Will be removed in v17. Migrate to Feed Generator Id.")] public enum ProductFeedType { [Description("Google Merchant Center Feed")] diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/PropertyValueExtractors/Application/IMultipleValuePropertyExtractorFactory.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/PropertyValueExtractors/Application/IMultipleValuePropertyExtractorFactory.cs index e1b345a..f7525ec 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Core/Features/PropertyValueExtractors/Application/IMultipleValuePropertyExtractorFactory.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/PropertyValueExtractors/Application/IMultipleValuePropertyExtractorFactory.cs @@ -3,7 +3,7 @@ namespace Umbraco.Commerce.ProductFeeds.Core.Features.PropertyValueExtractors.Ap public interface IMultipleValuePropertyExtractorFactory { /// - /// Try to get the property extractor. Returns the default extractor implementation if no extractor id is provided. + /// Try to get the property extractor. /// /// /// The located value extractor. It can be null if no extractor was found. diff --git a/src/Umbraco.Commerce.ProductFeeds.Core/Features/PropertyValueExtractors/Application/ISingleValuePropertyExtractor.cs b/src/Umbraco.Commerce.ProductFeeds.Core/Features/PropertyValueExtractors/Application/ISingleValuePropertyExtractor.cs index 2924964..b0a5677 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Core/Features/PropertyValueExtractors/Application/ISingleValuePropertyExtractor.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Core/Features/PropertyValueExtractors/Application/ISingleValuePropertyExtractor.cs @@ -8,7 +8,7 @@ namespace Umbraco.Commerce.ProductFeeds.Core.Features.PropertyValueExtractors.Ap public interface ISingleValuePropertyExtractor { /// - /// Returns the value extractor id. Must be unique. + /// Returns the value extractor id. Must be unique among the property value extractors. /// public string Id { get; } diff --git a/src/Umbraco.Commerce.ProductFeeds.Infrastructure/DbModels/UmbracoCommerceProductFeedSetting.cs b/src/Umbraco.Commerce.ProductFeeds.Infrastructure/DbModels/UmbracoCommerceProductFeedSetting.cs index fb5f6b5..857be30 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Infrastructure/DbModels/UmbracoCommerceProductFeedSetting.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Infrastructure/DbModels/UmbracoCommerceProductFeedSetting.cs @@ -8,7 +8,10 @@ public class UmbracoCommerceProductFeedSetting { public Guid Id { get; set; } = Guid.NewGuid(); - public string FeedType { get; set; } = string.Empty; + [Obsolete("Will be removed in v17. Migrate to Feed Generator Id.")] + public string? FeedType { get; set; } + + public Guid FeedGeneratorId { get; set; } /// /// Feed URL segment. diff --git a/src/Umbraco.Commerce.ProductFeeds.Infrastructure/DtoMappings/InfrastructureMappingProfile.cs b/src/Umbraco.Commerce.ProductFeeds.Infrastructure/DtoMappings/InfrastructureMappingProfile.cs index cf9b607..e22d1e0 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Infrastructure/DtoMappings/InfrastructureMappingProfile.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Infrastructure/DtoMappings/InfrastructureMappingProfile.cs @@ -16,6 +16,7 @@ public InfrastructureMappingProfile() .ForMember(dest => dest.ProductDocumentTypeIds, opt => opt.MapFrom((src, dest) => string.Join(';', src.ProductDocumentTypeIds))); CreateMap() + .ForMember(dest => dest.FeedType, opt => opt.MapFrom((src, dest) => Enum.Parse(src.FeedType ?? ProductFeedType.GoogleMerchantCenter.ToString()))) // TODO - v17: Remove .ForMember(dest => dest.PropertyNameMappings, opt => opt.MapFrom((src, dest) => JsonSerializer.Deserialize>(src.ProductPropertyNameMappings))) .ForMember(dest => dest.ProductChildVariantTypeIds, opt => opt.MapFrom((src, dest) => !string.IsNullOrEmpty(src.ProductChildVariantTypeIds) ? src.ProductChildVariantTypeIds?.Split(';') : [])) .ForMember(dest => dest.ProductDocumentTypeIds, opt => opt.MapFrom((src, dest) => !string.IsNullOrEmpty(src.ProductDocumentTypeIds) ? src.ProductDocumentTypeIds.Split(';') : [])); diff --git a/src/Umbraco.Commerce.ProductFeeds.Infrastructure/Implementations/ProductFeedSettingsService.cs b/src/Umbraco.Commerce.ProductFeeds.Infrastructure/Implementations/ProductFeedSettingsService.cs index 2845c40..6939768 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Infrastructure/Implementations/ProductFeedSettingsService.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Infrastructure/Implementations/ProductFeedSettingsService.cs @@ -3,7 +3,7 @@ using Microsoft.Data.SqlClient; using Microsoft.Extensions.Logging; using Umbraco.Cms.Infrastructure.Scoping; -using Umbraco.Cms.Web.Common; +using Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Implementations; using Umbraco.Commerce.ProductFeeds.Core.Features.FeedSettings.Application; using Umbraco.Commerce.ProductFeeds.Infrastructure.DbModels; @@ -14,18 +14,18 @@ internal class ProductFeedSettingsService : IProductFeedSettingsService private readonly IScopeProvider _scopeProvider; private readonly IMapper _mapper; private readonly ILogger _logger; - private readonly UmbracoHelper _umbracoHelper; + private readonly FeedGeneratorCollection _feedGenerators; public ProductFeedSettingsService( IScopeProvider scopeProvider, IMapper mapper, ILogger logger, - UmbracoHelper umbracoHelper) + FeedGeneratorCollection feedGenerators) { _scopeProvider = scopeProvider; _mapper = mapper; _logger = logger; - _umbracoHelper = umbracoHelper; + _feedGenerators = feedGenerators; } /// @@ -33,57 +33,53 @@ public ProductFeedSettingsService( { ArgumentNullException.ThrowIfNull(findSettingParams); - using (IScope scope = _scopeProvider.CreateScope()) - { - UmbracoCommerceProductFeedSetting? feedSetting = await scope - .Database - .SingleOrDefaultAsync( - @" + using IScope scope = _scopeProvider.CreateScope(); + UmbracoCommerceProductFeedSetting? feedSetting = await scope + .Database + .SingleOrDefaultAsync( + @" select * from umbracoCommerceProductFeedSetting where( @0 IS NULL OR feedRelativePath = @0) AND (@1 IS NULL OR id = @1)", - findSettingParams.FeedRelativePath, - findSettingParams.Id) - .ConfigureAwait(false); - scope.Complete(); - - if (feedSetting == null) - { - return null; - } + findSettingParams.FeedRelativePath, + findSettingParams.Id) + .ConfigureAwait(false); + scope.Complete(); - if (!Enum.TryParse(feedSetting.FeedType, true, out ProductFeedType feedType)) - { - throw new InvalidOperationException($"Unknown feed type: '{feedSetting.FeedType}'."); - } + if (feedSetting == null) + { + return null; + } - ProductFeedSettingReadModel readModel = _mapper.Map(feedSetting); - return readModel; + if (!_feedGenerators.Any(p => p.Id == feedSetting.FeedGeneratorId)) + { + throw new InvalidOperationException($"Unknown feed generator detected. Id: '{feedSetting.FeedGeneratorId}'."); } + + ProductFeedSettingReadModel readModel = _mapper.Map(feedSetting); + return readModel; } public async Task> GetListAsync(Guid storeId) { - using (IScope scope = _scopeProvider.CreateScope()) - { - List settings = await scope - .Database - .FetchAsync( - @" + using IScope scope = _scopeProvider.CreateScope(); + List settings = await scope + .Database + .FetchAsync( + @" select * from umbracoCommerceProductFeedSetting where storeId = @0", storeId) - .ConfigureAwait(false); - scope.Complete(); + .ConfigureAwait(false); + scope.Complete(); - if (settings == null) - { - return []; - } - - return _mapper.Map>(settings); + if (settings == null) + { + return []; } + + return _mapper.Map>(settings); } /// @@ -93,27 +89,25 @@ from umbracoCommerceProductFeedSetting try { - using (IScope scope = _scopeProvider.CreateScope()) + using IScope scope = _scopeProvider.CreateScope(); + if (input.Id == null) { - if (input.Id == null) - { - // add mode - dbModel.Id = Guid.NewGuid(); - _ = await scope.Database.InsertAsync(dbModel).ConfigureAwait(false); - } - else + // add mode + dbModel.Id = Guid.NewGuid(); + _ = await scope.Database.InsertAsync(dbModel).ConfigureAwait(false); + } + else + { + // edit mode + int affectedRowCount = await scope.Database.UpdateAsync(dbModel).ConfigureAwait(false); + if (affectedRowCount != 1) { - // edit mode - int affectedRowCount = await scope.Database.UpdateAsync(dbModel).ConfigureAwait(false); - if (affectedRowCount != 1) - { - return null; - } + return null; } - - scope.Complete(); - return dbModel.Id; } + + scope.Complete(); + return dbModel.Id; } catch (SqlException ex) { @@ -127,16 +121,14 @@ public async Task DeleteSettingAsync(Guid id) { try { - using (IScope scope = _scopeProvider.CreateScope()) + using IScope scope = _scopeProvider.CreateScope(); + int affectedRowCount = await scope.Database.DeleteAsync(new UmbracoCommerceProductFeedSetting { - int affectedRowCount = await scope.Database.DeleteAsync(new UmbracoCommerceProductFeedSetting - { - Id = id, - }).ConfigureAwait(false); - scope.Complete(); + Id = id, + }).ConfigureAwait(false); + scope.Complete(); - return affectedRowCount == 1; - } + return affectedRowCount == 1; } catch (SqlException ex) { diff --git a/src/Umbraco.Commerce.ProductFeeds.Infrastructure/Migrations/16.1.0_Add_FeedType_FeedGeneratorId.cs b/src/Umbraco.Commerce.ProductFeeds.Infrastructure/Migrations/16.1.0_Add_FeedType_FeedGeneratorId.cs new file mode 100644 index 0000000..ab8a43e --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Infrastructure/Migrations/16.1.0_Add_FeedType_FeedGeneratorId.cs @@ -0,0 +1,118 @@ +using Microsoft.Extensions.Logging; +using NPoco; +using NPoco.DatabaseTypes; +using Umbraco.Cms.Infrastructure.Migrations; +using Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations; + +namespace Umbraco.Commerce.ProductFeeds.Infrastructure.Migrations +{ + [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "")] + internal class Add_FeedType_FeedGeneratorId_16_1_0 : AsyncMigrationBase + { + public Add_FeedType_FeedGeneratorId_16_1_0(IMigrationContext context) + : base(context) + { + } + + protected override Task MigrateAsync() + { + const string tableName = "umbracoCommerceProductFeedSetting"; + + Logger.LogDebug("Altering table [{DbTable}].", tableName); + if (base.DatabaseType == DatabaseType.SQLite) + { + Logger.LogDebug("Running migration for SQLite db"); + if (TableExists(tableName)) + { + Logger.LogDebug("Drop existing table [{DbTable}].", tableName); + Delete.Table(tableName).Do(); + } + + Logger.LogDebug("Re-creating table [{DbTable}].", tableName); + Create.Table().Do(); + } + else if (Context.SqlContext.DatabaseType is not SQLiteDatabaseType) + { + if (!ColumnExists(tableName, "feedGeneratorId")) + { + Alter.Table(tableName) + .AddColumn("feedGeneratorId") + .AsGuid() + .Nullable() + .Do(); + + Update.Table(tableName) + .Set(new + { + feedGeneratorId = new Guid("101AE565-038F-443E-A29E-4FE0C7146C4A"), // Google Merchant Center Feed Service Id + }) + .AllRows() + .Do(); + } + + if (ColumnExists(tableName, "feedType")) + { + Alter.Table(tableName) + .AlterColumn("feedType") // TODO - v17: Drop column + .AsString() + .Nullable() + .Do(); + } + } + + return Task.CompletedTask; + } + + [TableName("umbracoCommerceProductFeedSetting")] + [PrimaryKey("id", AutoIncrement = false)] + public class UmbracoCommerceProductFeedSettingSchema_16_1_0 + { + [Column("id")] + public Guid Id { get; set; } + + [Column("feedType")] + [NullSetting(NullSetting = NullSettings.Null)] + public string? FeedType { get; set; } // TODO - v17: drop column + + [Column("feedGeneratorId")] + public Guid FeedGeneratorId { get; set; } + + [Column("feedRelativePath")] + public required string FeedRelativePath { get; set; } + + [Column("feedName")] + public required string FeedName { get; set; } + + [Column("feedDescription")] + [NullSetting(NullSetting = NullSettings.Null)] + public string? FeedDescription { get; set; } + + [Column("productDocumentTypeIds")] + [NullSetting(NullSetting = NullSettings.Null)] + [SpecialDbType(SpecialDbTypes.NVARCHARMAX)] + public string? ProductDocumentTypeIds { get; set; } + + [Column("productChildVariantTypeAlias")] + [NullSetting(NullSetting = NullSettings.Null)] + [SpecialDbType(SpecialDbTypes.NVARCHARMAX)] + public string? ProductChildVariantTypeAlias { get; set; } + + [Column("productChildVariantTypeIds")] + [NullSetting(NullSetting = NullSettings.Null)] + [SpecialDbType(SpecialDbTypes.NVARCHARMAX)] + public string? ProductChildVariantTypeIds { get; set; } + + [Column("productRootId")] + public required Guid ProductRootId { get; set; } + + [Column("storeId")] + public required Guid StoreId { get; set; } + + [Column("productPropertyNameMappings")] + [SpecialDbType(SpecialDbTypes.NVARCHARMAX)] + public required string ProductPropertyNameMappings { get; set; } + + public bool IncludeTaxInPrice { get; set; } + } + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Infrastructure/Migrations/RunDbMigrations.cs b/src/Umbraco.Commerce.ProductFeeds.Infrastructure/Migrations/RunDbMigrations.cs index cfce09a..debb615 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Infrastructure/Migrations/RunDbMigrations.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Infrastructure/Migrations/RunDbMigrations.cs @@ -50,7 +50,8 @@ public async Task HandleAsync(UmbracoApplicationStartingNotification notificatio .To("1.0.4") .To("1.0.5") .To("13.1.0") - .To("14.1.0"); + .To("14.1.0") + .To("16.1.0"); // Go and upgrade our site (Will check if it needs to do the work or not) // Based on the current/latest step diff --git a/src/Umbraco.Commerce.ProductFeeds.Startup/Initializations/CustomRouting.cs b/src/Umbraco.Commerce.ProductFeeds.Startup/Initializations/CustomRouting.cs index 9566494..dcfc8a0 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Startup/Initializations/CustomRouting.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Startup/Initializations/CustomRouting.cs @@ -13,7 +13,7 @@ public void CreateRoutes(IEndpointRouteBuilder endpoints) => endpoints.MapContro new { controller = "ProductFeed", - Action = "Xml", + Action = "Generate", }); } } diff --git a/src/Umbraco.Commerce.ProductFeeds.Startup/Initializations/IUmbracoCommerceBuilderExtensions.cs b/src/Umbraco.Commerce.ProductFeeds.Startup/Initializations/IUmbracoCommerceBuilderExtensions.cs index de159ef..0108033 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Startup/Initializations/IUmbracoCommerceBuilderExtensions.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Startup/Initializations/IUmbracoCommerceBuilderExtensions.cs @@ -42,6 +42,8 @@ public static IUmbracoCommerceBuilder AddCommerceProductFeeds(this IUmbracoComme public static MultipleValuePropertyExtractorCollectionBuilder MultipleValuePropertyExtractors(this IUmbracoCommerceBuilder builder) => builder.WithUmbracoBuilder().WithCollectionBuilder(); + public static FeedGeneratorCollectionBuilder FeedGenerators(this IUmbracoCommerceBuilder builder) => builder.WithUmbracoBuilder().WithCollectionBuilder(); + private static IUmbracoCommerceBuilder AddDbMigrations(this IUmbracoCommerceBuilder builder) { builder.WithUmbracoBuilder().AddNotificationAsyncHandler(); @@ -57,12 +59,17 @@ private static IUmbracoCommerceBuilder AddAutoMapper(this IUmbracoCommerceBuilde private static void AddServices(this IUmbracoCommerceBuilder builder) { IServiceCollection services = builder.Services; - services.AddScoped(); - services.AddScoped(); + services.AddScoped(sp => + { + return new ProductFeedGeneratorFactory(sp.GetRequiredService()); // TODO - v17: remove this explicit construction + }); services.AddScoped(); services.AddScoped(); + builder.FeedGenerators() + .Append(); + builder.SingleValuePropertyExtractors() .Append() .Append() diff --git a/src/Umbraco.Commerce.ProductFeeds.Startup/Swaggers/AddApiVersionToOperationIdFilter.cs b/src/Umbraco.Commerce.ProductFeeds.Startup/Swaggers/AddApiVersionToOperationIdFilter.cs new file mode 100644 index 0000000..257893e --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Startup/Swaggers/AddApiVersionToOperationIdFilter.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace Umbraco.Commerce.ProductFeeds.Startup.Swaggers +{ + internal class AddApiVersionToOperationIdFilter : IOperationFilter + { + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + Asp.Versioning.ApiVersion? version = context.ApiDescription.GetApiVersion(); // typically "v1", "v2", etc. + + if (version != null && version.MajorVersion > 1) + { + operation.OperationId += $"_v{version.MajorVersion ?? 1}"; + } + } + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Startup/Swaggers/ProductFeedsConfigureSwaggerGenOptions.cs b/src/Umbraco.Commerce.ProductFeeds.Startup/Swaggers/ProductFeedsConfigureSwaggerGenOptions.cs index 4a4a1eb..573b158 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Startup/Swaggers/ProductFeedsConfigureSwaggerGenOptions.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Startup/Swaggers/ProductFeedsConfigureSwaggerGenOptions.cs @@ -18,6 +18,7 @@ public void Configure(SwaggerGenOptions options) }); options.OperationFilter(); + options.OperationFilter(); } } } diff --git a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Lookups/GetDocumentTypesLookupController.cs b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Lookups/GetDocumentTypesLookupController.cs new file mode 100644 index 0000000..3095631 --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Lookups/GetDocumentTypesLookupController.cs @@ -0,0 +1,46 @@ +using System.Linq; +using Asp.Versioning; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Common.Attributes; +using Umbraco.Cms.Api.Management.Controllers; +using Umbraco.Cms.Core.Services; +using Umbraco.Commerce.Cms.Authorization; +using Umbraco.Commerce.ProductFeeds.Core.Common.Constants; + +namespace Umbraco.Commerce.ProductFeeds.Web.Apis.Backoffice.Controllers.Lookups +{ + [ApiVersion("2.0")] + [MapToApi(RouteParams.ApiName)] + [ProductFeedsVersionedApiBackofficeRoute("setting")] + [ApiExplorerSettings(GroupName = "Settings")] + [Authorize(UmbracoCommerceAuthorizationPolicies.SectionAccessCommerce)] + public class GetDocumentTypesLookupController : ManagementApiControllerBase + { + private readonly IContentTypeService _contentTypeService; + + public GetDocumentTypesLookupController(IContentTypeService contentTypeService) + { + _contentTypeService = contentTypeService; + } + + [HttpGet("documenttypes")] + public IActionResult GetDocumentTypes() + { + var aliases = _contentTypeService + .GetAll() + .Select(x => new + { + x.Id, + x.Icon, + x.Name, + x.Description, + x.Key, + x.Alias, + }) + .OrderBy(x => x.Name); + + return Ok(aliases); + } + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Lookups/GetFeedTypesLookupController.cs b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Lookups/GetFeedTypesLookupController.cs new file mode 100644 index 0000000..6da91d1 --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Lookups/GetFeedTypesLookupController.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.Linq; +using Asp.Versioning; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Common.Attributes; +using Umbraco.Cms.Api.Management.Controllers; +using Umbraco.Commerce.Cms.Authorization; +using Umbraco.Commerce.ProductFeeds.Core.Common.Constants; +using Umbraco.Commerce.ProductFeeds.Core.Features.FeedGenerators.Implementations; +using Umbraco.Commerce.ProductFeeds.Web.Apis.Backoffice.Controllers.Models; + +namespace Umbraco.Commerce.ProductFeeds.Web.Apis.Backoffice.Controllers.Lookups +{ + [ApiVersion("2.0")] + [MapToApi(RouteParams.ApiName)] + [ProductFeedsVersionedApiBackofficeRoute("setting")] + [ApiExplorerSettings(GroupName = "Settings")] + [Authorize(UmbracoCommerceAuthorizationPolicies.SectionAccessCommerce)] + public class GetFeedTypesLookupController : ManagementApiControllerBase + { + private readonly FeedGeneratorCollection _feedGenerators; + + public GetFeedTypesLookupController(FeedGeneratorCollection feedGenerators) + { + _feedGenerators = feedGenerators; + } + + [HttpGet("feedgenerators")] + public ActionResult> GetFeedGenerators() + { + return Ok(_feedGenerators.Select(x => new LookupReadModel { Value = x.Id.ToString(), Label = x.DisplayName })); + } + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Lookups/GetPropertyValueExtractorsLookupController.cs b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Lookups/GetPropertyValueExtractorsLookupController.cs new file mode 100644 index 0000000..bf8657a --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Lookups/GetPropertyValueExtractorsLookupController.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Linq; +using Asp.Versioning; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Common.Attributes; +using Umbraco.Cms.Api.Management.Controllers; +using Umbraco.Commerce.Cms.Authorization; +using Umbraco.Commerce.ProductFeeds.Core.Common.Constants; +using Umbraco.Commerce.ProductFeeds.Core.Features.PropertyValueExtractors.Implementations; +using Umbraco.Commerce.ProductFeeds.Web.Apis.Backoffice.Controllers.Models; + +namespace Umbraco.Commerce.ProductFeeds.Web.Apis.Backoffice.Controllers.Lookups +{ + [ApiVersion("2.0")] + [MapToApi(RouteParams.ApiName)] + [ProductFeedsVersionedApiBackofficeRoute("setting")] + [ApiExplorerSettings(GroupName = "Settings")] + [Authorize(UmbracoCommerceAuthorizationPolicies.SectionAccessCommerce)] + public class GetPropertyValueExtractorsLookupController : ManagementApiControllerBase + { + private readonly SingleValuePropertyExtractorCollection _singleValuePropertyExtractors; + private readonly MultipleValuePropertyExtractorCollection _multipleValuePropertyExtractors; + + public GetPropertyValueExtractorsLookupController( + SingleValuePropertyExtractorCollection singleValuePropertyExtractors, + MultipleValuePropertyExtractorCollection multipleValuePropertyExtractors) + { + _singleValuePropertyExtractors = singleValuePropertyExtractors; + _multipleValuePropertyExtractors = multipleValuePropertyExtractors; + } + + [HttpGet("propertyvalueextractors")] + public ActionResult> GetPropertyValueExtractors() + { + return Ok(_singleValuePropertyExtractors.Select(x => new LookupReadModel { Value = x.Id, Label = x.DisplayName }) + .Concat(_multipleValuePropertyExtractors.Select(x => new LookupReadModel { Value = x.Id, Label = x.DisplayName }))); + } + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Models/LookupReadModel.cs b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Lookups/Models/LookupReadModel.cs similarity index 100% rename from src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Models/LookupReadModel.cs rename to src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/Lookups/Models/LookupReadModel.cs diff --git a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettingController.cs b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettingController.cs index 246aca2..1514554 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettingController.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettingController.cs @@ -21,6 +21,7 @@ namespace Umbraco.Commerce.ProductFeeds.Web.Apis.Backoffice.Controllers { + [Obsolete("Will be removed in v17. Use single action controllers instead.")] [ApiVersion("1.0")] [MapToApi(RouteParams.ApiName)] [ProductFeedsVersionedApiBackofficeRoute("setting")] diff --git a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettings/DeleteProductFeedSettingsController.cs b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettings/DeleteProductFeedSettingsController.cs new file mode 100644 index 0000000..36aa43c --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettings/DeleteProductFeedSettingsController.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Asp.Versioning; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Common.Attributes; +using Umbraco.Cms.Api.Management.Controllers; +using Umbraco.Commerce.Cms.Authorization; +using Umbraco.Commerce.ProductFeeds.Core.Common.Constants; +using Umbraco.Commerce.ProductFeeds.Core.Features.FeedSettings.Application; + +namespace Umbraco.Commerce.ProductFeeds.Web.Apis.Backoffice.Controllers.ProductFeedSettings +{ + [ApiVersion("2.0")] + [MapToApi(RouteParams.ApiName)] + [ProductFeedsVersionedApiBackofficeRoute("setting")] + [ApiExplorerSettings(GroupName = "Settings")] + [Authorize(UmbracoCommerceAuthorizationPolicies.SectionAccessCommerce)] + public class DeleteProductFeedSettingsController : ManagementApiControllerBase + { + private readonly IProductFeedSettingsService _feedSettingsService; + + public DeleteProductFeedSettingsController(IProductFeedSettingsService feedSettingsService) + { + _feedSettingsService = feedSettingsService; + } + + [Route("delete")] + [HttpPost] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task Delete([FromForm] ICollection ids) + { + IEnumerable> deleteTasks = ids.Select(_feedSettingsService.DeleteSettingAsync); + + bool[] results = await Task.WhenAll(deleteTasks); + bool success = results.All(success => success); + if (!success) + { + return Problem("Some errors occurred, the data may not be deleted properly. Please check the server log.", statusCode: (int)HttpStatusCode.InternalServerError); + } + + return Ok(success); + } + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettings/GetProductFeedSettingByIdController.cs b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettings/GetProductFeedSettingByIdController.cs new file mode 100644 index 0000000..068863e --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettings/GetProductFeedSettingByIdController.cs @@ -0,0 +1,45 @@ +using System; +using System.Threading.Tasks; +using Asp.Versioning; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Common.Attributes; +using Umbraco.Cms.Api.Management.Controllers; +using Umbraco.Commerce.Cms.Authorization; +using Umbraco.Commerce.ProductFeeds.Core.Common.Constants; +using Umbraco.Commerce.ProductFeeds.Core.Features.FeedSettings.Application; + +namespace Umbraco.Commerce.ProductFeeds.Web.Apis.Backoffice.Controllers.ProductFeedSettings +{ + [ApiVersion("2.0")] + [MapToApi(RouteParams.ApiName)] + [ProductFeedsVersionedApiBackofficeRoute("setting")] + [ApiExplorerSettings(GroupName = "Settings")] + [Authorize(UmbracoCommerceAuthorizationPolicies.SectionAccessCommerce)] + public class GetProductFeedSettingByIdController : ManagementApiControllerBase + { + private readonly IProductFeedSettingsService _feedSettingsService; + + public GetProductFeedSettingByIdController(IProductFeedSettingsService feedSettingsService) + { + _feedSettingsService = feedSettingsService; + } + + [HttpGet("get/{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task GetDetails(Guid id) + { + ProductFeedSettingReadModel? feedSetting = await _feedSettingsService + .FindSettingAsync(new FindSettingParams { Id = id }) + .ConfigureAwait(true); + if (feedSetting == null) + { + return NotFound($"Couldn't find the feed setting with id = '{id}'."); + } + + return Ok(feedSetting); + } + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettings/GetProductFeedSettingByStoreController.cs b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettings/GetProductFeedSettingByStoreController.cs new file mode 100644 index 0000000..b16d3d7 --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettings/GetProductFeedSettingByStoreController.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Asp.Versioning; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Umbraco.Cms.Api.Common.Attributes; +using Umbraco.Cms.Api.Management.Controllers; +using Umbraco.Commerce.Cms.Authorization; +using Umbraco.Commerce.ProductFeeds.Core.Common.Constants; +using Umbraco.Commerce.ProductFeeds.Core.Features.FeedSettings.Application; + +namespace Umbraco.Commerce.ProductFeeds.Web.Apis.Backoffice.Controllers.ProductFeedSettings +{ + [ApiVersion("2.0")] + [MapToApi(RouteParams.ApiName)] + [ProductFeedsVersionedApiBackofficeRoute("setting")] + [ApiExplorerSettings(GroupName = "Settings")] + [Authorize(UmbracoCommerceAuthorizationPolicies.SectionAccessCommerce)] + public class GetProductFeedSettingByStoreController : ManagementApiControllerBase + { + private readonly IProductFeedSettingsService _feedSettingsService; + + public GetProductFeedSettingByStoreController(IProductFeedSettingsService feedSettingsService) + { + _feedSettingsService = feedSettingsService; + } + + [HttpGet("getbystore")] + public async Task>> GetByStore([FromQuery, BindRequired] Guid storeId) + { + List feedSettings = await _feedSettingsService.GetListAsync(storeId).ConfigureAwait(true); + return Ok(feedSettings); + } + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettings/SaveProductFeedSettingController.cs b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettings/SaveProductFeedSettingController.cs new file mode 100644 index 0000000..2971e65 --- /dev/null +++ b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Backoffice/Controllers/ProductFeedSettings/SaveProductFeedSettingController.cs @@ -0,0 +1,66 @@ +using System; +using System.Net; +using System.Threading.Tasks; +using Asp.Versioning; +using FluentValidation.Results; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Common.Attributes; +using Umbraco.Cms.Api.Management.Controllers; +using Umbraco.Commerce.Cms.Authorization; +using Umbraco.Commerce.ProductFeeds.Core.Common.Constants; +using Umbraco.Commerce.ProductFeeds.Core.Features.FeedSettings.Application; + +namespace Umbraco.Commerce.ProductFeeds.Web.Apis.Backoffice.Controllers.ProductFeedSettings +{ + [ApiVersion("2.0")] + [MapToApi(RouteParams.ApiName)] + [ProductFeedsVersionedApiBackofficeRoute("setting")] + [ApiExplorerSettings(GroupName = "Settings")] + [Authorize(UmbracoCommerceAuthorizationPolicies.SectionAccessCommerce)] + public class SaveProductFeedSettingController : ManagementApiControllerBase + { + private readonly IProductFeedSettingsService _feedSettingsService; + + public SaveProductFeedSettingController(IProductFeedSettingsService feedSettingsService) + { + _feedSettingsService = feedSettingsService; + } + + [HttpPost("save")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task Save(ProductFeedSettingWriteModel? model) + { + if (model == null) + { + return BadRequest("Unable to bind posted data to model."); + } + + var validator = new ProductFeedSettingWriteModelValidator(); + ValidationResult validationResult = await validator.ValidateAsync(model); + + if (!validationResult.IsValid) + { + return BadRequest(validationResult.Errors); + } + + Guid? recordId = await _feedSettingsService.SaveSettingAsync(model); + if (recordId == null) + { + return Problem("Save failed.", statusCode: (int)HttpStatusCode.InternalServerError); + } + + ContentResult actionResult = new() + { + Content = recordId.ToString(), + StatusCode = model.Id.HasValue ? (int)HttpStatusCode.OK : (int)HttpStatusCode.Created, + }; + + return actionResult; + } + } +} diff --git a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Publics/ProductFeedController.cs b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Publics/ProductFeedController.cs index d5f5cfc..6e23d73 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Publics/ProductFeedController.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Publics/ProductFeedController.cs @@ -1,3 +1,5 @@ +using System; +using System.Text.Json; using System.Threading.Tasks; using System.Xml; using Microsoft.AspNetCore.Mvc; @@ -19,21 +21,40 @@ public ProductFeedController( _feedConfigService = feedConfigService; } - public async Task Xml(string path) + public async Task Generate(string path) { ProductFeedSettingReadModel? feedSettings = await _feedConfigService .FindSettingAsync(new FindSettingParams { FeedRelativePath = path }) .ConfigureAwait(true); if (feedSettings == null) { - return NotFound("Unknown feed type."); + return NotFound("Feed not found. Please make sure that you've entered the correct URL."); } - IProductFeedGeneratorService feedGenerator = _feedGeneratorFactory.GetGenerator(feedSettings.FeedType); - XmlDocument feed = await feedGenerator.GenerateFeedAsync(feedSettings); + IProductFeedGeneratorService feedGenerator = _feedGeneratorFactory.GetGenerator(feedSettings.FeedGeneratorId); - var result = new XmlActionResult(feed) { Formatting = Formatting.Indented }; - return result; + switch (feedGenerator.Format) + { + case FeedFormat.Xml: + XmlDocument xmlFeed = await feedGenerator.GenerateXmlFeedAsync(feedSettings); + var result = new XmlActionResult(xmlFeed) { Formatting = Formatting.Indented }; + return result; + + case FeedFormat.Json: + JsonDocument jsonFeed = await feedGenerator.GenerateJsonFeedAsync(feedSettings); + var jsonResult = new JsonResult(jsonFeed.RootElement); + return jsonResult; + + case FeedFormat.Unknown: + default: + return Problem("Unknown feed format."); + } + } + + [Obsolete("Will be removed in v17. Use the Generate method instead.")] + public Task Xml(string path) + { + return Generate(path); } } } diff --git a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Publics/XmlActionResult.cs b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Publics/XmlActionResult.cs index 9db83b9..0c4b6fb 100644 --- a/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Publics/XmlActionResult.cs +++ b/src/Umbraco.Commerce.ProductFeeds.Web/Apis/Publics/XmlActionResult.cs @@ -5,6 +5,7 @@ using System.Xml; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Umbraco.Commerce.ProductFeeds.Core.Common.Exceptions; namespace Umbraco.Commerce.ProductFeeds.Web.Apis.Publics { @@ -48,9 +49,9 @@ public async Task ExecuteResultAsync(ActionContext context) // Async flush await xmlWriter.FlushAsync(); } - catch (Exception ex) + catch (UmbracoCommerceProductFeedsGeneralException ex) { - _logger.Error(ex, "Exception generating the XML response"); + _logger.Error(ex, "An error occurred while generating the XML response."); } } } diff --git a/tests/Umbraco.Commerce.ProductFeeds.Infrastructure.UnitTests/Umbraco.Commerce.ProductFeeds.Infrastructure.UnitTests.csproj b/tests/Umbraco.Commerce.ProductFeeds.Infrastructure.UnitTests/Umbraco.Commerce.ProductFeeds.Infrastructure.UnitTests.csproj index 1d1cf06..85a881d 100644 --- a/tests/Umbraco.Commerce.ProductFeeds.Infrastructure.UnitTests/Umbraco.Commerce.ProductFeeds.Infrastructure.UnitTests.csproj +++ b/tests/Umbraco.Commerce.ProductFeeds.Infrastructure.UnitTests/Umbraco.Commerce.ProductFeeds.Infrastructure.UnitTests.csproj @@ -7,6 +7,7 @@ false true CA1707 + false diff --git a/version.json b/version.json index 5682c37..fa780ae 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "16.0.0", + "version": "16.1.0", "assemblyVersion": { "precision": "build" },