diff --git a/src/Umbraco.Web.UI.Client/devops/icons/index.js b/src/Umbraco.Web.UI.Client/devops/icons/index.js index 0e35e7815c..7829a4d89e 100644 --- a/src/Umbraco.Web.UI.Client/devops/icons/index.js +++ b/src/Umbraco.Web.UI.Client/devops/icons/index.js @@ -124,16 +124,14 @@ const collectDiskIcons = async (icons) => { iconPaths.forEach((path) => { const rawData = readFileSync(path); const svg = rawData.toString(); - const pattern = /\/([^/]+)\.svg$/; + const parsed = pathModule.parse(path); - const match = path.match(pattern); - - if (!match) { - console.log('No match found.'); + if (!parsed) { + console.log('No match found for: ', path); return; } - const SVGFileName = match[1]; + const SVGFileName = parsed.name; const iconFileName = SVGFileName.replace('.svg', ''); const iconName = iconFileName; diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index d2c084279a..24c064470c 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -90,7 +90,7 @@ "eslint-plugin-wc": "^2.1.1", "glob": "^11.0.0", "globals": "^15.8.0", - "lucide-static": "^0.424.0", + "lucide-static": "^0.446.0", "madge": "^8.0.0", "msw": "^1.3.2", "playwright-msw": "^3.0.1", @@ -98,7 +98,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "remark-gfm": "^3.0.1", - "rollup": "^4.21.0", + "rollup": "^4.22.4", "rollup-plugin-esbuild": "^6.1.1", "rollup-plugin-import-css": "^3.5.0", "rollup-plugin-web-worker-loader": "^1.6.1", @@ -4836,9 +4836,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.0.tgz", - "integrity": "sha512-WTWD8PfoSAJ+qL87lE7votj3syLavxunWhzCnx3XFxFiI/BA/r3X7MUM8dVrH8rb2r4AiO8jJsr3ZjdaftmnfA==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", + "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", "cpu": [ "arm" ], @@ -4849,9 +4849,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.0.tgz", - "integrity": "sha512-a1sR2zSK1B4eYkiZu17ZUZhmUQcKjk2/j9Me2IDjk1GHW7LB5Z35LEzj9iJch6gtUfsnvZs1ZNyDW2oZSThrkA==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", + "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", "cpu": [ "arm64" ], @@ -4862,9 +4862,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.0.tgz", - "integrity": "sha512-zOnKWLgDld/svhKO5PD9ozmL6roy5OQ5T4ThvdYZLpiOhEGY+dp2NwUmxK0Ld91LrbjrvtNAE0ERBwjqhZTRAA==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", + "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", "cpu": [ "arm64" ], @@ -4875,9 +4875,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.0.tgz", - "integrity": "sha512-7doS8br0xAkg48SKE2QNtMSFPFUlRdw9+votl27MvT46vo44ATBmdZdGysOevNELmZlfd+NEa0UYOA8f01WSrg==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", + "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", "cpu": [ "x64" ], @@ -4888,9 +4888,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.0.tgz", - "integrity": "sha512-pWJsfQjNWNGsoCq53KjMtwdJDmh/6NubwQcz52aEwLEuvx08bzcy6tOUuawAOncPnxz/3siRtd8hiQ32G1y8VA==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", + "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", "cpu": [ "arm" ], @@ -4901,9 +4901,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.0.tgz", - "integrity": "sha512-efRIANsz3UHZrnZXuEvxS9LoCOWMGD1rweciD6uJQIx2myN3a8Im1FafZBzh7zk1RJ6oKcR16dU3UPldaKd83w==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", + "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", "cpu": [ "arm" ], @@ -4914,9 +4914,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.0.tgz", - "integrity": "sha512-ZrPhydkTVhyeGTW94WJ8pnl1uroqVHM3j3hjdquwAcWnmivjAwOYjTEAuEDeJvGX7xv3Z9GAvrBkEzCgHq9U1w==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", + "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", "cpu": [ "arm64" ], @@ -4927,9 +4927,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.0.tgz", - "integrity": "sha512-cfaupqd+UEFeURmqNP2eEvXqgbSox/LHOyN9/d2pSdV8xTrjdg3NgOFJCtc1vQ/jEke1qD0IejbBfxleBPHnPw==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", + "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", "cpu": [ "arm64" ], @@ -4940,9 +4940,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.0.tgz", - "integrity": "sha512-ZKPan1/RvAhrUylwBXC9t7B2hXdpb/ufeu22pG2psV7RN8roOfGurEghw1ySmX/CmDDHNTDDjY3lo9hRlgtaHg==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", + "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", "cpu": [ "ppc64" ], @@ -4953,9 +4953,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.0.tgz", - "integrity": "sha512-H1eRaCwd5E8eS8leiS+o/NqMdljkcb1d6r2h4fKSsCXQilLKArq6WS7XBLDu80Yz+nMqHVFDquwcVrQmGr28rg==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", + "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", "cpu": [ "riscv64" ], @@ -4966,9 +4966,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.0.tgz", - "integrity": "sha512-zJ4hA+3b5tu8u7L58CCSI0A9N1vkfwPhWd/puGXwtZlsB5bTkwDNW/+JCU84+3QYmKpLi+XvHdmrlwUwDA6kqw==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", + "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", "cpu": [ "s390x" ], @@ -4979,9 +4979,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.0.tgz", - "integrity": "sha512-e2hrvElFIh6kW/UNBQK/kzqMNY5mO+67YtEh9OA65RM5IJXYTWiXjX6fjIiPaqOkBthYF1EqgiZ6OXKcQsM0hg==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", + "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", "cpu": [ "x64" ], @@ -4992,9 +4992,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.0.tgz", - "integrity": "sha512-1vvmgDdUSebVGXWX2lIcgRebqfQSff0hMEkLJyakQ9JQUbLDkEaMsPTLOmyccyC6IJ/l3FZuJbmrBw/u0A0uCQ==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", + "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", "cpu": [ "x64" ], @@ -5005,9 +5005,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.0.tgz", - "integrity": "sha512-s5oFkZ/hFcrlAyBTONFY1TWndfyre1wOMwU+6KCpm/iatybvrRgmZVM+vCFwxmC5ZhdlgfE0N4XorsDpi7/4XQ==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", + "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", "cpu": [ "arm64" ], @@ -5018,9 +5018,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.0.tgz", - "integrity": "sha512-G9+TEqRnAA6nbpqyUqgTiopmnfgnMkR3kMukFBDsiyy23LZvUCpiUwjTRx6ezYCjJODXrh52rBR9oXvm+Fp5wg==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", + "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", "cpu": [ "ia32" ], @@ -5031,9 +5031,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.0.tgz", - "integrity": "sha512-2jsCDZwtQvRhejHLfZ1JY6w6kEuEtfF9nzYsZxzSlNVKDX+DpsDJ+Rbjkm74nvg2rdx0gwBS+IMdvwJuq3S9pQ==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", + "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", "cpu": [ "x64" ], @@ -8150,6 +8150,10 @@ "resolved": "src/packages/documents", "link": true }, + "node_modules/@umbraco-backoffice/embedded-media": { + "resolved": "src/packages/embedded-media", + "link": true + }, "node_modules/@umbraco-backoffice/extension-insights": { "resolved": "src/packages/extension-insights", "link": true @@ -16554,9 +16558,9 @@ } }, "node_modules/lucide-static": { - "version": "0.424.0", - "resolved": "https://registry.npmjs.org/lucide-static/-/lucide-static-0.424.0.tgz", - "integrity": "sha512-KUsIoKeIZF/rc5dttI/bZmd3+zQ/V9YA/G/NsGALA3QWqVncuZsyJ+IrM+jI0BTHiARwVZfp7zOEhc7gqn5x7A==", + "version": "0.446.0", + "resolved": "https://registry.npmjs.org/lucide-static/-/lucide-static-0.446.0.tgz", + "integrity": "sha512-u9IkgI8k7qk738A9rt+JlENM5Sz/18EaEfqTfMEhXy2Sjq1uJA2I1WacVn6wJPXNHzrFpI5BCSmi1GtnGhsVwA==", "dev": true }, "node_modules/lunr": { @@ -20373,9 +20377,9 @@ } }, "node_modules/rollup": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.0.tgz", - "integrity": "sha512-vo+S/lfA2lMS7rZ2Qoubi6I5hwZwzXeUIctILZLbHI+laNtvhhOIon2S1JksA5UEDQ7l3vberd0fxK44lTYjbQ==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", + "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -20388,22 +20392,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.21.0", - "@rollup/rollup-android-arm64": "4.21.0", - "@rollup/rollup-darwin-arm64": "4.21.0", - "@rollup/rollup-darwin-x64": "4.21.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.0", - "@rollup/rollup-linux-arm-musleabihf": "4.21.0", - "@rollup/rollup-linux-arm64-gnu": "4.21.0", - "@rollup/rollup-linux-arm64-musl": "4.21.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.0", - "@rollup/rollup-linux-riscv64-gnu": "4.21.0", - "@rollup/rollup-linux-s390x-gnu": "4.21.0", - "@rollup/rollup-linux-x64-gnu": "4.21.0", - "@rollup/rollup-linux-x64-musl": "4.21.0", - "@rollup/rollup-win32-arm64-msvc": "4.21.0", - "@rollup/rollup-win32-ia32-msvc": "4.21.0", - "@rollup/rollup-win32-x64-msvc": "4.21.0", + "@rollup/rollup-android-arm-eabi": "4.22.4", + "@rollup/rollup-android-arm64": "4.22.4", + "@rollup/rollup-darwin-arm64": "4.22.4", + "@rollup/rollup-darwin-x64": "4.22.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", + "@rollup/rollup-linux-arm-musleabihf": "4.22.4", + "@rollup/rollup-linux-arm64-gnu": "4.22.4", + "@rollup/rollup-linux-arm64-musl": "4.22.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", + "@rollup/rollup-linux-riscv64-gnu": "4.22.4", + "@rollup/rollup-linux-s390x-gnu": "4.22.4", + "@rollup/rollup-linux-x64-gnu": "4.22.4", + "@rollup/rollup-linux-x64-musl": "4.22.4", + "@rollup/rollup-win32-arm64-msvc": "4.22.4", + "@rollup/rollup-win32-ia32-msvc": "4.22.4", + "@rollup/rollup-win32-x64-msvc": "4.22.4", "fsevents": "~2.3.2" } }, @@ -23635,6 +23639,9 @@ "src/packages/documents": { "name": "@umbraco-backoffice/document" }, + "src/packages/embedded-media": { + "name": "@umbraco-backoffice/embedded-media" + }, "src/packages/extension-insights": { "name": "@umbraco-backoffice/extension-insights" }, diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index c45214cfdd..d058a21df1 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -10,6 +10,7 @@ "./context-api": "./dist-cms/libs/context-api/index.js", "./controller-api": "./dist-cms/libs/controller-api/index.js", "./element-api": "./dist-cms/libs/element-api/index.js", + "./embedded-media": "./dist-cms/packages/embedded-media/index.js", "./extension-api": "./dist-cms/libs/extension-api/index.js", "./formatting-api": "./dist-cms/libs/formatting-api/index.js", "./localization-api": "./dist-cms/libs/localization-api/index.js", @@ -94,6 +95,7 @@ "./tiptap": "./dist-cms/packages/rte/tiptap/index.js", "./tree": "./dist-cms/packages/core/tree/index.js", "./ufm": "./dist-cms/packages/ufm/index.js", + "./user-change-password": "./dist-cms/packages/user/change-password/index.js", "./user-group": "./dist-cms/packages/user/user-group/index.js", "./user-permission": "./dist-cms/packages/user/user-permission/index.js", "./user": "./dist-cms/packages/user/user/index.js", @@ -268,7 +270,7 @@ "eslint-plugin-wc": "^2.1.1", "glob": "^11.0.0", "globals": "^15.8.0", - "lucide-static": "^0.424.0", + "lucide-static": "^0.446.0", "madge": "^8.0.0", "msw": "^1.3.2", "playwright-msw": "^3.0.1", @@ -276,7 +278,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "remark-gfm": "^3.0.1", - "rollup": "^4.21.0", + "rollup": "^4.22.4", "rollup-plugin-esbuild": "^6.1.1", "rollup-plugin-import-css": "^3.5.0", "rollup-plugin-web-worker-loader": "^1.6.1", diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts index 036403df06..eee608f8e6 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts @@ -17,6 +17,7 @@ const CORE_PACKAGES = [ import('../../packages/data-type/umbraco-package.js'), import('../../packages/dictionary/umbraco-package.js'), import('../../packages/documents/umbraco-package.js'), + import('../../packages/embedded-media/umbraco-package.js'), import('../../packages/extension-insights/umbraco-package.js'), import('../../packages/health-check/umbraco-package.js'), import('../../packages/help/umbraco-package.js'), diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index b3da05cdf3..eb5bdaf5c7 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -447,8 +447,7 @@ export default { stay: 'Stay', discardChanges: 'Discard changes', unsavedChanges: 'You have unsaved changes', - unsavedChangesWarning: - 'Are you sure you want to navigate away from this page? - you have unsaved\n changes\n ', + unsavedChangesWarning: 'Are you sure you want to navigate away from this page? You have unsaved changes', confirmListViewPublish: 'Publishing will make the selected items visible on the site.', confirmListViewUnpublish: 'Unpublishing will remove the selected items and all their descendants from the\n site.\n ', diff --git a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts index 072eb0592d..b7dd5aa8e8 100644 --- a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts +++ b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts @@ -612,7 +612,7 @@ export type DocumentBlueprintItemResponseModel = { }; export type DocumentBlueprintResponseModel = { - values: Array<(DocumentValueModel)>; + values: Array<(DocumentValueResponseModel)>; variants: Array<(DocumentVariantResponseModel)>; id: string; documentType: (DocumentTypeReferenceResponseModel); @@ -628,7 +628,7 @@ export type DocumentBlueprintTreeItemResponseModel = { }; export type DocumentCollectionResponseModel = { - values: Array<(DocumentValueModel)>; + values: Array<(DocumentValueResponseModel)>; variants: Array<(DocumentVariantResponseModel)>; id: string; creator?: (string) | null; @@ -684,7 +684,7 @@ export type DocumentReferenceResponseModel = { }; export type DocumentResponseModel = { - values: Array<(DocumentValueModel)>; + values: Array<(DocumentValueResponseModel)>; variants: Array<(DocumentVariantResponseModel)>; id: string; documentType: (DocumentTypeReferenceResponseModel); @@ -834,6 +834,14 @@ export type DocumentValueModel = { value?: unknown; }; +export type DocumentValueResponseModel = { + culture?: (string) | null; + segment?: (string) | null; + alias: string; + value?: unknown; + editorAlias: string; +}; + export type DocumentVariantItemResponseModel = { name: string; culture?: (string) | null; @@ -875,7 +883,7 @@ export type DocumentVersionItemResponseModel = { }; export type DocumentVersionResponseModel = { - values: Array<(DocumentValueModel)>; + values: Array<(DocumentValueResponseModel)>; variants: Array<(DocumentVariantResponseModel)>; id: string; documentType: (DocumentTypeReferenceResponseModel); @@ -1156,7 +1164,7 @@ export type ManifestResponseModel = { }; export type MediaCollectionResponseModel = { - values: Array<(MediaValueModel)>; + values: Array<(MediaValueResponseModel)>; variants: Array<(MediaVariantResponseModel)>; id: string; creator?: (string) | null; @@ -1195,7 +1203,7 @@ export type MediaReferenceResponseModel = { }; export type MediaResponseModel = { - values: Array<(MediaValueModel)>; + values: Array<(MediaValueResponseModel)>; variants: Array<(MediaVariantResponseModel)>; id: string; urls: Array<(MediaUrlInfoModel)>; @@ -1325,6 +1333,14 @@ export type MediaValueModel = { value?: unknown; }; +export type MediaValueResponseModel = { + culture?: (string) | null; + segment?: (string) | null; + alias: string; + value?: unknown; + editorAlias: string; +}; + export type MediaVariantRequestModel = { culture?: (string) | null; segment?: (string) | null; @@ -1369,7 +1385,7 @@ export enum MemberKindModel { } export type MemberResponseModel = { - values: Array<(MemberValueModel)>; + values: Array<(MemberValueResponseModel)>; variants: Array<(MemberVariantResponseModel)>; id: string; email: string; @@ -1479,6 +1495,14 @@ export type MemberValueModel = { value?: unknown; }; +export type MemberValueResponseModel = { + culture?: (string) | null; + segment?: (string) | null; + alias: string; + value?: unknown; + editorAlias: string; +}; + export type MemberVariantRequestModel = { culture?: (string) | null; segment?: (string) | null; diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.data.ts index 46a252aeeb..0ca71a3f1c 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.data.ts @@ -36,6 +36,7 @@ export const data: Array = [ ], values: [ { + editorAlias: 'Umbraco.TextBox', alias: 'prop1', culture: null, segment: null, diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.db.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.db.ts index 9166a603dc..9ad279f722 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.db.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.db.ts @@ -12,6 +12,7 @@ import type { DocumentItemResponseModel, DocumentResponseModel, DocumentTreeItemResponseModel, + DocumentValueResponseModel, } from '@umbraco-cms/backoffice/external/backend-api'; export class UmbDocumentBlueprintMockDB extends UmbEntityMockDbBase { @@ -65,7 +66,7 @@ const createMockDocumentBlueprintMapper = (request: CreateDocumentRequestModel): isTrashed: false, noAccess: false, parent: request.parent, - values: request.values, + values: request.values as DocumentValueResponseModel[], variants: request.variants.map((variantRequest) => { return { culture: variantRequest.culture, diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts index cbdce9da9f..6b512da1de 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts @@ -39,6 +39,7 @@ export const data: Array = [ ], values: [ { + editorAlias: 'Umbraco.TextBox', alias: 'prop1', culture: null, segment: null, @@ -66,6 +67,7 @@ export const data: Array = [ isTrashed: false, values: [ { + editorAlias: 'Umbraco.RichText', alias: 'richTextEditor', culture: null, segment: null, @@ -83,6 +85,7 @@ export const data: Array = [ }, }, { + editorAlias: 'Umbraco.TextArea', alias: 'codeEditor', culture: null, segment: null, @@ -113,30 +116,35 @@ export const data: Array = [

`, }, { + editorAlias: 'Umbraco.TextBox', alias: 'email', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.ColorPicker', alias: 'colorPicker', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.MultiNodeTreePicker', alias: 'contentPicker', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.ColorPicker.EyeDropper', alias: 'eyeDropper', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.MultiUrlPicker', alias: 'multiUrlPicker', culture: 'en-US', segment: null, @@ -153,12 +161,14 @@ export const data: Array = [ ], }, { + editorAlias: 'Umbraco.MultiUrlPicker', alias: 'multiUrlPicker', culture: 'da-dk', segment: null, value: null, }, { + editorAlias: 'Umbraco.MultiNodeTreePicker', alias: 'multiNodeTreePicker', culture: null, segment: null, @@ -166,84 +176,98 @@ export const data: Array = [ 'all-property-editors-document-id,c05da24d-7740-447b-9cdc-bd8ce2172e38,fd56a0b5-01a0-4da2-b428-52773bfa9cc4', }, { + editorAlias: 'Umbraco.DateTime', alias: 'datePicker', culture: null, segment: null, value: '2023-12-24', }, { + editorAlias: 'Umbraco.DateTime', alias: 'datePickerTime', culture: null, segment: null, value: '2023-12-24 14:52', }, { + editorAlias: 'Umbraco.DateTime', alias: 'time', culture: null, segment: null, value: '14:52:00', }, { + editorAlias: 'Umbraco.EmailAddress', alias: 'email', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.TextBox', alias: 'textBox', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.DropDown.Flexible', alias: 'dropdown', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.TextArea', alias: 'textArea', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.Slider', alias: 'slider', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.TrueFalse', alias: 'toggle', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.Tags', alias: 'tags', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.MarkdownEditor', alias: 'markdownEditor', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.RadioButtonList', alias: 'radioButtonList', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.CheckBoxList', alias: 'checkboxList', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.BlockList', alias: 'blockList', culture: null, segment: null, @@ -298,12 +322,14 @@ export const data: Array = [ }, }, { + editorAlias: 'Umbraco.MediaPicker3', alias: 'mediaPicker', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.ImageCropper', alias: 'imageCropper', culture: null, segment: null, @@ -384,12 +410,14 @@ export const data: Array = [ }, }, { + editorAlias: 'Umbraco.UploadField', alias: 'uploadField', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.BlockGrid', alias: 'blockGrid', culture: null, segment: null, @@ -473,60 +501,70 @@ export const data: Array = [ }, }, { + editorAlias: 'Umbraco.BlockGrid', alias: 'blockGrid', culture: null, segment: null, value: null, }, { + editorAlias: '', alias: 'numberRange', culture: null, segment: null, value: null, }, { + editorAlias: '', alias: 'orderDirection', culture: null, segment: null, value: null, }, { + editorAlias: '', alias: 'overlaySize', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.Label', alias: 'label', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.Integer', alias: 'integer', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.Decimal', alias: 'decimal', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.MemberPicker', alias: 'memberPicker', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.MemberGroupPicker', alias: 'memberGroupPicker', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.UserPicker', alias: 'userPicker', culture: null, segment: null, @@ -574,60 +612,70 @@ export const data: Array = [ isTrashed: false, values: [ { + editorAlias: 'Umbraco.TextBox', culture: null, segment: null, alias: 'masterText', value: 'i have a master text', }, { + editorAlias: 'Umbraco.TextBox', culture: null, segment: null, alias: 'pageTitle', value: 'with a page title', }, { + editorAlias: 'Umbraco.TextArea', culture: null, segment: null, alias: 'blogPostText', value: 'My first blog post', }, { + editorAlias: 'Umbraco.TextBox', culture: 'en-US', segment: null, alias: 'blogTextStringUnderMasterTab', value: 'in the master tab', }, { + editorAlias: 'Umbraco.TextBox', culture: 'en-US', segment: null, alias: 'blogTextStringUnderGroupUnderMasterTab', value: 'which is under another group in the tab', }, { + editorAlias: 'Umbraco.TextBox', culture: 'da-dk', segment: null, alias: 'blogTextStringUnderMasterTab', value: 'på master dokument tab B', }, { + editorAlias: 'Umbraco.TextBox', culture: 'da-dk', segment: null, alias: 'blogTextStringUnderGroupUnderMasterTab', value: 'denne er under en anden gruppe i tab B', }, { + editorAlias: 'Umbraco.TextBox', culture: 'no-no', segment: null, alias: 'blogTextStringUnderMasterTab', value: 'Norsk på master dokument tab B', }, { + editorAlias: 'Umbraco.TextBox', culture: 'no-no', segment: null, alias: 'blogTextStringUnderGroupUnderMasterTab', value: 'Norsk denne er under en anden gruppe i tab B', }, { + editorAlias: 'Umbraco.TextBox', culture: null, segment: null, alias: 'localBlogTabString', @@ -697,48 +745,56 @@ export const data: Array = [ isTrashed: false, values: [ { + editorAlias: 'Umbraco.TextBox', culture: null, segment: null, alias: 'masterText', value: 'i have a master text B', }, { + editorAlias: 'Umbraco.TextBox', culture: null, segment: null, alias: 'pageTitle', value: 'with a page title B', }, { + editorAlias: 'Umbraco.TextBox', culture: null, segment: null, alias: 'blogPostText', value: 'My first blog post B', }, { + editorAlias: 'Umbraco.TextBox', culture: 'en-US', segment: null, alias: 'blogTextStringUnderMasterTab', value: 'in the master tab B', }, { + editorAlias: 'Umbraco.TextBox', culture: 'en-US', segment: null, alias: 'blogTextStringUnderGroupUnderMasterTab', value: 'which is under another group in the tab B', }, { + editorAlias: 'Umbraco.TextBox', culture: 'da-dk', segment: null, alias: 'blogTextStringUnderMasterTab', value: 'på master dokument tab B', }, { + editorAlias: 'Umbraco.TextBox', culture: 'da-dk', segment: null, alias: 'blogTextStringUnderGroupUnderMasterTab', value: 'denne er under en anden gruppe i tab B', }, { + editorAlias: 'Umbraco.TextBox', culture: null, segment: null, alias: 'localBlogTabString', @@ -789,12 +845,14 @@ export const data: Array = [ ], values: [ { + editorAlias: 'Umbraco.MultiNodeTreePicker', alias: 'multiNodeTreePicker', culture: null, segment: null, value: null, }, { + editorAlias: 'Umbraco.ListView', alias: 'listView', culture: null, segment: null, diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.db.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.db.ts index d9a36ba11b..5cace7dd50 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.db.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.db.ts @@ -18,6 +18,7 @@ import type { DocumentTreeItemResponseModel, DomainsResponseModel, DocumentConfigurationResponseModel, + DocumentValueResponseModel, } from '@umbraco-cms/backoffice/external/backend-api'; export class UmbDocumentMockDB extends UmbEntityMockDbBase { @@ -89,7 +90,8 @@ const createMockDocumentMapper = (request: CreateDocumentRequestModel): UmbMockD isTrashed: false, noAccess: false, parent: request.parent, - values: request.values, + // TODO: Currently trusting we did send the editorAlias to the create end point: + values: request.values as DocumentValueResponseModel[], variants: request.variants.map((variantRequest) => { return { culture: variantRequest.culture, diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/media/media.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/media/media.data.ts index 012ab54620..b6012a0494 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/media/media.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/media/media.data.ts @@ -19,6 +19,7 @@ export const data: Array = [ }, values: [ { + editorAlias: 'Umbraco.TextBox', alias: 'myMediaHeadline', value: 'The daily life at Umbraco HQ', }, @@ -47,6 +48,7 @@ export const data: Array = [ }, values: [ { + editorAlias: 'Umbraco.TextBox', alias: 'myMediaDescription', value: 'Every day, a rabbit in a military costume greets me at the front door', }, @@ -123,6 +125,7 @@ export const data: Array = [ }, values: [ { + editorAlias: 'Umbraco.TextBox', alias: 'myMediaDescription', value: 'Every day, a rabbit in a military costume greets me at the front door', }, @@ -151,6 +154,7 @@ export const data: Array = [ }, values: [ { + editorAlias: 'Umbraco.TextBox', alias: 'myMediaDescription', value: 'Every day, a rabbit in a military costume greets me at the front door', }, @@ -179,6 +183,7 @@ export const data: Array = [ }, values: [ { + editorAlias: 'Umbraco.TextBox', alias: 'myMediaDescription', value: 'Every day, a rabbit in a military costume greets me at the front door', }, @@ -207,6 +212,7 @@ export const data: Array = [ }, values: [ { + editorAlias: 'Umbraco.TextBox', alias: 'myMediaDescription', value: 'Every day, a rabbit in a military costume greets me at the front door', }, diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/media/media.db.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/media/media.db.ts index e0a6337152..f8e81cd0dc 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/media/media.db.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/media/media.db.ts @@ -14,6 +14,7 @@ import type { MediaItemResponseModel, MediaResponseModel, MediaTreeItemResponseModel, + MediaValueResponseModel, } from '@umbraco-cms/backoffice/external/backend-api'; export class UmbMediaMockDB extends UmbEntityMockDbBase { @@ -64,7 +65,8 @@ const createMockMediaMapper = (request: CreateMediaRequestModel): UmbMockMediaMo isTrashed: false, noAccess: false, parent: request.parent, - values: request.values, + // We trust blindly that we send of the editorAlias to the create end point. + values: request.values as MediaValueResponseModel[], variants: request.variants.map((variantRequest) => { return { culture: variantRequest.culture, diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.db.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.db.ts index ca5fb77e98..77f41e2cde 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.db.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.db.ts @@ -11,6 +11,7 @@ import { type CreateMemberRequestModel, type MemberItemResponseModel, type MemberResponseModel, + type MemberValueResponseModel, } from '@umbraco-cms/backoffice/external/backend-api'; class UmbMemberMockDB extends UmbEntityMockDbBase { @@ -46,7 +47,7 @@ const createDetailMockMapper = (request: CreateMemberRequestModel): UmbMockMembe icon: memberType.icon, }, username: request.username, - values: request.values, + values: request.values as MemberValueResponseModel[], variants: request.variants.map((variantRequest) => { return { culture: variantRequest.culture, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.modal-token.ts index a8d866932d..9dd0ee6146 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.modal-token.ts @@ -1,4 +1,4 @@ -import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/workspace'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; // eslint-disable-next-line @typescript-eslint/no-empty-object-type diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts index 0c597e5ded..afc2d9033b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts @@ -29,7 +29,7 @@ export class UmbPropertyEditorUIBlockGridElement extends UmbFormControlMixin(UmbLitElement) implements UmbPropertyEditorUiElement { - #validationContext = new UmbValidationContext(this).provide(); + #validationContext = new UmbValidationContext(this); #contentDataPathTranslator?: UmbBlockElementDataValidationPathTranslator; #settingsDataPathTranslator?: UmbBlockElementDataValidationPathTranslator; #context = new UmbBlockGridManagerContext(this); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts index 19d76caa88..61b344ca99 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts @@ -1,5 +1,5 @@ import { UMB_BLOCK_GRID_TYPE, type UmbBlockGridTypeModel } from '../types.js'; -import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/workspace'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export type UmbBlockGridTypeWorkspaceData = UmbWorkspaceModalData; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-workspace.modal-token.ts index f7c523dffc..2b98a3a097 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-workspace.modal-token.ts @@ -1,5 +1,5 @@ import type { UmbBlockWorkspaceData, UmbBlockWorkspaceOriginData } from '@umbraco-cms/backoffice/block'; -import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/workspace'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbBlockGridWorkspaceOriginData extends UmbBlockWorkspaceOriginData { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index a1823b0d3a..e281b29968 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -53,7 +53,7 @@ export class UmbPropertyEditorUIBlockListElement }, }); - #validationContext = new UmbValidationContext(this).provide(); + #validationContext = new UmbValidationContext(this); #contentDataPathTranslator?: UmbBlockElementDataValidationPathTranslator; #settingsDataPathTranslator?: UmbBlockElementDataValidationPathTranslator; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts index 53154a5743..f41bc152ea 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts @@ -8,7 +8,7 @@ import { type UmbPropertyEditorConfigCollection, } from '@umbraco-cms/backoffice/property-editor'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/workspace/block-list-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/workspace/block-list-workspace.modal-token.ts index ba7b620324..9d920e144f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/workspace/block-list-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/workspace/block-list-workspace.modal-token.ts @@ -1,5 +1,5 @@ import type { UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block'; -import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/workspace'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbBlockListWorkspaceOriginData { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/workspace/block-rte-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/workspace/block-rte-workspace.modal-token.ts index 11a110a595..0c4849d938 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/workspace/block-rte-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/workspace/block-rte-workspace.modal-token.ts @@ -1,5 +1,5 @@ import type { UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block'; -import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/workspace'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; // eslint-disable-next-line @typescript-eslint/no-empty-object-type diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts index cb1f037a1a..294a553c13 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts @@ -7,7 +7,7 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { type UmbClassInterface, UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; -import { UmbValidationContext } from '@umbraco-cms/backoffice/validation'; +import { UmbValidationController } from '@umbraco-cms/backoffice/validation'; export class UmbBlockElementManager extends UmbControllerBase { // @@ -29,7 +29,7 @@ export class UmbBlockElementManager extends UmbControllerBase { new UmbDocumentTypeDetailRepository(this), ); - readonly validation = new UmbValidationContext(this); + readonly validation = new UmbValidationController(this); constructor(host: UmbControllerHost, dataPathPropertyName: string) { super(host); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.modal-token.ts index 84e1aed4a5..ab491e185a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.modal-token.ts @@ -1,4 +1,4 @@ -import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/workspace'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; // eslint-disable-next-line @typescript-eslint/no-empty-object-type diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/code-editor/code-editor-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/code-editor-modal.element.ts similarity index 91% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/common/code-editor/code-editor-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/code-editor-modal.element.ts index bb7126baaf..93f4b59add 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/code-editor/code-editor-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/code-editor-modal.element.ts @@ -1,9 +1,7 @@ +import type { UmbCodeEditorElement } from '../components/code-editor.element.js'; +import type { UmbCodeEditorModalData, UmbCodeEditorModalValue } from './code-editor-modal.token.js'; import { css, html, ifDefined, customElement, query } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; -import type { UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor'; -import type { UmbCodeEditorModalData, UmbCodeEditorModalValue } from '@umbraco-cms/backoffice/modal'; - -import '@umbraco-cms/backoffice/code-editor'; const elementName = 'umb-code-editor-modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/code-editor/code-editor-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/code-editor-modal.stories.ts similarity index 85% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/common/code-editor/code-editor-modal.stories.ts rename to src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/code-editor-modal.stories.ts index 37dd470a28..6d25717e21 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/code-editor/code-editor-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/code-editor-modal.stories.ts @@ -1,8 +1,6 @@ -import '../confirm/confirm-modal.element.js'; - +import type { UmbCodeEditorModalData } from './code-editor-modal.token.js'; import type { Meta, Story } from '@storybook/web-components'; import { html } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbCodeEditorModalData } from '@umbraco-cms/backoffice/modal'; export default { title: 'API/Modals/Layouts/Code Editor', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/code-editor-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/code-editor-modal.token.ts similarity index 91% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/token/code-editor-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/code-editor-modal.token.ts index c62514f2ee..d722df2d8d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/code-editor-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/code-editor-modal.token.ts @@ -1,4 +1,4 @@ -import { UmbModalToken } from './modal-token.js'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; // TODO => investigate why exporting CodeEditorLanguage in code-editor barrel // causes the schema generation task to fail... For now, language property below diff --git a/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/index.ts new file mode 100644 index 0000000000..9c91a9f078 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/index.ts @@ -0,0 +1 @@ +export * from './code-editor-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/manifests.ts new file mode 100644 index 0000000000..027627c4a6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/manifests.ts @@ -0,0 +1,8 @@ +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.CodeEditor', + name: 'Code Editor Modal', + element: () => import('./code-editor-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/code-editor/index.ts b/src/Umbraco.Web.UI.Client/src/packages/code-editor/index.ts index 60335eb6e1..e3fb6a2f7c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/code-editor/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/code-editor/index.ts @@ -1,5 +1,7 @@ export * from './components/index.js'; export * from './models/index.js'; +export * from './code-editor-modal/index.js'; + export type { UmbCodeEditorController } from './code-editor.controller.js'; /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/code-editor/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/code-editor/manifests.ts index 47a0a1f5f3..5992ca6356 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/code-editor/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/code-editor/manifests.ts @@ -1,3 +1,4 @@ import { manifest as propertyEditorManifest } from './property-editor/manifests.js'; +import { manifests as codeEditorModalManifests } from './code-editor-modal/manifests.js'; -export const manifests: Array = [propertyEditorManifest]; +export const manifests: Array = [propertyEditorManifest, ...codeEditorModalManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-tab.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-tab.element.ts index ba77d8394a..3b18576327 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-tab.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-tab.element.ts @@ -6,7 +6,7 @@ import { UmbContentTypeContainerStructureHelper } from '@umbraco-cms/backoffice/ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import type { UmbContentTypeModel, UmbPropertyTypeContainerModel } from '@umbraco-cms/backoffice/content-type'; import type { UmbSorterConfig } from '@umbraco-cms/backoffice/sorter'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/debug/modals/debug/debug-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug-modal/debug-modal.element.ts similarity index 92% rename from src/Umbraco.Web.UI.Client/src/packages/core/debug/modals/debug/debug-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/debug/debug-modal/debug-modal.element.ts index 61837a12e1..1c826202cc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/debug/modals/debug/debug-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug-modal/debug-modal.element.ts @@ -1,7 +1,7 @@ +import type { UmbContextDebuggerModalData } from './debug-modal.token.js'; import { css, customElement, html } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbContextDebuggerModalData } from '@umbraco-cms/backoffice/modal'; @customElement('umb-context-debugger-modal') export default class UmbContextDebuggerModalElement extends UmbModalBaseElement { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/debug-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug-modal/debug-modal.token.ts similarity index 83% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/token/debug-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/debug/debug-modal/debug-modal.token.ts index 9e4c9060b5..391c76d90a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/debug-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug-modal/debug-modal.token.ts @@ -1,4 +1,4 @@ -import { UmbModalToken } from './modal-token.js'; +import { UmbModalToken } from '../../modal/token/modal-token.js'; import type { TemplateResult } from '@umbraco-cms/backoffice/external/lit'; export interface UmbContextDebuggerModalData { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug-modal/index.ts new file mode 100644 index 0000000000..6ae52d2f38 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug-modal/index.ts @@ -0,0 +1 @@ +export * from './debug-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug-modal/manifests.ts new file mode 100644 index 0000000000..b87b948afa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug-modal/manifests.ts @@ -0,0 +1,8 @@ +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.ContextDebugger', + name: 'Context Debugger Modal', + element: () => import('./debug-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug.element.ts index dda8a9297c..418b07fbc9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/debug/debug.element.ts @@ -1,7 +1,8 @@ +import { UMB_CONTEXT_DEBUGGER_MODAL } from './debug-modal/index.js'; import { css, customElement, html, map, nothing, property, state, when } from '@umbraco-cms/backoffice/external/lit'; import { contextData, UmbContextDebugRequest } from '@umbraco-cms/backoffice/context-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_CONTEXT_DEBUGGER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { UmbDebugContextData, UmbDebugContextItemData } from '@umbraco-cms/backoffice/context-api'; import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/debug/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/debug/index.ts index 3aae472235..a542c9a49e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/debug/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/debug/index.ts @@ -1,3 +1,4 @@ -export * from './debug.element.js'; export * from './context-debug.controller.js'; +export * from './debug-modal/index.js'; +export * from './debug.element.js'; export * from './manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/debug/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/debug/manifests.ts index 4cdc6cf2ce..b075c82b50 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/debug/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/debug/manifests.ts @@ -1,8 +1,3 @@ -export const manifests: Array = [ - { - type: 'modal', - alias: 'Umb.Modal.ContextDebugger', - name: 'Context Debugger Modal', - element: () => import('./modals/debug/debug-modal.element.js'), - }, -]; +import { manifests as debugModalManifests } from './debug-modal/manifests.js'; + +export const manifests: Array = [...debugModalManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/delete.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/delete.action.kind.ts index a6a031522e..07995746e6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/delete.action.kind.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/delete.action.kind.ts @@ -16,6 +16,7 @@ export const manifest: UmbExtensionManifestKind = { meta: { icon: 'icon-trash', label: '#actions_delete', + additionalOptions: true, itemRepositoryAlias: '', detailRepositoryAlias: '', }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/duplicate/duplicate.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/duplicate/duplicate.action.kind.ts index 375686b7fe..15ce0cde5e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/duplicate/duplicate.action.kind.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/duplicate/duplicate.action.kind.ts @@ -16,6 +16,7 @@ export const manifest: UmbExtensionManifestKind = { meta: { icon: 'icon-enter', label: '#actions_copy', + additionalOptions: true, treeRepositoryAlias: '', duplicateRepositoryAlias: '', }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/default/entity-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/default/entity-action.element.ts index cf097b7010..af65c5896e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/default/entity-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/default/entity-action.element.ts @@ -60,11 +60,11 @@ export class UmbEntityActionDefaultElement< } override render() { + const label = this.manifest?.meta.label ? this.localize.string(this.manifest.meta.label) : this.manifest?.name; + return html` diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts index 5baafff43d..096a59dbb5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts @@ -40,6 +40,14 @@ export interface MetaEntityActionDefaultKind extends MetaEntityAction { * ] */ label: string; + + /** + * The action requires additional input from the user. + * A dialog will prompt the user for more information or to make a choice. + * @type {boolean} + * @memberof MetaEntityActionDefaultKind + */ + additionalOptions?: boolean; } // DELETE diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json index 2ea36b53ed..4d592bfb10 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json @@ -68,22 +68,10 @@ "name": "icon-arrow-up", "file": "arrow-up.svg" }, - { - "_name": "icon-art-easel", - "_file": "wallpaper.svg" - }, - { - "_name": "icon-article", - "_file": "article.svg" - }, { "name": "icon-attachment", "file": "paperclip.svg" }, - { - "_name": "icon-auction-hammer", - "___file": "auction-hammer.svg" - }, { "name": "icon-autofill", "file": "text-cursor-input.svg" @@ -104,10 +92,6 @@ "name": "icon-axis-rotation", "file": "refresh-ccw.svg" }, - { - "_name": "icon-baby-stroller", - "___file": "baby.svg" - }, { "name": "icon-backspace", "file": "delete.svg" @@ -116,10 +100,6 @@ "name": "icon-badge-add", "file": "circle-plus.svg" }, - { - "_name": "icon-badge-count", - "___file": "badge-count.svg" - }, { "name": "icon-badge-remove", "file": "circle-minus.svg" @@ -133,10 +113,6 @@ "name": "icon-ball", "file": "dribbble.svg" }, - { - "_name": "icon-band-aid", - "____file": "" - }, { "name": "icon-bar-chart", "file": "chart-no-axes-column.svg" @@ -169,57 +145,14 @@ "name": "icon-bell", "file": "bell.svg" }, - { - "_name": "icon-bill-dollar", - "____file": "circle-dollar-sign.svg" - }, - { - "_name": "icon-bill-euro", - "____file": "bill-euro.svg" - }, - { - "_name": "icon-bill-pound", - "____file": "bill-pound.svg" - }, - { - "_name": "icon-bill-yen", - "____file": "bill-yen.svg" - }, - { - "_name": "icon-bill", - "____file": "bill.svg" - }, - { - "_name": "icon-billboard", - "____file": "billboard.svg" - }, - { - "_name": "icon-bills-dollar", - "____file": "bills-dollar.svg" - }, - { - "_name": "icon-bills-euro", - "____file": "bills-euro.svg" - }, - { - "_name": "icon-bills-pound", - "____file": "bills-pound.svg" - }, - { - "_name": "icon-bills-yen", - "____file": "bills-yen.svg" - }, - { - "_name": "icon-bills", - "____file": "bills.svg" - }, { "name": "icon-binarycode", "file": "binary.svg" }, { - "_name": "icon-binoculars", - "___file": "binoculars.svg" + "name": "icon-binoculars", + "file": "binoculars.svg", + "legacy": true }, { "name": "icon-bird", @@ -253,10 +186,6 @@ "name": "icon-bold", "file": "bold.svg" }, - { - "_name": "icon-bomb", - "____file": "bomb.svg" - }, { "name": "icon-bones", "file": "bone.svg" @@ -370,10 +299,6 @@ "name": "icon-car", "file": "car.svg" }, - { - "_name": "icon-cash-register", - "____file": "cash-register.svg" - }, { "name": "icon-categories", "file": "archive.svg" @@ -403,10 +328,6 @@ "name": "icon-check", "file": "check.svg" }, - { - "_name": "icon-checkbox-dotted-active", - "____file": "checkbox-dotted-active.svg" - }, { "name": "icon-checkbox-dotted", "file": "box-select.svg" @@ -420,10 +341,6 @@ "name": "icon-checkbox", "file": "square-check.svg" }, - { - "_name": "icon-chess", - "____file": "chess.svg" - }, { "name": "icon-chip-alt", "file": "cpu.svg", @@ -449,19 +366,11 @@ "name": "icon-circuits", "file": "circuit-board.svg" }, - { - "_name": "icon-circus", - "____file": "circus.svg" - }, { "name": "icon-client", "file": "user.svg", "legacy": true }, - { - "_name": "icon-clothes-hanger", - "____file": "clothes-hanger.svg" - }, { "name": "icon-cloud-drive", "file": "hard-drive.svg" @@ -510,47 +419,11 @@ "name": "icon-coin-yen", "file": "japanese-yen.svg" }, - { - "_name": "icon-coin", - "____file": "coin.svg" - }, { "name": "icon-coins-alt", "file": "coins.svg", "legacy": true }, - { - "_name": "icon-coins-dollar-alt", - "____file": "coins-dollar-alt.svg" - }, - { - "_name": "icon-coins-dollar", - "____file": "coins-dollar.svg" - }, - { - "_name": "icon-coins-euro-alt", - "____file": "coins-euro-alt.svg" - }, - { - "_name": "icon-coins-euro", - "____file": "coins-euro.svg" - }, - { - "_name": "icon-coins-pound-alt", - "____file": "coins-pound-alt.svg" - }, - { - "_name": "icon-coins-pound", - "____file": "coins-pound.svg" - }, - { - "_name": "icon-coins-yen-alt", - "____file": "coins-yen-alt.svg" - }, - { - "_name": "icon-coins-yen", - "____file": "coins-yen.svg" - }, { "name": "icon-coins", "file": "coins.svg" @@ -567,10 +440,6 @@ "name": "icon-columns", "file": "tally-3.svg" }, - { - "_name": "icon-comb", - "____file": "comb.svg" - }, { "name": "icon-combination-lock-open", "file": "lock-keyhole-open.svg" @@ -675,10 +544,6 @@ "name": "icon-departure", "file": "plane-takeoff.svg" }, - { - "_name": "icon-desk", - "____file": "desk.svg" - }, { "name": "icon-desktop", "file": "monitor.svg", @@ -758,10 +623,6 @@ "name": "icon-documents", "file": "files.svg" }, - { - "_name": "icon-dollar-bag", - "____file": "dollar-bag.svg" - }, { "name": "icon-donate", "file": "hand-helping.svg", @@ -801,10 +662,6 @@ "name": "icon-edit", "file": "pencil.svg" }, - { - "_name": "icon-eject", - "____file": "eject.svg" - }, { "name": "icon-embed", "file": "monitor-play.svg" @@ -834,10 +691,6 @@ "name": "icon-ethernet", "file": "network.svg" }, - { - "_name": "icon-euro-bag", - "____file": "euro-bag.svg" - }, { "name": "icon-eye", "file": "eye.svg" @@ -858,10 +711,6 @@ "name": "icon-favorite", "file": "heart.svg" }, - { - "_name": "icon-female-symbol", - "____file": "female-symbol.svg" - }, { "name": "icon-file-cabinet", "file": "square-library.svg" @@ -886,10 +735,6 @@ "name": "icon-fire", "file": "flame-kindling.svg" }, - { - "_name": "icon-firewall", - "____file": "firewall.svg" - }, { "name": "icon-firewire", "file": "usb.svg", @@ -915,14 +760,6 @@ "name": "icon-flowerpot", "file": "flower-2.svg" }, - { - "_name": "icon-folder-open", - "____file": "folder-open.svg" - }, - { - "_name": "icon-folder-outline", - "____file": "folder-outline.svg" - }, { "name": "icon-folder", "file": "folder.svg" @@ -1048,10 +885,6 @@ "name": "icon-hand-pointer", "file": "pointer.svg" }, - { - "_name": "icon-handprint", - "____file": "handprint.svg" - }, { "name": "icon-handshake", "file": "heart-handshake.svg" @@ -1075,14 +908,6 @@ "file": "hard-drive.svg", "legacy": true }, - { - "_name": "icon-hat", - "____file": "hat.svg" - }, - { - "_name": "icon-hd", - "____file": "hd.svg" - }, { "name": "icon-heading-1", "file": "heading-1.svg" @@ -1145,10 +970,6 @@ "name": "icon-image-up", "file": "image-up.svg" }, - { - "_name": "icon-inactive-line", - "____file": "inactive-line.svg" - }, { "name": "icon-inbox-full", "file": "inbox.svg", @@ -1206,14 +1027,6 @@ "name": "icon-keyboard", "file": "keyboard.svg" }, - { - "_name": "icon-keychain", - "____file": "keychain.svg" - }, - { - "_name": "icon-keyhole", - "____file": "keyhole.svg" - }, { "name": "icon-lab", "file": "flask-conical.svg" @@ -1277,10 +1090,6 @@ "name": "icon-link", "file": "link.svg" }, - { - "_name": "icon-linux-tux", - "____file": "linux-tux.svg" - }, { "name": "icon-list", "file": "align-justify.svg" @@ -1334,14 +1143,6 @@ "name": "icon-mailbox", "file": "mailbox.svg" }, - { - "_name": "icon-male-and-female", - "____file": "users-2.svg" - }, - { - "_name": "icon-male-symbol", - "____file": "male-symbol.svg" - }, { "name": "icon-map-alt", "file": "navigation.svg" @@ -1410,14 +1211,6 @@ "name": "icon-mobile", "file": "smartphone.svg" }, - { - "_name": "icon-molecular-network", - "____file": "molecular-network.svg" - }, - { - "_name": "icon-molecular", - "____file": "molecular.svg" - }, { "name": "icon-mountain", "file": "mountain-snow.svg" @@ -2352,10 +2145,6 @@ "file": "user.svg", "legacy": true }, - { - "_name": "icon-umbraco", - "____file": "umbraco.svg" - }, { "name": "icon-umbrella", "file": "umbrella.svg" @@ -2556,6 +2345,271 @@ } ], "umbraco": [ + { + "name": "icon-art-easel", + "file": "icon-art-easel.svg", + "legacy": true + }, + { + "name": "icon-article", + "file": "icon-article.svg", + "legacy": true + }, + { + "name": "icon-auction-hammer", + "file": "icon-auction-hammer.svg", + "legacy": true + }, + { + "name": "icon-badge-count", + "file": "icon-badge-count.svg", + "legacy": true + }, + { + "name": "icon-band-aid", + "file": "icon-band-aid.svg", + "legacy": true + }, + { + "name": "icon-baby-stroller", + "file": "icon-baby-stroller.svg", + "legacy": true + }, + { + "name": "icon-bill-dollar", + "file": "icon-bill-dollar.svg", + "legacy": true + }, + { + "name": "icon-bill-euro", + "file": "icon-bill-euro.svg", + "legacy": true + }, + { + "name": "icon-bill-pound", + "file": "icon-bill-pound.svg", + "legacy": true + }, + { + "name": "icon-bill-yen", + "file": "icon-bill-yen.svg", + "legacy": true + }, + { + "name": "icon-bill", + "file": "icon-bill.svg", + "legacy": true + }, + { + "name": "icon-billboard", + "file": "icon-billboard.svg", + "legacy": true + }, + { + "name": "icon-bills-dollar", + "file": "icon-bills-dollar.svg", + "legacy": true + }, + { + "name": "icon-bills-euro", + "file": "icon-bills-euro.svg", + "legacy": true + }, + { + "name": "icon-bills-pound", + "file": "icon-bills-pound.svg", + "legacy": true + }, + { + "name": "icon-bills-yen", + "file": "icon-bills-yen.svg", + "legacy": true + }, + { + "name": "icon-bills", + "file": "icon-bills.svg", + "legacy": true + }, + { + "name": "icon-blueprint", + "file": "icon-blueprint.svg", + "legacy": true + }, + { + "name": "icon-bomb", + "file": "icon-bomb.svg", + "legacy": true + }, + { + "name": "icon-cash-register", + "file": "icon-cash-register.svg", + "legacy": true + }, + { + "name": "icon-checkbox-dotted-active", + "file": "icon-checkbox-dotted-active.svg", + "legacy": true + }, + { + "name": "icon-chess", + "file": "icon-chess.svg", + "legacy": true + }, + { + "name": "icon-circus", + "file": "icon-circus.svg", + "legacy": true + }, + { + "name": "icon-clothes-hanger", + "file": "icon-clothes-hanger.svg", + "legacy": true + }, + { + "name": "icon-coin", + "file": "icon-coin.svg", + "legacy": true + }, + { + "name": "icon-coins-dollar-alt", + "file": "icon-coins-dollar-alt.svg", + "legacy": true + }, + { + "name": "icon-coins-dollar", + "file": "icon-coins-dollar.svg", + "legacy": true + }, + { + "name": "icon-coins-euro-alt", + "file": "icon-coins-euro-alt.svg", + "legacy": true + }, + { + "name": "icon-coins-euro", + "file": "icon-coins-euro.svg", + "legacy": true + }, + { + "name": "icon-coins-pound-alt", + "file": "icon-coins-pound-alt.svg", + "legacy": true + }, + { + "name": "icon-coins-pound", + "file": "icon-coins-pound.svg", + "legacy": true + }, + { + "name": "icon-coins-yen-alt", + "file": "icon-coins-yen-alt.svg", + "legacy": true + }, + { + "name": "icon-coins-yen", + "file": "icon-coins-yen.svg", + "legacy": true + }, + { + "name": "icon-comb", + "file": "icon-comb.svg", + "legacy": true + }, + { + "name": "icon-desk", + "file": "icon-desk.svg", + "legacy": true + }, + { + "name": "icon-dollar-bag", + "file": "icon-dollar-bag.svg", + "legacy": true + }, + { + "name": "icon-eject", + "file": "icon-eject.svg", + "legacy": true + }, + { + "name": "icon-euro-bag", + "file": "icon-euro-bag.svg", + "legacy": true + }, + { + "name": "icon-female-symbol", + "file": "icon-female-symbol.svg", + "legacy": true + }, + { + "name": "icon-firewall", + "file": "icon-firewall.svg", + "legacy": true + }, + { + "name": "icon-folder-open", + "file": "icon-folder-open.svg", + "legacy": true + }, + { + "name": "icon-folder-outline", + "file": "icon-folder-outline.svg", + "legacy": true + }, + { + "name": "icon-handprint", + "file": "icon-handprint.svg", + "legacy": true + }, + { + "name": "icon-hat", + "file": "icon-hat.svg", + "legacy": true + }, + { + "name": "icon-hd", + "file": "icon-hd.svg", + "legacy": true + }, + { + "name": "icon-inactive-line", + "file": "icon-inactive-line.svg", + "legacy": true + }, + { + "name": "icon-keychain", + "file": "icon-keychain.svg", + "legacy": true + }, + { + "name": "icon-keyhole", + "file": "icon-keyhole.svg", + "legacy": true + }, + { + "name": "icon-linux-tux", + "file": "icon-linux-tux.svg", + "legacy": true + }, + { + "name": "icon-male-and-female", + "file": "icon-users.svg", + "legacy": true + }, + { + "name": "icon-male-symbol", + "file": "icon-male-symbol.svg", + "legacy": true + }, + { + "name": "icon-molecular-network", + "file": "icon-molecular-network.svg", + "legacy": true + }, + { + "name": "icon-molecular", + "file": "icon-molecular.svg", + "legacy": true + }, { "name": "icon-umbraco", "file": "icon-umbraco.svg" diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/icon-picker/icon-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.element.ts similarity index 99% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/common/icon-picker/icon-picker-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.element.ts index 5455734cd0..a5204fc642 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/icon-picker/icon-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.element.ts @@ -1,10 +1,10 @@ +import type { UmbIconPickerModalData, UmbIconPickerModalValue } from './icon-picker-modal.token.js'; import { css, customElement, html, nothing, query, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { extractUmbColorVariable, umbracoColors } from '@umbraco-cms/backoffice/resources'; import { umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UMB_ICON_REGISTRY_CONTEXT, type UmbIconDefinition } from '@umbraco-cms/backoffice/icon'; -import type { UmbIconPickerModalData, UmbIconPickerModalValue } from '@umbraco-cms/backoffice/modal'; import type { UUIColorSwatchesEvent } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-icon-picker-modal') diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/icon-picker/icon-picker-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.stories.ts similarity index 84% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/common/icon-picker/icon-picker-modal.stories.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.stories.ts index 4b8eaf3d5c..5f34ce845e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/icon-picker/icon-picker-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.stories.ts @@ -1,12 +1,10 @@ -import '../../../components/body-layout/body-layout.element.js'; import './icon-picker-modal.element.js'; import type { UmbIconPickerModalElement } from './icon-picker-modal.element.js'; +import type { UmbIconPickerModalValue } from './icon-picker-modal.token.js'; import type { Meta, Story } from '@storybook/web-components'; import { html } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbIconPickerModalValue } from '@umbraco-cms/backoffice/modal'; - export default { title: 'API/Modals/Layouts/Icon Picker', component: 'umb-icon-picker-modal', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/icon-picker/icon-picker-modal.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.test.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/common/icon-picker/icon-picker-modal.test.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.test.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/icon-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.token.ts similarity index 84% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/token/icon-picker-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.token.ts index 86ce0e8115..6ac5b7b155 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/icon-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.token.ts @@ -1,4 +1,4 @@ -import { UmbModalToken } from './modal-token.js'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export type UmbIconPickerModalData = never; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/index.ts new file mode 100644 index 0000000000..10e5659b24 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/index.ts @@ -0,0 +1,2 @@ +export * from './icon-picker-modal.token.js'; +export * from './icon-picker-modal.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/manifests.ts new file mode 100644 index 0000000000..b4b3e11502 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/manifests.ts @@ -0,0 +1,8 @@ +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.IconPicker', + name: 'Icon Picker Modal', + element: () => import('./icon-picker-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts index c7c47d23d6..3139743a15 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts @@ -147,6 +147,10 @@ name: "icon-binarycode", path: () => import("./icons/icon-binarycode.js"), },{ +name: "icon-binoculars", +legacy: true, +path: () => import("./icons/icon-binoculars.js"), +},{ name: "icon-bird", path: () => import("./icons/icon-bird.js"), @@ -2203,10 +2207,6 @@ name: "icon-twitter-x", path: () => import("./icons/icon-twitter-x.js"), },{ -name: "icon-umbraco", - -path: () => import("./icons/icon-umbraco.js"), -},{ name: "icon-art-easel", legacy: true, path: () => import("./icons/icon-art-easel.js"), @@ -2219,14 +2219,6 @@ name: "icon-auction-hammer", legacy: true, path: () => import("./icons/icon-auction-hammer.js"), },{ -name: "icon-azure", -legacy: true, -path: () => import("./icons/icon-azure.js"), -},{ -name: "icon-baby-stroller", -legacy: true, -path: () => import("./icons/icon-baby-stroller.js"), -},{ name: "icon-badge-count", legacy: true, path: () => import("./icons/icon-badge-count.js"), @@ -2235,6 +2227,10 @@ name: "icon-band-aid", legacy: true, path: () => import("./icons/icon-band-aid.js"), },{ +name: "icon-baby-stroller", +legacy: true, +path: () => import("./icons/icon-baby-stroller.js"), +},{ name: "icon-bill-dollar", legacy: true, path: () => import("./icons/icon-bill-dollar.js"), @@ -2279,10 +2275,6 @@ name: "icon-bills", legacy: true, path: () => import("./icons/icon-bills.js"), },{ -name: "icon-binoculars", -legacy: true, -path: () => import("./icons/icon-binoculars.js"), -},{ name: "icon-blueprint", legacy: true, path: () => import("./icons/icon-blueprint.js"), @@ -2419,10 +2411,6 @@ name: "icon-male-symbol", legacy: true, path: () => import("./icons/icon-male-symbol.js"), },{ -name: "icon-microsoft", -legacy: true, -path: () => import("./icons/icon-microsoft.js"), -},{ name: "icon-molecular-network", legacy: true, path: () => import("./icons/icon-molecular-network.js"), @@ -2431,6 +2419,18 @@ name: "icon-molecular", legacy: true, path: () => import("./icons/icon-molecular.js"), },{ +name: "icon-umbraco", + +path: () => import("./icons/icon-umbraco.js"), +},{ +name: "icon-azure", +legacy: true, +path: () => import("./icons/icon-azure.js"), +},{ +name: "icon-microsoft", +legacy: true, +path: () => import("./icons/icon-microsoft.js"), +},{ name: "icon-os-x", legacy: true, path: () => import("./icons/icon-os-x.js"), diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-activity.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-activity.ts index bde54263f9..ee76324f33 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-activity.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-activity.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` `; \ No newline at end of file +export default ` + + + + + + + + +`; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-bird.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-bird.ts index 64d10bf931..27ea94f8bd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-bird.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-bird.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - - - - - + + + + + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-book-alt.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-book-alt.ts index ae5cba2f0c..3fb1701cf4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-book-alt.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-book-alt.ts @@ -1,4 +1,4 @@ -export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - - + + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-book.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-book.ts index 23ca1f5c3e..3f0cb0db5e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-book.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-book.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-conversation.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-conversation.ts index 1e9fd8acf1..77c2000b49 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-conversation.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-conversation.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - - + + + + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-diagonal-arrow-alt.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-diagonal-arrow-alt.ts index 8cf608728a..2195373504 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-diagonal-arrow-alt.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-diagonal-arrow-alt.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` `; \ No newline at end of file +export default ``; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-map-alt.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-map-alt.ts index 790454cc8f..3938c1d1cb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-map-alt.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-map-alt.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - - + + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-mouse.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-mouse.ts index 546a302eb8..1b3f15eb69 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-mouse.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-mouse.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - - - - - + + + + + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-navigation-bottom.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-navigation-bottom.ts index 24b570eeca..5d94d3239c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-navigation-bottom.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-navigation-bottom.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-paper-plane.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-paper-plane.ts index e8fe760df1..aaf4c2513b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-paper-plane.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-paper-plane.ts @@ -1,4 +1,4 @@ -export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - - + + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-partly-cloudy.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-partly-cloudy.ts index f40d589c14..5762ccb6de 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-partly-cloudy.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-partly-cloudy.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-rocket.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-rocket.ts index 8ac3f62062..b42654cb4b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-rocket.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-rocket.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - - + + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-sound-medium.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-sound-medium.ts index e503fc0641..cef7a6e968 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-sound-medium.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-sound-medium.ts @@ -1,4 +1,4 @@ -export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - - - + + + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-sound-off.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-sound-off.ts index 3b3fde9df0..748eaae3ac 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-sound-off.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-sound-off.ts @@ -1,4 +1,4 @@ -export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-sound-waves.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-sound-waves.ts index 6557b3c99a..3addda6aec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-sound-waves.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-sound-waves.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - - - + + + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-spades.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-spades.ts index 9373b8c3ad..1b53973e7b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-spades.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-spades.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` stroke-linecap="round" stroke-linejoin="round" > - - - - - + + + + + `; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-video.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-video.ts index 66c38a1d79..b4ac021b5b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-video.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-video.ts @@ -1,4 +1,4 @@ -export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` +export default ` = [ { type: 'icons', @@ -11,4 +13,5 @@ export const manifests: Array = [ name: 'Icons Context', api: () => import('./icon-registry.context.js'), }, + ...iconPickerModalManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts index 62441b6e3a..25e388e063 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts @@ -10,9 +10,10 @@ import { manifests as extensionManifests } from './extension-registry/manifests. import { manifests as iconRegistryManifests } from './icon-registry/manifests.js'; import { manifests as localizationManifests } from './localization/manifests.js'; import { manifests as menuManifests } from './menu/manifests.js'; -import { manifests as modalManifests } from './modal/common/manifests.js'; +import { manifests as modalManifests } from './modal/manifests.js'; import { manifests as pickerManifests } from './picker/manifests.js'; import { manifests as propertyActionManifests } from './property-action/manifests.js'; +import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as propertyManifests } from './property/manifests.js'; import { manifests as propertyTypeManifests } from './property-type/manifests.js'; import { manifests as recycleBinManifests } from './recycle-bin/manifests.js'; @@ -40,6 +41,7 @@ export const manifests: Array = ...modalManifests, ...pickerManifests, ...propertyActionManifests, + ...propertyEditorManifests, ...propertyManifests, ...propertyTypeManifests, ...recycleBinManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/confirm-modal.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/confirm-modal.controller.ts index 917d35ed9a..8deb91202b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/confirm-modal.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/confirm-modal.controller.ts @@ -1,5 +1,5 @@ -import { UMB_CONFIRM_MODAL, type UmbConfirmModalData } from '../../token/confirm-modal.token.js'; -import { UMB_MODAL_MANAGER_CONTEXT } from '../../context/modal-manager.context.js'; +import { UMB_MODAL_MANAGER_CONTEXT } from '../../context/index.js'; +import { UMB_CONFIRM_MODAL, type UmbConfirmModalData } from './confirm-modal.token.js'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/confirm-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/confirm-modal.token.ts similarity index 89% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/token/confirm-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/confirm-modal.token.ts index 45bd9f9709..d840de6147 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/confirm-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/confirm-modal.token.ts @@ -1,4 +1,4 @@ -import { UmbModalToken } from './modal-token.js'; +import { UmbModalToken } from '../../token/index.js'; import type { TemplateResult } from '@umbraco-cms/backoffice/external/lit'; export interface UmbConfirmModalData { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/index.ts new file mode 100644 index 0000000000..2bbe77a438 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/index.ts @@ -0,0 +1,3 @@ +export * from './confirm-modal.controller.js'; +export * from './confirm-modal.element.js'; +export * from './confirm-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/manifests.ts new file mode 100644 index 0000000000..9428106e1b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/manifests.ts @@ -0,0 +1,8 @@ +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.Confirm', + name: 'Confirm Modal', + element: () => import('./confirm-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/discard-changes-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/discard-changes-modal.element.ts new file mode 100644 index 0000000000..8019017932 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/discard-changes-modal.element.ts @@ -0,0 +1,36 @@ +import { UmbModalBaseElement } from '../../component/modal-base.element.js'; +import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; + +@customElement('umb-discard-changes-modal') +export class UmbDiscardChangesModalElement extends UmbModalBaseElement { + override render() { + return html` + + + + + + `; + } + + static override styles = [UmbTextStyles]; +} + +export { UmbDiscardChangesModalElement as element }; + +declare global { + interface HTMLElementTagNameMap { + 'umb-discard-changes-modal': UmbDiscardChangesModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/discard-changes-modal.tokent.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/discard-changes-modal.tokent.ts new file mode 100644 index 0000000000..0588c59fb7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/discard-changes-modal.tokent.ts @@ -0,0 +1,7 @@ +import { UmbModalToken } from '../../token/index.js'; + +export const UMB_DISCARD_CHANGES_MODAL = new UmbModalToken('Umb.Modal.DiscardChanges', { + modal: { + type: 'dialog', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/index.ts new file mode 100644 index 0000000000..987d718f87 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/index.ts @@ -0,0 +1,2 @@ +export * from './discard-changes-modal.element.js'; +export * from './discard-changes-modal.tokent.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/manifests.ts new file mode 100644 index 0000000000..6816839e55 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/manifests.ts @@ -0,0 +1,8 @@ +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.DiscardChanges', + name: 'Discard Changes Modal', + element: () => import('./discard-changes-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/manifests.ts deleted file mode 100644 index 9cf9968724..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/manifests.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { manifests as repositories } from './repository/manifests.js'; -import type { ManifestModal } from '@umbraco-cms/backoffice/extension-registry'; - -const modals: Array = [ - { - type: 'modal', - alias: 'Umb.Modal.EmbeddedMedia', - name: 'Embedded Media Modal', - element: () => import('./embedded-media-modal.element.js'), - }, -]; - -export const manifests = [...modals, ...repositories]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/index.ts deleted file mode 100644 index 1a6e303708..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { UmbOEmbedRepository } from './oembed.repository.js'; -export { UMB_OEMBED_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/index.ts index 5a1c0033a6..3781b76645 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/index.ts @@ -1 +1,3 @@ -export * from './embedded-media/index.js'; +export * from './confirm/index.js'; +export * from './discard-changes/index.js'; +export * from './item-picker/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/index.ts new file mode 100644 index 0000000000..1639c7e5db --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/index.ts @@ -0,0 +1 @@ +export * from './item-picker-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/item-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/item-picker-modal.token.ts similarity index 88% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/token/item-picker-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/item-picker-modal.token.ts index 365c2f8088..d98658118a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/item-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/item-picker-modal.token.ts @@ -1,4 +1,4 @@ -import { UmbModalToken } from './modal-token.js'; +import { UmbModalToken } from '../../token/index.js'; export type UmbItemPickerModalData = { headline: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/manifests.ts new file mode 100644 index 0000000000..302ae9fa01 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/manifests.ts @@ -0,0 +1,8 @@ +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.ItemPicker', + name: 'Item Picker Modal', + element: () => import('./item-picker-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/manifests.ts index 2a2ab02467..6def05faa8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/manifests.ts @@ -1,32 +1,9 @@ +import { manifests as confirmManifests } from './confirm/manifests.js'; +import { manifests as discardChangesManifests } from './discard-changes/manifests.js'; +import { manifests as itemPickerManifests } from './item-picker/manifests.js'; + export const manifests: Array = [ - { - type: 'modal', - alias: 'Umb.Modal.Confirm', - name: 'Confirm Modal', - element: () => import('./confirm/confirm-modal.element.js'), - }, - { - type: 'modal', - alias: 'Umb.Modal.IconPicker', - name: 'Icon Picker Modal', - element: () => import('./icon-picker/icon-picker-modal.element.js'), - }, - { - type: 'modal', - alias: 'Umb.Modal.CodeEditor', - name: 'Code Editor Modal', - element: () => import('./code-editor/code-editor-modal.element.js'), - }, - { - type: 'modal', - alias: 'Umb.Modal.EmbeddedMedia', - name: 'Embedded Media Modal', - element: () => import('./embedded-media/embedded-media-modal.element.js'), - }, - { - type: 'modal', - alias: 'Umb.Modal.ItemPicker', - name: 'Item Picker Modal', - element: () => import('./item-picker/item-picker-modal.element.js'), - }, + ...confirmManifests, + ...discardChangesManifests, + ...itemPickerManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts index 59329387f8..55ca1f1885 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts @@ -1,8 +1,8 @@ import './component/modal.element.js'; +export * from './common/index.js'; +export * from './component/modal-base.element.js'; +export * from './component/modal.element.js'; export * from './context/index.js'; export * from './token/index.js'; export * from './types.js'; -export * from './component/modal-base.element.js'; -export * from './component/modal.element.js'; -export * from './common/confirm/confirm-modal.controller.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/manifests.ts new file mode 100644 index 0000000000..edd06202ae --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/manifests.ts @@ -0,0 +1,3 @@ +import { manifests as commonManifests } from './common/manifests.js'; + +export const manifests: Array = [...commonManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/index.ts index a2958ea597..7fcdaada28 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/index.ts @@ -1,11 +1 @@ -export * from './change-password-modal.token.js'; -export * from './code-editor-modal.token.js'; -export * from './confirm-modal.token.js'; -export * from './debug-modal.token.js'; -export * from './embedded-media-modal.token.js'; -export * from './entity-user-permission-settings-modal.token.js'; -export * from './icon-picker-modal.token.js'; -export * from './item-picker-modal.token.js'; export * from './modal-token.js'; -export * from './property-editor-ui-picker-modal.token.js'; -export * from './workspace-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/index.ts index 5f5c1f5388..abd78bfa28 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/index.ts @@ -1,4 +1,5 @@ export * from './components/index.js'; export * from './config/index.js'; -export * from './events/index.js'; export * from './constants.js'; +export * from './events/index.js'; +export * from './ui-picker-modal/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/manifests.ts new file mode 100644 index 0000000000..fb5a8ae26f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/manifests.ts @@ -0,0 +1,3 @@ +import { manifests as uiPickerModalManifests } from './ui-picker-modal/manifests.js'; + +export const manifests: Array = [...uiPickerModalManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/index.ts new file mode 100644 index 0000000000..10ce5e62e5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/index.ts @@ -0,0 +1 @@ +export * from './property-editor-ui-picker-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/manifests.ts new file mode 100644 index 0000000000..95c29a5ee0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/manifests.ts @@ -0,0 +1,8 @@ +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.PropertyEditorUiPicker', + name: 'Property Editor UI Picker Modal', + element: () => import('./property-editor-ui-picker-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/property-editor-ui-picker-modal.element.ts similarity index 99% rename from src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/property-editor-ui-picker-modal.element.ts index 3fb5bd97c2..b3aeeede87 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/property-editor-ui-picker-modal.element.ts @@ -1,13 +1,13 @@ +import type { + UmbPropertyEditorUIPickerModalData, + UmbPropertyEditorUIPickerModalValue, +} from './property-editor-ui-picker-modal.token.js'; import { css, customElement, html, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { fromCamelCase } from '@umbraco-cms/backoffice/utils'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension-registry'; -import type { - UmbPropertyEditorUIPickerModalData, - UmbPropertyEditorUIPickerModalValue, -} from '@umbraco-cms/backoffice/modal'; import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-property-editor-ui-picker-modal') diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/property-editor-ui-picker-modal.stories.ts similarity index 81% rename from src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.stories.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/property-editor-ui-picker-modal.stories.ts index 036a9c7c58..6d9d81d8a6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/property-editor-ui-picker-modal.stories.ts @@ -1,10 +1,10 @@ import type { UmbPropertyEditorUIPickerModalElement } from './property-editor-ui-picker-modal.element.js'; +import type { UmbPropertyEditorUIPickerModalValue } from './property-editor-ui-picker-modal.token.js'; import type { Meta, Story } from '@storybook/web-components'; import { html } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbPropertyEditorUIPickerModalValue } from '@umbraco-cms/backoffice/modal'; import './property-editor-ui-picker-modal.element.js'; -import '../../../core/components/body-layout/body-layout.element.js'; +import '../../components/body-layout/body-layout.element.js'; export default { title: 'API/Modals/Layouts/Property Editor UI Picker', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/property-editor-ui-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/property-editor-ui-picker-modal.token.ts similarity index 88% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/token/property-editor-ui-picker-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/property-editor-ui-picker-modal.token.ts index 185f5ff781..d6aacdea4b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/property-editor-ui-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/property-editor-ui-picker-modal.token.ts @@ -1,4 +1,4 @@ -import { UmbModalToken } from './modal-token.js'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbPropertyEditorUIPickerModalData { /** @deprecated This property will be removed in Umbraco 15. */ diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context.ts index 8de775c6c1..022c0b5f88 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context.ts @@ -41,7 +41,7 @@ export class UmbPropertyTypeWorkspaceContext('UmbValidationContext'); +export const UMB_VALIDATION_CONTEXT = new UmbContextToken('UmbValidationContext'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/validation.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/validation.context.ts index f4d7193ec4..6deed36696 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/validation.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/validation.context.ts @@ -1,296 +1,32 @@ -import type { UmbValidator } from '../interfaces/validator.interface.js'; -import type { UmbValidationMessageTranslator } from '../translators/index.js'; -import { GetValueByJsonPath } from '../utils/json-path.function.js'; -import { type UmbValidationMessage, UmbValidationMessagesManager } from './validation-messages.manager.js'; +import { UmbValidationController } from '../controllers/validation.controller.js'; import { UMB_VALIDATION_CONTEXT } from './validation.context-token.js'; -import type { UmbContextProviderController } from '@umbraco-cms/backoffice/context-api'; -import { type UmbClassInterface, UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import type { UmbClassInterface } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; - -/** - * Helper method to replace the start of a string with another string. - * @param path {string} - * @param startFrom {string} - * @param startTo {string} - * @returns {string} - */ -function ReplaceStartOfString(path: string, startFrom: string, startTo: string): string { - if (path.startsWith(startFrom + '.')) { - return startTo + path.slice(startFrom.length); - } - return path; -} - /** * Validation Context is the core of Validation. * It hosts Validators that has to validate for the context to be valid. * It can also be used as a Validator as part of a parent Validation Context. */ -export class UmbValidationContext extends UmbControllerBase implements UmbValidator { - // The current provider controller, that is providing this context: - #providerCtrl?: UmbContextProviderController; - - // Local version of the data send to the server, only use-case is for translation. - #translationData = new UmbObjectState(undefined); - translationDataOf(path: string): any { - return this.#translationData.asObservablePart((data) => GetValueByJsonPath(data, path)); - } - setTranslationData(data: any): void { - this.#translationData.setValue(data); - } - getTranslationData(): any { - return this.#translationData.getValue(); - } - - #validators: Array = []; - #validationMode: boolean = false; - #isValid: boolean = false; - - #parent?: UmbValidationContext; - #parentMessages?: Array; - #localMessages?: Array; - #baseDataPath?: string; - - public readonly messages = new UmbValidationMessagesManager(); - +export class UmbValidationContext extends UmbValidationController { constructor(host: UmbControllerHost) { // This is overridden to avoid setting a controllerAlias, this might make sense, but currently i want to leave it out. [NL] super(host); - } - - /** - * Add a path translator to this validation context. - * @param translator - */ - async addTranslator(translator: UmbValidationMessageTranslator) { - this.messages.addTranslator(translator); - } - - /** - * Remove a path translator from this validation context. - * @param translator - */ - async removeTranslator(translator: UmbValidationMessageTranslator) { - this.messages.removeTranslator(translator); + this.provideContext(UMB_VALIDATION_CONTEXT, this); } /** * Provides the validation context to the current host, if not already provided to a different host. - * @returns instance {UmbValidationContext} - Returns it self. + * @deprecated No need to provide, this happens automatically. (Do notice this was necessary in 14.3.-rc, but removed in 14.3 release) + * @returns instance {UmbValidationController} - Returns it self. */ - provide(): UmbValidationContext { - if (this.#providerCtrl) return this; - this.provideContext(UMB_VALIDATION_CONTEXT, this); + provide(): UmbValidationController { return this; } - /** - * Provide this validation context to a specific controller host. - * This can be used to Host a validation context in a Workspace, but provide it on a certain scope, like a specific Workspace View. - * @param controllerHost {UmbClassInterface} - */ - provideAt(controllerHost: UmbClassInterface): void { - this.#providerCtrl?.destroy(); - this.#providerCtrl = controllerHost.provideContext(UMB_VALIDATION_CONTEXT, this); - } - /** - * Define a specific data path for this validation context. - * This will turn this validation context into a sub-context of the parent validation context. - * This means that a two-way binding for messages will be established between the parent and the sub-context. - * And it will inherit the Translation Data from its parent. - * - * messages and data will be localizes accordingly to the given data path. - * @param dataPath {string} - The data path to bind this validation context to. - * @example - * ```ts - * const validationContext = new UmbValidationContext(host); - * validationContext.setDataPath("$.values[?(@.alias='my-property')].value"); - * ``` - * - * A message with the path: '$.values[?(@.alias='my-property')].value.innerProperty', will for above example become '$.innerProperty' for the local Validation Context. - */ - setDataPath(dataPath: string): void { - if (this.#baseDataPath) { - if (this.#baseDataPath === dataPath) return; - console.log(this.#baseDataPath, dataPath); - // Just fire an error, as I haven't made the right clean up jet. Or haven't thought about what should happen if it changes while already setup. - // cause maybe all the messages should be removed as we are not interested in the old once any more. But then on the other side, some might be relevant as this is the same entity that changed its paths? - throw new Error('Data path is already set, we do not support changing the context data-path as of now.'); - } - if (!dataPath) return; - this.#baseDataPath = dataPath; - - this.consumeContext(UMB_VALIDATION_CONTEXT, (parent) => { - if (this.#parent) { - this.#parent.removeValidator(this); - } - this.#parent = parent; - parent.addValidator(this); - - this.messages.clear(); - - this.observe(parent.translationDataOf(dataPath), (data) => { - this.setTranslationData(data); - }); - - this.observe( - parent.messages.messagesOfPathAndDescendant(dataPath), - (msgs) => { - //this.messages.appendMessages(msgs); - if (this.#parentMessages) { - // Remove the local messages that does not exist in the parent anymore: - const toRemove = this.#parentMessages.filter((msg) => !msgs.find((m) => m.key === msg.key)); - toRemove.forEach((msg) => { - this.messages.removeMessageByKey(msg.key); - }); - } - this.#parentMessages = msgs; - msgs.forEach((msg) => { - const path = ReplaceStartOfString(msg.path, this.#baseDataPath!, '$'); - // Notice, the local message uses the same key. [NL] - this.messages.addMessage(msg.type, path, msg.body, msg.key); - }); - }, - 'observeParentMessages', - ); - - this.observe( - this.messages.messages, - (msgs) => { - if (!this.#parent) return; - //this.messages.appendMessages(msgs); - if (this.#localMessages) { - // Remove the parent messages that does not exist locally anymore: - const toRemove = this.#localMessages.filter((msg) => !msgs.find((m) => m.key === msg.key)); - toRemove.forEach((msg) => { - this.#parent!.messages.removeMessageByKey(msg.key); - }); - } - this.#localMessages = msgs; - msgs.forEach((msg) => { - // replace this.#baseDataPath (if it starts with it) with $ in the path, so it becomes relative to the parent context - const path = ReplaceStartOfString(msg.path, '$', this.#baseDataPath!); - // Notice, the parent message uses the same key. [NL] - this.#parent!.messages.addMessage(msg.type, path, msg.body, msg.key); - }); - }, - 'observeLocalMessages', - ); - }).skipHost(); - // Notice skipHost ^^, this is because we do not want it to consume it self, as this would be a match for this consumption, instead we will look at the parent and above. [NL] - } - - /** - * Get if this context is valid. - * Notice this does not verify the validity. - * @returns {boolean} - */ - get isValid(): boolean { - return this.#isValid; - } - - /** - * Add a validator to this context. - * This validator will have to be valid for the context to be valid. - * If the context is in validation mode, the validator will be validated immediately. - * @param validator { UmbValidator } - The validator to add to this context. - */ - addValidator(validator: UmbValidator): void { - if (this.#validators.includes(validator)) return; - this.#validators.push(validator); - //validator.addEventListener('change', this.#onValidatorChange); - if (this.#validationMode) { - this.validate(); - } - } - - /** - * Remove a validator from this context. - * @param validator {UmbValidator} - The validator to remove from this context. - */ - removeValidator(validator: UmbValidator): void { - const index = this.#validators.indexOf(validator); - if (index !== -1) { - // Remove the validator: - this.#validators.splice(index, 1); - // If we are in validation mode then we should re-validate to focus next invalid element: - if (this.#validationMode) { - this.validate(); - } - } - } - - /** - * Validate this context, all the validators of this context will be validated. - * Notice its a recursive check meaning sub validation contexts also validates their validators. - * @returns succeed {Promise} - Returns a promise that resolves to true if the validator succeeded, this depends on the validators and wether forceSucceed is set. - */ - async validate(): Promise { - // TODO: clear server messages here?, well maybe only if we know we will get new server messages? Do the server messages hook into the system like another validator? - this.#validationMode = true; - - const resultsStatus = await Promise.all(this.#validators.map((v) => v.validate())).then( - () => Promise.resolve(true), - () => Promise.resolve(false), + // eslint-disable-next-line @typescript-eslint/no-unused-vars + override provideAt(controllerHost: UmbClassInterface): void { + throw new Error( + 'UmbValidationContext cannot be used to provide at a different host. Use the UmbValidationController instead.', ); - - if (!this.messages) { - // This Context has been destroyed while is was validating, so we should not continue. - return; - } - - // If we have any messages then we are not valid, otherwise lets check the validation results: [NL] - // This enables us to keep client validations though UI is not present anymore — because the client validations got defined as messages. [NL] - const isValid = this.messages.getHasAnyMessages() ? false : resultsStatus; - - this.#isValid = isValid; - - if (isValid === false) { - // Focus first invalid element: - this.focusFirstInvalidElement(); - return Promise.reject(); - } - - return Promise.resolve(); - } - - /** - * Focus the first invalid element that this context can find. - */ - focusFirstInvalidElement(): void { - const firstInvalid = this.#validators.find((v) => !v.isValid); - if (firstInvalid) { - firstInvalid.focusFirstInvalidElement(); - } - } - - /** - * Reset the validation state of this context. - */ - reset(): void { - this.#validationMode = false; - this.#validators.forEach((v) => v.reset()); - } - - #destroyValidators(): void { - if (this.#validators === undefined || this.#validators.length === 0) return; - this.#validators.forEach((validator) => { - validator.destroy(); - //validator.removeEventListener('change', this.#runValidate); - }); - this.#validators = []; - } - - override destroy(): void { - this.#providerCtrl = undefined; - if (this.#parent) { - this.#parent.removeValidator(this); - } - this.#parent = undefined; - this.#destroyValidators(); - this.messages?.destroy(); - (this.messages as unknown) = undefined; - super.destroy(); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/index.ts index 66e51504c5..4649c9f322 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/index.ts @@ -1,5 +1,4 @@ export * from './bind-server-validation-to-form-control.controller.js'; export * from './form-control-validator.controller.js'; export * from './observe-validation-state.controller.js'; -export * from './server-model-validator.context-token.js'; -export * from './server-model-validator.context.js'; +export * from './validation.controller.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts new file mode 100644 index 0000000000..80a819b598 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts @@ -0,0 +1,291 @@ +import type { UmbValidator } from '../interfaces/validator.interface.js'; +import type { UmbValidationMessageTranslator } from '../translators/index.js'; +import { GetValueByJsonPath } from '../utils/json-path.function.js'; +import { UMB_VALIDATION_CONTEXT } from '../context/validation.context-token.js'; +import { type UmbValidationMessage, UmbValidationMessagesManager } from '../context/validation-messages.manager.js'; +import type { UmbContextProviderController } from '@umbraco-cms/backoffice/context-api'; +import { type UmbClassInterface, UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; + +/** + * Helper method to replace the start of a string with another string. + * @param path {string} + * @param startFrom {string} + * @param startTo {string} + * @returns {string} + */ +function ReplaceStartOfString(path: string, startFrom: string, startTo: string): string { + if (path.startsWith(startFrom + '.')) { + return startTo + path.slice(startFrom.length); + } + return path; +} + +/** + * Validation Context is the core of Validation. + * It hosts Validators that has to validate for the context to be valid. + * It can also be used as a Validator as part of a parent Validation Context. + */ +export class UmbValidationController extends UmbControllerBase implements UmbValidator { + // The current provider controller, that is providing this context: + #providerCtrl?: UmbContextProviderController< + UmbValidationController, + UmbValidationController, + UmbValidationController + >; + + // Local version of the data send to the server, only use-case is for translation. + #translationData = new UmbObjectState(undefined); + translationDataOf(path: string): any { + return this.#translationData.asObservablePart((data) => GetValueByJsonPath(data, path)); + } + setTranslationData(data: any): void { + this.#translationData.setValue(data); + } + getTranslationData(): any { + return this.#translationData.getValue(); + } + + #validators: Array = []; + #validationMode: boolean = false; + #isValid: boolean = false; + + #parent?: UmbValidationController; + #parentMessages?: Array; + #localMessages?: Array; + #baseDataPath?: string; + + public readonly messages = new UmbValidationMessagesManager(); + + constructor(host: UmbControllerHost) { + // This is overridden to avoid setting a controllerAlias, this might make sense, but currently i want to leave it out. [NL] + super(host); + } + + /** + * Add a path translator to this validation context. + * @param translator + */ + async addTranslator(translator: UmbValidationMessageTranslator) { + this.messages.addTranslator(translator); + } + + /** + * Remove a path translator from this validation context. + * @param translator + */ + async removeTranslator(translator: UmbValidationMessageTranslator) { + this.messages.removeTranslator(translator); + } + + /** + * Provide this validation context to a specific controller host. + * This can be used to Host a validation context in a Workspace, but provide it on a certain scope, like a specific Workspace View. + * @param controllerHost {UmbClassInterface} + */ + provideAt(controllerHost: UmbClassInterface): void { + this.#providerCtrl?.destroy(); + this.#providerCtrl = controllerHost.provideContext(UMB_VALIDATION_CONTEXT, this); + } + + /** + * Define a specific data path for this validation context. + * This will turn this validation context into a sub-context of the parent validation context. + * This means that a two-way binding for messages will be established between the parent and the sub-context. + * And it will inherit the Translation Data from its parent. + * + * messages and data will be localizes accordingly to the given data path. + * @param dataPath {string} - The data path to bind this validation context to. + * @example + * ```ts + * const validationContext = new UmbValidationContext(this); + * validationContext.setDataPath("$.values[?(@.alias='my-property')].value"); + * ``` + * + * A message with the path: '$.values[?(@.alias='my-property')].value.innerProperty', will for above example become '$.innerProperty' for the local Validation Context. + */ + setDataPath(dataPath: string): void { + if (this.#baseDataPath) { + if (this.#baseDataPath === dataPath) return; + console.log(this.#baseDataPath, dataPath); + // Just fire an error, as I haven't made the right clean up jet. Or haven't thought about what should happen if it changes while already setup. + // cause maybe all the messages should be removed as we are not interested in the old once any more. But then on the other side, some might be relevant as this is the same entity that changed its paths? + throw new Error('Data path is already set, we do not support changing the context data-path as of now.'); + } + if (!dataPath) return; + this.#baseDataPath = dataPath; + + this.consumeContext(UMB_VALIDATION_CONTEXT, (parent) => { + if (this.#parent) { + this.#parent.removeValidator(this); + } + this.#parent = parent; + parent.addValidator(this); + + this.messages.clear(); + + this.observe(parent.translationDataOf(dataPath), (data) => { + this.setTranslationData(data); + }); + + this.observe( + parent.messages.messagesOfPathAndDescendant(dataPath), + (msgs) => { + //this.messages.appendMessages(msgs); + if (this.#parentMessages) { + // Remove the local messages that does not exist in the parent anymore: + const toRemove = this.#parentMessages.filter((msg) => !msgs.find((m) => m.key === msg.key)); + toRemove.forEach((msg) => { + this.messages.removeMessageByKey(msg.key); + }); + } + this.#parentMessages = msgs; + msgs.forEach((msg) => { + const path = ReplaceStartOfString(msg.path, this.#baseDataPath!, '$'); + // Notice, the local message uses the same key. [NL] + this.messages.addMessage(msg.type, path, msg.body, msg.key); + }); + }, + 'observeParentMessages', + ); + + this.observe( + this.messages.messages, + (msgs) => { + if (!this.#parent) return; + //this.messages.appendMessages(msgs); + if (this.#localMessages) { + // Remove the parent messages that does not exist locally anymore: + const toRemove = this.#localMessages.filter((msg) => !msgs.find((m) => m.key === msg.key)); + toRemove.forEach((msg) => { + this.#parent!.messages.removeMessageByKey(msg.key); + }); + } + this.#localMessages = msgs; + msgs.forEach((msg) => { + // replace this.#baseDataPath (if it starts with it) with $ in the path, so it becomes relative to the parent context + const path = ReplaceStartOfString(msg.path, '$', this.#baseDataPath!); + // Notice, the parent message uses the same key. [NL] + this.#parent!.messages.addMessage(msg.type, path, msg.body, msg.key); + }); + }, + 'observeLocalMessages', + ); + }).skipHost(); + // Notice skipHost ^^, this is because we do not want it to consume it self, as this would be a match for this consumption, instead we will look at the parent and above. [NL] + } + + /** + * Get if this context is valid. + * Notice this does not verify the validity. + * @returns {boolean} + */ + get isValid(): boolean { + return this.#isValid; + } + + /** + * Add a validator to this context. + * This validator will have to be valid for the context to be valid. + * If the context is in validation mode, the validator will be validated immediately. + * @param validator { UmbValidator } - The validator to add to this context. + */ + addValidator(validator: UmbValidator): void { + if (this.#validators.includes(validator)) return; + this.#validators.push(validator); + //validator.addEventListener('change', this.#onValidatorChange); + if (this.#validationMode) { + this.validate(); + } + } + + /** + * Remove a validator from this context. + * @param validator {UmbValidator} - The validator to remove from this context. + */ + removeValidator(validator: UmbValidator): void { + const index = this.#validators.indexOf(validator); + if (index !== -1) { + // Remove the validator: + this.#validators.splice(index, 1); + // If we are in validation mode then we should re-validate to focus next invalid element: + if (this.#validationMode) { + this.validate(); + } + } + } + + /** + * Validate this context, all the validators of this context will be validated. + * Notice its a recursive check meaning sub validation contexts also validates their validators. + * @returns succeed {Promise} - Returns a promise that resolves to true if the validation succeeded. + */ + async validate(): Promise { + // TODO: clear server messages here?, well maybe only if we know we will get new server messages? Do the server messages hook into the system like another validator? + this.#validationMode = true; + + const resultsStatus = await Promise.all(this.#validators.map((v) => v.validate())).then( + () => Promise.resolve(true), + () => Promise.resolve(false), + ); + + if (!this.messages) { + // This Context has been destroyed while is was validating, so we should not continue. + return; + } + + // If we have any messages then we are not valid, otherwise lets check the validation results: [NL] + // This enables us to keep client validations though UI is not present anymore — because the client validations got defined as messages. [NL] + const isValid = this.messages.getHasAnyMessages() ? false : resultsStatus; + + this.#isValid = isValid; + + if (isValid === false) { + // Focus first invalid element: + this.focusFirstInvalidElement(); + return Promise.reject(); + } + + return Promise.resolve(); + } + + /** + * Focus the first invalid element that this context can find. + */ + focusFirstInvalidElement(): void { + const firstInvalid = this.#validators.find((v) => !v.isValid); + if (firstInvalid) { + firstInvalid.focusFirstInvalidElement(); + } + } + + /** + * Reset the validation state of this context. + */ + reset(): void { + this.#validationMode = false; + this.#validators.forEach((v) => v.reset()); + } + + #destroyValidators(): void { + if (this.#validators === undefined || this.#validators.length === 0) return; + this.#validators.forEach((validator) => { + validator.destroy(); + //validator.removeEventListener('change', this.#runValidate); + }); + this.#validators = []; + } + + override destroy(): void { + this.#providerCtrl = undefined; + if (this.#parent) { + this.#parent.removeValidator(this); + } + this.#parent = undefined; + this.#destroyValidators(); + this.messages?.destroy(); + (this.messages as unknown) = undefined; + super.destroy(); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/index.ts index d6ffbc4792..57b04ad199 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/index.ts @@ -1,3 +1,2 @@ export * from './default-workspace.context.js'; -export * from './submittable-workspace-context-base.js'; export * from './tokens/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts index daabfc3140..926b7d5fa6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts @@ -1,4 +1,4 @@ -import type { UmbSubmittableWorkspaceContextBase } from '../contexts/index.js'; +import type { UmbSubmittableWorkspaceContextBase } from '../submittable/index.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbRouterSlotElement } from '@umbraco-cms/backoffice/router'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-route-manager.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-route-manager.controller.ts index 44eb95bdfb..216844c0e7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-route-manager.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-route-manager.controller.ts @@ -1,19 +1,66 @@ import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; -import type { UmbRoute } from '@umbraco-cms/backoffice/router'; +import { UmbArrayState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; +import type { IComponentRoute, UmbRoute } from '@umbraco-cms/backoffice/router'; +/** + * The workspace route manager. + * @class UmbWorkspaceRouteManager + * @augments {UmbControllerBase} + */ export class UmbWorkspaceRouteManager extends UmbControllerBase { // #routes = new UmbArrayState([], (x) => x.path); public readonly routes = this.#routes.asObservable(); + #activeLocalPath = new UmbStringState(''); + + /** + * Set the routes for the workspace. + * @param {Array} routes The routes for the workspace. + * @memberof UmbWorkspaceRouteManager + */ setRoutes(routes: Array) { - this.#routes.setValue([ + const allRoutes = [ ...routes, { path: `**`, component: async () => (await import('@umbraco-cms/backoffice/router')).UmbRouteNotFoundElement, }, - ]); + ] as Array; + + const mappedRoutes = allRoutes.map((route) => { + // override the setup method to set the active local path + const oldSetupCallback = route.setup; + + route.setup = (_component: any, info: any) => { + this.#activeLocalPath.setValue(info.match.fragments.consumed); + + if (oldSetupCallback) { + oldSetupCallback(_component, info); + } + }; + + return route; + }); + + this.#routes.setValue([...mappedRoutes]); + } + + /** + * Get the routes for the workspace. + * @returns {Array} The routes for the workspace. + * @memberof UmbWorkspaceRouteManager + */ + getRoutes(): Array { + return this.#routes.getValue(); + } + + /** + * Get the active local path. + * @returns {*} {string} + * @memberof UmbWorkspaceRouteManager + */ + getActiveLocalPath(): string { + return this.#activeLocalPath.getValue(); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/index.ts new file mode 100644 index 0000000000..ad3eea1ea7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/index.ts @@ -0,0 +1 @@ +export type * from './workspace-data-manager.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/workspace-data-manager.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/workspace-data-manager.interface.ts new file mode 100644 index 0000000000..3f3a3d9685 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/workspace-data-manager.interface.ts @@ -0,0 +1,9 @@ +import type { UmbController } from '@umbraco-cms/backoffice/controller-api'; +import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; + +export interface UmbWorkspaceDataManager extends UmbController { + getPersisted(): ModelType | undefined; + getCurrent(): ModelType | undefined; + setPersisted(data: ModelType | undefined): void; + setCurrent(data: ModelType | undefined): void; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace-base.ts new file mode 100644 index 0000000000..4d9b9fad62 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace-base.ts @@ -0,0 +1,238 @@ +import { UmbSubmittableWorkspaceContextBase } from '../submittable/index.js'; +import { UmbEntityWorkspaceDataManager } from '../entity/entity-workspace-data-manager.js'; +import { UMB_WORKSPACE_PATH_PATTERN } from '../paths.js'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; +import { UMB_DISCARD_CHANGES_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; +import { + UmbRequestReloadChildrenOfEntityEvent, + UmbRequestReloadStructureForEntityEvent, +} from '@umbraco-cms/backoffice/entity-action'; +import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; +import { umbExtensionsRegistry, type ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbDetailRepository } from '@umbraco-cms/backoffice/repository'; + +export interface UmbEntityWorkspaceContextArgs { + entityType: string; + workspaceAlias: string; + detailRepositoryAlias: string; +} + +export interface UmbEntityDetailWorkspaceContextCreateArgs { + parent: UmbEntityModel; +} + +export abstract class UmbEntityDetailWorkspaceContextBase< + EntityModelType extends UmbEntityModel, + DetailRepositoryType extends UmbDetailRepository = UmbDetailRepository, +> extends UmbSubmittableWorkspaceContextBase { + /** + * @description Data manager for the workspace. + * @protected + * @memberof UmbEntityWorkspaceContextBase + */ + protected readonly _data = new UmbEntityWorkspaceDataManager(this); + + protected _getDataPromise?: Promise; + + protected _detailRepository?: DetailRepositoryType; + + #entityType: string; + + #parent = new UmbObjectState<{ entityType: string; unique: string | null } | undefined>(undefined); + readonly parentUnique = this.#parent.asObservablePart((parent) => (parent ? parent.unique : undefined)); + readonly parentEntityType = this.#parent.asObservablePart((parent) => (parent ? parent.entityType : undefined)); + + #initResolver?: () => void; + #initialized = false; + + #init = new Promise((resolve) => { + if (this.#initialized) { + resolve(); + } else { + this.#initResolver = resolve; + } + }); + + constructor(host: UmbControllerHost, args: UmbEntityWorkspaceContextArgs) { + super(host, args.workspaceAlias); + this.#entityType = args.entityType; + window.addEventListener('willchangestate', this.#onWillNavigate); + this.#observeRepository(args.detailRepositoryAlias); + } + + getEntityType() { + return this.#entityType; + } + + getData() { + return this._data.getCurrent(); + } + + getUnique() { + return this._data.getCurrent()?.unique; + } + + async load(unique: string) { + await this.#init; + this.resetState(); + this._getDataPromise = this._detailRepository!.requestByUnique(unique); + type GetDataType = Awaited['requestByUnique']>>; + const response = (await this._getDataPromise) as GetDataType; + const data = response.data; + + if (data) { + this.setIsNew(false); + this._data.setPersisted(data); + this._data.setCurrent(data); + } + + return response; + } + + public isLoaded() { + return this._getDataPromise; + } + + async submit() { + await this.#init; + const currentData = this._data.getCurrent(); + + if (!currentData) { + throw new Error('Data is not set'); + } + if (!currentData.unique) { + throw new Error('Unique is not set'); + } + + if (this.getIsNew()) { + const parent = this.#parent.getValue(); + if (!parent) throw new Error('Parent is not set'); + const { error, data } = await this._detailRepository!.create(currentData, parent.unique); + if (error || !data) { + throw error?.message ?? 'Repository did not return data after create.'; + } + + this._data.setPersisted(data); + + // TODO: this might not be the right place to alert the tree, but it works for now + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadChildrenOfEntityEvent({ + entityType: parent.entityType, + unique: parent.unique, + }); + eventContext.dispatchEvent(event); + this.setIsNew(false); + } else { + const { error, data } = await this._detailRepository!.save(currentData); + if (error || !data) { + throw error?.message ?? 'Repository did not return data after create.'; + } + + this._data.setPersisted(data); + + const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadStructureForEntityEvent({ + unique: this.getUnique()!, + entityType: this.getEntityType(), + }); + + actionEventContext.dispatchEvent(event); + } + } + + async create(args: UmbEntityDetailWorkspaceContextCreateArgs) { + await this.#init; + this.resetState(); + this.#parent.setValue(args.parent); + const request = this._detailRepository!.createScaffold(); + this._getDataPromise = request; + let { data } = await request; + if (!data) return undefined; + + if (this.modalContext) { + data = { ...data, ...this.modalContext.data.preset }; + } + this.setIsNew(true); + this._data.setPersisted(data); + this._data.setCurrent(data); + return data; + } + + async delete(unique: string) { + await this.#init; + await this._detailRepository!.delete(unique); + } + + /** + * @description method to check if the workspace is about to navigate away. + * @protected + * @param {string} newUrl + * @returns {*} + * @memberof UmbEntityWorkspaceContextBase + */ + protected _checkWillNavigateAway(newUrl: string) { + const workspaceBasePath = UMB_WORKSPACE_PATH_PATTERN.generateLocal({ entityType: this.getEntityType() }); + const currentWorkspacePathIdentifier = '/' + workspaceBasePath + '/' + this.routes.getActiveLocalPath(); + return !newUrl.includes(currentWorkspacePathIdentifier); + } + + #onWillNavigate = async (e: CustomEvent) => { + const newUrl = e.detail.url; + + if (this._checkWillNavigateAway(newUrl) && this._data.getHasUnpersistedChanges()) { + e.preventDefault(); + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const modal = modalManager.open(this, UMB_DISCARD_CHANGES_MODAL); + + try { + // navigate to the new url when discarding changes + await modal.onSubmit(); + // Reset the current data so we don't end in a endless loop of asking to discard changes. + this._data.resetCurrent(); + history.pushState({}, '', e.detail.url); + return true; + } catch { + return false; + } + } + + return true; + }; + + override resetState() { + super.resetState(); + this._data.clear(); + } + + #checkIfInitialized() { + if (this._detailRepository) { + this.#initialized = true; + this.#initResolver?.(); + } + } + + #observeRepository(repositoryAlias: string) { + if (!repositoryAlias) throw new Error('Entity Workspace must have a repository alias.'); + + new UmbExtensionApiInitializer>( + this, + umbExtensionsRegistry, + repositoryAlias, + [this._host], + (permitted, ctrl) => { + this._detailRepository = permitted ? ctrl.api : undefined; + this.#checkIfInitialized(); + }, + ); + } + + public override destroy(): void { + this._data.destroy(); + this._detailRepository?.destroy(); + window.removeEventListener('willchangestate', this.#onWillNavigate); + super.destroy(); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/index.ts new file mode 100644 index 0000000000..df254d21f0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/index.ts @@ -0,0 +1 @@ +export * from './entity-detail-workspace-base.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/entity-workspace-data-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/entity-workspace-data-manager.ts new file mode 100644 index 0000000000..ab21d9476a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/entity-workspace-data-manager.ts @@ -0,0 +1,141 @@ +import type { UmbWorkspaceDataManager } from '../data-manager/workspace-data-manager.interface.js'; +import { jsonStringComparison, UmbObjectState, type MappingFunction } from '@umbraco-cms/backoffice/observable-api'; +import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; + +/** + * Manages the workspace data for an entity. + * @class UmbEntityWorkspaceDataManager + * @augments {UmbControllerBase} + * @implements {UmbWorkspaceDataManager} + * @template ModelType + */ +export class UmbEntityWorkspaceDataManager + extends UmbControllerBase + implements UmbWorkspaceDataManager +{ + #persisted = new UmbObjectState(undefined); + #current = new UmbObjectState(undefined); + + /** + * Observable of the persisted data + * @memberof UmbEntityWorkspaceDataManager + */ + public readonly persisted = this.#persisted.asObservable(); + + /** + * Observable of the current data + * @memberof UmbEntityWorkspaceDataManager + */ + public readonly current = this.#current.asObservable(); + + /** + * Gets persisted data + * @returns {(ModelType | undefined)} + * @memberof UmbSubmittableWorkspaceDataManager + */ + getPersisted() { + return this.#persisted.getValue(); + } + + /** + * Sets the persisted data + * @param {(ModelType | undefined)} data + * @memberof UmbSubmittableWorkspaceDataManager + */ + setPersisted(data: ModelType | undefined) { + this.#persisted.setValue(data); + } + + /** + * Updates the persisted data + * @param {Partial} partialData + * @memberof UmbSubmittableWorkspaceDataManager + */ + updatePersisted(partialData: Partial) { + this.#persisted.update(partialData); + } + + /** + * Creates an observable part of the persisted data + * @template ReturnType + * @param {(MappingFunction)} mappingFunction + * @returns {*} + * @memberof UmbEntityWorkspaceDataManager + */ + createObservablePartOfPersisted(mappingFunction: MappingFunction) { + return this.#persisted.asObservablePart(mappingFunction); + } + + /** + * Gets the current data + * @returns {(ModelType | undefined)} + * @memberof UmbSubmittableWorkspaceDataManager + */ + getCurrent() { + return this.#current.getValue(); + } + + /** + * Sets the current data + * @param {(ModelType | undefined)} data + * @memberof UmbSubmittableWorkspaceDataManager + */ + setCurrent(data: ModelType | undefined) { + this.#current.setValue(data); + } + + /** + * Updates the current data + * @param {Partial} partialData + * @memberof UmbSubmittableWorkspaceDataManager + */ + updateCurrent(partialData: Partial) { + this.#current.update(partialData); + } + + /** + * Creates an observable part of the current data + * @template ReturnType + * @param {(MappingFunction)} mappingFunction + * @returns {*} + * @memberof UmbEntityWorkspaceDataManager + */ + createObservablePartOfCurrent(mappingFunction: MappingFunction) { + return this.#current.asObservablePart(mappingFunction); + } + + /** + * Checks if there are unpersisted changes + * @returns {*} + * @memberof UmbSubmittableWorkspaceDataManager + */ + getHasUnpersistedChanges() { + const persisted = this.#persisted.getValue(); + const current = this.#current.getValue(); + return jsonStringComparison(persisted, current) === false; + } + + /** + * Resets the current data to the persisted data + * @memberof UmbSubmittableWorkspaceDataManager + */ + resetCurrent() { + this.#current.setValue(this.#persisted.getValue()); + } + + /** + * Clears the data + * @memberof UmbSubmittableWorkspaceDataManager + */ + clear() { + this.#persisted.setValue(undefined); + this.#current.setValue(undefined); + } + + override destroy() { + this.#persisted.destroy(); + this.#current.destroy(); + super.destroy(); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/index.ts new file mode 100644 index 0000000000..fb57f1db7c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/index.ts @@ -0,0 +1 @@ +export * from './entity-workspace-data-manager.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts index 0896610ff9..79765fee3f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts @@ -1,10 +1,14 @@ export * from './components/index.js'; export * from './contexts/index.js'; export * from './controllers/index.js'; +export * from './data-manager/index.js'; +export * from './entity/index.js'; +export * from './entity-detail/index.js'; export * from './modals/index.js'; +export * from './paths.js'; +export * from './submittable/index.js'; export * from './workspace-property-dataset/index.js'; export * from './workspace.element.js'; -export * from './paths.js'; export type * from './conditions/index.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/index.ts index c5c54c9ab0..5cfe6c1fb5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/index.ts @@ -1 +1,2 @@ export * from './workspace-modal.element.js'; +export * from './workspace-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.element.ts index 57361e17e6..40fd96f0ef 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.element.ts @@ -1,7 +1,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbWorkspaceModalData } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData } from '@umbraco-cms/backoffice/workspace'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-workspace-modal') diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/workspace-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.token.ts similarity index 86% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/token/workspace-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.token.ts index 27b52e61bf..b78617a648 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/workspace-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.token.ts @@ -1,4 +1,4 @@ -import { UmbModalToken } from './modal-token.js'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbWorkspaceModalData { entityType: string; preset: Partial; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/submittable/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/submittable/index.ts new file mode 100644 index 0000000000..2a8160c8b5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/submittable/index.ts @@ -0,0 +1 @@ +export * from './submittable-workspace-context-base.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/submittable-workspace-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/submittable/submittable-workspace-context-base.ts similarity index 92% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/submittable-workspace-context-base.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/submittable/submittable-workspace-context-base.ts index ccc13c9526..3ee9e75874 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/submittable-workspace-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/submittable/submittable-workspace-context-base.ts @@ -1,13 +1,13 @@ import { UmbWorkspaceRouteManager } from '../controllers/workspace-route-manager.controller.js'; -import { UMB_WORKSPACE_CONTEXT } from './tokens/workspace.context-token.js'; -import type { UmbSubmittableWorkspaceContext } from './tokens/submittable-workspace-context.interface.js'; +import { UMB_WORKSPACE_CONTEXT } from '../contexts/tokens/workspace.context-token.js'; +import type { UmbSubmittableWorkspaceContext } from '../contexts/tokens/submittable-workspace-context.interface.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbModalContext } from '@umbraco-cms/backoffice/modal'; import { UMB_MODAL_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import type { UmbValidationContext } from '@umbraco-cms/backoffice/validation'; +import type { UmbValidationController } from '@umbraco-cms/backoffice/validation'; export abstract class UmbSubmittableWorkspaceContextBase extends UmbContextBase> @@ -19,13 +19,13 @@ export abstract class UmbSubmittableWorkspaceContextBase public readonly modalContext?: UmbModalContext<{ preset: object }>; //public readonly validation = new UmbValidationContext(this); - #validationContexts: Array = []; + #validationContexts: Array = []; /** * Appends a validation context to the workspace. * @param context */ - addValidationContext(context: UmbValidationContext) { + addValidationContext(context: UmbValidationController) { this.#validationContexts.push(context); } @@ -141,7 +141,7 @@ export abstract class UmbSubmittableWorkspaceContextBase }; //abstract getIsDirty(): Promise; - abstract getUnique(): string | undefined; + abstract getUnique(): string | null | undefined; abstract getEntityType(): string; abstract getData(): WorkspaceDataModelType | undefined; protected abstract submit(): Promise; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/create/manifests.ts index d8e013cc24..6f3aaa1dee 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/create/manifests.ts @@ -12,6 +12,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/manifests.ts index 253bef89c2..f93db92b61 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/manifests.ts @@ -1,10 +1,4 @@ export const manifests: Array = [ - { - type: 'modal', - alias: 'Umb.Modal.PropertyEditorUiPicker', - name: 'Property Editor UI Picker Modal', - element: () => import('./property-editor-ui-picker/property-editor-ui-picker-modal.element.js'), - }, { type: 'modal', alias: 'Umb.Modal.DataTypePickerFlow', diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/constants.ts new file mode 100644 index 0000000000..6441da8735 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/constants.ts @@ -0,0 +1 @@ +export const UMB_DATA_TYPE_WORKSPACE_ALIAS = 'Umb.Workspace.DataType'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts index 0f8bb744ec..590ce04c26 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts @@ -1,33 +1,25 @@ import type { UmbDataTypeDetailModel, UmbDataTypePropertyModel } from '../types.js'; -import { UmbDataTypeDetailRepository } from '../repository/detail/data-type-detail.repository.js'; +import { type UmbDataTypeDetailRepository, UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../repository/index.js'; +import { UMB_DATA_TYPE_ENTITY_TYPE } from '../entity.js'; import { UmbDataTypeWorkspaceEditorElement } from './data-type-workspace-editor.element.js'; +import { UMB_DATA_TYPE_WORKSPACE_ALIAS } from './constants.js'; import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; import type { UmbInvariantDatasetWorkspaceContext, UmbRoutableWorkspaceContext, } from '@umbraco-cms/backoffice/workspace'; import { - UmbSubmittableWorkspaceContextBase, UmbInvariantWorkspacePropertyDatasetContext, UmbWorkspaceIsNewRedirectController, + UmbEntityDetailWorkspaceContextBase, } from '@umbraco-cms/backoffice/workspace'; -import { - appendToFrozenArray, - UmbArrayState, - UmbObjectState, - UmbStringState, -} from '@umbraco-cms/backoffice/observable-api'; +import { appendToFrozenArray, UmbArrayState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { PropertyEditorSettingsDefaultData, PropertyEditorSettingsProperty, } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { - UmbRequestReloadChildrenOfEntityEvent, - UmbRequestReloadStructureForEntityEvent, -} from '@umbraco-cms/backoffice/entity-action'; import { UmbValidationContext } from '@umbraco-cms/backoffice/validation'; type EntityType = UmbDataTypeDetailModel; @@ -50,31 +42,15 @@ type EntityType = UmbDataTypeDetailModel; * - a new property editor ui is picked for a data-type, uses the data-type configuration to set the schema, if such is configured for the Property Editor UI. (The user picks the UI via the UI, the schema comes from the UI that the user picked, we store both on the data-type) */ export class UmbDataTypeWorkspaceContext - extends UmbSubmittableWorkspaceContextBase + extends UmbEntityDetailWorkspaceContextBase implements UmbInvariantDatasetWorkspaceContext, UmbRoutableWorkspaceContext { - // - public readonly repository: UmbDataTypeDetailRepository = new UmbDataTypeDetailRepository(this); + readonly name = this._data.createObservablePartOfCurrent((data) => data?.name); + readonly unique = this._data.createObservablePartOfCurrent((data) => data?.unique); + readonly entityType = this._data.createObservablePartOfCurrent((data) => data?.entityType); - #parent = new UmbObjectState<{ entityType: string; unique: string | null } | undefined>(undefined); - readonly parentUnique = this.#parent.asObservablePart((parent) => (parent ? parent.unique : undefined)); - readonly parentEntityType = this.#parent.asObservablePart((parent) => (parent ? parent.entityType : undefined)); - - #persistedData = new UmbObjectState(undefined); - #currentData = new UmbObjectState(undefined); - - #getDataPromise?: Promise; - - public isLoaded() { - return this.#getDataPromise; - } - - readonly name = this.#currentData.asObservablePart((data) => data?.name); - readonly unique = this.#currentData.asObservablePart((data) => data?.unique); - readonly entityType = this.#currentData.asObservablePart((data) => data?.entityType); - - readonly propertyEditorUiAlias = this.#currentData.asObservablePart((data) => data?.editorUiAlias); - readonly propertyEditorSchemaAlias = this.#currentData.asObservablePart((data) => data?.editorAlias); + readonly propertyEditorUiAlias = this._data.createObservablePartOfCurrent((data) => data?.editorUiAlias); + readonly propertyEditorSchemaAlias = this._data.createObservablePartOfCurrent((data) => data?.editorAlias); #properties = new UmbArrayState([], (x) => x.alias).sortBy( (a, b) => (a.weight || 0) - (b.weight || 0), @@ -98,9 +74,13 @@ export class UmbDataTypeWorkspaceContext readonly propertyEditorUiName = this.#propertyEditorUiName.asObservable(); constructor(host: UmbControllerHost) { - super(host, 'Umb.Workspace.DataType'); + super(host, { + workspaceAlias: UMB_DATA_TYPE_WORKSPACE_ALIAS, + entityType: UMB_DATA_TYPE_ENTITY_TYPE, + detailRepositoryAlias: UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS, + }); - this.addValidationContext(new UmbValidationContext(this).provide()); + this.addValidationContext(new UmbValidationContext(this)); this.#observePropertyEditorSchemaAlias(); this.#observePropertyEditorUIAlias(); @@ -112,7 +92,7 @@ export class UmbDataTypeWorkspaceContext setup: (_component, info) => { const parentEntityType = info.match.params.entityType; const parentUnique = info.match.params.parentUnique === 'null' ? null : info.match.params.parentUnique; - this.create({ entityType: parentEntityType, unique: parentUnique }); + this.create({ parent: { entityType: parentEntityType, unique: parentUnique } }); new UmbWorkspaceIsNewRedirectController( this, @@ -132,16 +112,26 @@ export class UmbDataTypeWorkspaceContext ]); } + override async load(unique: string) { + const response = await super.load(unique); + this.observe(response.asObservable?.(), (entity) => this.#onStoreChange(entity), 'umbDataTypeStoreObserver'); + return response; + } + + #onStoreChange(entity: EntityType | undefined) { + if (!entity) { + //TODO: This solution is alright for now. But reconsider when we introduce signal-r + history.pushState(null, '', 'section/settings/workspace/data-type-root'); + } + } + override resetState() { super.resetState(); - this.#persistedData.setValue(undefined); - this.#currentData.setValue(undefined); this.#propertyEditorSchemaSettingsProperties = []; this.#propertyEditorUISettingsProperties = []; this.#propertyEditorSchemaSettingsDefaultData = []; this.#propertyEditorUISettingsDefaultData = []; this.#settingsDefaultData = undefined; - this.#mergeConfigProperties(); } @@ -249,7 +239,7 @@ export class UmbDataTypeWorkspaceContext #transferConfigDefaultData() { if (!this.#propertyEditorSchemaSettingsDefaultData || !this.#propertyEditorUISettingsDefaultData) return; - const data = this.#currentData.getValue(); + const data = this._data.getCurrent(); if (!data) return; this.#settingsDefaultData = [ @@ -258,8 +248,8 @@ export class UmbDataTypeWorkspaceContext ] satisfies Array; // We check for satisfied type, because we will be directly transferring them to become value. Future note, if they are not satisfied, we need to transfer alias and value. [NL] - this.#persistedData.update({ values: this.#settingsDefaultData }); - this.#currentData.update({ values: this.#settingsDefaultData }); + this._data.updatePersisted({ values: this.#settingsDefaultData }); + this._data.updateCurrent({ values: this.#settingsDefaultData }); } public getPropertyDefaultValue(alias: string) { @@ -270,78 +260,28 @@ export class UmbDataTypeWorkspaceContext return new UmbInvariantWorkspacePropertyDatasetContext(host, this); } - async load(unique: string) { - this.resetState(); - this.#getDataPromise = this.repository.requestByUnique(unique); - type GetDataType = Awaited>; - const { data, asObservable } = (await this.#getDataPromise) as GetDataType; - if (!data) return undefined; - - if (data) { - this.setIsNew(false); - this.#persistedData.setValue(data); - this.#currentData.setValue(data); - } - - if (asObservable) { - this.observe(asObservable(), (entity) => this.#onStoreChange(entity), 'umbDataTypeStoreObserver'); - } - } - - #onStoreChange(entity: EntityType | undefined) { - if (!entity) { - //TODO: This solution is alright for now. But reconsider when we introduce signal-r - history.pushState(null, '', 'section/settings/workspace/data-type-root'); - } - } - - async create(parent: { entityType: string; unique: string | null }) { - this.resetState(); - this.#parent.setValue(parent); - const request = this.repository.createScaffold(); - this.#getDataPromise = request; - let { data } = await request; - if (!data) return undefined; - - if (this.modalContext) { - data = { ...data, ...this.modalContext.data.preset }; - } - this.setIsNew(true); - this.#persistedData.setValue(data); - this.#currentData.setValue(data); - return data; - } - - getData() { - return this.#currentData.getValue(); - } - - getUnique() { - return this.getData()?.unique || ''; - } - - getEntityType() { - return 'data-type'; - } - getName() { - return this.#currentData.getValue()?.name; + return this._data.getCurrent()?.name; } + setName(name: string | undefined) { - this.#currentData.update({ name }); + this._data.updateCurrent({ name }); } getPropertyEditorSchemaAlias() { - return this.#currentData.getValue()?.editorAlias; + return this._data.getCurrent()?.editorAlias; } + setPropertyEditorSchemaAlias(alias?: string) { - this.#currentData.update({ editorAlias: alias }); + this._data.updateCurrent({ editorAlias: alias }); } + getPropertyEditorUiAlias() { - return this.#currentData.getValue()?.editorUiAlias; + return this._data.getCurrent()?.editorUiAlias; } + setPropertyEditorUiAlias(alias?: string) { - this.#currentData.update({ editorUiAlias: alias }); + this._data.updateCurrent({ editorUiAlias: alias }); } /** @@ -351,83 +291,36 @@ export class UmbDataTypeWorkspaceContext * @description Get an Observable for the value of this property. */ async propertyValueByAlias(propertyAlias: string) { - await this.#getDataPromise; - return this.#currentData.asObservablePart( + await this._getDataPromise; + return this._data.createObservablePartOfCurrent( (data) => data?.values?.find((x) => x.alias === propertyAlias)?.value as ReturnType, ); } getPropertyValue(propertyAlias: string) { return ( - (this.#currentData.getValue()?.values?.find((x) => x.alias === propertyAlias)?.value as ReturnType) ?? + (this._data.getCurrent()?.values?.find((x) => x.alias === propertyAlias)?.value as ReturnType) ?? (this.getPropertyDefaultValue(propertyAlias) as ReturnType) ); } // TODO: its not called a property in the model, but we do consider this way in our front-end async setPropertyValue(alias: string, value: unknown) { - await this.#getDataPromise; + await this._getDataPromise; const entry = { alias: alias, value: value }; - const currentData = this.#currentData.value; + const currentData = this._data.getCurrent(); if (currentData) { // TODO: make a partial update method for array of data, (idea/concept, use if this case is getting common) const newDataSet = appendToFrozenArray(currentData.values || [], entry, (x) => x.alias); - this.#currentData.update({ values: newDataSet }); + this._data.updateCurrent({ values: newDataSet }); } } - async submit() { - if (!this.#currentData.value) { - throw new Error('Data is not set'); - } - if (!this.#currentData.value.unique) { - throw new Error('Unique is not set'); - } - - if (this.getIsNew()) { - const parent = this.#parent.getValue(); - if (!parent) throw new Error('Parent is not set'); - const { error, data } = await this.repository.create(this.#currentData.value, parent.unique); - if (error || !data) { - throw error?.message ?? 'Repository did not return data after create.'; - } - - // TODO: this might not be the right place to alert the tree, but it works for now - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadChildrenOfEntityEvent({ - entityType: parent.entityType, - unique: parent.unique, - }); - eventContext.dispatchEvent(event); - this.setIsNew(false); - } else { - const { error, data } = await this.repository.save(this.#currentData.value); - if (error || !data) { - throw error?.message ?? 'Repository did not return data after create.'; - } - - const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadStructureForEntityEvent({ - unique: this.getUnique()!, - entityType: this.getEntityType(), - }); - - actionEventContext.dispatchEvent(event); - } - } - - async delete(unique: string) { - await this.repository.delete(unique); - } - public override destroy(): void { - this.#persistedData.destroy(); - this.#currentData.destroy(); this.#properties.destroy(); this.#propertyEditorUiIcon.destroy(); this.#propertyEditorUiName.destroy(); - this.repository.destroy(); super.destroy(); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.modal-token.ts index 457a0f5ff4..2629211daf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.modal-token.ts @@ -1,5 +1,5 @@ import type { UmbDataTypeDetailModel } from '../types.js'; -import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/workspace'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export const UMB_DATATYPE_WORKSPACE_MODAL = new UmbModalToken< diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/manifests.ts index 769a7498b5..06c4007e1e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/manifests.ts @@ -1,7 +1,6 @@ +import { UMB_DATA_TYPE_WORKSPACE_ALIAS } from './constants.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; -const UMB_DATA_TYPE_WORKSPACE_ALIAS = 'Umb.Workspace.DataType'; - export const manifests: Array = [ { type: 'workspace', diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/details/data-type-details-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/details/data-type-details-workspace-view.element.ts index 3d19245fe3..8b246fd9f3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/details/data-type-details-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/details/data-type-details-workspace-view.element.ts @@ -2,7 +2,8 @@ import { UMB_DATA_TYPE_WORKSPACE_CONTEXT } from '../../data-type-workspace.conte import { css, customElement, html, nothing, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UMB_MODAL_MANAGER_CONTEXT, UMB_PROPERTY_EDITOR_UI_PICKER_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_PROPERTY_EDITOR_UI_PICKER_MODAL } from '@umbraco-cms/backoffice/property-editor'; import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/workspace'; import { umbBindToValidation } from '@umbraco-cms/backoffice/validation'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/data-type-workspace-view-info-reference.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/data-type-workspace-view-info-reference.element.ts index 5e34b90128..a1f0d2476f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/data-type-workspace-view-info-reference.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/data-type-workspace-view-info-reference.element.ts @@ -3,7 +3,7 @@ import type { UmbDataTypeReferenceModel } from '../../../reference/index.js'; import { css, html, customElement, state, repeat, property, when } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/manifests.ts index e4fc381c29..8b70942952 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/manifests.ts @@ -13,7 +13,8 @@ export const manifests: Array = [ forEntityTypes: [UMB_DICTIONARY_ENTITY_TYPE, UMB_DICTIONARY_ROOT_ENTITY_TYPE], meta: { icon: 'icon-add', - label: '#dictionary_createNew', + label: '#general_create', + additionalOptions: true, }, }, { @@ -27,6 +28,7 @@ export const manifests: Array = [ meta: { icon: 'icon-download-alt', label: '#actions_export', + additionalOptions: true, }, }, { @@ -40,6 +42,7 @@ export const manifests: Array = [ meta: { icon: 'icon-page-up', label: '#actions_import', + additionalOptions: true, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/manifests.ts index 859efb2dd0..46a67c103b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/manifests.ts @@ -12,6 +12,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_createblueprint', + additionalOptions: true, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts index 8d211bad4c..acb3437977 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts @@ -92,6 +92,7 @@ export class UmbDocumentBlueprintServerDataSource implements UmbDetailDataSource unique: data.id, values: data.values.map((value) => { return { + editorAlias: value.editorAlias, alias: value.alias, culture: value.culture || null, segment: value.segment || null, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts index 214e9ba02e..7098648af1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts @@ -292,7 +292,17 @@ export class UmbDocumentBlueprintWorkspaceContext ) { if (!variantId) throw new Error('VariantId is missing'); - const entry = { ...variantId.toObject(), alias, value }; + const property = await this.structure.getPropertyStructureByAlias(alias); + + if (!property) { + throw new Error(`Property alias "${alias}" not found.`); + } + + //const dataType = await this.#dataTypeItemManager.getItemByUnique(property.dataType.unique); + //const editorAlias = dataType.editorAlias; + const editorAlias = 'Umbraco.TextBox'; + + const entry = { ...variantId.toObject(), alias, editorAlias, value }; const currentData = this.#currentData.value; if (currentData) { const values = appendToFrozenArray( diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/manifests.ts index 9a74346977..2879df41cf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/manifests.ts @@ -12,6 +12,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/export/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/export/manifests.ts index 508e76f36c..100037da23 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/export/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/export/manifests.ts @@ -12,6 +12,7 @@ export const manifests: Array = [ meta: { icon: 'icon-download-alt', label: '#actions_export', + additionalOptions: true, }, }, ...repositoryManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/import/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/import/manifests.ts index fb1f2d8ca7..8d39bb23e7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/import/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/import/manifests.ts @@ -13,6 +13,7 @@ export const manifests: Array = [ meta: { icon: 'icon-page-up', label: '#actions_import', + additionalOptions: true, }, }, ...repositoryManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/manifests.ts index 9dc3d4d032..e7b191bda3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/manifests.ts @@ -19,6 +19,7 @@ export const manifests: Array = [ meta: { itemRepositoryAlias: UMB_DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS, detailRepositoryAlias: UMB_DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS, + additionalOptions: true, }, }, ...createManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts index 18f4a74ced..f12529bed3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts @@ -2,7 +2,8 @@ import { UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT } from './document-type-workspace.c import type { UmbInputWithAliasElement } from '@umbraco-cms/backoffice/components'; import { umbFocus, UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { css, html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; -import { UMB_MODAL_MANAGER_CONTEXT, UMB_ICON_PICKER_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_ICON_PICKER_MODAL } from '@umbraco-cms/backoffice/icon'; import type { UUITextareaElement } from '@umbraco-cms/backoffice/external/uui'; import { umbBindToValidation } from '@umbraco-cms/backoffice/validation'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts index 65ab3f5c5f..a18f945efd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts @@ -80,7 +80,7 @@ export class UmbDocumentTypeWorkspaceContext constructor(host: UmbControllerHost) { super(host, 'Umb.Workspace.DocumentType'); - this.addValidationContext(new UmbValidationContext(this).provide()); + this.addValidationContext(new UmbValidationContext(this)); // General for content types: //this.data = this.structure.ownerContentType; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.modal-token.ts index b0bd378a3f..46162c38e0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.modal-token.ts @@ -1,7 +1,8 @@ import { UMB_DOCUMENT_TYPE_ENTITY_TYPE } from '../entity.js'; -import { UMB_WORKSPACE_MODAL, UmbModalToken } from '@umbraco-cms/backoffice/modal'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import type { UmbDeepPartialObject } from '@umbraco-cms/backoffice/utils'; -import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/workspace'; // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbDocumentTypeWorkspaceData extends UmbWorkspaceModalData {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/action/create-document-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/action/create-document-collection-action.element.ts index 91b87ac52a..29e72c693b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/action/create-document-collection-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/action/create-document-collection-action.element.ts @@ -8,7 +8,7 @@ import { UMB_DOCUMENT_ROOT_ENTITY_TYPE, UMB_DOCUMENT_WORKSPACE_CONTEXT, } from '@umbraco-cms/backoffice/document'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import type { ManifestCollectionAction } from '@umbraco-cms/backoffice/collection'; import type { UmbAllowedDocumentTypeModel } from '@umbraco-cms/backoffice/document-type'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/grid/document-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/grid/document-grid-collection-view.element.ts index 5218ca0e54..4f23a12d88 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/grid/document-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/grid/document-grid-collection-view.element.ts @@ -7,7 +7,7 @@ import { fromCamelCase } from '@umbraco-cms/backoffice/utils'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import type { UmbDefaultCollectionContext, UmbCollectionColumnConfiguration } from '@umbraco-cms/backoffice/collection'; import type { UUIInterfaceColor } from '@umbraco-cms/backoffice/external/uui'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts index e82195fe67..c01986a218 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts @@ -7,7 +7,7 @@ import type { UmbCollectionColumnConfiguration } from '@umbraco-cms/backoffice/c import { css, customElement, html, nothing, state, when } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import type { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts index 7799fc1260..7ade0434a2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts @@ -14,7 +14,7 @@ import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import type { UmbDocumentItemModel } from '@umbraco-cms/backoffice/document'; import type { UmbTreeStartNode } from '@umbraco-cms/backoffice/tree'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/manifests.ts index 349f70422e..95fbbaf9f3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/manifests.ts @@ -14,6 +14,7 @@ export const manifests: Array = [ meta: { icon: 'icon-blueprint', label: '#actions_createblueprint', + additionalOptions: true, }, conditions: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts index 3f6751d76b..a0eca87a0e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts @@ -132,24 +132,39 @@ export class UmbDocumentCreateOptionsModalElement extends UmbModalBaseElement< `; } + #renderNoDocumentTypes() { + if (this.data?.documentType?.unique) { + return html` + + There are no allowed Document Types available for creating content here. You must enable these in + Document Types within the Settings section, by editing the + Allowed child node types under Structure. + +
+ this._rejectModal()}> + `; + } else { + return html` + + There are no allowed Document Types available for creating content here. You must enable these in + Document Types within the Settings section, by changing the + Allow as root option under Structure. + + `; + } + } + #renderDocumentTypes() { return html` ${when( this._allowedDocumentTypes.length === 0, - () => html` - - There are no allowed Document Types available for creating content here. You must enable these in - Document Types within the Settings section, by editing the - Allowed child node types under Permissions.
-
- this._rejectModal()}> - `, + () => this.#renderNoDocumentTypes(), () => repeat( this._allowedDocumentTypes, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/manifests.ts index a43e8aff22..be6a0c6c23 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/manifests.ts @@ -14,6 +14,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, conditions: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames/manifests.ts index 30b6a408f0..7ef0929693 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames/manifests.ts @@ -14,6 +14,7 @@ export const manifests: Array = [ meta: { icon: 'icon-home', label: '#actions_assigndomain', + additionalOptions: true, }, conditions: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts index 504dd89848..3825245423 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts @@ -51,6 +51,7 @@ const entityActions: Array = [ meta: { icon: 'icon-globe', label: '#actions_publish', + additionalOptions: true, }, conditions: [ { @@ -73,6 +74,7 @@ const entityActions: Array = [ meta: { icon: 'icon-globe', label: '#actions_unpublish', + additionalOptions: true, }, conditions: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/manifests.ts index 109b596631..9cb74c9fcb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/manifests.ts @@ -17,6 +17,7 @@ const actionManifests: Array = [ meta: { icon: 'icon-megaphone', label: '#actions_notify', + additionalOptions: true, }, conditions: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/manifests.ts index 7bbcfed7df..7a6cb6bf24 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/manifests.ts @@ -14,6 +14,7 @@ export const manifests: Array = [ meta: { icon: 'icon-lock', label: '#actions_protect', + additionalOptions: true, }, conditions: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/manifests.ts index 990009a509..41a9ecade2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/manifests.ts @@ -18,6 +18,7 @@ export const manifests: Array = [ itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS, sortChildrenOfRepositoryAlias: UMB_SORT_CHILDREN_OF_DOCUMENT_REPOSITORY_ALIAS, treeRepositoryAlias: UMB_DOCUMENT_TREE_REPOSITORY_ALIAS, + additionalOptions: true, }, conditions: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts index ea03ccd083..46708951d5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts @@ -92,6 +92,7 @@ export class UmbDocumentServerDataSource implements UmbDetailDataSource { return { + editorAlias: value.editorAlias, alias: value.alias, culture: value.culture || null, segment: value.segment || null, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts index dc605b47f8..e7d27e5f1b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts @@ -4,12 +4,13 @@ import { UMB_DOCUMENT_PICKER_MODAL } from '../../modals/index.js'; import { css, customElement, html, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; -import { UMB_ENTITY_USER_PERMISSION_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { UmbDeselectedEvent } from '@umbraco-cms/backoffice/event'; import { UmbChangeEvent, UmbSelectedEvent } from '@umbraco-cms/backoffice/event'; import type { ManifestEntityUserPermission } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; +import { UMB_ENTITY_USER_PERMISSION_MODAL } from '@umbraco-cms/backoffice/user-permission'; @customElement('umb-input-document-granular-user-permission') export class UmbInputDocumentGranularUserPermissionElement extends UUIFormControlMixin(UmbLitElement, '') { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index 9f11620d47..59fdf9f187 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -171,7 +171,7 @@ export class UmbDocumentWorkspaceContext constructor(host: UmbControllerHost) { super(host, UMB_DOCUMENT_WORKSPACE_ALIAS); - this.addValidationContext(new UmbValidationContext(this).provide()); + this.addValidationContext(new UmbValidationContext(this)); new UmbVariantValuesValidationPathTranslator(this); new UmbVariantsValidationPathTranslator(this); @@ -415,6 +415,7 @@ export class UmbDocumentWorkspaceContext } async setPropertyValue(alias: string, value: ValueType, variantId?: UmbVariantId) { variantId ??= UmbVariantId.CreateInvariant(); + //const property = await this.structure.getPropertyStructureByAlias(alias); const entry = { ...variantId.toObject(), alias, value } as UmbDocumentValueModel; const currentData = this.getData(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-reference.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-reference.element.ts index b1324e5ac9..28ad1b37ae 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-reference.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-reference.element.ts @@ -3,7 +3,7 @@ import { css, html, customElement, state, nothing, repeat, property } from '@umb import type { UUIPaginationEvent } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { isDefaultReference, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts index 13344c29a1..b5e16de658 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts @@ -5,7 +5,8 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/document'; -import { UMB_MODAL_MANAGER_CONTEXT, UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UMB_TEMPLATE_PICKER_MODAL, UmbTemplateItemRepository } from '@umbraco-cms/backoffice/template'; import type { DocumentUrlInfoModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbDocumentTypeDetailModel } from '@umbraco-cms/backoffice/document-type'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/index.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/index.ts similarity index 53% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/embedded-media/index.ts index 3d76f338dd..e130217e61 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/index.ts @@ -1 +1,2 @@ +export * from './modal/index.js'; export * from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/embedded-media/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/manifests.ts new file mode 100644 index 0000000000..6b7cf27f51 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as modalManifests } from './modal/manifests.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; + +export const manifests: Array = [...modalManifests, ...repositoryManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/embedded-media-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.element.ts similarity index 97% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/embedded-media-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.element.ts index 9125e64aaf..fcf5ff01a6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/embedded-media-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.element.ts @@ -1,7 +1,7 @@ -import { UmbOEmbedRepository } from './repository/oembed.repository.js'; +import { UmbOEmbedRepository } from '../repository/oembed.repository.js'; +import type { UmbEmbeddedMediaModalData, UmbEmbeddedMediaModalValue } from './embedded-media-modal.token.js'; import { css, html, unsafeHTML, when, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbEmbeddedMediaModalData, UmbEmbeddedMediaModalValue } from '@umbraco-cms/backoffice/modal'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import type { UUIButtonState, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/embedded-media-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.stories.ts similarity index 83% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/embedded-media-modal.stories.ts rename to src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.stories.ts index ee850fdeb1..35e21f4aea 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/embedded-media-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.stories.ts @@ -1,9 +1,8 @@ -import '../../../components/body-layout/body-layout.element.js'; import './embedded-media-modal.element.js'; +import type { UmbEmbeddedMediaModalData } from './embedded-media-modal.token.js'; import type { Meta } from '@storybook/web-components'; import { html } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbEmbeddedMediaModalData } from '@umbraco-cms/backoffice/modal'; export default { title: 'API/Modals/Layouts/Embedded Media', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/embedded-media-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.token.ts similarity index 89% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/token/embedded-media-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.token.ts index 0fb7df92ca..25737bbcbf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/embedded-media-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.token.ts @@ -1,4 +1,4 @@ -import { UmbModalToken } from './modal-token.js'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbEmbeddedMediaModalData extends Partial { url?: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/index.ts new file mode 100644 index 0000000000..363deb1226 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/index.ts @@ -0,0 +1 @@ +export * from './embedded-media-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/manifests.ts new file mode 100644 index 0000000000..aef2dbd580 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/manifests.ts @@ -0,0 +1,8 @@ +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.EmbeddedMedia', + name: 'Embedded Media Modal', + element: () => import('./embedded-media-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/embedded-media/package.json b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/package.json new file mode 100644 index 0000000000..6c7a488f0f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/package.json @@ -0,0 +1,8 @@ +{ + "name": "@umbraco-backoffice/embedded-media", + "private": true, + "type": "module", + "scripts": { + "build": "vite build" + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/constants.ts new file mode 100644 index 0000000000..a28213cbcd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/constants.ts @@ -0,0 +1 @@ +export const UMB_OEMBED_REPOSITORY_ALIAS = 'Umb.Repository.OEmbed'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/index.ts new file mode 100644 index 0000000000..7b45174122 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/index.ts @@ -0,0 +1,2 @@ +export * from './oembed.repository.js'; +export * from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/manifests.ts similarity index 74% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/manifests.ts index 39720a3494..364aeb3893 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/manifests.ts @@ -1,4 +1,4 @@ -export const UMB_OEMBED_REPOSITORY_ALIAS = 'Umb.Repository.OEmbed'; +import { UMB_OEMBED_REPOSITORY_ALIAS } from './constants.js'; export const manifests: Array = [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/oembed.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/oembed.repository.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/oembed.repository.ts rename to src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/oembed.repository.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/oembed.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/oembed.server.data.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/oembed.server.data.ts rename to src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/oembed.server.data.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/embedded-media/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/umbraco-package.ts new file mode 100644 index 0000000000..ca74b9b9ab --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/umbraco-package.ts @@ -0,0 +1,9 @@ +export const name = 'Umbraco.Core.EmbeddedMedia'; +export const extensions = [ + { + name: 'Embedded Media Bundle', + alias: 'Umb.Bundle.EmbeddedMedia', + type: 'bundle', + js: () => import('./manifests.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/embedded-media/vite.config.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/vite.config.ts new file mode 100644 index 0000000000..365fefd614 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/vite.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vite'; +import { rmSync } from 'fs'; +import { getDefaultConfig } from '../../vite-config-base'; + +const dist = '../../../dist-cms/packages/embedded-media'; + +// delete the unbundled dist folder +rmSync(dist, { recursive: true, force: true }); + +export default defineConfig({ + ...getDefaultConfig({ dist }), +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/language/entity-actions/manifests.ts index a3168b2e6b..1fad0995e1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/entity-actions/manifests.ts @@ -24,6 +24,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.context.ts index 934b5700d8..1caf0e7b16 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.context.ts @@ -1,41 +1,40 @@ -import { UmbLanguageDetailRepository } from '../../repository/index.js'; +import { UMB_LANGUAGE_DETAIL_REPOSITORY_ALIAS, UmbLanguageDetailRepository } from '../../repository/index.js'; import type { UmbLanguageDetailModel } from '../../types.js'; +import { UMB_LANGUAGE_ENTITY_TYPE, UMB_LANGUAGE_ROOT_ENTITY_TYPE } from '../../entity.js'; import { UmbLanguageWorkspaceEditorElement } from './language-workspace-editor.element.js'; import { UMB_LANGUAGE_WORKSPACE_ALIAS } from './constants.js'; import { type UmbSubmittableWorkspaceContext, - UmbSubmittableWorkspaceContextBase, UmbWorkspaceIsNewRedirectController, type UmbRoutableWorkspaceContext, + UmbEntityDetailWorkspaceContextBase, } from '@umbraco-cms/backoffice/workspace'; -import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; export class UmbLanguageWorkspaceContext - extends UmbSubmittableWorkspaceContextBase + extends UmbEntityDetailWorkspaceContextBase implements UmbSubmittableWorkspaceContext, UmbRoutableWorkspaceContext { public readonly repository: UmbLanguageDetailRepository = new UmbLanguageDetailRepository(this); - #data = new UmbObjectState(undefined); - readonly data = this.#data.asObservable(); + readonly data = this._data.current; - readonly unique = this.#data.asObservablePart((data) => data?.unique); - readonly name = this.#data.asObservablePart((data) => data?.name); - - // TODO: this is a temp solution to bubble validation errors to the UI - #validationErrors = new UmbObjectState(undefined); - readonly validationErrors = this.#validationErrors.asObservable(); + readonly unique = this._data.createObservablePartOfCurrent((data) => data?.unique); + readonly name = this._data.createObservablePartOfCurrent((data) => data?.name); constructor(host: UmbControllerHost) { - super(host, UMB_LANGUAGE_WORKSPACE_ALIAS); + super(host, { + workspaceAlias: UMB_LANGUAGE_WORKSPACE_ALIAS, + entityType: UMB_LANGUAGE_ENTITY_TYPE, + detailRepositoryAlias: UMB_LANGUAGE_DETAIL_REPOSITORY_ALIAS, + }); this.routes.setRoutes([ { path: 'create', component: UmbLanguageWorkspaceEditorElement, setup: async () => { - this.create(); + this.create({ parent: { entityType: UMB_LANGUAGE_ROOT_ENTITY_TYPE, unique: null } }); new UmbWorkspaceIsNewRedirectController( this, @@ -55,85 +54,24 @@ export class UmbLanguageWorkspaceContext ]); } - protected override resetState(): void { - super.resetState(); - this.#data.setValue(undefined); - } - - async load(unique: string) { - this.resetState(); - const { data } = await this.repository.requestByUnique(unique); - if (data) { - this.setIsNew(false); - this.#data.update(data); - } - } - - async create() { - this.resetState(); - const { data } = await this.repository.createScaffold(); - if (!data) return; - this.setIsNew(true); - this.#data.update(data); - return { data }; - } - - getData() { - return this.#data.getValue(); - } - - getEntityType() { - return 'language'; - } - - // TODO: Convert to uniques: - getUnique() { - return this.#data.getValue()?.unique; - } - setName(name: string) { - this.#data.update({ name }); + this._data.updateCurrent({ name }); } setCulture(unique: string) { - this.#data.update({ unique }); + this._data.updateCurrent({ unique }); } setMandatory(isMandatory: boolean) { - this.#data.update({ isMandatory }); + this._data.updateCurrent({ isMandatory }); } setDefault(isDefault: boolean) { - this.#data.update({ isDefault }); + this._data.updateCurrent({ isDefault }); } setFallbackCulture(unique: string) { - this.#data.update({ fallbackIsoCode: unique }); - } - - async submit() { - const newData = this.getData(); - if (!newData) { - throw new Error('No data to submit'); - } - - if (this.getIsNew()) { - const { error } = await this.repository.create(newData); - if (error) { - throw new Error(error.message); - } - this.setIsNew(false); - } else { - const { error } = await this.repository.save(newData); - if (error) { - throw new Error(error.message); - } - } - } - - override destroy(): void { - this.#data.destroy(); - super.destroy(); + this._data.updateCurrent({ fallbackIsoCode: unique }); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.modal-token.ts index 1e82ee6dd6..02250aa8ac 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.modal-token.ts @@ -1,5 +1,5 @@ import type { UmbLanguageDetailModel } from '../../types.js'; -import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/workspace'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export const UMB_LANGUAGE_WORKSPACE_MODAL = new UmbModalToken< diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/input-media-type/input-media-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/input-media-type/input-media-type.element.ts index 0adcf8212a..fe3e33c4a0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/input-media-type/input-media-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/input-media-type/input-media-type.element.ts @@ -4,7 +4,7 @@ import { css, html, customElement, property, state, repeat, nothing } from '@umb import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts index baef2e94e6..b87893666e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts @@ -16,6 +16,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/export/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/export/manifests.ts index c9a31f7d87..7c6b768ea0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/export/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/export/manifests.ts @@ -12,6 +12,7 @@ export const manifests: Array = [ meta: { icon: 'icon-download-alt', label: '#actions_export', + additionalOptions: true, }, }, ...repositoryManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/import/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/import/manifests.ts index 6d9abf24d7..85974f6c14 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/import/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/import/manifests.ts @@ -13,6 +13,7 @@ export const manifests: Array = [ meta: { icon: 'icon-page-up', label: '#actions_import', + additionalOptions: true, }, }, ...repositoryManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace-editor.element.ts index 1f9d3c0556..2a70489df8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace-editor.element.ts @@ -2,7 +2,8 @@ import type { UmbMediaTypeWorkspaceContext } from './media-type-workspace.contex import { UMB_MEDIA_TYPE_WORKSPACE_CONTEXT } from './media-type-workspace.context-token.js'; import { css, html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_ICON_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_ICON_PICKER_MODAL } from '@umbraco-cms/backoffice/icon'; import type { UmbInputWithAliasElement } from '@umbraco-cms/backoffice/components'; import type { UUITextareaElement } from '@umbraco-cms/backoffice/external/uui'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/action/create-media-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/action/create-media-collection-action.element.ts index 8c52336ef3..5ae5b98f3a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/action/create-media-collection-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/action/create-media-collection-action.element.ts @@ -5,7 +5,7 @@ import { UMB_MEDIA_ENTITY_TYPE, UMB_MEDIA_ROOT_ENTITY_TYPE } from '../../entity. import { html, customElement, property, state, map } from '@umbraco-cms/backoffice/external/lit'; import { UmbMediaTypeStructureRepository } from '@umbraco-cms/backoffice/media-type'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import type { ManifestCollectionAction } from '@umbraco-cms/backoffice/collection'; import type { UmbAllowedMediaTypeModel } from '@umbraco-cms/backoffice/media-type'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/grid/media-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/grid/media-grid-collection-view.element.ts index 27042a9738..a333c4598c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/grid/media-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/grid/media-grid-collection-view.element.ts @@ -5,7 +5,7 @@ import { UMB_MEDIA_COLLECTION_CONTEXT } from '../../media-collection.context-tok import { css, customElement, html, nothing, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import '@umbraco-cms/backoffice/imaging'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts index 0c301d18f4..7f31f2cb0c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts @@ -14,7 +14,7 @@ import type { UmbTableOrderedEvent, UmbTableSelectedEvent, } from '@umbraco-cms/backoffice/components'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController, type UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router'; import './column-layouts/media-table-column-name.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.element.ts index b6cbe7a4ef..7a33b3de12 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.element.ts @@ -16,7 +16,7 @@ import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; import '@umbraco-cms/backoffice/imaging'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/dropzone/dropzone-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/dropzone/dropzone-manager.class.ts index 8e397f05cd..e075925700 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/dropzone/dropzone-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/dropzone/dropzone-manager.class.ts @@ -224,6 +224,7 @@ export class UmbDropzoneManager extends UmbControllerBase { if (upload.status === TemporaryFileStatus.SUCCESS) { // Upload successful. Create media item. + // TODO: Use a scaffolding feature to ensure consistency. [NL] const preset: Partial = { unique: file.unique, mediaType: { @@ -241,6 +242,8 @@ export class UmbDropzoneManager extends UmbControllerBase { ], values: [ { + // We do not need to parse the right editorAlias here, because the server does not read it. If we need to parse it we would need to load the contentType to make this happen properly. [NL] + //editorAlias: null as any, alias: 'umbracoFile', value: { temporaryFileId: upload.temporaryUnique }, culture: null, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/create/manifests.ts index 199a6d4664..7572bca3eb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/create/manifests.ts @@ -13,6 +13,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, conditions: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/image-cropper-editor/image-cropper-editor-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/image-cropper-editor/image-cropper-editor-modal.element.ts index 846e26822c..33a7bbfa08 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/image-cropper-editor/image-cropper-editor-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/image-cropper-editor/image-cropper-editor-modal.element.ts @@ -9,7 +9,8 @@ import type { } from './image-cropper-editor-modal.token.js'; import { css, customElement, html, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; -import { UMB_MODAL_MANAGER_CONTEXT, UMB_WORKSPACE_MODAL, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import './components/image-cropper-editor-field.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts index a0a6d3cacd..abb9051de3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts @@ -297,7 +297,17 @@ export class UmbMediaWorkspaceContext ) { if (!variantId) throw new Error('VariantId is missing'); - const entry = { ...variantId.toObject(), alias, value }; + const property = await this.structure.getPropertyStructureByAlias(alias); + + if (!property) { + throw new Error(`Property alias "${alias}" not found.`); + } + + //const dataType = await this.#dataTypeItemManager.getItemByUnique(property.dataType.unique); + //const editorAlias = dataType.editorAlias; + const editorAlias = 'Umbraco.TextBox'; + + const entry = { ...variantId.toObject(), alias, editorAlias, value }; const currentData = this.#currentData.value; if (currentData) { const values = appendToFrozenArray( diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-reference.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-reference.element.ts index ebf9da81fe..90169d6666 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-reference.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info-reference.element.ts @@ -4,7 +4,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbMediaReferenceRepository } from '@umbraco-cms/backoffice/media'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import type { UmbReferenceModel } from '@umbraco-cms/backoffice/relations'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router'; import type { UUIPaginationEvent } from '@umbraco-cms/backoffice/external/uui'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info.element.ts index 26f78f33c5..529d781978 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info.element.ts @@ -6,7 +6,7 @@ import { UMB_MEDIA_TYPE_ENTITY_TYPE, UmbMediaTypeItemRepository } from '@umbraco import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UMB_MEDIA_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/media'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import type { MediaUrlInfoModel } from '@umbraco-cms/backoffice/external/backend-api'; // import of local components diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/components/input-member-group/input-member-group.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/components/input-member-group/input-member-group.element.ts index c4f8a03a6e..bd14086c99 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/components/input-member-group/input-member-group.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/components/input-member-group/input-member-group.element.ts @@ -5,7 +5,7 @@ import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/entity-actions/manifests.ts index 86b196a8b4..125cd2156c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/entity-actions/manifests.ts @@ -16,6 +16,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/entity-actions/manifests.ts index ee2d2bc8c3..baf51ce7b1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/entity-actions/manifests.ts @@ -16,6 +16,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/member-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/member-type-workspace-editor.element.ts index 0bcf694903..aa5ac40c3f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/member-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/member-type-workspace-editor.element.ts @@ -3,7 +3,8 @@ import type { UmbInputWithAliasElement } from '@umbraco-cms/backoffice/component import { css, html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import type { UUITextareaElement } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_ICON_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_ICON_PICKER_MODAL } from '@umbraco-cms/backoffice/icon'; @customElement('umb-member-type-workspace-editor') export class UmbMemberTypeWorkspaceEditorElement extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.element.ts index 6e5c55dc03..9f782e9ea9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.element.ts @@ -4,7 +4,7 @@ import { css, customElement, html, nothing, property, repeat, state } from '@umb import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/entity-actions/create/manifests.ts index 2bb593b71a..3a145b2c02 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/entity-actions/create/manifests.ts @@ -13,6 +13,7 @@ const entityActions: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts index 976a069842..674205460c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts @@ -100,6 +100,7 @@ export class UmbMemberServerDataSource implements UmbDetailDataSource { return { + editorAlias: value.editorAlias, culture: value.culture || null, segment: value.segment || null, alias: value.alias, diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts index fce275292b..0bee716008 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts @@ -269,7 +269,17 @@ export class UmbMemberWorkspaceContext ) { variantId ??= UmbVariantId.CreateInvariant(); - const entry = { ...variantId.toObject(), alias, value }; + const property = await this.structure.getPropertyStructureByAlias(alias); + + if (!property) { + throw new Error(`Property alias "${alias}" not found.`); + } + + //const dataType = await this.#dataTypeItemManager.getItemByUnique(property.dataType.unique); + //const editorAlias = dataType.editorAlias; + const editorAlias = 'Umbraco.TextBox'; + + const entry = { ...variantId.toObject(), alias, editorAlias, value }; const currentData = this.getData(); if (currentData) { const values = appendToFrozenArray( diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts index 5c5d1c12ad..e649605ee3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts @@ -6,7 +6,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/workspace'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbMemberTypeItemRepository } from '@umbraco-cms/backoffice/member-type'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/layout/layout-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/layout/layout-configuration.element.ts index a26b1565df..f65310d05b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/layout/layout-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/layout/layout-configuration.element.ts @@ -14,11 +14,12 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UMB_ICON_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { UmbInputManifestElement } from '@umbraco-cms/backoffice/components'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import type { UUIInputElement, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; +import { UMB_ICON_PICKER_MODAL } from '@umbraco-cms/backoffice/icon'; interface UmbCollectionLayoutConfiguration { icon?: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.element.ts index 3455b3a5ad..ccbdcd5a2d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.element.ts @@ -1,6 +1,7 @@ import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; -import { UMB_MODAL_MANAGER_CONTEXT, UMB_ICON_PICKER_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_ICON_PICKER_MODAL } from '@umbraco-cms/backoffice/icon'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { extractUmbColorVariable } from '@umbraco-cms/backoffice/resources'; import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.stories.ts index 1a0e94d0cb..b978ac2ece 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.stories.ts @@ -1,4 +1,4 @@ -import type { UmbIconPickerModalElement } from '../../core/modal/common/icon-picker/icon-picker-modal.element.js'; +import type { UmbIconPickerModalElement } from '@umbraco-cms/backoffice/icon'; import type { Meta, Story } from '@storybook/web-components'; import { html } from '@umbraco-cms/backoffice/external/lit'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-searchers.ts b/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-searchers.ts index 441d5b90b8..1f300726a1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-searchers.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-searchers.ts @@ -1,7 +1,8 @@ import { UMB_EXAMINE_FIELDS_SETTINGS_MODAL, UMB_EXAMINE_FIELDS_VIEWER_MODAL } from '../modal/index.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, nothing, customElement, state, query, property } from '@umbraco-cms/backoffice/external/lit'; -import { UMB_MODAL_MANAGER_CONTEXT, UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import type { SearchResultResponseModel, FieldPresentationModel } from '@umbraco-cms/backoffice/external/backend-api'; import { SearcherService } from '@umbraco-cms/backoffice/external/backend-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts index ef744bf99c..d199e00ea3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts @@ -16,6 +16,11 @@ import type { UUIComboboxEvent, UUIComboboxElement } from '@umbraco-cms/backoffi import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbMediaTypeDetailRepository, UMB_MEDIA_TYPE_PICKER_MODAL } from '@umbraco-cms/backoffice/media-type'; import { UMB_MODAL_MANAGER_CONTEXT, type UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; +import { + UMB_VALIDATION_EMPTY_LOCALIZATION_KEY, + UmbFormControlMixin, + type UmbFormControlValidatorConfig, +} from '@umbraco-cms/backoffice/validation'; interface FieldPickerValue { alias: string; @@ -29,19 +34,44 @@ enum FieldType { } @customElement('umb-template-field-dropdown-list') -export class UmbTemplateFieldDropdownListElement extends UmbLitElement { +export class UmbTemplateFieldDropdownListElement extends UmbFormControlMixin< + FieldPickerValue | undefined, + typeof UmbLitElement, + undefined +>(UmbLitElement) { + // + #requiredValidation?: UmbFormControlValidatorConfig; + @property({ type: Boolean }) + public get required(): boolean | undefined { + return undefined; + } + public set required(value: boolean | undefined) { + if (value === true) { + this.#requiredValidation ??= this.addValidator( + 'valueMissing', + () => this.requiredMessage, + () => !this._value, + ); + } else if (this.#requiredValidation) { + this.removeValidator(this.#requiredValidation); + } + } + + @property({ type: String }) + requiredMessage = UMB_VALIDATION_EMPTY_LOCALIZATION_KEY; + @property({ type: Boolean, attribute: 'exclude-media-type', reflect: true }) public excludeMediaType = false; private _value: FieldPickerValue | undefined; @property({ type: Object }) - public set value(val: FieldPickerValue | undefined) { + public override set value(val: FieldPickerValue | undefined) { const oldVal = this._value; this._value = val; this.requestUpdate('value', oldVal); this.dispatchEvent(new UmbChangeEvent()); } - public get value(): FieldPickerValue | undefined { + public override get value(): FieldPickerValue | undefined { return this._value; } @@ -176,8 +206,8 @@ export class UmbTemplateFieldDropdownListElement extends UmbLitElement { if (this._type !== FieldType.SYSTEM && !this._unique) return; return html` ${this.localize.string(this._uniqueName ?? '')} - - + + ${repeat( this._customFields, (field) => field.alias, diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.element.ts index 9f8ea3fbba..9d1eec32e3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.element.ts @@ -7,24 +7,35 @@ import type { UmbTemplateFieldDropdownListElement } from './components/template- import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; -import type { UUIBooleanInputEvent, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; +import type { UUIBooleanInputEvent, UUIButtonState, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; // import of local components import './components/template-field-dropdown-list/index.js'; +import { UmbValidationContext, umbBindToValidation } from '@umbraco-cms/backoffice/validation'; @customElement('umb-templating-page-field-builder-modal') export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseElement< UmbTemplatingPageFieldBuilderModalData, UmbTemplatingPageFieldBuilderModalValue > { - private _close() { + #validation = new UmbValidationContext(this); + + #close() { this.modalContext?.reject(); } - private _submit() { - if (!this._field) return; - this.value = { output: getUmbracoFieldSnippet(this._field, this._default, this._recursive) }; - this.modalContext?.submit(); + async #submit() { + this._submitButtonState = 'waiting'; + + try { + await this.#validation.validate(); + this._submitButtonState = 'success'; + + this.value = { output: getUmbracoFieldSnippet(this._field!, this._default, this._recursive) }; + this.modalContext?.submit(); + } catch { + this._submitButtonState = 'failed'; + } } @state() @@ -39,6 +50,9 @@ export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseEleme @state() private _recursive: boolean = false; + @state() + private _submitButtonState: UUIButtonState; + /** TODO: Implement "Choose field" */ #onChangeFieldValue(e: Event) { @@ -50,12 +64,14 @@ export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseEleme
- - Choose field - - + + + Default value @@ -85,14 +101,15 @@ export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseEleme `; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/manifests.ts index 89e4653c7a..6ba2c40dc8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/manifests.ts @@ -12,6 +12,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/manifests.ts index 015363073f..68cb772ad2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/manifests.ts @@ -12,6 +12,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/manifests.ts index 22bbd951fa..c5a933f817 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/manifests.ts @@ -12,6 +12,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts index e0b2068614..fb548f4166 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts @@ -13,6 +13,7 @@ export const manifests: Array = [ meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/global-components/input-template/input-template.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/global-components/input-template/input-template.element.ts index 352c8b4427..d59a88d83c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/global-components/input-template/input-template.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/global-components/input-template/input-template.element.ts @@ -5,7 +5,8 @@ import { UmbTemplateItemRepository } from '../../repository/item/index.js'; import { UMB_TEMPLATE_PICKER_MODAL } from '../../modals/index.js'; import { css, html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; -import { UMB_MODAL_MANAGER_CONTEXT, UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-code-editor.plugin.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-code-editor.plugin.ts index 9de4e35d0f..54c16a3818 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-code-editor.plugin.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-code-editor.plugin.ts @@ -1,6 +1,7 @@ import { type TinyMcePluginArguments, UmbTinyMcePluginBase } from '../components/input-tiny-mce/tiny-mce-plugin.js'; import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; -import { UMB_CODE_EDITOR_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_CODE_EDITOR_MODAL } from '@umbraco-cms/backoffice/code-editor'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; export default class UmbTinyMceCodeEditorPlugin extends UmbTinyMcePluginBase { constructor(args: TinyMcePluginArguments) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-embeddedmedia.plugin.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-embeddedmedia.plugin.ts index 8995fc66b9..e451c9d6d7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-embeddedmedia.plugin.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-embeddedmedia.plugin.ts @@ -1,7 +1,8 @@ import { type TinyMcePluginArguments, UmbTinyMcePluginBase } from '../components/input-tiny-mce/tiny-mce-plugin.js'; import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; -import type { UmbEmbeddedMediaModalData, UmbEmbeddedMediaModalValue } from '@umbraco-cms/backoffice/modal'; -import { UMB_EMBEDDED_MEDIA_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import type { UmbEmbeddedMediaModalData, UmbEmbeddedMediaModalValue } from '@umbraco-cms/backoffice/embedded-media'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_EMBEDDED_MEDIA_MODAL } from '@umbraco-cms/backoffice/embedded-media'; export default class UmbTinyMceEmbeddedMediaPlugin extends UmbTinyMcePluginBase { constructor(args: TinyMcePluginArguments) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/block/property-editor-ui-block-rte-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/block/property-editor-ui-block-rte-type-configuration.element.ts index 264dab15ba..174e14fe02 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/block/property-editor-ui-block-rte-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/block/property-editor-ui-block-rte-type-configuration.element.ts @@ -7,7 +7,7 @@ import { type UmbPropertyEditorConfigCollection, } from '@umbraco-cms/backoffice/property-editor'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/change-password/change-user-password.action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/entity-action/change-user-password.action.ts similarity index 91% rename from src/Umbraco.Web.UI.Client/src/packages/user/change-password/change-user-password.action.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/change-password/entity-action/change-user-password.action.ts index fbf0e35929..6e836d9bf8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/change-password/change-user-password.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/entity-action/change-user-password.action.ts @@ -1,8 +1,9 @@ +import { UMB_CHANGE_PASSWORD_MODAL } from '../modal/index.js'; import { UmbChangeUserPasswordRepository } from '@umbraco-cms/backoffice/user'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbEntityActionArgs } from '@umbraco-cms/backoffice/entity-action'; import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; -import { UMB_MODAL_MANAGER_CONTEXT, UMB_CHANGE_PASSWORD_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { UMB_CURRENT_USER_CONTEXT, UmbCurrentUserRepository } from '@umbraco-cms/backoffice/current-user'; export class UmbChangeUserPasswordEntityAction extends UmbEntityActionBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/change-password/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/entity-action/manifests.ts new file mode 100644 index 0000000000..01148ac695 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/entity-action/manifests.ts @@ -0,0 +1,22 @@ +import { UMB_USER_ENTITY_TYPE } from '@umbraco-cms/backoffice/user'; + +export const manifests: Array = [ + { + type: 'entityAction', + kind: 'default', + alias: 'Umb.EntityAction.User.ChangePassword', + name: 'Change User Password Entity Action', + weight: 600, + api: () => import('./change-user-password.action.js'), + forEntityTypes: [UMB_USER_ENTITY_TYPE], + meta: { + icon: 'icon-key', + label: '#user_changePassword', + }, + conditions: [ + { + alias: 'Umb.Condition.User.AllowChangePassword', + }, + ], + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/change-password/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/index.ts new file mode 100644 index 0000000000..28d9f38fba --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/index.ts @@ -0,0 +1 @@ +export * from './modal/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/change-password/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/manifests.ts index 02d2d6af5d..a779cde6a9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/change-password/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/manifests.ts @@ -1,28 +1,4 @@ -import { UMB_USER_ENTITY_TYPE } from '@umbraco-cms/backoffice/user'; +import { manifests as entityActionManifests } from './entity-action/manifests.js'; +import { manifests as modalManifests } from './modal/manifests.js'; -export const manifests: Array = [ - { - type: 'entityAction', - kind: 'default', - alias: 'Umb.EntityAction.User.ChangePassword', - name: 'Change User Password Entity Action', - weight: 600, - api: () => import('./change-user-password.action.js'), - forEntityTypes: [UMB_USER_ENTITY_TYPE], - meta: { - icon: 'icon-key', - label: '#user_changePassword', - }, - conditions: [ - { - alias: 'Umb.Condition.User.AllowChangePassword', - }, - ], - }, - { - type: 'modal', - alias: 'Umb.Modal.ChangePassword', - name: 'Change Password Modal', - js: () => import('./change-password-modal.element.js'), - }, -]; +export const manifests: Array = [...entityActionManifests, ...modalManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/change-password/change-password-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/modal/change-password-modal.element.ts similarity index 98% rename from src/Umbraco.Web.UI.Client/src/packages/user/change-password/change-password-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/change-password/modal/change-password-modal.element.ts index 09a0819e60..bdff723460 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/change-password/change-password-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/modal/change-password-modal.element.ts @@ -1,9 +1,9 @@ +import type { UmbChangePasswordModalData, UmbChangePasswordModalValue } from './change-password-modal.token.js'; import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user'; import { UmbUserItemRepository } from '@umbraco-cms/backoffice/user'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbChangePasswordModalData, UmbChangePasswordModalValue } from '@umbraco-cms/backoffice/modal'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; @customElement('umb-change-password-modal') diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/change-password-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/modal/change-password-modal.token.ts similarity index 85% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/token/change-password-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/change-password/modal/change-password-modal.token.ts index d6a41803fb..8c8cf1b9a6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/change-password-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/modal/change-password-modal.token.ts @@ -1,4 +1,4 @@ -import { UmbModalToken } from './modal-token.js'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbChangePasswordModalData { user: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/change-password/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/modal/index.ts new file mode 100644 index 0000000000..dbfc55d6cf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/modal/index.ts @@ -0,0 +1 @@ +export * from './change-password-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/change-password/modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/modal/manifests.ts new file mode 100644 index 0000000000..f08d08322a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/change-password/modal/manifests.ts @@ -0,0 +1,8 @@ +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.ChangePassword', + name: 'Change Password Modal', + js: () => import('./change-password-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/profile/change-password-current-user.action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/profile/change-password-current-user.action.ts index b37cfaeaa7..9a780e13f6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/profile/change-password-current-user.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/profile/change-password-current-user.action.ts @@ -3,7 +3,8 @@ import { UmbCurrentUserRepository } from '../repository/index.js'; import { UmbActionBase } from '@umbraco-cms/backoffice/action'; import type { UmbCurrentUserAction, UmbCurrentUserActionArgs } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UMB_CHANGE_PASSWORD_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_CHANGE_PASSWORD_MODAL } from '@umbraco-cms/backoffice/user-change-password'; export class UmbChangePasswordCurrentUserAction extends UmbActionBase> implements UmbCurrentUserAction diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/input-user-group/user-group-input.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/input-user-group/user-group-input.element.ts index dd376a64a1..f509aee058 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/input-user-group/user-group-input.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/input-user-group/user-group-input.element.ts @@ -4,7 +4,7 @@ import { UmbUserGroupPickerInputContext } from './user-group-input.context.js'; import { css, html, customElement, property, state, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts index 01835e7c2a..ad0243fa8c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts @@ -10,8 +10,9 @@ import type { UmbInputDocumentElement } from '@umbraco-cms/backoffice/document'; import type { UmbInputSectionElement } from '@umbraco-cms/backoffice/section'; import type { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbInputMediaElement } from '@umbraco-cms/backoffice/media'; -import { UMB_ICON_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { UmbInputLanguageElement } from '@umbraco-cms/backoffice/language'; +import { UMB_ICON_PICKER_MODAL } from '@umbraco-cms/backoffice/icon'; import './components/user-group-entity-user-permission-list.element.js'; import './components/user-group-granular-permission-list.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts index 85f5141999..d6f28c19b5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts @@ -1,3 +1,4 @@ export * from './components/index.js'; +export * from './modals/index.js'; export type { UmbUserPermissionModel } from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/index.ts new file mode 100644 index 0000000000..f5425503d0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/index.ts @@ -0,0 +1 @@ +export * from './settings/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/manifests.ts index d73911fde1..fada1af2d4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/manifests.ts @@ -1,8 +1,3 @@ -export const manifests: Array = [ - { - type: 'modal', - alias: 'Umb.Modal.EntityUserPermissionSettings', - name: 'Entity User Permission Settings Modal', - js: () => import('./settings/entity-user-permission-settings-modal.element.js'), - }, -]; +import { manifests as settingsManifests } from './settings/manifests.js'; + +export const manifests: Array = [...settingsManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.element.ts index 6b088bc5c1..b09adc176a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.element.ts @@ -1,9 +1,9 @@ -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { html, customElement, css, nothing, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbEntityUserPermissionSettingsModalData, UmbEntityUserPermissionSettingsModalValue, -} from '@umbraco-cms/backoffice/modal'; +} from './entity-user-permission-settings-modal.token.js'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { html, customElement, css, nothing, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import type { UmbSelectionChangeEvent } from '@umbraco-cms/backoffice/event'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/entity-user-permission-settings-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.token.ts similarity index 87% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/token/entity-user-permission-settings-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.token.ts index 50bc5515ad..a63dc036d2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/entity-user-permission-settings-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.token.ts @@ -1,4 +1,4 @@ -import { UmbModalToken } from './modal-token.js'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbEntityUserPermissionSettingsModalData { unique: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/index.ts new file mode 100644 index 0000000000..97f4988c62 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/index.ts @@ -0,0 +1 @@ +export * from './entity-user-permission-settings-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/manifests.ts new file mode 100644 index 0000000000..f3052f637f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/manifests.ts @@ -0,0 +1,8 @@ +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.EntityUserPermissionSettings', + name: 'Entity User Permission Settings Modal', + js: () => import('./entity-user-permission-settings-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts index d63d70d72a..b92ae65395 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts @@ -16,6 +16,7 @@ export const manifests: Array = meta: { icon: 'icon-add', label: '#actions_create', + additionalOptions: true, }, }, ...modalManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/manifests.ts index 5774cf4147..d059c0d812 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/manifests.ts @@ -87,6 +87,7 @@ const entityActions: Array = [ meta: { icon: 'icon-settings', label: '#user_configureMfa', + additionalOptions: true, }, conditions: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/invite/entity-action/invite/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/invite/entity-action/invite/manifests.ts index ccbd7dcfd1..8f599b4541 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/invite/entity-action/invite/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/invite/entity-action/invite/manifests.ts @@ -12,6 +12,7 @@ export const manifests: Array = [ meta: { icon: 'icon-paper-plane', label: '#user_invite', + additionalOptions: true, }, }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts index 4ed55c6ae9..0f3d9bb724 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts @@ -12,6 +12,7 @@ export const manifests: Array = [ meta: { icon: 'icon-message', label: '#actions_resendInvite', + additionalOptions: true, }, conditions: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts index 0d313eb130..c3a6a54501 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts @@ -6,6 +6,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbUiCultureInputElement } from '@umbraco-cms/backoffice/localization'; +import { umbBindToValidation } from '@umbraco-cms/backoffice/validation'; @customElement('umb-user-workspace-profile-settings') export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { @@ -79,6 +80,7 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { @change="${this.#onEmailChange}" required required-message=${this.localize.term('user_emailRequired')} + ${umbBindToValidation(this)} value=${ifDefined(this._user?.email)}> `; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/user-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/user-workspace.context.ts index 18963318ec..0aa79554f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/user-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/user-workspace.context.ts @@ -1,50 +1,59 @@ import type { UmbUserDetailModel, UmbUserStartNodesModel, UmbUserStateEnum } from '../../types.js'; import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; -import { UmbUserDetailRepository } from '../../repository/index.js'; +import type { UmbUserDetailRepository } from '../../repository/index.js'; +import { UMB_USER_DETAIL_REPOSITORY_ALIAS } from '../../repository/index.js'; import { UmbUserAvatarRepository } from '../../repository/avatar/index.js'; import { UmbUserConfigRepository } from '../../repository/config/index.js'; import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; import { UmbUserWorkspaceEditorElement } from './user-workspace-editor.element.js'; import type { UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; -import { UmbSubmittableWorkspaceContextBase } from '@umbraco-cms/backoffice/workspace'; +import { UmbEntityDetailWorkspaceContextBase } from '@umbraco-cms/backoffice/workspace'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; +import { UmbValidationContext } from '@umbraco-cms/backoffice/validation'; type EntityType = UmbUserDetailModel; export class UmbUserWorkspaceContext - extends UmbSubmittableWorkspaceContextBase + extends UmbEntityDetailWorkspaceContextBase implements UmbSubmittableWorkspaceContext { - public readonly detailRepository: UmbUserDetailRepository = new UmbUserDetailRepository(this); public readonly avatarRepository: UmbUserAvatarRepository = new UmbUserAvatarRepository(this); public readonly configRepository = new UmbUserConfigRepository(this); - #persistedData = new UmbObjectState(undefined); - #currentData = new UmbObjectState(undefined); - readonly data = this.#currentData.asObservable(); - readonly state = this.#currentData.asObservablePart((x) => x?.state); - readonly unique = this.#currentData.asObservablePart((x) => x?.unique); - readonly kind = this.#currentData.asObservablePart((x) => x?.kind); - readonly userGroupUniques = this.#currentData.asObservablePart((x) => x?.userGroupUniques || []); - readonly documentStartNodeUniques = this.#currentData.asObservablePart( + readonly data = this._data.current; + readonly state = this._data.createObservablePartOfCurrent((x) => x?.state); + readonly unique = this._data.createObservablePartOfCurrent((x) => x?.unique); + readonly kind = this._data.createObservablePartOfCurrent((x) => x?.kind); + readonly userGroupUniques = this._data.createObservablePartOfCurrent((x) => x?.userGroupUniques || []); + readonly documentStartNodeUniques = this._data.createObservablePartOfCurrent( (data) => data?.documentStartNodeUniques || [], ); - readonly hasDocumentRootAccess = this.#currentData.asObservablePart((data) => data?.hasDocumentRootAccess || false); - readonly mediaStartNodeUniques = this.#currentData.asObservablePart((data) => data?.mediaStartNodeUniques || []); - readonly hasMediaRootAccess = this.#currentData.asObservablePart((data) => data?.hasMediaRootAccess || false); + readonly hasDocumentRootAccess = this._data.createObservablePartOfCurrent( + (data) => data?.hasDocumentRootAccess || false, + ); + readonly mediaStartNodeUniques = this._data.createObservablePartOfCurrent( + (data) => data?.mediaStartNodeUniques || [], + ); + readonly hasMediaRootAccess = this._data.createObservablePartOfCurrent((data) => data?.hasMediaRootAccess || false); #calculatedStartNodes = new UmbObjectState(undefined); readonly calculatedStartNodes = this.#calculatedStartNodes.asObservable(); constructor(host: UmbControllerHost) { - super(host, UMB_USER_WORKSPACE_ALIAS); + super(host, { + workspaceAlias: UMB_USER_WORKSPACE_ALIAS, + entityType: UMB_USER_ENTITY_TYPE, + detailRepositoryAlias: UMB_USER_DETAIL_REPOSITORY_ALIAS, + }); + + this.addValidationContext(new UmbValidationContext(this)); this.routes.setRoutes([ { path: 'edit/:id', component: UmbUserWorkspaceEditorElement, - setup: (component, info) => { + setup: (_component, info) => { const id = info.match.params.id; this.load(id); }, @@ -52,20 +61,20 @@ export class UmbUserWorkspaceContext ]); } - async load(unique: string) { - const { data, asObservable } = await this.detailRepository.requestByUnique(unique); + override async load(unique: string) { + const response = await super.load(unique); - if (data) { - this.setIsNew(false); - this.#persistedData.update(data); - this.#currentData.update(data); + this.observe(response.asObservable?.(), (user) => this.onUserStoreChanges(user), 'umbUserStoreObserver'); + + if (!this._detailRepository) { + throw new Error('Detail repository is missing'); } - this.observe(asObservable(), (user) => this.onUserStoreChanges(user), 'umbUserStoreObserver'); - // Get the calculated start nodes - const { data: calculatedStartNodes } = await this.detailRepository.requestCalculateStartNodes(unique); + const { data: calculatedStartNodes } = await this._detailRepository.requestCalculateStartNodes(unique); this.#calculatedStartNodes.setValue(calculatedStartNodes); + + return response; } /* TODO: some properties are allowed to update without saving. @@ -79,43 +88,15 @@ export class UmbUserWorkspaceContext history.pushState(null, '', 'section/user-management'); return; } - this.#currentData.update({ state: user.state, avatarUrls: user.avatarUrls }); + this._data.updateCurrent({ state: user.state, avatarUrls: user.avatarUrls }); } - getUnique(): string | undefined { - return this.getData()?.unique; - } getState(): UmbUserStateEnum | null | undefined { - return this.getData()?.state; - } - - getEntityType(): string { - return UMB_USER_ENTITY_TYPE; - } - - getData() { - return this.#currentData.getValue(); + return this._data.getCurrent()?.state; } updateProperty(propertyName: PropertyName, value: EntityType[PropertyName]) { - this.#currentData.update({ [propertyName]: value }); - } - - async submit() { - if (!this.#currentData.value) throw new Error('Data is missing'); - if (!this.#currentData.value.unique) throw new Error('Unique is missing'); - - if (this.getIsNew()) { - const { error, data } = await this.detailRepository.create(this.#currentData.value); - if (error) throw new Error(error.message); - this.#persistedData.setValue(data); - this.#currentData.setValue(data); - } else { - const { error, data } = await this.detailRepository.save(this.#currentData.value); - if (error) throw new Error(error.message); - this.#persistedData.setValue(data); - this.#currentData.setValue(data); - } + this._data.updateCurrent({ [propertyName]: value }); } // TODO: implement upload progress @@ -132,9 +113,6 @@ export class UmbUserWorkspaceContext } override destroy(): void { - this.#persistedData.destroy(); - this.#currentData.destroy(); - this.detailRepository.destroy(); this.avatarRepository.destroy(); super.destroy(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/vite.config.ts b/src/Umbraco.Web.UI.Client/src/packages/user/vite.config.ts index f498904a85..aba6f508c2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/vite.config.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/vite.config.ts @@ -11,12 +11,13 @@ export default defineConfig({ ...getDefaultConfig({ dist, entry: { + 'current-user/index': 'current-user/index.ts', + 'umbraco-package': 'umbraco-package.ts', + 'change-password/index': 'change-password/index.ts', 'user-group/index': 'user-group/index.ts', 'user-permission/index': 'user-permission/index.ts', 'user/index': 'user/index.ts', - 'current-user/index': 'current-user/index.ts', manifests: 'manifests.ts', - 'umbraco-package': 'umbraco-package.ts', }, }), }); diff --git a/src/Umbraco.Web.UI.Client/tsconfig.json b/src/Umbraco.Web.UI.Client/tsconfig.json index d5c79b90a3..9951bfe191 100644 --- a/src/Umbraco.Web.UI.Client/tsconfig.json +++ b/src/Umbraco.Web.UI.Client/tsconfig.json @@ -38,6 +38,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@umbraco-cms/backoffice/context-api": ["./src/libs/context-api/index.ts"], "@umbraco-cms/backoffice/controller-api": ["./src/libs/controller-api/index.ts"], "@umbraco-cms/backoffice/element-api": ["./src/libs/element-api/index.ts"], + "@umbraco-cms/backoffice/embedded-media": ["./src/packages/embedded-media/index.ts"], "@umbraco-cms/backoffice/extension-api": ["./src/libs/extension-api/index.ts"], "@umbraco-cms/backoffice/formatting-api": ["./src/libs/formatting-api/index.ts"], "@umbraco-cms/backoffice/localization-api": ["./src/libs/localization-api/index.ts"], @@ -122,6 +123,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@umbraco-cms/backoffice/tiptap": ["./src/packages/rte/tiptap/index.ts"], "@umbraco-cms/backoffice/tree": ["./src/packages/core/tree/index.ts"], "@umbraco-cms/backoffice/ufm": ["./src/packages/ufm/index.ts"], + "@umbraco-cms/backoffice/user-change-password": ["./src/packages/user/change-password/index.ts"], "@umbraco-cms/backoffice/user-group": ["./src/packages/user/user-group/index.ts"], "@umbraco-cms/backoffice/user-permission": ["./src/packages/user/user-permission/index.ts"], "@umbraco-cms/backoffice/user": ["./src/packages/user/user/index.ts"],