Merge branch 'main' into feature/permissions
This commit is contained in:
6
src/Umbraco.Web.UI.Client/.github/README.md
vendored
6
src/Umbraco.Web.UI.Client/.github/README.md
vendored
@@ -1,4 +1,4 @@
|
||||
# Umbraco.CMS.Bacoffice (Bellissima)
|
||||
# Umbraco.CMS.Backoffice (Bellissima)
|
||||
|
||||
This is the working repository of the upcoming new Backoffice to Umbraco CMS.
|
||||
|
||||
@@ -48,3 +48,7 @@ Storybook is also being built and deployed automatically on the Main branch, inc
|
||||
## Contributing
|
||||
|
||||
We accept contributions to this project. However be aware that we are mainly working on a private backlog, so not everyone will be immediately obvious. If you want to get started on contributing, please read the [contribute space](https://github.com/umbraco/Umbraco.CMS.Backoffice/contribute) where you will be able to find the guidelines on how to contribute as well as a list of good first issues.
|
||||
|
||||
## Documentation
|
||||
|
||||
The documentation can be found on [Umbraco Docs](https://docs.umbraco.com/umbraco-backoffice/). The documentation is a work in progress.
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build and Deploy Job
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Build And Deploy
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build and Deploy Job
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Build And Deploy
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
node-version: [18.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
@@ -15,6 +15,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@v3
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run DevSkim scanner
|
||||
uses: microsoft/DevSkim-Action@v1
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
group: npm-publish
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
525
src/Umbraco.Web.UI.Client/package-lock.json
generated
525
src/Umbraco.Web.UI.Client/package-lock.json
generated
@@ -23,10 +23,10 @@
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.22.10",
|
||||
"@babel/core": "^7.22.17",
|
||||
"@mdx-js/react": "^2.3.0",
|
||||
"@open-wc/testing": "^3.2.0",
|
||||
"@playwright/test": "^1.36.2",
|
||||
"@playwright/test": "^1.37.1",
|
||||
"@rollup/plugin-commonjs": "^25.0.3",
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
"@rollup/plugin-node-resolve": "^15.1.0",
|
||||
@@ -42,7 +42,7 @@
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/uuid": "^9.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^6.3.0",
|
||||
"@typescript-eslint/parser": "^6.3.0",
|
||||
"@typescript-eslint/parser": "^6.5.0",
|
||||
"@web/dev-server-esbuild": "^0.4.1",
|
||||
"@web/dev-server-import-maps": "^0.1.1",
|
||||
"@web/test-runner": "^0.17.0",
|
||||
@@ -50,7 +50,7 @@
|
||||
"babel-loader": "^9.1.3",
|
||||
"eslint": "^8.46.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.5",
|
||||
"eslint-import-resolver-typescript": "^3.6.0",
|
||||
"eslint-plugin-import": "^2.28.0",
|
||||
"eslint-plugin-lit": "^1.8.3",
|
||||
"eslint-plugin-lit-a11y": "^4.1.0",
|
||||
@@ -172,12 +172,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.22.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz",
|
||||
"integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==",
|
||||
"version": "7.22.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
|
||||
"integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/highlight": "^7.22.10",
|
||||
"@babel/highlight": "^7.22.13",
|
||||
"chalk": "^2.4.2"
|
||||
},
|
||||
"engines": {
|
||||
@@ -194,25 +194,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/core": {
|
||||
"version": "7.22.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz",
|
||||
"integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==",
|
||||
"version": "7.22.17",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.17.tgz",
|
||||
"integrity": "sha512-2EENLmhpwplDux5PSsZnSbnSkB3tZ6QTksgO25xwEL7pIDcNOMhF5v/s6RzwjMZzZzw9Ofc30gHv5ChCC8pifQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.22.10",
|
||||
"@babel/generator": "^7.22.10",
|
||||
"@babel/helper-compilation-targets": "^7.22.10",
|
||||
"@babel/helper-module-transforms": "^7.22.9",
|
||||
"@babel/helpers": "^7.22.10",
|
||||
"@babel/parser": "^7.22.10",
|
||||
"@babel/template": "^7.22.5",
|
||||
"@babel/traverse": "^7.22.10",
|
||||
"@babel/types": "^7.22.10",
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/generator": "^7.22.15",
|
||||
"@babel/helper-compilation-targets": "^7.22.15",
|
||||
"@babel/helper-module-transforms": "^7.22.17",
|
||||
"@babel/helpers": "^7.22.15",
|
||||
"@babel/parser": "^7.22.16",
|
||||
"@babel/template": "^7.22.15",
|
||||
"@babel/traverse": "^7.22.17",
|
||||
"@babel/types": "^7.22.17",
|
||||
"convert-source-map": "^1.7.0",
|
||||
"debug": "^4.1.0",
|
||||
"gensync": "^1.0.0-beta.2",
|
||||
"json5": "^2.2.2",
|
||||
"json5": "^2.2.3",
|
||||
"semver": "^6.3.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -224,12 +224,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.22.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz",
|
||||
"integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==",
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz",
|
||||
"integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.22.10",
|
||||
"@babel/types": "^7.22.15",
|
||||
"@jridgewell/gen-mapping": "^0.3.2",
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"jsesc": "^2.5.1"
|
||||
@@ -263,13 +263,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-compilation-targets": {
|
||||
"version": "7.22.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz",
|
||||
"integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==",
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
|
||||
"integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.22.9",
|
||||
"@babel/helper-validator-option": "^7.22.5",
|
||||
"@babel/helper-validator-option": "^7.22.15",
|
||||
"browserslist": "^4.21.9",
|
||||
"lru-cache": "^5.1.1",
|
||||
"semver": "^6.3.1"
|
||||
@@ -381,28 +381,28 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-module-imports": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz",
|
||||
"integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==",
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
|
||||
"integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.22.5"
|
||||
"@babel/types": "^7.22.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-module-transforms": {
|
||||
"version": "7.22.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz",
|
||||
"integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==",
|
||||
"version": "7.22.17",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
|
||||
"integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-environment-visitor": "^7.22.5",
|
||||
"@babel/helper-module-imports": "^7.22.5",
|
||||
"@babel/helper-module-imports": "^7.22.15",
|
||||
"@babel/helper-simple-access": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/helper-validator-identifier": "^7.22.5"
|
||||
"@babel/helper-validator-identifier": "^7.22.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -512,18 +512,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
|
||||
"integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
|
||||
"integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-option": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz",
|
||||
"integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==",
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
|
||||
"integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -544,23 +544,23 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helpers": {
|
||||
"version": "7.22.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz",
|
||||
"integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==",
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.15.tgz",
|
||||
"integrity": "sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.22.5",
|
||||
"@babel/traverse": "^7.22.10",
|
||||
"@babel/types": "^7.22.10"
|
||||
"@babel/template": "^7.22.15",
|
||||
"@babel/traverse": "^7.22.15",
|
||||
"@babel/types": "^7.22.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight": {
|
||||
"version": "7.22.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz",
|
||||
"integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==",
|
||||
"version": "7.22.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
|
||||
"integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.22.5",
|
||||
@@ -572,9 +572,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.22.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz",
|
||||
"integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==",
|
||||
"version": "7.22.16",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
|
||||
"integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
@@ -2053,33 +2053,33 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz",
|
||||
"integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==",
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
|
||||
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.22.5",
|
||||
"@babel/parser": "^7.22.5",
|
||||
"@babel/types": "^7.22.5"
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/parser": "^7.22.15",
|
||||
"@babel/types": "^7.22.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse": {
|
||||
"version": "7.22.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz",
|
||||
"integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==",
|
||||
"version": "7.22.17",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.17.tgz",
|
||||
"integrity": "sha512-xK4Uwm0JnAMvxYZxOVecss85WxTEIbTa7bnGyf/+EgCL5Zt3U7htUpEOWv9detPlamGKuRzCqw74xVglDWpPdg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.22.10",
|
||||
"@babel/generator": "^7.22.10",
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/generator": "^7.22.15",
|
||||
"@babel/helper-environment-visitor": "^7.22.5",
|
||||
"@babel/helper-function-name": "^7.22.5",
|
||||
"@babel/helper-hoist-variables": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/parser": "^7.22.10",
|
||||
"@babel/types": "^7.22.10",
|
||||
"@babel/parser": "^7.22.16",
|
||||
"@babel/types": "^7.22.17",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
@@ -2088,13 +2088,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.22.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz",
|
||||
"integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==",
|
||||
"version": "7.22.17",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
|
||||
"integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.22.5",
|
||||
"@babel/helper-validator-identifier": "^7.22.5",
|
||||
"@babel/helper-validator-identifier": "^7.22.15",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -3358,64 +3358,14 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgr/utils": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.1.tgz",
|
||||
"integrity": "sha512-JOqwkgFEyi+OROIyq7l4Jy28h/WwhDnG/cPkXG2Z1iFbubB6jsHW1NDvmyOzTBxHr3yg68YGirmh1JUgMqa+9w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.3",
|
||||
"fast-glob": "^3.2.12",
|
||||
"is-glob": "^4.0.3",
|
||||
"open": "^9.1.0",
|
||||
"picocolors": "^1.0.0",
|
||||
"tslib": "^2.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/unts"
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgr/utils/node_modules/define-lazy-prop": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
|
||||
"integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgr/utils/node_modules/open": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz",
|
||||
"integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"default-browser": "^4.0.0",
|
||||
"define-lazy-prop": "^3.0.0",
|
||||
"is-inside-container": "^1.0.0",
|
||||
"is-wsl": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.36.2.tgz",
|
||||
"integrity": "sha512-2rVZeyPRjxfPH6J0oGJqE8YxiM1IBRyM8hyrXYK7eSiAqmbNhxwcLa7dZ7fy9Kj26V7FYia5fh9XJRq4Dqme+g==",
|
||||
"version": "1.37.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.37.1.tgz",
|
||||
"integrity": "sha512-bq9zTli3vWJo8S3LwB91U0qDNQDpEXnw7knhxLM0nwDvexQAwx9tO8iKDZSqqneVq+URd/WIoz+BALMqUTgdSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"playwright-core": "1.36.2"
|
||||
"playwright-core": "1.37.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@@ -3428,9 +3378,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test/node_modules/playwright-core": {
|
||||
"version": "1.36.2",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.36.2.tgz",
|
||||
"integrity": "sha512-sQYZt31dwkqxOrP7xy2ggDfEzUxM1lodjhsQ3NMMv5uGTRDsLxU0e4xf4wwMkF2gplIxf17QMBCodSFgm6bFVQ==",
|
||||
"version": "1.37.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.37.1.tgz",
|
||||
"integrity": "sha512-17EuQxlSIYCmEMwzMqusJ2ztDgJePjrbttaefgdsiqeLWidjYz9BxXaTaZWxH1J95SHGk6tjE+dwgWILJoUZfA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
@@ -7347,15 +7297,15 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.3.0.tgz",
|
||||
"integrity": "sha512-ibP+y2Gr6p0qsUkhs7InMdXrwldjxZw66wpcQq9/PzAroM45wdwyu81T+7RibNCh8oc0AgrsyCwJByncY0Ongg==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.5.0.tgz",
|
||||
"integrity": "sha512-LMAVtR5GN8nY0G0BadkG0XIe4AcNMeyEy3DyhKGAh9k4pLSMBO7rF29JvDBpZGCmp5Pgz5RLHP6eCpSYZJQDuQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "6.3.0",
|
||||
"@typescript-eslint/types": "6.3.0",
|
||||
"@typescript-eslint/typescript-estree": "6.3.0",
|
||||
"@typescript-eslint/visitor-keys": "6.3.0",
|
||||
"@typescript-eslint/scope-manager": "6.5.0",
|
||||
"@typescript-eslint/types": "6.5.0",
|
||||
"@typescript-eslint/typescript-estree": "6.5.0",
|
||||
"@typescript-eslint/visitor-keys": "6.5.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -7375,13 +7325,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz",
|
||||
"integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.5.0.tgz",
|
||||
"integrity": "sha512-A8hZ7OlxURricpycp5kdPTH3XnjG85UpJS6Fn4VzeoH4T388gQJ/PGP4ole5NfKt4WDVhmLaQ/dBLNDC4Xl/Kw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.3.0",
|
||||
"@typescript-eslint/visitor-keys": "6.3.0"
|
||||
"@typescript-eslint/types": "6.5.0",
|
||||
"@typescript-eslint/visitor-keys": "6.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
@@ -7392,9 +7342,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz",
|
||||
"integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.5.0.tgz",
|
||||
"integrity": "sha512-eqLLOEF5/lU8jW3Bw+8auf4lZSbbljHR2saKnYqON12G/WsJrGeeDHWuQePoEf9ro22+JkbPfWQwKEC5WwLQ3w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
@@ -7405,13 +7355,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz",
|
||||
"integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.5.0.tgz",
|
||||
"integrity": "sha512-q0rGwSe9e5Kk/XzliB9h2LBc9tmXX25G0833r7kffbl5437FPWb2tbpIV9wAATebC/018pGa9fwPDuvGN+LxWQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.3.0",
|
||||
"@typescript-eslint/visitor-keys": "6.3.0",
|
||||
"@typescript-eslint/types": "6.5.0",
|
||||
"@typescript-eslint/visitor-keys": "6.5.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
@@ -7432,12 +7382,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz",
|
||||
"integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.5.0.tgz",
|
||||
"integrity": "sha512-yCB/2wkbv3hPsh02ZS8dFQnij9VVQXJMN/gbQsaaY+zxALkZnxa/wagvLEFsAWMPv7d7lxQmNsIzGU1w/T/WyA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.3.0",
|
||||
"@typescript-eslint/types": "6.5.0",
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -9994,21 +9944,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/bundle-name": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
|
||||
"integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"run-applescript": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
|
||||
@@ -10903,24 +10838,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/default-browser": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz",
|
||||
"integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"bundle-name": "^3.0.0",
|
||||
"default-browser-id": "^3.0.0",
|
||||
"execa": "^7.1.1",
|
||||
"titleize": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/default-browser-id": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz",
|
||||
@@ -10937,116 +10854,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/default-browser/node_modules/execa": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz",
|
||||
"integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.3",
|
||||
"get-stream": "^6.0.1",
|
||||
"human-signals": "^4.3.0",
|
||||
"is-stream": "^3.0.0",
|
||||
"merge-stream": "^2.0.0",
|
||||
"npm-run-path": "^5.1.0",
|
||||
"onetime": "^6.0.0",
|
||||
"signal-exit": "^3.0.7",
|
||||
"strip-final-newline": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || ^16.14.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/execa?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/default-browser/node_modules/human-signals": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
|
||||
"integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14.18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/default-browser/node_modules/is-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
|
||||
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/default-browser/node_modules/mimic-fn": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
||||
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/default-browser/node_modules/npm-run-path": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
|
||||
"integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"path-key": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/default-browser/node_modules/onetime": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
|
||||
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"mimic-fn": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/default-browser/node_modules/path-key": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
|
||||
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/default-browser/node_modules/strip-final-newline": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
|
||||
"integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/defaults": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
|
||||
@@ -11751,19 +11558,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-import-resolver-typescript": {
|
||||
"version": "3.5.5",
|
||||
"resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz",
|
||||
"integrity": "sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==",
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.0.tgz",
|
||||
"integrity": "sha512-QTHR9ddNnn35RTxlaEnx2gCxqFlF2SEN0SE2d17SqwyM7YOSI2GHWRYp5BiRkObTUNYPupC/3Fq2a0PpT+EKpg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
"enhanced-resolve": "^5.12.0",
|
||||
"eslint-module-utils": "^2.7.4",
|
||||
"fast-glob": "^3.3.1",
|
||||
"get-tsconfig": "^4.5.0",
|
||||
"globby": "^13.1.3",
|
||||
"is-core-module": "^2.11.0",
|
||||
"is-glob": "^4.0.3",
|
||||
"synckit": "^0.8.5"
|
||||
"is-glob": "^4.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
@@ -11776,37 +11582,6 @@
|
||||
"eslint-plugin-import": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-import-resolver-typescript/node_modules/globby": {
|
||||
"version": "13.2.2",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz",
|
||||
"integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"dir-glob": "^3.0.1",
|
||||
"fast-glob": "^3.3.0",
|
||||
"ignore": "^5.2.4",
|
||||
"merge2": "^1.4.1",
|
||||
"slash": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-import-resolver-typescript/node_modules/slash": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
|
||||
"integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-module-utils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
|
||||
@@ -12461,9 +12236,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz",
|
||||
"integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==",
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
|
||||
"integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
@@ -14133,39 +13908,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-inside-container": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
|
||||
"integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-docker": "^3.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"is-inside-container": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-inside-container/node_modules/is-docker": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
|
||||
"integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"is-docker": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-interactive": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
|
||||
@@ -19067,21 +18809,6 @@
|
||||
"integrity": "sha512-bH3g1/xOwbkuwE4iQ0tLwp1/r+dqttQr/ezO0tzp+KCttsCcxxgSCbEYy8+ePuSCLsiS3WhuTfFSED74d+tMjg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/run-applescript": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz",
|
||||
"integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"execa": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/run-async": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
|
||||
@@ -19928,22 +19655,6 @@
|
||||
"integrity": "sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/synckit": {
|
||||
"version": "0.8.5",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
|
||||
"integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@pkgr/utils": "^2.3.1",
|
||||
"tslib": "^2.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/unts"
|
||||
}
|
||||
},
|
||||
"node_modules/table-layout": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/table-layout/-/table-layout-3.0.2.tgz",
|
||||
@@ -20242,18 +19953,6 @@
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/titleize": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz",
|
||||
"integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": null,
|
||||
"./app": "./dist-cms/apps/app/index.js",
|
||||
"./class-api": "./dist-cms/libs/class-api/index.js",
|
||||
"./context-api": "./dist-cms/libs/context-api/index.js",
|
||||
"./controller-api": "./dist-cms/libs/controller-api/index.js",
|
||||
@@ -13,7 +14,6 @@
|
||||
"./localization-api": "./dist-cms/libs/localization-api/index.js",
|
||||
"./observable-api": "./dist-cms/libs/observable-api/index.js",
|
||||
"./auth": "./dist-cms/shared/auth/index.js",
|
||||
"./context": "./dist-cms/shared/context/index.js",
|
||||
"./events": "./dist-cms/shared/umb-events/index.js",
|
||||
"./icon": "./dist-cms/shared/icon/index.js",
|
||||
"./models": "./dist-cms/shared/models/index.js",
|
||||
@@ -26,6 +26,7 @@
|
||||
"./collection": "./dist-cms/packages/core/collection/index.js",
|
||||
"./components": "./dist-cms/packages/core/components/index.js",
|
||||
"./content-type": "./dist-cms/packages/core/content-type/index.js",
|
||||
"./culture": "./dist-cms/packages/core/culture/index.js",
|
||||
"./debug": "./dist-cms/packages/core/debug/index.js",
|
||||
"./entity-action": "./dist-cms/packages/core/entity-action/index.js",
|
||||
"./entity-bulk-action": "./dist-cms/packages/core/entity-bulk-action/index.js",
|
||||
@@ -139,10 +140,10 @@
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.22.10",
|
||||
"@babel/core": "^7.22.17",
|
||||
"@mdx-js/react": "^2.3.0",
|
||||
"@open-wc/testing": "^3.2.0",
|
||||
"@playwright/test": "^1.36.2",
|
||||
"@playwright/test": "^1.37.1",
|
||||
"@rollup/plugin-commonjs": "^25.0.3",
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
"@rollup/plugin-node-resolve": "^15.1.0",
|
||||
@@ -158,7 +159,7 @@
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/uuid": "^9.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^6.3.0",
|
||||
"@typescript-eslint/parser": "^6.3.0",
|
||||
"@typescript-eslint/parser": "^6.5.0",
|
||||
"@web/dev-server-esbuild": "^0.4.1",
|
||||
"@web/dev-server-import-maps": "^0.1.1",
|
||||
"@web/test-runner": "^0.17.0",
|
||||
@@ -166,7 +167,7 @@
|
||||
"babel-loader": "^9.1.3",
|
||||
"eslint": "^8.46.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.5",
|
||||
"eslint-import-resolver-typescript": "^3.6.0",
|
||||
"eslint-plugin-import": "^2.28.0",
|
||||
"eslint-plugin-lit": "^1.8.3",
|
||||
"eslint-plugin-lit-a11y": "^4.1.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { UmbAppErrorElement } from './app-error.element.js';
|
||||
import { UMB_APP, UmbAppContext } from './app.context.js';
|
||||
import { umbLocalizationRegistry } from '@umbraco-cms/backoffice/localization';
|
||||
import { UMB_AUTH, UmbAuthFlow, UmbAuthContext } from '@umbraco-cms/backoffice/auth';
|
||||
import { UMB_APP, UmbAppContext } from '@umbraco-cms/backoffice/context';
|
||||
import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UUIIconRegistryEssential } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbIconRegistry } from '@umbraco-cms/backoffice/icon';
|
||||
@@ -114,6 +114,10 @@ export class UmbAppElement extends UmbLitElement {
|
||||
|
||||
// Try to initialise the auth flow and get the runtime status
|
||||
try {
|
||||
if (this.bypassAuth === false) {
|
||||
await this.#authFlow.fetchServiceConfiguration();
|
||||
}
|
||||
|
||||
// Get the current runtime level
|
||||
await this.#setInitStatus();
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './app-context-config.interface.js';
|
||||
export * from './app-error.element.js';
|
||||
export * from './app.element.js';
|
||||
export * from './app.context.js';
|
||||
|
||||
@@ -25,6 +25,7 @@ const CORE_PACKAGES = [
|
||||
import('../../packages/umbraco-news/umbraco-package.js'),
|
||||
import('../../packages/tags/umbraco-package.js'),
|
||||
import('../../packages/log-viewer/umbraco-package.js'),
|
||||
import('../../packages/health-check/umbraco-package.js'),
|
||||
];
|
||||
|
||||
@customElement('umb-backoffice')
|
||||
|
||||
@@ -31,6 +31,7 @@ import { handlers as stylesheetHandlers } from './handlers/stylesheet.handlers.j
|
||||
import { handlers as partialViewsHandlers } from './handlers/partial-views.handlers.js';
|
||||
import { handlers as tagHandlers } from './handlers/tag-handlers.js';
|
||||
import { handlers as configHandlers } from './handlers/config.handlers.js';
|
||||
import { handlers as scriptHandlers } from './handlers/scripts.handlers.js';
|
||||
|
||||
const handlers = [
|
||||
serverHandlers.serverVersionHandler,
|
||||
@@ -65,6 +66,7 @@ const handlers = [
|
||||
...partialViewsHandlers,
|
||||
...tagHandlers,
|
||||
...configHandlers,
|
||||
...scriptHandlers,
|
||||
];
|
||||
|
||||
switch (import.meta.env.VITE_UMBRACO_INSTALL_STATUS) {
|
||||
|
||||
238
src/Umbraco.Web.UI.Client/src/mocks/data/scripts.data.ts
Normal file
238
src/Umbraco.Web.UI.Client/src/mocks/data/scripts.data.ts
Normal file
@@ -0,0 +1,238 @@
|
||||
import { UmbData } from './data.js';
|
||||
import { UmbEntityData } from './entity.data.js';
|
||||
import { createFileItemResponseModelBaseModel, createFileSystemTreeItem, createTextFileItem } from './utils.js';
|
||||
import {
|
||||
CreatePathFolderRequestModel,
|
||||
CreateTextFileViewModelBaseModel,
|
||||
FileSystemTreeItemPresentationModel,
|
||||
PagedFileSystemTreeItemPresentationModel,
|
||||
ScriptItemResponseModel,
|
||||
ScriptResponseModel,
|
||||
UpdateScriptRequestModel,
|
||||
} from '@umbraco-cms/backoffice/backend-api';
|
||||
|
||||
type ScriptsDataItem = ScriptResponseModel & FileSystemTreeItemPresentationModel;
|
||||
|
||||
export const data: Array<ScriptsDataItem> = [
|
||||
{
|
||||
path: 'some-folder',
|
||||
isFolder: true,
|
||||
name: 'some-folder',
|
||||
type: 'script',
|
||||
hasChildren: true,
|
||||
},
|
||||
{
|
||||
path: 'another-folder',
|
||||
isFolder: true,
|
||||
name: 'another-folder',
|
||||
type: 'script',
|
||||
hasChildren: true,
|
||||
},
|
||||
{
|
||||
path: 'very important folder',
|
||||
isFolder: true,
|
||||
name: 'very important folder',
|
||||
type: 'script',
|
||||
hasChildren: true,
|
||||
},
|
||||
{
|
||||
path: 'some-folder/ugly script.js',
|
||||
isFolder: false,
|
||||
name: 'ugly script.js',
|
||||
type: 'script',
|
||||
hasChildren: false,
|
||||
content: `function makeid(length) {
|
||||
var result = '';
|
||||
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
var charactersLength = characters.length;
|
||||
for ( var i = 0; i < length; i++ ) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
console.log(makeid(5));`,
|
||||
},
|
||||
{
|
||||
path: 'some-folder/nice script.js',
|
||||
isFolder: false,
|
||||
name: 'nice script.js',
|
||||
type: 'script',
|
||||
hasChildren: false,
|
||||
content: `var items = {
|
||||
"item_1": "1",
|
||||
"item_2": "2",
|
||||
"item_3": "3"
|
||||
}
|
||||
for (var item in items) {
|
||||
console.log(items[item]);
|
||||
}`,
|
||||
},
|
||||
{
|
||||
path: 'another-folder/only bugs.js',
|
||||
isFolder: false,
|
||||
name: 'only bugs.js',
|
||||
type: 'script',
|
||||
hasChildren: false,
|
||||
content: `var my_arr = [4, '', 0, 10, 7, '', false, 10];
|
||||
|
||||
my_arr = my_arr.filter(Boolean);
|
||||
|
||||
console.log(my_arr);`,
|
||||
},
|
||||
{
|
||||
path: 'very important folder/no bugs at all.js',
|
||||
isFolder: false,
|
||||
name: 'no bugs at all.js',
|
||||
type: 'script',
|
||||
hasChildren: false,
|
||||
content: `const date_str = "07/20/2021";
|
||||
const date = new Date(date_str);
|
||||
const full_day_name = date.toLocaleDateString('default', { weekday: 'long' });
|
||||
// -> to get full day name e.g. Tuesday
|
||||
|
||||
const short_day_name = date.toLocaleDateString('default', { weekday: 'short' });
|
||||
console.log(short_day_name);
|
||||
// -> TO get the short day name e.g. Tue`,
|
||||
},
|
||||
{
|
||||
path: 'very important folder/nope.js',
|
||||
isFolder: false,
|
||||
name: 'nope.js',
|
||||
type: 'script',
|
||||
hasChildren: false,
|
||||
content: `// Define an object
|
||||
const employee = {
|
||||
"name": "John Deo",
|
||||
"department": "IT",
|
||||
"project": "Inventory Manager"
|
||||
};
|
||||
|
||||
// Remove a property
|
||||
delete employee["project"];
|
||||
|
||||
console.log(employee);`,
|
||||
},
|
||||
];
|
||||
|
||||
class UmbScriptsData extends UmbData<ScriptsDataItem> {
|
||||
constructor() {
|
||||
super(data);
|
||||
}
|
||||
|
||||
getTreeRoot(): PagedFileSystemTreeItemPresentationModel {
|
||||
const items = this.data.filter((item) => item.path?.includes('/') === false);
|
||||
const treeItems = items.map((item) => createFileSystemTreeItem(item));
|
||||
const total = items.length;
|
||||
return { items: treeItems, total };
|
||||
}
|
||||
|
||||
getTreeItemChildren(parentPath: string): PagedFileSystemTreeItemPresentationModel {
|
||||
const items = this.data.filter((item) => item.path?.startsWith(parentPath));
|
||||
const treeItems = items.map((item) => createFileSystemTreeItem(item));
|
||||
const total = items.length;
|
||||
return { items: treeItems, total };
|
||||
}
|
||||
|
||||
getTreeItem(paths: Array<string>): Array<FileSystemTreeItemPresentationModel> {
|
||||
const items = this.data.filter((item) => paths.includes(item.path ?? ''));
|
||||
return items.map((item) => createFileSystemTreeItem(item));
|
||||
}
|
||||
|
||||
getItem(paths: Array<string>): Array<ScriptItemResponseModel> {
|
||||
const items = this.data.filter((item) => paths.includes(item.path ?? ''));
|
||||
return items.map((item) => createFileItemResponseModelBaseModel(item));
|
||||
}
|
||||
|
||||
getFolder(path: string): FileSystemTreeItemPresentationModel {
|
||||
const items = data.filter((item) => item.isFolder && item.path === path);
|
||||
return items as FileSystemTreeItemPresentationModel;
|
||||
}
|
||||
|
||||
postFolder(payload: CreatePathFolderRequestModel) {
|
||||
const newFolder = {
|
||||
path: `${payload.parentPath ?? ''}/${payload.name}`,
|
||||
isFolder: true,
|
||||
name: payload.name,
|
||||
type: 'script',
|
||||
hasChildren: false,
|
||||
};
|
||||
return this.insert(newFolder);
|
||||
}
|
||||
|
||||
deleteFolder(path: string) {
|
||||
return this.delete([path]);
|
||||
}
|
||||
|
||||
getScript(path: string): ScriptResponseModel | undefined {
|
||||
return createTextFileItem(this.data.find((item) => item.path === path));
|
||||
}
|
||||
|
||||
insertScript(item: CreateTextFileViewModelBaseModel) {
|
||||
const newItem: ScriptsDataItem = {
|
||||
...item,
|
||||
path: `${item.parentPath}/${item.name}.js}`,
|
||||
isFolder: false,
|
||||
hasChildren: false,
|
||||
type: 'script',
|
||||
};
|
||||
|
||||
this.insert(newItem);
|
||||
return newItem;
|
||||
}
|
||||
|
||||
insert(item: ScriptsDataItem) {
|
||||
const exits = this.data.find((i) => i.path === item.path);
|
||||
|
||||
if (exits) {
|
||||
throw new Error(`Item with path ${item.path} already exists`);
|
||||
}
|
||||
|
||||
this.data.push(item);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
updateData(updateItem: UpdateScriptRequestModel) {
|
||||
const itemIndex = this.data.findIndex((item) => item.path === updateItem.existingPath);
|
||||
const item = this.data[itemIndex];
|
||||
if (!item) return;
|
||||
|
||||
// TODO: revisit this code, seems like something we can solve smarter/type safer now:
|
||||
const itemKeys = Object.keys(item);
|
||||
const newItem = { ...item };
|
||||
|
||||
for (const [key] of Object.entries(updateItem)) {
|
||||
if (itemKeys.indexOf(key) !== -1) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
newItem[key] = updateItem[key];
|
||||
}
|
||||
}
|
||||
// Specific to fileSystem, we need to update path based on name:
|
||||
const dirName = updateItem.existingPath?.substring(0, updateItem.existingPath.lastIndexOf('/'));
|
||||
newItem.path = `${dirName}${dirName ? '/' : ''}${updateItem.name}`;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
this.data[itemIndex] = newItem;
|
||||
}
|
||||
|
||||
delete(paths: Array<string>) {
|
||||
const pathsOfItemsToDelete = this.data
|
||||
.filter((item) => {
|
||||
if (!item.path) throw new Error('Item has no path');
|
||||
return paths.includes(item.path);
|
||||
})
|
||||
.map((item) => item.path);
|
||||
|
||||
this.data = this.data.filter((item) => {
|
||||
if (!item.path) throw new Error('Item has no path');
|
||||
return paths.indexOf(item.path) === -1;
|
||||
});
|
||||
|
||||
return pathsOfItemsToDelete;
|
||||
}
|
||||
}
|
||||
|
||||
export const umbScriptsData = new UmbScriptsData();
|
||||
@@ -0,0 +1,86 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { RestHandler, MockedRequest, DefaultBodyType } from 'msw';
|
||||
import { umbScriptsData } from '../data/scripts.data.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
import { CreatePathFolderRequestModel, CreateTextFileViewModelBaseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
|
||||
const treeHandlers = [
|
||||
rest.get(umbracoPath('/tree/script/root'), (req, res, ctx) => {
|
||||
const response = umbScriptsData.getTreeRoot();
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath('/tree/script/children'), (req, res, ctx) => {
|
||||
const path = req.url.searchParams.get('path');
|
||||
if (!path) return;
|
||||
|
||||
const response = umbScriptsData.getTreeItemChildren(path);
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath('/tree/script/item'), (req, res, ctx) => {
|
||||
const paths = req.url.searchParams.getAll('paths');
|
||||
if (!paths) return;
|
||||
|
||||
const items = umbScriptsData.getTreeItem(paths);
|
||||
return res(ctx.status(200), ctx.json(items));
|
||||
}),
|
||||
];
|
||||
|
||||
const detailHandlers: RestHandler<MockedRequest<DefaultBodyType>>[] = [
|
||||
rest.get(umbracoPath('/script'), (req, res, ctx) => {
|
||||
const path = decodeURIComponent(req.url.searchParams.get('path') ?? '').replace('-js', '.js');
|
||||
if (!path) return res(ctx.status(400));
|
||||
const response = umbScriptsData.getScript(path);
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath('/script/item'), (req, res, ctx) => {
|
||||
const path = decodeURIComponent(req.url.searchParams.get('path') ?? '').replace('-js', '.js');
|
||||
if (!path) return res(ctx.status(400, 'no body found'));
|
||||
const response = umbScriptsData.getItem([path]);
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.post(umbracoPath('/script'), async (req, res, ctx) => {
|
||||
const requestBody = (await req.json()) as CreateTextFileViewModelBaseModel;
|
||||
if (!requestBody) return res(ctx.status(400, 'no body found'));
|
||||
const response = umbScriptsData.insertScript(requestBody);
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.delete(umbracoPath('/script'), (req, res, ctx) => {
|
||||
const path = req.url.searchParams.get('path');
|
||||
if (!path) return res(ctx.status(400));
|
||||
const response = umbScriptsData.delete([path]);
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
rest.put(umbracoPath('/script'), async (req, res, ctx) => {
|
||||
const requestBody = (await req.json()) as CreateTextFileViewModelBaseModel;
|
||||
if (!requestBody) return res(ctx.status(400, 'no body found'));
|
||||
const response = umbScriptsData.updateData(requestBody);
|
||||
return res(ctx.status(200));
|
||||
}),
|
||||
];
|
||||
|
||||
const folderHandlers: RestHandler<MockedRequest<DefaultBodyType>>[] = [
|
||||
rest.get(umbracoPath('script/folder'), (req, res, ctx) => {
|
||||
const path = decodeURIComponent(req.url.searchParams.get('path') ?? '').replace('-js', '.js');
|
||||
if (!path) return res(ctx.status(400));
|
||||
const response = umbScriptsData.getFolder(path);
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
rest.post(umbracoPath('script/folder'), (req, res, ctx) => {
|
||||
const requestBody = req.json() as CreatePathFolderRequestModel;
|
||||
if (!requestBody) return res(ctx.status(400, 'no body found'));
|
||||
return res(ctx.status(200));
|
||||
}),
|
||||
rest.delete(umbracoPath('script/folder'), (req, res, ctx) => {
|
||||
const path = decodeURIComponent(req.url.searchParams.get('path') ?? '').replace('-js', '.js');
|
||||
if (!path) return res(ctx.status(400));
|
||||
const response = umbScriptsData.deleteFolder(path);
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
];
|
||||
|
||||
export const handlers = [...treeHandlers, ...detailHandlers, ...folderHandlers];
|
||||
@@ -22,7 +22,7 @@ export class UmbContentTypeContainerStructureHelper {
|
||||
// Containers defined in data might be more than actual containers to display as we merge them by name.
|
||||
// Direct containers are the containers defining the total of this container(Multiple containers with the same name and type)
|
||||
private _ownerAlikeContainers: PropertyTypeContainerModelBaseModel[] = [];
|
||||
// Owner containers are containers owned by the owner Document Type (The specific one up for editing)
|
||||
// Owner containers are containers owned by the owner Content Type (The specific one up for editing)
|
||||
private _ownerContainers: PropertyTypeContainerModelBaseModel[] = [];
|
||||
|
||||
// State containing the merged containers (only one pr. name):
|
||||
@@ -106,7 +106,7 @@ export class UmbContentTypeContainerStructureHelper {
|
||||
(ownerContainers) => {
|
||||
this._ownerContainers = ownerContainers || [];
|
||||
},
|
||||
'_observeOwnerContainers'
|
||||
'_observeOwnerContainers',
|
||||
);
|
||||
} else if (this._ownerName) {
|
||||
new UmbObserverController(
|
||||
@@ -121,7 +121,7 @@ export class UmbContentTypeContainerStructureHelper {
|
||||
this._observeChildContainers();
|
||||
}
|
||||
},
|
||||
'_observeOwnerContainers'
|
||||
'_observeOwnerContainers',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -136,7 +136,7 @@ export class UmbContentTypeContainerStructureHelper {
|
||||
(hasProperties) => {
|
||||
this.#hasProperties.next(hasProperties);
|
||||
},
|
||||
'_observeOwnerHasProperties_' + container.id
|
||||
'_observeOwnerHasProperties_' + container.id,
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -149,7 +149,7 @@ export class UmbContentTypeContainerStructureHelper {
|
||||
this.#host,
|
||||
this.#structure!.containersOfParentKey(container.id, this._childType!),
|
||||
this._insertGroupContainers,
|
||||
'_observeGroupsOf_' + container.id
|
||||
'_observeGroupsOf_' + container.id,
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -164,7 +164,7 @@ export class UmbContentTypeContainerStructureHelper {
|
||||
this.#containers.next([]);
|
||||
this._insertGroupContainers(rootContainers);
|
||||
},
|
||||
'_observeRootContainers'
|
||||
'_observeRootContainers',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ export class UmbContentTypeContainerStructureHelper {
|
||||
if (!this.#structure) return;
|
||||
|
||||
const newName =
|
||||
this.#structure.makeContainerNameUniqueForOwnerDocument(name, this._childType, containerParentId) ?? name;
|
||||
this.#structure.makeContainerNameUniqueForOwnerContentType(name, this._childType, containerParentId) ?? name;
|
||||
|
||||
return await this.partialUpdateContainer(containerId, { name: newName });
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ export class UmbContentTypePropertyStructureHelper {
|
||||
this.#propertyStructure.sortBy((a, b) => ((a as any).sortOrder ?? 0) - ((b as any).sortOrder ?? 0));
|
||||
}
|
||||
|
||||
public getOwnerDocumentTypes() {
|
||||
return this.#structure?.documentTypes;
|
||||
get ownerDocumentTypes() {
|
||||
return this.#structure?.contentTypes;
|
||||
}
|
||||
|
||||
public setStructureManager(structure: UmbContentTypePropertyStructureManager) {
|
||||
|
||||
@@ -28,11 +28,11 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
|
||||
#contentTypeRepository: R;
|
||||
|
||||
#ownerDocumentTypeId?: string;
|
||||
#documentTypeObservers = new Array<UmbController>();
|
||||
#documentTypes = new UmbArrayState<T>([], (x) => x.id);
|
||||
readonly documentTypes = this.#documentTypes.asObservable();
|
||||
private readonly _documentTypeContainers = this.#documentTypes.asObservablePart((x) =>
|
||||
#ownerContentTypeId?: string;
|
||||
#contentTypeObservers = new Array<UmbController>();
|
||||
#contentTypes = new UmbArrayState<T>([], (x) => x.id);
|
||||
readonly contentTypes = this.#contentTypes.asObservable();
|
||||
private readonly _contentTypeContainers = this.#contentTypes.asObservablePart((x) =>
|
||||
x.flatMap((x) => x.containers ?? []),
|
||||
);
|
||||
|
||||
@@ -43,13 +43,13 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
this.#host = host;
|
||||
this.#contentTypeRepository = typeRepository;
|
||||
|
||||
new UmbObserverController(host, this.documentTypes, (documentTypes) => {
|
||||
documentTypes.forEach((documentType) => {
|
||||
this._loadDocumentTypeCompositions(documentType);
|
||||
new UmbObserverController(host, this.contentTypes, (contentTypes) => {
|
||||
contentTypes.forEach((contentType) => {
|
||||
this._loadContentTypeCompositions(contentType);
|
||||
});
|
||||
});
|
||||
new UmbObserverController(host, this._documentTypeContainers, (documentTypeContainers) => {
|
||||
this.#containers.next(documentTypeContainers);
|
||||
new UmbObserverController(host, this._contentTypeContainers, (contentTypeContainers) => {
|
||||
this.#containers.next(contentTypeContainers);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
public async loadType(id?: string) {
|
||||
this._reset();
|
||||
|
||||
this.#ownerDocumentTypeId = id;
|
||||
this.#ownerContentTypeId = id;
|
||||
|
||||
const promiseResult = this._loadType(id);
|
||||
this.#init = promiseResult;
|
||||
@@ -76,29 +76,27 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
const { data } = await this.#contentTypeRepository.createScaffold(parentId);
|
||||
if (!data) return {};
|
||||
|
||||
this.#ownerDocumentTypeId = data.id;
|
||||
this.#ownerContentTypeId = data.id;
|
||||
|
||||
this.#init = this._observeDocumentType(data);
|
||||
this.#init = this._observeContentType(data);
|
||||
await this.#init;
|
||||
return { data };
|
||||
}
|
||||
|
||||
public async save() {
|
||||
const documentType = this.getOwnerDocumentType();
|
||||
if (!documentType || !documentType.id) return false;
|
||||
const contentType = this.getOwnerContentType();
|
||||
if (!contentType || !contentType.id) return false;
|
||||
|
||||
await this.#contentTypeRepository.save(documentType.id, documentType);
|
||||
await this.#contentTypeRepository.save(contentType.id, contentType);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async create() {
|
||||
const documentType = this.getOwnerDocumentType();
|
||||
if (!documentType || !documentType.id) return false;
|
||||
|
||||
//const value = documentType as CreateDocumentTypeRequestModel & { id: string };
|
||||
const { data } = await this.#contentTypeRepository.create(documentType);
|
||||
const contentType = this.getOwnerContentType();
|
||||
if (!contentType || !contentType.id) return false;
|
||||
|
||||
const { data } = await this.#contentTypeRepository.create(contentType);
|
||||
if (!data) return false;
|
||||
|
||||
await this.loadType(data.id);
|
||||
@@ -108,7 +106,7 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
|
||||
private async _ensureType(id?: string) {
|
||||
if (!id) return;
|
||||
if (this.#documentTypes.getValue().find((x) => x.id === id)) return;
|
||||
if (this.#contentTypes.getValue().find((x) => x.id === id)) return;
|
||||
await this._loadType(id);
|
||||
}
|
||||
|
||||
@@ -118,53 +116,47 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
const { data } = await this.#contentTypeRepository.requestById(id);
|
||||
if (!data) return {};
|
||||
|
||||
await this._observeDocumentType(data);
|
||||
await this._observeContentType(data);
|
||||
return { data };
|
||||
}
|
||||
|
||||
public async _observeDocumentType(data: T) {
|
||||
public async _observeContentType(data: T) {
|
||||
if (!data.id) return;
|
||||
|
||||
// Load inherited and composed types:
|
||||
this._loadDocumentTypeCompositions(data);
|
||||
this._loadContentTypeCompositions(data);
|
||||
|
||||
this.#documentTypeObservers.push(
|
||||
this.#contentTypeObservers.push(
|
||||
new UmbObserverController(this.#host, await this.#contentTypeRepository.byId(data.id), (docType) => {
|
||||
if (docType) {
|
||||
// TODO: Handle if there was changes made to the owner document type in this context.
|
||||
/*
|
||||
possible easy solutions could be to notify user wether they want to update(Discard the changes to accept the new ones).
|
||||
*/
|
||||
this.#documentTypes.appendOne(docType);
|
||||
this.#contentTypes.appendOne(docType);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
private async _loadDocumentTypeCompositions(documentType: T) {
|
||||
documentType.compositions?.forEach((composition) => {
|
||||
private async _loadContentTypeCompositions(contentType: T) {
|
||||
contentType.compositions?.forEach((composition) => {
|
||||
this._ensureType(composition.id);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
private async _initDocumentTypeContainers(documentType: T) {
|
||||
documentType.containers?.forEach((container) => {
|
||||
this.#containers.appendOne({ ...container, _ownerDocumentTypeKey: documentType.id });
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
/** Public methods for consuming structure: */
|
||||
|
||||
ownerDocumentType() {
|
||||
return this.#documentTypes.asObservablePart((x) => x.find((y) => y.id === this.#ownerDocumentTypeId));
|
||||
ownerContentType() {
|
||||
return this.#contentTypes.asObservablePart((x) => x.find((y) => y.id === this.#ownerContentTypeId));
|
||||
}
|
||||
getOwnerDocumentType() {
|
||||
return this.#documentTypes.getValue().find((y) => y.id === this.#ownerDocumentTypeId);
|
||||
|
||||
getOwnerContentType() {
|
||||
return this.#contentTypes.getValue().find((y) => y.id === this.#ownerContentTypeId);
|
||||
}
|
||||
updateOwnerDocumentType(entry: T) {
|
||||
this.#documentTypes.updateOne(this.#ownerDocumentTypeId, entry);
|
||||
|
||||
updateOwnerContentType(entry: T) {
|
||||
this.#contentTypes.updateOne(this.#ownerContentTypeId, entry);
|
||||
}
|
||||
|
||||
// We could move the actions to another class?
|
||||
@@ -176,7 +168,7 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
sortOrder?: number,
|
||||
) {
|
||||
await this.#init;
|
||||
contentTypeId = contentTypeId ?? this.#ownerDocumentTypeId!;
|
||||
contentTypeId = contentTypeId ?? this.#ownerContentTypeId!;
|
||||
|
||||
const container: PropertyTypeContainerModelBaseModel = {
|
||||
id: UmbId.new(),
|
||||
@@ -186,15 +178,15 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
sortOrder: sortOrder ?? 0,
|
||||
};
|
||||
|
||||
const containers = [...(this.#documentTypes.getValue().find((x) => x.id === contentTypeId)?.containers ?? [])];
|
||||
const containers = [...(this.#contentTypes.getValue().find((x) => x.id === contentTypeId)?.containers ?? [])];
|
||||
containers.push(container);
|
||||
|
||||
this.#documentTypes.updateOne(contentTypeId, { containers });
|
||||
this.#contentTypes.updateOne(contentTypeId, { containers });
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
makeContainerNameUniqueForOwnerDocument(
|
||||
makeContainerNameUniqueForOwnerContentType(
|
||||
newName: string,
|
||||
containerType: PropertyContainerTypes = 'Tab',
|
||||
parentId: string | null = null,
|
||||
@@ -213,28 +205,28 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
}
|
||||
|
||||
async updateContainer(
|
||||
documentTypeId: string | null,
|
||||
contentTypeId: string | null,
|
||||
containerId: string,
|
||||
partialUpdate: Partial<PropertyTypeContainerModelBaseModel>,
|
||||
) {
|
||||
await this.#init;
|
||||
documentTypeId = documentTypeId ?? this.#ownerDocumentTypeId!;
|
||||
contentTypeId = contentTypeId ?? this.#ownerContentTypeId!;
|
||||
|
||||
const frozenContainers = this.#documentTypes.getValue().find((x) => x.id === documentTypeId)?.containers ?? [];
|
||||
const frozenContainers = this.#contentTypes.getValue().find((x) => x.id === contentTypeId)?.containers ?? [];
|
||||
|
||||
const containers = partialUpdateFrozenArray(frozenContainers, partialUpdate, (x) => x.id === containerId);
|
||||
|
||||
this.#documentTypes.updateOne(documentTypeId, { containers });
|
||||
this.#contentTypes.updateOne(contentTypeId, { containers });
|
||||
}
|
||||
|
||||
async removeContainer(documentTypeKey: string | null, containerId: string | null = null) {
|
||||
async removeContainer(contentTypeId: string | null, containerId: string | null = null) {
|
||||
await this.#init;
|
||||
documentTypeKey = documentTypeKey ?? this.#ownerDocumentTypeId!;
|
||||
contentTypeId = contentTypeId ?? this.#ownerContentTypeId!;
|
||||
|
||||
const frozenContainers = this.#documentTypes.getValue().find((x) => x.id === documentTypeKey)?.containers ?? [];
|
||||
const frozenContainers = this.#contentTypes.getValue().find((x) => x.id === contentTypeId)?.containers ?? [];
|
||||
const containers = frozenContainers.filter((x) => x.id !== containerId);
|
||||
|
||||
this.#documentTypes.updateOne(documentTypeKey, { containers });
|
||||
this.#contentTypes.updateOne(contentTypeId, { containers });
|
||||
}
|
||||
|
||||
createPropertyScaffold(containerId: string | null = null, sortOrder?: number) {
|
||||
@@ -262,80 +254,76 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
return property;
|
||||
}
|
||||
|
||||
async createProperty(documentTypeId: string | null, containerId: string | null = null, sortOrder?: number) {
|
||||
async createProperty(contentTypeId: string | null, containerId: string | null = null, sortOrder?: number) {
|
||||
await this.#init;
|
||||
documentTypeId = documentTypeId ?? this.#ownerDocumentTypeId!;
|
||||
contentTypeId = contentTypeId ?? this.#ownerContentTypeId!;
|
||||
|
||||
const property: PropertyTypeModelBaseModel = this.createPropertyScaffold(containerId, sortOrder);
|
||||
|
||||
const properties = [...(this.#documentTypes.getValue().find((x) => x.id === documentTypeId)?.properties ?? [])];
|
||||
const properties = [...(this.#contentTypes.getValue().find((x) => x.id === contentTypeId)?.properties ?? [])];
|
||||
properties.push(property);
|
||||
|
||||
this.#documentTypes.updateOne(documentTypeId, { properties });
|
||||
this.#contentTypes.updateOne(contentTypeId, { properties });
|
||||
|
||||
return property;
|
||||
}
|
||||
|
||||
async insertProperty(documentTypeId: string | null, property: PropertyTypeModelBaseModel) {
|
||||
async insertProperty(contentTypeId: string | null, property: PropertyTypeModelBaseModel) {
|
||||
await this.#init;
|
||||
documentTypeId = documentTypeId ?? this.#ownerDocumentTypeId!;
|
||||
contentTypeId = contentTypeId ?? this.#ownerContentTypeId!;
|
||||
|
||||
const frozenProperties = this.#documentTypes.getValue().find((x) => x.id === documentTypeId)?.properties ?? [];
|
||||
const frozenProperties = this.#contentTypes.getValue().find((x) => x.id === contentTypeId)?.properties ?? [];
|
||||
|
||||
const properties = appendToFrozenArray(frozenProperties, property, (x) => x.id === property.id);
|
||||
|
||||
this.#documentTypes.updateOne(documentTypeId, { properties });
|
||||
this.#contentTypes.updateOne(contentTypeId, { properties });
|
||||
}
|
||||
|
||||
async removeProperty(documentTypeId: string | null, propertyId: string) {
|
||||
async removeProperty(contentTypeId: string | null, propertyId: string) {
|
||||
await this.#init;
|
||||
documentTypeId = documentTypeId ?? this.#ownerDocumentTypeId!;
|
||||
contentTypeId = contentTypeId ?? this.#ownerContentTypeId!;
|
||||
|
||||
const frozenProperties = this.#documentTypes.getValue().find((x) => x.id === documentTypeId)?.properties ?? [];
|
||||
const frozenProperties = this.#contentTypes.getValue().find((x) => x.id === contentTypeId)?.properties ?? [];
|
||||
|
||||
const properties = filterFrozenArray(frozenProperties, (x) => x.id !== propertyId);
|
||||
|
||||
this.#documentTypes.updateOne(documentTypeId, { properties });
|
||||
this.#contentTypes.updateOne(contentTypeId, { properties });
|
||||
}
|
||||
|
||||
async updateProperty(
|
||||
documentTypeId: string | null,
|
||||
contentTypeId: string | null,
|
||||
propertyId: string,
|
||||
partialUpdate: Partial<PropertyTypeModelBaseModel>,
|
||||
) {
|
||||
await this.#init;
|
||||
documentTypeId = documentTypeId ?? this.#ownerDocumentTypeId!;
|
||||
contentTypeId = contentTypeId ?? this.#ownerContentTypeId!;
|
||||
|
||||
const frozenProperties = this.#documentTypes.getValue().find((x) => x.id === documentTypeId)?.properties ?? [];
|
||||
const frozenProperties = this.#contentTypes.getValue().find((x) => x.id === contentTypeId)?.properties ?? [];
|
||||
|
||||
const properties = partialUpdateFrozenArray(frozenProperties, partialUpdate, (x) => x.id === propertyId);
|
||||
|
||||
this.#documentTypes.updateOne(documentTypeId, { properties });
|
||||
this.#contentTypes.updateOne(contentTypeId, { properties });
|
||||
}
|
||||
|
||||
// TODO: Refactor: These property methods, should maybe be named without structure in their name.
|
||||
async propertyStructureById(
|
||||
propertyId: string
|
||||
) {
|
||||
async propertyStructureById(propertyId: string) {
|
||||
await this.#init;
|
||||
return this.#documentTypes.asObservablePart((docTypes) => {
|
||||
return this.#contentTypes.asObservablePart((docTypes) => {
|
||||
for (const docType of docTypes) {
|
||||
const foundProp = docType.properties?.find((property) => property.id === propertyId);
|
||||
if(foundProp) {
|
||||
if (foundProp) {
|
||||
return foundProp;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
async propertyStructureByAlias(
|
||||
propertyAlias: string
|
||||
) {
|
||||
async propertyStructureByAlias(propertyAlias: string) {
|
||||
await this.#init;
|
||||
return this.#documentTypes.asObservablePart((docTypes) => {
|
||||
return this.#contentTypes.asObservablePart((docTypes) => {
|
||||
for (const docType of docTypes) {
|
||||
const foundProp = docType.properties?.find((property) => property.alias === propertyAlias);
|
||||
if(foundProp) {
|
||||
if (foundProp) {
|
||||
return foundProp;
|
||||
}
|
||||
}
|
||||
@@ -345,52 +333,35 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
|
||||
async getPropertyStructureById(propertyId: string) {
|
||||
await this.#init;
|
||||
for (const docType of this.#documentTypes.getValue()) {
|
||||
for (const docType of this.#contentTypes.getValue()) {
|
||||
const foundProp = docType.properties?.find((property) => property.id === propertyId);
|
||||
if(foundProp) {
|
||||
if (foundProp) {
|
||||
return foundProp;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async getPropertyStructureByAlias(propertyAlias: string) {
|
||||
await this.#init;
|
||||
for (const docType of this.#documentTypes.getValue()) {
|
||||
for (const docType of this.#contentTypes.getValue()) {
|
||||
const foundProp = docType.properties?.find((property) => property.alias === propertyAlias);
|
||||
if(foundProp) {
|
||||
if (foundProp) {
|
||||
return foundProp;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
rootDocumentTypeName() {
|
||||
return this.#documentTypes.asObservablePart((docTypes) => {
|
||||
const docType = docTypes.find((x) => x.id === this.#rootDocumentTypeKey);
|
||||
return docType?.name ?? '';
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
ownerDocumentTypeObservablePart<PartResult>(mappingFunction: MappingFunction<T, PartResult>) {
|
||||
return this.#documentTypes.asObservablePart((docTypes) => {
|
||||
const docType = docTypes.find((x) => x.id === this.#ownerDocumentTypeId);
|
||||
ownerContentTypeObservablePart<PartResult>(mappingFunction: MappingFunction<T, PartResult>) {
|
||||
return this.#contentTypes.asObservablePart((docTypes) => {
|
||||
const docType = docTypes.find((x) => x.id === this.#ownerContentTypeId);
|
||||
return docType ? mappingFunction(docType) : undefined;
|
||||
});
|
||||
}
|
||||
/*
|
||||
nameOfDocumentType(id: string) {
|
||||
return this.#documentTypes.asObservablePart((docTypes) => {
|
||||
const docType = docTypes.find((x) => x.id === id);
|
||||
return docType?.name ?? '';
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
hasPropertyStructuresOf(containerId: string | null) {
|
||||
return this.#documentTypes.asObservablePart((docTypes) => {
|
||||
return this.#contentTypes.asObservablePart((docTypes) => {
|
||||
return (
|
||||
docTypes.find((docType) => {
|
||||
return docType.properties?.find((property) => property.containerId === containerId);
|
||||
@@ -398,11 +369,13 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
rootPropertyStructures() {
|
||||
return this.propertyStructuresOf(null);
|
||||
}
|
||||
|
||||
propertyStructuresOf(containerId: string | null) {
|
||||
return this.#documentTypes.asObservablePart((docTypes) => {
|
||||
return this.#contentTypes.asObservablePart((docTypes) => {
|
||||
const props: DocumentTypePropertyTypeResponseModel[] = [];
|
||||
docTypes.forEach((docType) => {
|
||||
docType.properties?.forEach((property) => {
|
||||
@@ -432,15 +405,15 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
}
|
||||
|
||||
ownerContainersOf(containerType: PropertyContainerTypes) {
|
||||
return this.ownerDocumentTypeObservablePart((x) => x.containers?.filter((x) => x.type === containerType) ?? []);
|
||||
return this.ownerContentTypeObservablePart((x) => x.containers?.filter((x) => x.type === containerType) ?? []);
|
||||
}
|
||||
|
||||
getOwnerContainers(containerType: PropertyContainerTypes, parentId: string | null = null) {
|
||||
return this.getOwnerDocumentType()?.containers?.filter((x) => x.parentId === parentId && x.type === containerType);
|
||||
return this.getOwnerContentType()?.containers?.filter((x) => x.parentId === parentId && x.type === containerType);
|
||||
}
|
||||
|
||||
isOwnerContainer(containerId: string) {
|
||||
return this.getOwnerDocumentType()?.containers?.filter((x) => x.id === containerId);
|
||||
return this.getOwnerContentType()?.containers?.filter((x) => x.id === containerId);
|
||||
}
|
||||
|
||||
containersOfParentKey(
|
||||
@@ -460,14 +433,14 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
|
||||
}
|
||||
|
||||
private _reset() {
|
||||
this.#documentTypeObservers.forEach((observer) => observer.destroy());
|
||||
this.#documentTypeObservers = [];
|
||||
this.#documentTypes.next([]);
|
||||
this.#contentTypeObservers.forEach((observer) => observer.destroy());
|
||||
this.#contentTypeObservers = [];
|
||||
this.#contentTypes.next([]);
|
||||
this.#containers.next([]);
|
||||
}
|
||||
public destroy() {
|
||||
this._reset();
|
||||
this.#documentTypes.complete();
|
||||
this.#contentTypes.complete();
|
||||
this.#containers.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './input-culture-select/input-culture-select.element.js';
|
||||
@@ -1,10 +1,6 @@
|
||||
import { UmbCultureRepository } from '../../repository/culture.repository.js';
|
||||
import { css, html, repeat, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import {
|
||||
FormControlMixin,
|
||||
UUIComboboxElement,
|
||||
UUIComboboxEvent,
|
||||
} from '@umbraco-cms/backoffice/external/uui';
|
||||
import { html, repeat, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { FormControlMixin, UUIComboboxElement, UUIComboboxEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbChangeEvent } from '@umbraco-cms/backoffice/events';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
import { CultureReponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
@@ -89,12 +85,11 @@ export class UmbInputCultureSelectElement extends FormControlMixin(UmbLitElement
|
||||
${repeat(
|
||||
this.#filteredCultures,
|
||||
(culture) => culture.name,
|
||||
(culture) =>
|
||||
html`
|
||||
<uui-combobox-list-option value=${ifDefined(culture.name)}
|
||||
>${culture.englishName}</uui-combobox-list-option
|
||||
>
|
||||
`
|
||||
(culture) => html`
|
||||
<uui-combobox-list-option value=${ifDefined(culture.name)}
|
||||
>${culture.englishName}</uui-combobox-list-option
|
||||
>
|
||||
`,
|
||||
)}
|
||||
</uui-combobox-list>
|
||||
</uui-combobox>
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './components/index.js';
|
||||
export * from './repository/culture.repository.js';
|
||||
@@ -1,4 +1,4 @@
|
||||
import { UmbCultureRepository } from '../repository/culture.repository.js';
|
||||
import { UmbCultureRepository } from './culture.repository.js';
|
||||
import { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const CULTURE_REPOSITORY_ALIAS = 'Umb.Repository.Culture';
|
||||
@@ -8,6 +8,7 @@ import { manifests as workspaceManifests } from './workspace/manifests.js';
|
||||
import { manifests as modalManifests } from './modal/common/manifests.js';
|
||||
import { manifests as themeManifests } from './themes/manifests.js';
|
||||
import { manifests as conditionManifests } from './extension-registry/conditions/manifests.js';
|
||||
import { manifests as cultureManifests } from './culture/manifests.js';
|
||||
|
||||
import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification';
|
||||
import { UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal';
|
||||
@@ -42,6 +43,7 @@ export * from './store/index.js';
|
||||
export * from './tree/index.js';
|
||||
export * from './variant/index.js';
|
||||
export * from './workspace/index.js';
|
||||
export * from './culture/index.js';
|
||||
|
||||
const manifests: Array<ManifestTypes | UmbBackofficeManifestKind> = [
|
||||
...conditionManifests,
|
||||
@@ -53,6 +55,7 @@ const manifests: Array<ManifestTypes | UmbBackofficeManifestKind> = [
|
||||
...workspaceManifests,
|
||||
...modalManifests,
|
||||
...themeManifests,
|
||||
...cultureManifests,
|
||||
];
|
||||
|
||||
export const onInit: UmbEntryPointOnInit = (host, extensionRegistry) => {
|
||||
|
||||
@@ -8,6 +8,7 @@ import { PropertyValueMap, css, html, nothing, customElement, state } from '@umb
|
||||
import { UmbModalBaseElement } from '@umbraco-cms/internal/modal';
|
||||
import { UmbPropertySettingsModalResult, UmbPropertySettingsModalData } from '@umbraco-cms/backoffice/modal';
|
||||
import { generateAlias } from '@umbraco-cms/backoffice/utils';
|
||||
import { UMB_DOCUMENT_TYPE_STORE_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/document-type';
|
||||
// TODO: Could base take a token to get its types?.
|
||||
// TODO: Missing a workspace context... unless this should not be a workspace any way.
|
||||
@customElement('umb-property-settings-modal')
|
||||
@@ -43,12 +44,24 @@ export class UmbPropertySettingsModalElement extends UmbModalBaseElement<
|
||||
|
||||
@state() private _aliasLocked = true;
|
||||
|
||||
@state()
|
||||
protected _ownerDocumentType?: UmbPropertySettingsModalResult;
|
||||
|
||||
@state()
|
||||
protected _returnData!: UmbPropertySettingsModalResult;
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this._returnData = JSON.parse(JSON.stringify(this.data));
|
||||
|
||||
// TODO: This is actually not good enough, we need to be able to get to the DOCUMENT_WORKSPACE_CONTEXT, so we can have a look at the draft/runtime version of the document. Otherwise 'Vary by culture' is first updated when saved.
|
||||
this.consumeContext(UMB_DOCUMENT_TYPE_STORE_CONTEXT_TOKEN, (instance) => {
|
||||
this.observe(instance.byId(this.data?.documentTypeId), (documentType) => {
|
||||
this._ownerDocumentType = documentType;
|
||||
this.requestUpdate('_ownerDocumentType');
|
||||
}, '_observeDocumentType');
|
||||
});
|
||||
|
||||
this._returnData = JSON.parse(JSON.stringify(this.data?.propertyData ?? {}));
|
||||
|
||||
this._returnData.validation ??= {};
|
||||
|
||||
@@ -105,7 +118,7 @@ export class UmbPropertySettingsModalElement extends UmbModalBaseElement<
|
||||
if (!this._aliasLocked) {
|
||||
this._returnData.alias = alias;
|
||||
} else {
|
||||
this._returnData.alias = this.data?.alias;
|
||||
this._returnData.alias = this.data?.propertyData?.alias;
|
||||
}
|
||||
this.requestUpdate('_returnData');
|
||||
}
|
||||
@@ -177,6 +190,11 @@ export class UmbPropertySettingsModalElement extends UmbModalBaseElement<
|
||||
this.requestUpdate('_returnData');
|
||||
}
|
||||
|
||||
#onVaryByCultureChange(event: UUIBooleanInputEvent) {
|
||||
this._returnData.variesByCulture = event.target.checked;
|
||||
this.requestUpdate('_returnData');
|
||||
}
|
||||
|
||||
// TODO: This would conceptually be a Property Editor Workspace, should be changed at one point in the future.
|
||||
// For now this is hacky made available by giving the element an fixed alias.
|
||||
// This would allow for workspace views and workspace actions.
|
||||
@@ -226,6 +244,7 @@ export class UmbPropertySettingsModalElement extends UmbModalBaseElement<
|
||||
${this.#renderCustomValidation()}
|
||||
</div>
|
||||
<hr />
|
||||
${this.#renderVariationControls()}
|
||||
<div class="container">
|
||||
<b style="margin-bottom: var(--uui-size-space-3)">Appearance</b>
|
||||
<div id="appearances">${this.#renderAlignLeftIcon()} ${this.#renderAlignTopIcon()}</div>
|
||||
@@ -277,13 +296,13 @@ export class UmbPropertySettingsModalElement extends UmbModalBaseElement<
|
||||
<uui-toggle
|
||||
@change=${this.#onMandatoryChange}
|
||||
id="mandatory"
|
||||
value=${this._returnData.validation?.mandatory}
|
||||
.checked=${this._returnData.validation?.mandatory ?? false}
|
||||
slot="editor"></uui-toggle>
|
||||
</div>
|
||||
${this._returnData.validation?.mandatory
|
||||
? html`<uui-input
|
||||
name="mandatory-message"
|
||||
value=${this._returnData.validation?.mandatoryMessage}
|
||||
value=${this._returnData.validation?.mandatoryMessage ?? ''}
|
||||
@change=${this.#onMandatoryMessageChange}
|
||||
style="margin-top: var(--uui-size-space-1)"
|
||||
id="mandatory-message"
|
||||
@@ -312,6 +331,24 @@ export class UmbPropertySettingsModalElement extends UmbModalBaseElement<
|
||||
: nothing} `;
|
||||
}
|
||||
|
||||
#renderVariationControls() {
|
||||
return this._ownerDocumentType?.variesByCulture || this._ownerDocumentType?.variesBySegment ?
|
||||
html`
|
||||
<div class="container">
|
||||
<b>Variation</b>
|
||||
${this._ownerDocumentType?.variesByCulture ? this.#renderVaryByCulture() : ''}
|
||||
</div>
|
||||
<hr />`
|
||||
: '';
|
||||
}
|
||||
#renderVaryByCulture() {
|
||||
return html`<uui-toggle
|
||||
@change=${this.#onVaryByCultureChange}
|
||||
.checked=${this._returnData.variesByCulture ?? false}
|
||||
label="Vary by culture"></uui-toggle>
|
||||
`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { PropertyTypeModelBaseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
export type UmbPropertySettingsModalData = PropertyTypeModelBaseModel;
|
||||
export type UmbPropertySettingsModalData = {
|
||||
documentTypeId: string;
|
||||
propertyData: PropertyTypeModelBaseModel
|
||||
};
|
||||
export type UmbPropertySettingsModalResult = PropertyTypeModelBaseModel;
|
||||
|
||||
export const UMB_PROPERTY_SETTINGS_MODAL = new UmbModalToken<
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import {
|
||||
UUIButtonState,
|
||||
UUIPaginationElement,
|
||||
UUIPaginationEvent,
|
||||
} from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UUIButtonState, UUIPaginationElement, UUIPaginationEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { css, html, nothing, customElement, state, query, property } from '@umbraco-cms/backoffice/external/lit';
|
||||
import {
|
||||
UmbModalManagerContext,
|
||||
@@ -23,26 +19,26 @@ export class UmbDashboardRedirectManagementElement extends UmbLitElement {
|
||||
@property({ type: Number, attribute: 'items-per-page' })
|
||||
itemsPerPage = 20;
|
||||
|
||||
@property({ type: Number })
|
||||
page = 1;
|
||||
|
||||
@state()
|
||||
private _trackerEnabled = true;
|
||||
|
||||
@state()
|
||||
private _total = 0;
|
||||
|
||||
@state()
|
||||
private _redirectData?: RedirectUrlResponseModel[];
|
||||
|
||||
@state()
|
||||
private _trackerStatus = true;
|
||||
|
||||
@state()
|
||||
private _currentPage = 1;
|
||||
|
||||
@state()
|
||||
private _total?: number;
|
||||
|
||||
@state()
|
||||
private _buttonState: UUIButtonState;
|
||||
|
||||
@state()
|
||||
private _filter?: string;
|
||||
|
||||
@query('#search-input')
|
||||
private _searchField!: HTMLInputElement;
|
||||
@query('#search')
|
||||
private _search!: HTMLInputElement;
|
||||
|
||||
@query('uui-pagination')
|
||||
private _pagination?: UUIPaginationElement;
|
||||
@@ -58,214 +54,214 @@ export class UmbDashboardRedirectManagementElement extends UmbLitElement {
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this._getTrackerStatus();
|
||||
this._getRedirectData();
|
||||
this.#getTrackerStatus();
|
||||
this.#getRedirectData();
|
||||
}
|
||||
|
||||
private async _getTrackerStatus() {
|
||||
async #getTrackerStatus() {
|
||||
const { data } = await tryExecuteAndNotify(this, RedirectManagementResource.getRedirectManagementStatus());
|
||||
if (data && data.status) this._trackerStatus = data.status === RedirectStatusModel.ENABLED ? true : false;
|
||||
if (data && data.status) this._trackerEnabled = data.status === RedirectStatusModel.ENABLED ? true : false;
|
||||
}
|
||||
|
||||
private _removeRedirectHandler(data: RedirectUrlResponseModel) {
|
||||
// Fetch data
|
||||
async #getRedirectData(filter: string | undefined = undefined) {
|
||||
const skip = this.page * this.itemsPerPage - this.itemsPerPage;
|
||||
const { data } = await tryExecuteAndNotify(
|
||||
this,
|
||||
RedirectManagementResource.getRedirectManagement({ filter, take: this.itemsPerPage, skip }),
|
||||
);
|
||||
if (!data) return;
|
||||
|
||||
this._total = data?.total;
|
||||
this._redirectData = data?.items;
|
||||
|
||||
if (filter !== undefined) this._buttonState = 'success';
|
||||
}
|
||||
|
||||
// Pagination
|
||||
#onPageChange(event: UUIPaginationEvent) {
|
||||
if (this.page === event.target.current) return;
|
||||
this.page = event.target.current;
|
||||
this.#getRedirectData();
|
||||
}
|
||||
|
||||
// Delete Redirect Action
|
||||
#onRequestDelete(data: RedirectUrlResponseModel) {
|
||||
if (!data.id) return;
|
||||
const modalContext = this._modalContext?.open(UMB_CONFIRM_MODAL, {
|
||||
headline: 'Delete',
|
||||
content: html`
|
||||
<div style="width:300px">
|
||||
<p>This will remove the redirect</p>
|
||||
Original URL: <strong>${data.originalUrl}</strong><br />
|
||||
Redirected To: <strong>${data.destinationUrl}</strong>
|
||||
<p>Are you sure you want to delete?</p>
|
||||
<p>${this.localize.term('redirectUrls_redirectRemoveWarning')}</p>
|
||||
${this.localize.term('redirectUrls_originalUrl')}: <strong>${data.originalUrl}</strong><br />
|
||||
${this.localize.term('redirectUrls_redirectedTo')}: <strong>${data.destinationUrl}</strong>
|
||||
</div>
|
||||
`,
|
||||
color: 'danger',
|
||||
confirmLabel: 'Delete',
|
||||
});
|
||||
modalContext?.onSubmit().then(() => {
|
||||
this._removeRedirect(data);
|
||||
});
|
||||
|
||||
modalContext
|
||||
?.onSubmit()
|
||||
.then(() => {
|
||||
this.#redirectDelete(data.id!);
|
||||
})
|
||||
.catch(() => undefined);
|
||||
}
|
||||
async #redirectDelete(id: string) {
|
||||
const { error } = await tryExecuteAndNotify(this, RedirectManagementResource.deleteRedirectManagementById({ id }));
|
||||
if (error) return;
|
||||
|
||||
this._redirectData = this._redirectData?.filter((x) => x.id !== id);
|
||||
}
|
||||
|
||||
private async _removeRedirect(r: RedirectUrlResponseModel) {
|
||||
if (!r.id) return;
|
||||
const res = await tryExecuteAndNotify(this, RedirectManagementResource.deleteRedirectManagementById({ id: r.id }));
|
||||
if (!res.error) {
|
||||
// or just run a this._getRedirectData() again?
|
||||
//this.shadowRoot?.getElementById(`redirect-key-${r.id}`)?.remove();
|
||||
// No no, never manipulate DOM manipulate the data for the DOM:
|
||||
this._redirectData = this._redirectData?.filter((x) => x.id !== r.id);
|
||||
// Search action
|
||||
#onKeypress(e: KeyboardEvent) {
|
||||
if (e.key === 'Enter') this.#onSearch();
|
||||
}
|
||||
#onSearch() {
|
||||
this._buttonState = 'waiting';
|
||||
this._filter = this._search?.value ?? '';
|
||||
if (this._pagination) this._pagination.current = 1;
|
||||
this.page = 1;
|
||||
|
||||
this.#getRedirectData(this._search.value);
|
||||
}
|
||||
|
||||
// Tracker disable/enable
|
||||
#onRequestTrackerToggle() {
|
||||
if (!this._trackerEnabled) {
|
||||
this.#trackerToggle();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private _disableRedirectHandler() {
|
||||
const modalContext = this._modalContext?.open(UMB_CONFIRM_MODAL, {
|
||||
headline: 'Disable URL tracker',
|
||||
content: html`Are you sure you want to disable the URL tracker?`,
|
||||
headline: `${this.localize.term('redirectUrls_disableUrlTracker')}`,
|
||||
content: `${this.localize.term('redirectUrls_confirmDisable')}`,
|
||||
color: 'danger',
|
||||
confirmLabel: 'Disable',
|
||||
});
|
||||
modalContext?.onSubmit().then(() => {
|
||||
this._toggleRedirect();
|
||||
});
|
||||
modalContext
|
||||
?.onSubmit()
|
||||
.then(() => {
|
||||
this.#trackerToggle();
|
||||
})
|
||||
.catch(() => undefined);
|
||||
}
|
||||
|
||||
private async _toggleRedirect() {
|
||||
async #trackerToggle() {
|
||||
const status = this._trackerEnabled ? RedirectStatusModel.DISABLED : RedirectStatusModel.ENABLED;
|
||||
const { error } = await tryExecuteAndNotify(
|
||||
this,
|
||||
RedirectManagementResource.postRedirectManagementStatus({ status: RedirectStatusModel.ENABLED })
|
||||
RedirectManagementResource.postRedirectManagementStatus({ status }),
|
||||
);
|
||||
|
||||
if (!error) {
|
||||
this._trackerStatus = !this._trackerStatus;
|
||||
}
|
||||
}
|
||||
|
||||
private _inputHandler(pressed: KeyboardEvent) {
|
||||
if (pressed.key === 'Enter') this._searchHandler();
|
||||
}
|
||||
|
||||
private async _searchHandler() {
|
||||
this._filter = this._searchField.value;
|
||||
if (this._pagination) this._pagination.current = 1;
|
||||
this._currentPage = 1;
|
||||
if (this._filter.length) {
|
||||
this._buttonState = 'waiting';
|
||||
}
|
||||
this._getRedirectData();
|
||||
}
|
||||
|
||||
private _onPageChange(event: UUIPaginationEvent) {
|
||||
if (this._currentPage === event.target.current) return;
|
||||
this._currentPage = event.target.current;
|
||||
this._getRedirectData();
|
||||
}
|
||||
|
||||
private async _getRedirectData() {
|
||||
const skip = this._currentPage * this.itemsPerPage - this.itemsPerPage;
|
||||
const { data } = await tryExecuteAndNotify(
|
||||
this,
|
||||
RedirectManagementResource.getRedirectManagement({ filter: this._filter, take: this.itemsPerPage, skip })
|
||||
);
|
||||
if (data) {
|
||||
this._total = data?.total;
|
||||
this._redirectData = data?.items;
|
||||
if (this._filter?.length) {
|
||||
this._buttonState = 'success';
|
||||
}
|
||||
}
|
||||
if (error) return;
|
||||
this._trackerEnabled = !this._trackerEnabled;
|
||||
}
|
||||
|
||||
// Renders
|
||||
render() {
|
||||
return html`
|
||||
<umb-body-layout header-transparent class="uui-text">
|
||||
<div slot="header" id="header">
|
||||
${this._trackerStatus
|
||||
? html`<div>
|
||||
<uui-input
|
||||
id="search-input"
|
||||
placeholder="Original URL"
|
||||
label="input for search"
|
||||
@keypress="${this._inputHandler}">
|
||||
</uui-input>
|
||||
<uui-button
|
||||
id="search-button"
|
||||
look="primary"
|
||||
color="positive"
|
||||
label="search"
|
||||
.state="${this._buttonState}"
|
||||
@click="${this._searchHandler}">
|
||||
Search<uui-icon name="umb:search"></uui-icon>
|
||||
</uui-button>
|
||||
</div>
|
||||
return html` <div id="redirect-actions">
|
||||
${this._trackerEnabled
|
||||
? html`<div id="search-wrapper">
|
||||
<uui-input
|
||||
id="search"
|
||||
placeholder="${this.localize.term('redirectUrls_originalUrl')}"
|
||||
label="${this.localize.term('redirectUrls_originalUrl')}"
|
||||
@keypress=${this.#onKeypress}></uui-input>
|
||||
<uui-button
|
||||
label="Disable URL tracker"
|
||||
look="outline"
|
||||
color="danger"
|
||||
@click="${this._disableRedirectHandler}">
|
||||
Disable URL tracker
|
||||
</uui-button> `
|
||||
: html`<uui-button
|
||||
label="Enable URL tracker"
|
||||
look="primary"
|
||||
look="primary"
|
||||
color="positive"
|
||||
label="${this.localize.term('general_search')}"
|
||||
@click=${this.#onSearch}
|
||||
.state=${this._buttonState}>
|
||||
${this.localize.term('general_search')}
|
||||
</uui-button>
|
||||
</div>
|
||||
<uui-button
|
||||
look="outline"
|
||||
color="danger"
|
||||
label="${this.localize.term('redirectUrls_disableUrlTracker')}"
|
||||
@click=${this.#onRequestTrackerToggle}>
|
||||
${this.localize.term('redirectUrls_disableUrlTracker')}
|
||||
</uui-button>`
|
||||
: html`<div></div>
|
||||
<uui-button
|
||||
look="outline"
|
||||
color="positive"
|
||||
@click="${this._toggleRedirect}">
|
||||
Enable URL tracker
|
||||
</uui-button>`}
|
||||
</div>
|
||||
|
||||
<div id="main">
|
||||
${this._total && this._total > 0
|
||||
? html`<div class="wrapper ${this._trackerStatus ? 'trackerEnabled' : 'trackerDisabled'}">
|
||||
${this.renderTable()}
|
||||
</div>`
|
||||
: this._filter?.length
|
||||
? this._renderZeroResults()
|
||||
: this.renderNoRedirects()}
|
||||
</div>
|
||||
</umb-body-layout>
|
||||
`;
|
||||
label="${this.localize.term('redirectUrls_enableUrlTracker')}"
|
||||
@click=${this.#onRequestTrackerToggle}>
|
||||
${this.localize.term('redirectUrls_enableUrlTracker')}
|
||||
</uui-button>`}
|
||||
</div>
|
||||
${this._redirectData?.length
|
||||
? html`<uui-box id="redirect-wrapper" style="--uui-box-default-padding:0">
|
||||
${this._trackerEnabled ? '' : html`<div id="grey-out"></div>`} ${this.#renderTable()}
|
||||
</uui-box>`
|
||||
: this._filter !== undefined
|
||||
? this.#renderZeroResults()
|
||||
: this.#renderNoRedirects()}
|
||||
${this.#renderPagination()}`;
|
||||
}
|
||||
|
||||
private _renderZeroResults() {
|
||||
#renderZeroResults() {
|
||||
return html`<uui-box>
|
||||
<strong>No redirects matching this search criteria</strong>
|
||||
<p>Double check your search for any error or spelling mistakes.</p>
|
||||
</uui-box>`;
|
||||
}
|
||||
|
||||
private renderNoRedirects() {
|
||||
#renderNoRedirects() {
|
||||
return html`<uui-box>
|
||||
<strong>No redirects have been made</strong>
|
||||
<p>When a published page gets renamed or moved, a redirect will automatically be made to the new page.</p>
|
||||
<strong>${this.localize.term('redirectUrls_noRedirects')}</strong>
|
||||
<p>${this.localize.term('redirectUrls_noRedirectsDescription')}</p>
|
||||
</uui-box>`;
|
||||
}
|
||||
|
||||
private renderTable() {
|
||||
// TODO: Instead of map, use repeat lit util:
|
||||
return html`<uui-box style="--uui-box-default-padding: 0;">
|
||||
<uui-table>
|
||||
<uui-table-head>
|
||||
<uui-table-head-cell style="width:10%;">Culture</uui-table-head-cell>
|
||||
<uui-table-head-cell>Original URL</uui-table-head-cell>
|
||||
<uui-table-head-cell style="width:10%;"></uui-table-head-cell>
|
||||
<uui-table-head-cell>Redirected To</uui-table-head-cell>
|
||||
<uui-table-head-cell style="width:10%;">Actions</uui-table-head-cell>
|
||||
</uui-table-head>
|
||||
${this._redirectData?.map((data) => {
|
||||
return html` <uui-table-row>
|
||||
<uui-table-cell> ${data.culture || '*'} </uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<a href="${data.originalUrl || '#'}" target="_blank"> ${data.originalUrl}</a>
|
||||
<uui-icon name="umb:out"></uui-icon>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<uui-icon name="umb:arrow-right"></uui-icon>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<a href="${data.destinationUrl || '#'}" target="_blank"> ${data.destinationUrl}</a>
|
||||
<uui-icon name="umb:out"></uui-icon>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<uui-action-bar style="justify-self: left;">
|
||||
<uui-button
|
||||
label="Delete"
|
||||
look="secondary"
|
||||
.disabled=${!this._trackerStatus}
|
||||
@click="${() => this._removeRedirectHandler(data)}">
|
||||
<uui-icon name="delete"></uui-icon>
|
||||
</uui-button>
|
||||
</uui-action-bar>
|
||||
</uui-table-cell>
|
||||
</uui-table-row>`;
|
||||
})}
|
||||
</uui-table>
|
||||
</uui-box>
|
||||
${this._renderPagination()}
|
||||
</uui-scroll-container
|
||||
>`;
|
||||
#renderTable() {
|
||||
return html`<uui-table>
|
||||
<uui-table-head>
|
||||
<uui-table-head-cell style="width:10%;">${this.localize.term('redirectUrls_culture')}</uui-table-head-cell>
|
||||
<uui-table-head-cell>${this.localize.term('redirectUrls_originalUrl')}</uui-table-head-cell>
|
||||
<uui-table-head-cell style="width:10%;"></uui-table-head-cell>
|
||||
<uui-table-head-cell>${this.localize.term('redirectUrls_redirectedTo')}</uui-table-head-cell>
|
||||
<uui-table-head-cell style="width:10%;">${this.localize.term('general_actions')}</uui-table-head-cell>
|
||||
</uui-table-head>
|
||||
${this.#renderTableData()}
|
||||
</uui-table>`;
|
||||
}
|
||||
|
||||
private _renderPagination() {
|
||||
#renderTableData() {
|
||||
return html`${this._redirectData?.map((data) => {
|
||||
return html` <uui-table-row>
|
||||
<uui-table-cell> ${data.culture || '*'} </uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<a href="${data.originalUrl || '#'}" target="_blank"> ${data.originalUrl}</a>
|
||||
<uui-icon name="umb:out"></uui-icon>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<uui-icon name="umb:arrow-right"></uui-icon>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<a href="${data.destinationUrl || '#'}" target="_blank"> ${data.destinationUrl}</a>
|
||||
<uui-icon name="umb:out"></uui-icon>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<uui-action-bar style="justify-self: left;">
|
||||
<uui-button
|
||||
label="Delete"
|
||||
look="secondary"
|
||||
.disabled=${!this._trackerEnabled}
|
||||
@click=${() => this.#onRequestDelete(data)}>
|
||||
<uui-icon name="delete"></uui-icon>
|
||||
</uui-button>
|
||||
</uui-action-bar>
|
||||
</uui-table-cell>
|
||||
</uui-table-row>`;
|
||||
})}`;
|
||||
}
|
||||
|
||||
#renderPagination() {
|
||||
if (!this._total) return nothing;
|
||||
|
||||
const totalPages = Math.ceil(this._total / this.itemsPerPage);
|
||||
@@ -273,7 +269,7 @@ export class UmbDashboardRedirectManagementElement extends UmbLitElement {
|
||||
if (totalPages <= 1) return nothing;
|
||||
|
||||
return html`<div class="pagination">
|
||||
<uui-pagination .total=${totalPages} @change="${this._onPageChange}"></uui-pagination>
|
||||
<uui-pagination .total=${totalPages} @change=${this.#onPageChange}></uui-pagination>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@@ -281,74 +277,43 @@ export class UmbDashboardRedirectManagementElement extends UmbLitElement {
|
||||
UmbTextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#header {
|
||||
display: flex;
|
||||
gap: var(--uui-size-space-1);
|
||||
flex-direction: column;
|
||||
gap: var(--uui-size-4);
|
||||
padding: var(--uui-size-layout-1);
|
||||
}
|
||||
|
||||
#redirect-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 0 var(--uui-size-layout-1);
|
||||
}
|
||||
|
||||
#header uui-icon {
|
||||
transform: translateX(50%);
|
||||
#search-wrapper {
|
||||
display: flex;
|
||||
gap: var(--uui-size-4);
|
||||
}
|
||||
|
||||
uui-table {
|
||||
table-layout: fixed;
|
||||
#redirect-wrapper {
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
#redirect-wrapper #grey-out {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-color: var(--uui-color-surface-alt);
|
||||
opacity: 0.7;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
uui-table-head-cell:nth-child(2*n) {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
uui-table-head-cell:last-child,
|
||||
uui-table-cell:last-child {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
uui-table uui-icon {
|
||||
vertical-align: sub;
|
||||
}
|
||||
uui-pagination {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: var(--uui-size-space-5);
|
||||
}
|
||||
|
||||
.trackerDisabled {
|
||||
position: relative;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.trackerDisabled::after {
|
||||
content: '';
|
||||
background-color: var(--uui-color-disabled);
|
||||
position: absolute;
|
||||
border-radius: 2px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--uui-color-interactive);
|
||||
}
|
||||
a:hover,
|
||||
a:focus {
|
||||
color: var(--uui-color-interactive-emphasis);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ const entityActions: Array<ManifestEntityAction> = [
|
||||
weight: 900,
|
||||
meta: {
|
||||
icon: 'umb:trash',
|
||||
label: 'Delete (TBD)',
|
||||
label: 'Delete',
|
||||
repositoryAlias: DOCUMENT_TYPE_REPOSITORY_ALIAS,
|
||||
api: UmbDeleteEntityAction,
|
||||
entityTypes: [entityType],
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import './components/index.js';
|
||||
|
||||
export * from './repository/index.js';
|
||||
|
||||
export const DOCUMENT_TYPE_ROOT_ENTITY_TYPE = 'document-type-root';
|
||||
export const DOCUMENT_TYPE_ENTITY_TYPE = 'document-type';
|
||||
export const DOCUMENT_TYPE_FOLDER_ENTITY_TYPE = 'document-type-folder';
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { DocumentTypeItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbItemStore, UmbStoreBase } from '@umbraco-cms/backoffice/store';
|
||||
import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api';
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @class UmbDocumentTypeItemStore
|
||||
* @extends {UmbStoreBase}
|
||||
* @description - Data Store for Document Type items
|
||||
*/
|
||||
|
||||
export class UmbDocumentTypeItemStore
|
||||
extends UmbStoreBase<DocumentTypeItemResponseModel>
|
||||
implements UmbItemStore<DocumentTypeItemResponseModel>
|
||||
{
|
||||
/**
|
||||
* Creates an instance of UmbDocumentTypeItemStore.
|
||||
* @param {UmbControllerHostElement} host
|
||||
* @memberof UmbDocumentTypeItemStore
|
||||
*/
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
super(
|
||||
host,
|
||||
UMB_DOCUMENT_TYPE_ITEM_STORE_CONTEXT_TOKEN.toString(),
|
||||
new UmbArrayState<DocumentTypeItemResponseModel>([], (x) => x.id),
|
||||
);
|
||||
}
|
||||
|
||||
items(ids: Array<string>) {
|
||||
return this._data.asObservablePart((items) => items.filter((item) => ids.includes(item.id ?? '')));
|
||||
}
|
||||
}
|
||||
|
||||
export const UMB_DOCUMENT_TYPE_ITEM_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbDocumentTypeItemStore>(
|
||||
'UmbDocumentTypeItemStore',
|
||||
);
|
||||
@@ -2,6 +2,8 @@ import { UmbDocumentTypeTreeServerDataSource } from './sources/document-type.tre
|
||||
import { UmbDocumentTypeServerDataSource } from './sources/document-type.server.data.js';
|
||||
import { UmbDocumentTypeTreeStore, UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN } from './document-type.tree.store.js';
|
||||
import { UmbDocumentTypeStore, UMB_DOCUMENT_TYPE_STORE_CONTEXT_TOKEN } from './document-type.store.js';
|
||||
import { UMB_DOCUMENT_TYPE_ITEM_STORE_CONTEXT_TOKEN, UmbDocumentTypeItemStore } from './document-type-item.store.js';
|
||||
import { UmbDocumentTypeItemServerDataSource } from './sources/document-type-item.server.data.js';
|
||||
import type { UmbTreeDataSource, UmbTreeRepository, UmbDetailRepository } from '@umbraco-cms/backoffice/repository';
|
||||
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
|
||||
@@ -31,6 +33,9 @@ export class UmbDocumentTypeRepository
|
||||
#detailDataSource: UmbDocumentTypeServerDataSource;
|
||||
#detailStore?: UmbDocumentTypeStore;
|
||||
|
||||
#itemSource: UmbDocumentTypeItemServerDataSource;
|
||||
#itemStore?: UmbDocumentTypeItemStore;
|
||||
|
||||
#notificationContext?: UmbNotificationContext;
|
||||
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
@@ -39,6 +44,7 @@ export class UmbDocumentTypeRepository
|
||||
// TODO: figure out how spin up get the correct data source
|
||||
this.#treeSource = new UmbDocumentTypeTreeServerDataSource(this.#host);
|
||||
this.#detailDataSource = new UmbDocumentTypeServerDataSource(this.#host);
|
||||
this.#itemSource = new UmbDocumentTypeItemServerDataSource(this.#host);
|
||||
|
||||
this.#init = Promise.all([
|
||||
new UmbContextConsumerController(this.#host, UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN, (instance) => {
|
||||
@@ -49,15 +55,17 @@ export class UmbDocumentTypeRepository
|
||||
this.#detailStore = instance;
|
||||
}),
|
||||
|
||||
new UmbContextConsumerController(this.#host, UMB_DOCUMENT_TYPE_ITEM_STORE_CONTEXT_TOKEN, (instance) => {
|
||||
this.#itemStore = instance;
|
||||
}),
|
||||
|
||||
new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => {
|
||||
this.#notificationContext = instance;
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
// TODO: Trash
|
||||
// TODO: Move
|
||||
|
||||
async requestTreeRoot() {
|
||||
await this.#init;
|
||||
|
||||
@@ -97,6 +105,19 @@ export class UmbDocumentTypeRepository
|
||||
return { data, error, asObservable: () => this.#treeStore!.childrenOf(parentId) };
|
||||
}
|
||||
|
||||
async requestItems(ids: Array<string>) {
|
||||
if (!ids) throw new Error('Document Type Ids are missing');
|
||||
await this.#init;
|
||||
|
||||
const { data, error } = await this.#itemSource.getItems(ids);
|
||||
|
||||
if (data) {
|
||||
this.#itemStore?.appendItems(data);
|
||||
}
|
||||
|
||||
return { data, error, asObservable: () => this.#itemStore!.items(ids) };
|
||||
}
|
||||
|
||||
async requestItemsLegacy(ids: Array<string>) {
|
||||
await this.#init;
|
||||
|
||||
@@ -168,35 +189,15 @@ export class UmbDocumentTypeRepository
|
||||
// Could potentially be general methods:
|
||||
|
||||
async create(documentType: ItemType) {
|
||||
if (!documentType || !documentType.id) throw new Error('Template is missing');
|
||||
if (!documentType || !documentType.id) throw new Error('Document Type is missing');
|
||||
await this.#init;
|
||||
|
||||
const { error, data } = await this.#detailDataSource.insert(documentType);
|
||||
const { error } = await this.#detailDataSource.insert(documentType);
|
||||
|
||||
if (!error && data) {
|
||||
// TODO: The parts here is a hack, when we can trust the IDs we send, then this should be removed/changed:
|
||||
|
||||
const splitResultUrl = data.split('/');
|
||||
const newId = splitResultUrl[splitResultUrl.length - 1];
|
||||
|
||||
// Temporary hack while we are not in control of IDs:
|
||||
|
||||
const newDocument = { ...(await this.requestById(newId)).data };
|
||||
|
||||
if (newDocument) {
|
||||
const notification = { data: { message: `Document Type created` } };
|
||||
this.#notificationContext?.peek('positive', notification);
|
||||
|
||||
await this.requestRootTreeItems();
|
||||
|
||||
// TODO: currently we cannot put this data into our store, cause we don't have the right ID, as the server currently changes it (and other ids of it, container-id and property-id)
|
||||
//this.#detailStore?.append(newDocument);
|
||||
|
||||
//const treeItem = createTreeItem(newDocument);
|
||||
//this.#treeStore?.appendItems([treeItem]);
|
||||
|
||||
return { data: newDocument };
|
||||
}
|
||||
if (!error) {
|
||||
this.#detailStore?.append(documentType);
|
||||
const treeItem = createTreeItem(documentType);
|
||||
this.#treeStore?.appendItems([treeItem]);
|
||||
}
|
||||
|
||||
return { error };
|
||||
@@ -226,7 +227,6 @@ export class UmbDocumentTypeRepository
|
||||
}
|
||||
|
||||
// General:
|
||||
|
||||
async delete(id: string) {
|
||||
if (!id) throw new Error('Document Type id is missing');
|
||||
await this.#init;
|
||||
@@ -240,9 +240,10 @@ export class UmbDocumentTypeRepository
|
||||
// TODO: we currently don't use the detail store for anything.
|
||||
// Consider to look up the data before fetching from the server.
|
||||
// Consider notify a workspace if a template is deleted from the store while someone is editing it.
|
||||
// TODO: would be nice to align the stores on methods/methodNames.
|
||||
this.#detailStore?.remove([id]);
|
||||
this.#treeStore?.removeItem(id);
|
||||
// TODO: would be nice to align the stores on methods/methodNames.
|
||||
this.#itemStore?.removeItem(id);
|
||||
}
|
||||
|
||||
return { error };
|
||||
|
||||
@@ -10,7 +10,7 @@ import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api
|
||||
* @extends {UmbStoreBase}
|
||||
* @description - Data Store for Document Types
|
||||
*/
|
||||
export class UmbDocumentTypeStore extends UmbStoreBase {
|
||||
export class UmbDocumentTypeStore extends UmbStoreBase<DocumentTypeResponseModel> {
|
||||
/**
|
||||
* Creates an instance of UmbDocumentTypeStore.
|
||||
* @param {UmbControllerHostElement} host
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './document-type.repository.js';
|
||||
export * from './document-type.store.js';
|
||||
export * from './document-type.tree.store.js';
|
||||
@@ -1,7 +1,13 @@
|
||||
import { UmbDocumentTypeItemStore } from './document-type-item.store.js';
|
||||
import { UmbDocumentTypeRepository } from './document-type.repository.js';
|
||||
import { UmbDocumentTypeStore } from './document-type.store.js';
|
||||
import { UmbDocumentTypeTreeStore } from './document-type.tree.store.js';
|
||||
import { ManifestRepository, ManifestStore, ManifestTreeStore } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import {
|
||||
ManifestItemStore,
|
||||
ManifestRepository,
|
||||
ManifestStore,
|
||||
ManifestTreeStore,
|
||||
} from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const DOCUMENT_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DocumentType';
|
||||
|
||||
@@ -14,6 +20,7 @@ const repository: ManifestRepository = {
|
||||
|
||||
export const DOCUMENT_TYPE_STORE_ALIAS = 'Umb.Store.DocumentType';
|
||||
export const DOCUMENT_TYPE_TREE_STORE_ALIAS = 'Umb.Store.DocumentTypeTree';
|
||||
export const DOCUMENT_TYPE_ITEM_STORE_ALIAS = 'Umb.Store.DocumentTypeItem';
|
||||
|
||||
const store: ManifestStore = {
|
||||
type: 'store',
|
||||
@@ -29,4 +36,11 @@ const treeStore: ManifestTreeStore = {
|
||||
class: UmbDocumentTypeTreeStore,
|
||||
};
|
||||
|
||||
export const manifests = [repository, store, treeStore];
|
||||
const itemStore: ManifestItemStore = {
|
||||
type: 'itemStore',
|
||||
alias: DOCUMENT_TYPE_ITEM_STORE_ALIAS,
|
||||
name: 'Document Type Item Store',
|
||||
class: UmbDocumentTypeItemStore,
|
||||
};
|
||||
|
||||
export const manifests = [repository, store, treeStore, itemStore];
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import type { UmbItemDataSource } from '@umbraco-cms/backoffice/repository';
|
||||
import { DocumentTypeItemResponseModel, DocumentTypeResource } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
|
||||
|
||||
/**
|
||||
* A data source for Document Type items that fetches data from the server
|
||||
* @export
|
||||
* @class UmbDocumentTypeItemServerDataSource
|
||||
* @implements {UmbItemDataSource}
|
||||
*/
|
||||
export class UmbDocumentTypeItemServerDataSource implements UmbItemDataSource<DocumentTypeItemResponseModel> {
|
||||
#host: UmbControllerHostElement;
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbDocumentTypeItemServerDataSource.
|
||||
* @param {UmbControllerHostElement} host
|
||||
* @memberof UmbDocumentTypeItemServerDataSource
|
||||
*/
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
this.#host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the items for the given ids from the server
|
||||
* @param {Array<string>} ids
|
||||
* @return {*}
|
||||
* @memberof UmbDocumentTypeItemServerDataSource
|
||||
*/
|
||||
async getItems(ids: Array<string>) {
|
||||
if (!ids) throw new Error('Ids are missing');
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
DocumentTypeResource.getDocumentTypeItem({
|
||||
id: ids,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ export class UmbDocumentTypeServerDataSource
|
||||
this.#host,
|
||||
DocumentTypeResource.getDocumentTypeById({
|
||||
id: id,
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -91,27 +91,12 @@ export class UmbDocumentTypeServerDataSource
|
||||
* @memberof UmbDocumentTypeServerDataSource
|
||||
*/
|
||||
async insert(documentType: CreateDocumentTypeRequestModel) {
|
||||
if (!documentType) throw new Error('Document is missing');
|
||||
//if (!document.id) throw new Error('ID is missing');
|
||||
|
||||
documentType = { ...documentType };
|
||||
|
||||
// TODO: Hack to remove some props that ruins the document-type post end-point.
|
||||
(documentType as any).id = undefined;
|
||||
|
||||
// TODO: Investigate if this matters (should go away anyway when we have the end-point accepts us defining the ids.)
|
||||
documentType.properties = documentType.properties?.map((prop) => {
|
||||
return {
|
||||
...prop,
|
||||
id: undefined,
|
||||
};
|
||||
});
|
||||
|
||||
if (!documentType) throw new Error('Document Type is missing');
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
DocumentTypeResource.postDocumentType({
|
||||
requestBody: documentType,
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -164,7 +149,7 @@ export class UmbDocumentTypeServerDataSource
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}).then((res) => res.json())
|
||||
}).then((res) => res.json()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,26 +43,26 @@ export class UmbDocumentTypeWorkspaceContext
|
||||
this.structure = new UmbContentTypePropertyStructureManager(this.host, this.repository);
|
||||
|
||||
// General for content types:
|
||||
this.data = this.structure.ownerDocumentType;
|
||||
this.name = this.structure.ownerDocumentTypeObservablePart((data) => data?.name);
|
||||
this.alias = this.structure.ownerDocumentTypeObservablePart((data) => data?.alias);
|
||||
this.description = this.structure.ownerDocumentTypeObservablePart((data) => data?.description);
|
||||
this.icon = this.structure.ownerDocumentTypeObservablePart((data) => data?.icon);
|
||||
this.allowedAsRoot = this.structure.ownerDocumentTypeObservablePart((data) => data?.allowedAsRoot);
|
||||
this.variesByCulture = this.structure.ownerDocumentTypeObservablePart((data) => data?.variesByCulture);
|
||||
this.variesBySegment = this.structure.ownerDocumentTypeObservablePart((data) => data?.variesBySegment);
|
||||
this.isElement = this.structure.ownerDocumentTypeObservablePart((data) => data?.isElement);
|
||||
this.allowedContentTypes = this.structure.ownerDocumentTypeObservablePart((data) => data?.allowedContentTypes);
|
||||
this.compositions = this.structure.ownerDocumentTypeObservablePart((data) => data?.compositions);
|
||||
this.data = this.structure.ownerContentType;
|
||||
this.name = this.structure.ownerContentTypeObservablePart((data) => data?.name);
|
||||
this.alias = this.structure.ownerContentTypeObservablePart((data) => data?.alias);
|
||||
this.description = this.structure.ownerContentTypeObservablePart((data) => data?.description);
|
||||
this.icon = this.structure.ownerContentTypeObservablePart((data) => data?.icon);
|
||||
this.allowedAsRoot = this.structure.ownerContentTypeObservablePart((data) => data?.allowedAsRoot);
|
||||
this.variesByCulture = this.structure.ownerContentTypeObservablePart((data) => data?.variesByCulture);
|
||||
this.variesBySegment = this.structure.ownerContentTypeObservablePart((data) => data?.variesBySegment);
|
||||
this.isElement = this.structure.ownerContentTypeObservablePart((data) => data?.isElement);
|
||||
this.allowedContentTypes = this.structure.ownerContentTypeObservablePart((data) => data?.allowedContentTypes);
|
||||
this.compositions = this.structure.ownerContentTypeObservablePart((data) => data?.compositions);
|
||||
|
||||
// Document type specific:
|
||||
this.allowedTemplateIds = this.structure.ownerDocumentTypeObservablePart((data) => data?.allowedTemplateIds);
|
||||
this.defaultTemplateId = this.structure.ownerDocumentTypeObservablePart((data) => data?.defaultTemplateId);
|
||||
this.cleanup = this.structure.ownerDocumentTypeObservablePart((data) => data?.defaultTemplateId);
|
||||
this.allowedTemplateIds = this.structure.ownerContentTypeObservablePart((data) => data?.allowedTemplateIds);
|
||||
this.defaultTemplateId = this.structure.ownerContentTypeObservablePart((data) => data?.defaultTemplateId);
|
||||
this.cleanup = this.structure.ownerContentTypeObservablePart((data) => data?.defaultTemplateId);
|
||||
}
|
||||
|
||||
getData() {
|
||||
return this.structure.getOwnerDocumentType() || {};
|
||||
return this.structure.getOwnerContentType() || {};
|
||||
}
|
||||
|
||||
getEntityId() {
|
||||
@@ -74,45 +74,45 @@ export class UmbDocumentTypeWorkspaceContext
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.structure.updateOwnerDocumentType({ name });
|
||||
this.structure.updateOwnerContentType({ name });
|
||||
}
|
||||
setAlias(alias: string) {
|
||||
this.structure.updateOwnerDocumentType({ alias });
|
||||
this.structure.updateOwnerContentType({ alias });
|
||||
}
|
||||
setDescription(description: string) {
|
||||
this.structure.updateOwnerDocumentType({ description });
|
||||
this.structure.updateOwnerContentType({ description });
|
||||
}
|
||||
|
||||
// TODO: manage setting icon color alias?
|
||||
setIcon(icon: string) {
|
||||
this.structure.updateOwnerDocumentType({ icon });
|
||||
this.structure.updateOwnerContentType({ icon });
|
||||
}
|
||||
|
||||
setAllowedAsRoot(allowedAsRoot: boolean) {
|
||||
this.structure.updateOwnerDocumentType({ allowedAsRoot });
|
||||
this.structure.updateOwnerContentType({ allowedAsRoot });
|
||||
}
|
||||
setVariesByCulture(variesByCulture: boolean) {
|
||||
this.structure.updateOwnerDocumentType({ variesByCulture });
|
||||
this.structure.updateOwnerContentType({ variesByCulture });
|
||||
}
|
||||
setVariesBySegment(variesBySegment: boolean) {
|
||||
this.structure.updateOwnerDocumentType({ variesBySegment });
|
||||
this.structure.updateOwnerContentType({ variesBySegment });
|
||||
}
|
||||
setIsElement(isElement: boolean) {
|
||||
this.structure.updateOwnerDocumentType({ isElement });
|
||||
this.structure.updateOwnerContentType({ isElement });
|
||||
}
|
||||
setAllowedContentTypes(allowedContentTypes: Array<ContentTypeSortModel>) {
|
||||
this.structure.updateOwnerDocumentType({ allowedContentTypes });
|
||||
this.structure.updateOwnerContentType({ allowedContentTypes });
|
||||
}
|
||||
setCompositions(compositions: Array<ContentTypeCompositionModel>) {
|
||||
this.structure.updateOwnerDocumentType({ compositions });
|
||||
this.structure.updateOwnerContentType({ compositions });
|
||||
}
|
||||
|
||||
// Document type specific:
|
||||
setAllowedTemplateIds(allowedTemplateIds: Array<string>) {
|
||||
this.structure.updateOwnerDocumentType({ allowedTemplateIds });
|
||||
this.structure.updateOwnerContentType({ allowedTemplateIds });
|
||||
}
|
||||
setDefaultTemplateId(defaultTemplateId: string) {
|
||||
this.structure.updateOwnerDocumentType({ defaultTemplateId });
|
||||
this.structure.updateOwnerContentType({ defaultTemplateId });
|
||||
}
|
||||
|
||||
async create(parentId: string | null) {
|
||||
@@ -156,9 +156,10 @@ export class UmbDocumentTypeWorkspaceContext
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<UmbSaveableWorkspaceContextInterface, UmbDocumentTypeWorkspaceContext>(
|
||||
export const UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbSaveableWorkspaceContextInterface,
|
||||
UmbDocumentTypeWorkspaceContext
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
(context): context is UmbDocumentTypeWorkspaceContext => context.getEntityType?.() === 'document-type'
|
||||
(context): context is UmbDocumentTypeWorkspaceContext => context.getEntityType?.() === 'document-type',
|
||||
);
|
||||
|
||||
|
||||
@@ -104,7 +104,14 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle
|
||||
new UmbModalRouteRegistrationController(this, UMB_PROPERTY_SETTINGS_MODAL)
|
||||
.addAdditionalPath('new-property')
|
||||
.onSetup(async () => {
|
||||
return (await this._propertyStructureHelper.createPropertyScaffold(this._containerId)) ?? false;
|
||||
|
||||
const documentTypeId = this._ownerDocumentTypes?.find(
|
||||
(types) => types.containers?.find((containers) => containers.id === this.containerId),
|
||||
)?.id;
|
||||
if(documentTypeId === undefined) return false;
|
||||
const propertyData = await this._propertyStructureHelper.createPropertyScaffold(this._containerId);
|
||||
if(propertyData === undefined) return false;
|
||||
return {propertyData, documentTypeId};
|
||||
})
|
||||
.onSubmit((result) => {
|
||||
this.#addProperty(result);
|
||||
@@ -116,7 +123,7 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
const doctypes = this._propertyStructureHelper.getOwnerDocumentTypes();
|
||||
const doctypes = this._propertyStructureHelper.ownerDocumentTypes;
|
||||
if (!doctypes) return;
|
||||
this.observe(
|
||||
doctypes,
|
||||
|
||||
@@ -86,7 +86,11 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement {
|
||||
this.#modalRegistration = new UmbModalRouteRegistrationController(this, UMB_PROPERTY_SETTINGS_MODAL)
|
||||
.addUniquePaths(['propertyId'])
|
||||
.onSetup(() => {
|
||||
return this.property ?? false;
|
||||
const documentTypeId = this.ownerDocumentTypeId;
|
||||
if(documentTypeId === undefined) return false;
|
||||
const propertyData = this.property;
|
||||
if(propertyData === undefined) return false;
|
||||
return {propertyData, documentTypeId};
|
||||
})
|
||||
.onSubmit((result) => {
|
||||
this._partialUpdate(result);
|
||||
|
||||
@@ -128,9 +128,13 @@ export class UmbDocumentTypeWorkspaceViewEditElement
|
||||
#requestRemoveTab(tab: PropertyTypeContainerModelBaseModel | undefined) {
|
||||
const Message: UmbConfirmModalData = {
|
||||
headline: 'Delete tab',
|
||||
content: html`<umb-localize key="contentTypeEditor_confirmDeleteTabMessage" .args=${[tab?.name ?? tab?.id]}>Are you sure you want to delete the tab <strong>${tab?.name ?? tab?.id}</strong></umb-localize>
|
||||
content: html`<umb-localize key="contentTypeEditor_confirmDeleteTabMessage" .args=${[tab?.name ?? tab?.id]}
|
||||
>Are you sure you want to delete the tab <strong>${tab?.name ?? tab?.id}</strong></umb-localize
|
||||
>
|
||||
<div style="color:var(--uui-color-danger-emphasis)">
|
||||
<umb-localize key="contentTypeEditor_confirmDeleteTabNotice">This will delete all items that doesn't belong to a composition.</umb-localize>
|
||||
<umb-localize key="contentTypeEditor_confirmDeleteTabNotice"
|
||||
>This will delete all items that doesn't belong to a composition.</umb-localize
|
||||
>
|
||||
</div>`,
|
||||
confirmLabel: this.localize.term('actions_delete'),
|
||||
color: 'danger',
|
||||
@@ -183,7 +187,7 @@ export class UmbDocumentTypeWorkspaceViewEditElement
|
||||
(event.target as HTMLInputElement).value = 'Unnamed';
|
||||
}
|
||||
|
||||
const changedName = this._workspaceContext?.structure.makeContainerNameUniqueForOwnerDocument(
|
||||
const changedName = this._workspaceContext?.structure.makeContainerNameUniqueForOwnerContentType(
|
||||
newName,
|
||||
'Tab',
|
||||
tab.id,
|
||||
@@ -280,7 +284,7 @@ export class UmbDocumentTypeWorkspaceViewEditElement
|
||||
</uui-button>
|
||||
<uui-button label=${this.localize.term('general_reorder')} compact>
|
||||
<uui-icon name="umb:navigation"></uui-icon>
|
||||
<umb-localize key="general_reorder">Reorder</umb-localize>
|
||||
<umb-localize key="general_reorder">Reorder</umb-localize>
|
||||
</uui-button>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './manifests.js';
|
||||
@@ -0,0 +1,20 @@
|
||||
export const manifests = [
|
||||
{
|
||||
type: 'dashboard',
|
||||
alias: 'Umb.Dashboard.HealthCheck',
|
||||
name: 'Health Check',
|
||||
elementName: 'umb-dashboard-health-check',
|
||||
loader: () => import('./dashboard-health-check.element.js'),
|
||||
weight: 102,
|
||||
meta: {
|
||||
label: 'Health Check',
|
||||
pathname: 'health-check',
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
alias: 'Umb.Condition.SectionAlias',
|
||||
match: 'Umb.Section.Settings',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,9 @@
|
||||
export const name = 'Umbraco.Core.HealthCheck';
|
||||
export const extensions = [
|
||||
{
|
||||
name: 'Health Check Bundle',
|
||||
alias: 'Umb.Bundle.HealthCheck',
|
||||
type: 'bundle',
|
||||
loader: () => import('./manifests.js'),
|
||||
},
|
||||
];
|
||||
@@ -1 +0,0 @@
|
||||
import './input-culture-select/input-culture-select.element.js';
|
||||
@@ -57,24 +57,6 @@ const dashboards: Array<ManifestDashboard> = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'dashboard',
|
||||
alias: 'Umb.Dashboard.HealthCheck',
|
||||
name: 'Health Check',
|
||||
elementName: 'umb-dashboard-health-check',
|
||||
loader: () => import('./health-check/dashboard-health-check.element.js'),
|
||||
weight: 102,
|
||||
meta: {
|
||||
label: 'Health Check',
|
||||
pathname: 'health-check',
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
alias: 'Umb.Condition.SectionAlias',
|
||||
match: sectionAlias,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'dashboard',
|
||||
alias: 'Umb.Dashboard.Profiling',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UmbInputCultureSelectElement } from '@umbraco-cms/backoffice/culture';
|
||||
import { UMB_LANGUAGE_WORKSPACE_CONTEXT } from '../../language-workspace.context.js';
|
||||
import type { UmbInputCultureSelectElement } from '../../../../../cultures/components/input-culture-select/input-culture-select.element.js';
|
||||
import type { UmbInputLanguagePickerElement } from '../../../../components/input-language-picker/input-language-picker.element.js';
|
||||
import { UUIBooleanInputEvent, UUIToggleElement } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { css, html, nothing, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
|
||||
@@ -129,7 +129,7 @@ export class UmbLanguageDetailsWorkspaceViewElement
|
||||
|
||||
<!-- TEMP VALIDATION ERROR -->
|
||||
${this._validationErrors?.isoCode.map(
|
||||
(isoCodeError) => html`<div class="validation-message">${isoCodeError}</div>`
|
||||
(isoCodeError) => html`<div class="validation-message">${isoCodeError}</div>`,
|
||||
)}
|
||||
</div>
|
||||
</umb-workspace-property-layout>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { manifests as cultureManifests } from './cultures/manifests.js';
|
||||
import { manifests as dashboardManifests } from './dashboards/manifests.js';
|
||||
import { manifests as dataTypeManifests } from './data-types/manifests.js';
|
||||
import { manifests as extensionManifests } from './extensions/manifests.js';
|
||||
@@ -8,7 +7,6 @@ import { manifests as settingsMenuManifests } from './menu.manifests.js';
|
||||
import { manifests as settingsSectionManifests } from './section.manifests.js';
|
||||
|
||||
export const manifests = [
|
||||
...cultureManifests,
|
||||
...dashboardManifests,
|
||||
...dataTypeManifests,
|
||||
...extensionManifests,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { manifests as menuManifests } from './menu.manifests.js';
|
||||
import { manifests as templateManifests } from './templates/manifests.js';
|
||||
import { manifests as stylesheetManifests } from './stylesheets/manifests.js';
|
||||
import { manifests as partialManifests } from './partial-views/manifests.js';
|
||||
import { manifests as scriptsManifest } from './scripts/manifests.js';
|
||||
import { manifests as modalManifests } from './modals/manifests.js';
|
||||
|
||||
export const manifests = [
|
||||
@@ -10,4 +11,5 @@ export const manifests = [
|
||||
...stylesheetManifests,
|
||||
...partialManifests,
|
||||
...modalManifests,
|
||||
...scriptsManifest,
|
||||
];
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { ScriptResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
|
||||
export type ScriptDetails = ScriptResponseModel;
|
||||
|
||||
//ENTITY TYPES
|
||||
export const SCRIPTS_ENTITY_TYPE = 'script';
|
||||
export const SCRIPTS_ROOT_ENTITY_TYPE = 'script-root';
|
||||
export const SCRIPTS_FOLDER_ENTITY_TYPE = 'script-folder';
|
||||
export const SCRIPTS_FOLDER_EMPTY_ENTITY_TYPE = 'script-folder-empty';
|
||||
|
||||
|
||||
export const SCRIPTS_STORE_ALIAS = 'Umb.Store.Scripts';
|
||||
export const UMB_SCRIPTS_STORE_CONTEXT_TOKEN_ALIAS = 'Umb.Store.Scripts.Context.Token';
|
||||
|
||||
export const SCRIPTS_REPOSITORY_ALIAS = 'Umb.Repository.Scripts';
|
||||
|
||||
export const SCRIPTS_MENU_ITEM_ALIAS = 'Umb.MenuItem.Scripts';
|
||||
|
||||
//TREE
|
||||
export const SCRIPTS_TREE_ALIAS = 'Umb.Tree.Scripts';
|
||||
export const SCRIPTS_TREE_ITEM_ALIAS = 'Umb.TreeItem.Scripts';
|
||||
export const SCRIPTS_TREE_STORE_ALIAS = 'Umb.Store.Scripts.Tree';
|
||||
export const UMB_SCRIPTS_TREE_STORE_CONTEXT_TOKEN_ALIAS = 'Umb.Store.Scripts.Tree.Context.Token';
|
||||
|
||||
//ENTITY (tree) ACTIONS
|
||||
export const SCRIPTS_ENTITY_ACTION_DELETE_ALIAS = 'Umb.EntityAction.Scripts.Delete';
|
||||
export const SCRIPTS_ENTITY_ACTION_CREATE_NEW_ALIAS = 'Umb.EntityAction.ScriptsFolder.Create.New';
|
||||
export const SCRIPTS_ENTITY_ACTION_DELETE_FOLDER_ALIAS = 'Umb.EntityAction.ScriptsFolder.DeleteFolder';
|
||||
export const SCRIPTS_ENTITY_ACTION_CREATE_FOLDER_NEW_ALIAS = 'Umb.EntityAction.ScriptsFolder.CreateFolder';
|
||||
|
||||
//WORKSPACE
|
||||
export const SCRIPTS_WORKSPACE_ALIAS = 'Umb.Workspace.Scripts';
|
||||
export const SCRIPTS_WORKSPACE_ACTION_SAVE_ALIAS = 'Umb.WorkspaceAction.Scripts.Save';
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbCreateScriptAction<T extends { copy(): Promise<void> }> extends UmbEntityActionBase<T> {
|
||||
constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) {
|
||||
super(host, repositoryAlias, unique);
|
||||
}
|
||||
|
||||
async execute() {
|
||||
history.pushState(null, '', `section/settings/workspace/script/create/${this.unique ?? 'null'}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import {
|
||||
SCRIPTS_REPOSITORY_ALIAS,
|
||||
SCRIPTS_ENTITY_TYPE,
|
||||
SCRIPTS_FOLDER_ENTITY_TYPE,
|
||||
SCRIPTS_ROOT_ENTITY_TYPE,
|
||||
SCRIPTS_FOLDER_EMPTY_ENTITY_TYPE,
|
||||
SCRIPTS_ENTITY_ACTION_DELETE_ALIAS,
|
||||
SCRIPTS_ENTITY_ACTION_CREATE_NEW_ALIAS,
|
||||
SCRIPTS_ENTITY_ACTION_DELETE_FOLDER_ALIAS,
|
||||
SCRIPTS_ENTITY_ACTION_CREATE_FOLDER_NEW_ALIAS,
|
||||
} from '../config.js';
|
||||
import { UmbCreateScriptAction } from './create/create-empty.action.js';
|
||||
import {
|
||||
UmbCreateFolderEntityAction,
|
||||
UmbDeleteEntityAction,
|
||||
UmbDeleteFolderEntityAction,
|
||||
} from '@umbraco-cms/backoffice/entity-action';
|
||||
import { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
const scriptsViewActions: Array<ManifestEntityAction> = [
|
||||
{
|
||||
type: 'entityAction',
|
||||
alias: SCRIPTS_ENTITY_ACTION_DELETE_ALIAS,
|
||||
name: 'Delete Scripts Entity Action',
|
||||
meta: {
|
||||
icon: 'umb:trash',
|
||||
label: 'Delete',
|
||||
api: UmbDeleteEntityAction,
|
||||
repositoryAlias: SCRIPTS_REPOSITORY_ALIAS,
|
||||
entityTypes: [SCRIPTS_ENTITY_TYPE],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const scriptsFolderActions: Array<ManifestEntityAction> = [
|
||||
{
|
||||
type: 'entityAction',
|
||||
alias: SCRIPTS_ENTITY_ACTION_CREATE_NEW_ALIAS,
|
||||
name: 'Create Scripts Entity Under Directory Action',
|
||||
meta: {
|
||||
icon: 'umb:article',
|
||||
label: 'New empty script',
|
||||
api: UmbCreateScriptAction,
|
||||
repositoryAlias: SCRIPTS_REPOSITORY_ALIAS,
|
||||
entityTypes: [SCRIPTS_FOLDER_ENTITY_TYPE, SCRIPTS_FOLDER_EMPTY_ENTITY_TYPE, SCRIPTS_ROOT_ENTITY_TYPE],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'entityAction',
|
||||
alias: SCRIPTS_ENTITY_ACTION_DELETE_FOLDER_ALIAS,
|
||||
name: 'Remove empty folder',
|
||||
meta: {
|
||||
icon: 'umb:trash',
|
||||
label: 'Remove folder',
|
||||
api: UmbDeleteFolderEntityAction,
|
||||
repositoryAlias: SCRIPTS_REPOSITORY_ALIAS,
|
||||
entityTypes: [SCRIPTS_FOLDER_EMPTY_ENTITY_TYPE],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'entityAction',
|
||||
alias: SCRIPTS_ENTITY_ACTION_CREATE_FOLDER_NEW_ALIAS,
|
||||
name: 'Create empty folder',
|
||||
meta: {
|
||||
icon: 'umb:add',
|
||||
label: 'Create folder',
|
||||
api: UmbCreateFolderEntityAction,
|
||||
repositoryAlias: SCRIPTS_REPOSITORY_ALIAS,
|
||||
entityTypes: [SCRIPTS_FOLDER_EMPTY_ENTITY_TYPE, SCRIPTS_FOLDER_ENTITY_TYPE, SCRIPTS_ROOT_ENTITY_TYPE],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const manifests = [...scriptsViewActions, ...scriptsFolderActions];
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './repository/index.js';
|
||||
export * from './config.js';
|
||||
@@ -0,0 +1,13 @@
|
||||
import { manifests as repositoryManifests } from './repository/manifests.js';
|
||||
import { manifests as menuItemManifests } from './menu-item/manifests.js';
|
||||
import { manifests as treeManifests } from './tree/manifests.js';
|
||||
import { manifests as entityActionsManifests } from './entity-actions/manifests.js';
|
||||
import { manifests as workspaceManifests } from './workspace/manifests.js';
|
||||
|
||||
export const manifests = [
|
||||
...repositoryManifests,
|
||||
...menuItemManifests,
|
||||
...treeManifests,
|
||||
...entityActionsManifests,
|
||||
...workspaceManifests,
|
||||
];
|
||||
@@ -0,0 +1,19 @@
|
||||
import { SCRIPTS_ENTITY_TYPE, SCRIPTS_MENU_ITEM_ALIAS, SCRIPTS_TREE_ALIAS } from '../config.js';
|
||||
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
const menuItem: ManifestTypes = {
|
||||
type: 'menuItem',
|
||||
kind: 'tree',
|
||||
alias: SCRIPTS_MENU_ITEM_ALIAS,
|
||||
name: 'Scripts Menu Item',
|
||||
weight: 10,
|
||||
meta: {
|
||||
label: 'Scripts',
|
||||
icon: 'umb:folder',
|
||||
entityType: SCRIPTS_ENTITY_TYPE,
|
||||
treeAlias: SCRIPTS_TREE_ALIAS,
|
||||
menus: ['Umb.Menu.Templating'],
|
||||
},
|
||||
};
|
||||
|
||||
export const manifests = [menuItem];
|
||||
@@ -0,0 +1 @@
|
||||
export * from './scripts.repository.js';
|
||||
@@ -0,0 +1,28 @@
|
||||
import { SCRIPTS_REPOSITORY_ALIAS, SCRIPTS_STORE_ALIAS, SCRIPTS_TREE_STORE_ALIAS } from '../config.js';
|
||||
import { UmbScriptsRepository } from './scripts.repository.js';
|
||||
import { UmbScriptsStore } from './scripts.store.js';
|
||||
import { UmbScriptsTreeStore } from './scripts.tree.store.js';
|
||||
import { ManifestRepository, ManifestStore, ManifestTreeStore } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
const repository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: SCRIPTS_REPOSITORY_ALIAS,
|
||||
name: 'Scripts Repository',
|
||||
class: UmbScriptsRepository,
|
||||
};
|
||||
|
||||
const store: ManifestStore = {
|
||||
type: 'store',
|
||||
alias: SCRIPTS_STORE_ALIAS,
|
||||
name: 'Scripts Store',
|
||||
class: UmbScriptsStore,
|
||||
};
|
||||
|
||||
const treeStore: ManifestTreeStore = {
|
||||
type: 'treeStore',
|
||||
alias: SCRIPTS_TREE_STORE_ALIAS,
|
||||
name: 'Scripts Tree Store',
|
||||
class: UmbScriptsTreeStore,
|
||||
};
|
||||
|
||||
export const manifests = [repository, store, treeStore];
|
||||
@@ -0,0 +1,216 @@
|
||||
import { SCRIPTS_ROOT_ENTITY_TYPE } from '../config.js';
|
||||
import { UmbScriptsTreeServerDataSource } from './sources/scripts.tree.server.data.js';
|
||||
import { UmbScriptsServerDataSource } from './sources/scripts.detail.server.data.js';
|
||||
import { ScriptsGetFolderResponse, UmbScriptsFolderServerDataSource } from './sources/scripts.folder.server.data.js';
|
||||
import { UMB_SCRIPTS_TREE_STORE_CONTEXT_TOKEN, UmbScriptsTreeStore } from './scripts.tree.store.js';
|
||||
import {
|
||||
DataSourceResponse,
|
||||
UmbDataSourceErrorResponse,
|
||||
UmbDetailRepository,
|
||||
UmbFolderRepository,
|
||||
UmbTreeRepository,
|
||||
} from '@umbraco-cms/backoffice/repository';
|
||||
import {
|
||||
CreateFolderRequestModel,
|
||||
CreateScriptRequestModel,
|
||||
FileItemResponseModelBaseModel,
|
||||
FileSystemTreeItemPresentationModel,
|
||||
FolderModelBaseModel,
|
||||
FolderResponseModel,
|
||||
ProblemDetails,
|
||||
ScriptResponseModel,
|
||||
TextFileResponseModelBaseModel,
|
||||
UpdateScriptRequestModel,
|
||||
} from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
|
||||
export class UmbScriptsRepository
|
||||
implements
|
||||
UmbTreeRepository<FileSystemTreeItemPresentationModel>,
|
||||
UmbDetailRepository<CreateScriptRequestModel, string, UpdateScriptRequestModel, ScriptResponseModel, string>,
|
||||
UmbFolderRepository
|
||||
{
|
||||
#init;
|
||||
#host: UmbControllerHostElement;
|
||||
|
||||
#treeDataSource: UmbScriptsTreeServerDataSource;
|
||||
#detailDataSource: UmbScriptsServerDataSource;
|
||||
#folderDataSource: UmbScriptsFolderServerDataSource;
|
||||
|
||||
#treeStore?: UmbScriptsTreeStore;
|
||||
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
this.#host = host;
|
||||
|
||||
this.#treeDataSource = new UmbScriptsTreeServerDataSource(this.#host);
|
||||
this.#detailDataSource = new UmbScriptsServerDataSource(this.#host);
|
||||
this.#folderDataSource = new UmbScriptsFolderServerDataSource(this.#host);
|
||||
|
||||
this.#init = Promise.all([
|
||||
new UmbContextConsumerController(this.#host, UMB_SCRIPTS_TREE_STORE_CONTEXT_TOKEN, (instance) => {
|
||||
this.#treeStore = instance;
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
//#region FOLDER
|
||||
createFolderScaffold(
|
||||
parentId: string | null,
|
||||
): Promise<{ data?: FolderResponseModel | undefined; error?: ProblemDetails | undefined }> {
|
||||
const data: FolderResponseModel = {
|
||||
name: '',
|
||||
parentId,
|
||||
};
|
||||
return Promise.resolve({ data, error: undefined });
|
||||
}
|
||||
async createFolder(
|
||||
requestBody: CreateFolderRequestModel,
|
||||
): Promise<{ data?: string | undefined; error?: ProblemDetails | undefined }> {
|
||||
await this.#init;
|
||||
const req = {
|
||||
parentPath: requestBody.parentId,
|
||||
name: requestBody.name,
|
||||
};
|
||||
const promise = this.#folderDataSource.insert(req);
|
||||
await promise;
|
||||
this.requestTreeItemsOf(requestBody.parentId ? requestBody.parentId : null);
|
||||
return promise;
|
||||
}
|
||||
async requestFolder(
|
||||
unique: string,
|
||||
): Promise<{ data?: ScriptsGetFolderResponse | undefined; error?: ProblemDetails | undefined }> {
|
||||
await this.#init;
|
||||
return this.#folderDataSource.get(unique);
|
||||
}
|
||||
updateFolder(
|
||||
unique: string,
|
||||
folder: FolderModelBaseModel,
|
||||
): Promise<{ data?: FolderModelBaseModel | undefined; error?: ProblemDetails | undefined }> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
async deleteFolder(path: string): Promise<{ error?: ProblemDetails | undefined }> {
|
||||
await this.#init;
|
||||
const { data } = await this.requestFolder(path);
|
||||
const promise = this.#folderDataSource.delete(path);
|
||||
await promise;
|
||||
this.requestTreeItemsOf(data?.parentPath ? data?.parentPath : null);
|
||||
return promise;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region TREE
|
||||
|
||||
async requestTreeRoot() {
|
||||
await this.#init;
|
||||
|
||||
const data = {
|
||||
id: null,
|
||||
path: null,
|
||||
type: SCRIPTS_ROOT_ENTITY_TYPE,
|
||||
name: 'Scripts',
|
||||
icon: 'umb:folder',
|
||||
hasChildren: true,
|
||||
};
|
||||
return { data };
|
||||
}
|
||||
|
||||
async requestRootTreeItems() {
|
||||
await this.#init;
|
||||
|
||||
const { data, error } = await this.#treeDataSource.getRootItems();
|
||||
|
||||
if (data) {
|
||||
this.#treeStore?.appendItems(data.items);
|
||||
}
|
||||
|
||||
return { data, error, asObservable: () => this.#treeStore!.rootItems };
|
||||
}
|
||||
|
||||
async requestTreeItemsOf(path: string | null) {
|
||||
if (path === null || path === '/' || path === '') {
|
||||
return this.requestRootTreeItems();
|
||||
}
|
||||
|
||||
await this.#init;
|
||||
const response = await this.#treeDataSource.getChildrenOf({ path, skip: 0, take: 100 });
|
||||
const { data, error } = response;
|
||||
if (data) {
|
||||
this.#treeStore!.appendItems(data.items);
|
||||
}
|
||||
|
||||
return { data, error, asObservable: () => this.#treeStore!.childrenOf(path) };
|
||||
}
|
||||
|
||||
async requestTreeItems(keys: Array<string>) {
|
||||
await this.#init;
|
||||
|
||||
if (!keys) {
|
||||
const error: ProblemDetails = { title: 'Keys are missing' };
|
||||
return { data: undefined, error };
|
||||
}
|
||||
|
||||
const { data, error } = await this.#treeDataSource.getItem(keys);
|
||||
|
||||
return { data, error, asObservable: () => this.#treeStore!.items(keys) };
|
||||
}
|
||||
|
||||
async rootTreeItems() {
|
||||
await this.#init;
|
||||
return this.#treeStore!.rootItems;
|
||||
}
|
||||
|
||||
async treeItemsOf(parentPath: string | null) {
|
||||
if (!parentPath) throw new Error('Parent Path is missing');
|
||||
await this.#init;
|
||||
return this.#treeStore!.childrenOf(parentPath);
|
||||
}
|
||||
|
||||
async treeItems(paths: Array<string>) {
|
||||
if (!paths) throw new Error('Paths are missing');
|
||||
await this.#init;
|
||||
return this.#treeStore!.items(paths);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region DETAILS
|
||||
async requestByKey(path: string) {
|
||||
if (!path) throw new Error('Path is missing');
|
||||
await this.#init;
|
||||
const { data, error } = await this.#detailDataSource.get(path);
|
||||
return { data, error };
|
||||
}
|
||||
|
||||
requestById(id: string): Promise<DataSourceResponse<any>> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
byId(id: string): Promise<Observable<any>> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
createScaffold(parentId: string | null, preset: string): Promise<DataSourceResponse<TextFileResponseModelBaseModel>> {
|
||||
return this.#detailDataSource.createScaffold(parentId, preset);
|
||||
}
|
||||
async create(data: CreateScriptRequestModel): Promise<DataSourceResponse<any>> {
|
||||
const promise = this.#detailDataSource.insert(data);
|
||||
await promise;
|
||||
this.requestTreeItemsOf(data.parentPath ? data.parentPath : null);
|
||||
return promise;
|
||||
}
|
||||
save(id: string, requestBody: UpdateScriptRequestModel): Promise<UmbDataSourceErrorResponse> {
|
||||
return this.#detailDataSource.update(id, requestBody);
|
||||
}
|
||||
async delete(id: string): Promise<UmbDataSourceErrorResponse> {
|
||||
const promise = this.#detailDataSource.delete(id);
|
||||
const parentPath = id.substring(0, id.lastIndexOf('/'));
|
||||
this.requestTreeItemsOf(parentPath ? parentPath : null);
|
||||
return promise;
|
||||
}
|
||||
|
||||
requestItems(keys: Array<string>): Promise<DataSourceResponse<FileItemResponseModelBaseModel[]>> {
|
||||
return this.#detailDataSource.getItems(keys);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { UMB_SCRIPTS_STORE_CONTEXT_TOKEN_ALIAS } from '../config.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api';
|
||||
import { UmbStoreBase } from '@umbraco-cms/backoffice/store';
|
||||
import type { TemplateResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @class UmbScriptsStore
|
||||
* @extends {UmbStoreBase}
|
||||
* @description - Data Store for scripts
|
||||
*/
|
||||
export class UmbScriptsStore extends UmbStoreBase {
|
||||
/**
|
||||
* Creates an instance of UmbScriptsStore.
|
||||
* @param {UmbControllerHostInterface} host
|
||||
* @memberof UmbScriptsStore
|
||||
*/
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
super(host, UMB_SCRIPTS_STORE_CONTEXT_TOKEN.toString(), new UmbArrayState<TemplateResponseModel>([], (x) => x.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a script to the store
|
||||
* @param {Template} template
|
||||
* @memberof UmbScriptsStore
|
||||
*/
|
||||
append(template: TemplateResponseModel) {
|
||||
this._data.append([template]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes scripts in the store with the given uniques
|
||||
* @param {string[]} uniques
|
||||
* @memberof UmbScriptsStore
|
||||
*/
|
||||
remove(uniques: string[]) {
|
||||
this._data.remove(uniques);
|
||||
}
|
||||
}
|
||||
|
||||
export const UMB_SCRIPTS_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbScriptsStore>(
|
||||
UMB_SCRIPTS_STORE_CONTEXT_TOKEN_ALIAS,
|
||||
);
|
||||
@@ -0,0 +1,26 @@
|
||||
import { UMB_SCRIPTS_TREE_STORE_CONTEXT_TOKEN_ALIAS } from '../config.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbFileSystemTreeStore } from '@umbraco-cms/backoffice/store';
|
||||
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export const UMB_SCRIPTS_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbScriptsTreeStore>(
|
||||
UMB_SCRIPTS_TREE_STORE_CONTEXT_TOKEN_ALIAS,
|
||||
);
|
||||
|
||||
/**
|
||||
* Tree Store for scripts
|
||||
*
|
||||
* @export
|
||||
* @class
|
||||
* @extends {UmbEntityTreeStore}
|
||||
*/
|
||||
export class UmbScriptsTreeStore extends UmbFileSystemTreeStore {
|
||||
/**
|
||||
* Creates an instance of UmbScriptsTreeStore.
|
||||
* @param {UmbControllerHostInterface} host
|
||||
* @memberof UmbScriptsTreeStore
|
||||
*/
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
super(host, UMB_SCRIPTS_TREE_STORE_CONTEXT_TOKEN.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import {
|
||||
FileSystemTreeItemPresentationModel,
|
||||
PagedFileSystemTreeItemPresentationModel,
|
||||
} from '@umbraco-cms/backoffice/backend-api';
|
||||
import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
export interface ScriptsTreeDataSource {
|
||||
getRootItems(): Promise<DataSourceResponse<PagedFileSystemTreeItemPresentationModel>>;
|
||||
getChildrenOf({
|
||||
path,
|
||||
skip,
|
||||
take,
|
||||
}: {
|
||||
path?: string | undefined;
|
||||
skip?: number | undefined;
|
||||
take?: number | undefined;
|
||||
}): Promise<DataSourceResponse<PagedFileSystemTreeItemPresentationModel>>;
|
||||
getItem(ids: Array<string>): Promise<DataSourceResponse<FileSystemTreeItemPresentationModel[]>>;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import {
|
||||
CreateScriptRequestModel,
|
||||
CreateTextFileViewModelBaseModel,
|
||||
ScriptItemResponseModel,
|
||||
ScriptResource,
|
||||
ScriptResponseModel,
|
||||
UpdateScriptRequestModel,
|
||||
} from '@umbraco-cms/backoffice/backend-api';
|
||||
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { DataSourceResponse, UmbDataSource } from '@umbraco-cms/backoffice/repository';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
|
||||
|
||||
export class UmbScriptsServerDataSource
|
||||
implements UmbDataSource<CreateScriptRequestModel, string, UpdateScriptRequestModel, ScriptResponseModel, string>
|
||||
{
|
||||
#host: UmbControllerHostElement;
|
||||
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
this.#host = host;
|
||||
}
|
||||
createScaffold(
|
||||
parentId: string | null,
|
||||
preset?: string | Partial<CreateTextFileViewModelBaseModel> | undefined,
|
||||
): Promise<DataSourceResponse<CreateTextFileViewModelBaseModel>> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a script with the given path from the server
|
||||
* @param {string} path
|
||||
* @return {*}
|
||||
* @memberof UmbScriptsDetailServerDataSource
|
||||
*/
|
||||
get(path: string): Promise<DataSourceResponse<ScriptResponseModel>> {
|
||||
if (!path) throw new Error('Path is missing');
|
||||
return tryExecuteAndNotify(this.#host, ScriptResource.getScript({ path }));
|
||||
}
|
||||
/**
|
||||
* Creates a new script
|
||||
*
|
||||
* @param {CreateScriptRequestModel} requestBody
|
||||
* @return {*} {Promise<DataSourceResponse<string>>}
|
||||
* @memberof UmbScriptsDetailServerDataSource
|
||||
*/
|
||||
insert(requestBody: CreateScriptRequestModel): Promise<DataSourceResponse<string>> {
|
||||
return tryExecuteAndNotify(this.#host, ScriptResource.postScript({ requestBody }));
|
||||
}
|
||||
|
||||
//TODO the parameters here are bit ugly, since unique is already in the request body parameter, but it has to be done to marry the UmbDataSource interface an backend API together... maybe come up with some nicer solution
|
||||
/**
|
||||
* Updates a script
|
||||
*
|
||||
* @param {string} [unique='']
|
||||
* @param {UpdateScriptRequestModel} requestBody
|
||||
* @return {*} {Promise<DataSourceResponse<any>>}
|
||||
* @memberof UmbScriptsDetailServerDataSource
|
||||
*/
|
||||
update(unique = '', requestBody: UpdateScriptRequestModel): Promise<DataSourceResponse<any>> {
|
||||
return tryExecuteAndNotify(this.#host, ScriptResource.putScript({ requestBody }));
|
||||
}
|
||||
/**
|
||||
* Deletes a script
|
||||
*
|
||||
* @param {string} path
|
||||
* @return {*} {Promise<DataSourceResponse>}
|
||||
* @memberof UmbScriptsDetailServerDataSource
|
||||
*/
|
||||
delete(path: string): Promise<DataSourceResponse> {
|
||||
return tryExecuteAndNotify(this.#host, ScriptResource.deleteScript({ path }));
|
||||
}
|
||||
|
||||
getItems(keys: Array<string>): Promise<DataSourceResponse<ScriptItemResponseModel[]>> {
|
||||
return tryExecuteAndNotify(this.#host, ScriptResource.getScriptItem({ path: keys }));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import {
|
||||
CreateFolderRequestModel,
|
||||
FolderModelBaseModel,
|
||||
FolderResponseModel,
|
||||
ScriptResource,
|
||||
} from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { DataSourceResponse, UmbFolderDataSource } from '@umbraco-cms/backoffice/repository';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
|
||||
|
||||
//! this is of any type in the backend-api
|
||||
export type ScriptsGetFolderResponse = { path: string; parentPath: string; name: string };
|
||||
|
||||
export class UmbScriptsFolderServerDataSource implements UmbFolderDataSource {
|
||||
#host: UmbControllerHostElement;
|
||||
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
this.#host = host;
|
||||
}
|
||||
createScaffold(parentId: string | null): Promise<DataSourceResponse<FolderResponseModel>> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
get(unique: string): Promise<DataSourceResponse<ScriptsGetFolderResponse>> {
|
||||
return tryExecuteAndNotify(this.#host, ScriptResource.getScriptFolder({ path: unique }));
|
||||
}
|
||||
insert(requestBody: CreateFolderRequestModel): Promise<DataSourceResponse<string>> {
|
||||
return tryExecuteAndNotify(this.#host, ScriptResource.postScriptFolder({ requestBody }));
|
||||
}
|
||||
update(unique: string, data: CreateFolderRequestModel): Promise<DataSourceResponse<FolderModelBaseModel>> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
delete(path: string): Promise<DataSourceResponse<unknown>> {
|
||||
return tryExecuteAndNotify(this.#host, ScriptResource.deleteScriptFolder({ path }));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { ScriptsTreeDataSource } from './index.js';
|
||||
import { ScriptResource, ProblemDetails } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
|
||||
|
||||
export class UmbScriptsTreeServerDataSource implements ScriptsTreeDataSource {
|
||||
#host: UmbControllerHostElement;
|
||||
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
this.#host = host;
|
||||
}
|
||||
|
||||
async getRootItems() {
|
||||
return tryExecuteAndNotify(this.#host, ScriptResource.getTreeScriptRoot({}));
|
||||
}
|
||||
|
||||
async getChildrenOf({
|
||||
path,
|
||||
skip,
|
||||
take,
|
||||
}: {
|
||||
path?: string | undefined;
|
||||
skip?: number | undefined;
|
||||
take?: number | undefined;
|
||||
}) {
|
||||
if (!path) {
|
||||
const error: ProblemDetails = { title: 'Path is missing' };
|
||||
return error;
|
||||
}
|
||||
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
ScriptResource.getTreeScriptChildren({
|
||||
path,
|
||||
skip,
|
||||
take,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async getItem(path: Array<string>) {
|
||||
if (!path) {
|
||||
const error: ProblemDetails = { title: 'Paths are missing' };
|
||||
return error;
|
||||
}
|
||||
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
ScriptResource.getScriptItem({
|
||||
path,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import {
|
||||
SCRIPTS_ENTITY_TYPE,
|
||||
SCRIPTS_REPOSITORY_ALIAS,
|
||||
SCRIPTS_ROOT_ENTITY_TYPE,
|
||||
SCRIPTS_TREE_ALIAS,
|
||||
SCRIPTS_TREE_ITEM_ALIAS,
|
||||
} from '../config.js';
|
||||
import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
const tree: ManifestTree = {
|
||||
type: 'tree',
|
||||
alias: SCRIPTS_TREE_ALIAS,
|
||||
name: 'Scripts Tree',
|
||||
weight: 30,
|
||||
meta: {
|
||||
repositoryAlias: SCRIPTS_REPOSITORY_ALIAS,
|
||||
},
|
||||
};
|
||||
|
||||
const treeItem: ManifestTreeItem = {
|
||||
type: 'treeItem',
|
||||
kind: 'fileSystem',
|
||||
alias: SCRIPTS_TREE_ITEM_ALIAS,
|
||||
name: 'Scripts Tree Item',
|
||||
meta: {
|
||||
entityTypes: [SCRIPTS_ROOT_ENTITY_TYPE, SCRIPTS_ENTITY_TYPE],
|
||||
},
|
||||
};
|
||||
|
||||
export const manifests = [tree, treeItem];
|
||||
@@ -0,0 +1,36 @@
|
||||
import { SCRIPTS_ENTITY_TYPE, SCRIPTS_WORKSPACE_ACTION_SAVE_ALIAS, SCRIPTS_WORKSPACE_ALIAS } from '../config.js';
|
||||
import { UmbSaveWorkspaceAction } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { ManifestWorkspace, ManifestWorkspaceAction } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
const workspace: ManifestWorkspace = {
|
||||
type: 'workspace',
|
||||
alias: SCRIPTS_WORKSPACE_ALIAS,
|
||||
name: 'Scripts Workspace',
|
||||
loader: () => import('./scripts-workspace.element.js'),
|
||||
meta: {
|
||||
entityType: SCRIPTS_ENTITY_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
//TODO: this does not work for some reason
|
||||
const workspaceActions: Array<ManifestWorkspaceAction> = [
|
||||
{
|
||||
type: 'workspaceAction',
|
||||
alias: 'Umb.WorkspaceAction.Scripts.Save',
|
||||
name: 'Save Script Workspace Action',
|
||||
meta: {
|
||||
label: 'Save',
|
||||
look: 'primary',
|
||||
color: 'positive',
|
||||
api: UmbSaveWorkspaceAction,
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
alias: 'Umb.Condition.WorkspaceAlias',
|
||||
match: workspace.alias,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const manifests = [workspace, ...workspaceActions];
|
||||
@@ -0,0 +1,185 @@
|
||||
import { UmbScriptsWorkspaceContext } from './scripts-workspace.context.js';
|
||||
import type { UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor';
|
||||
import { UUITextStyles, UUIInputElement } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { css, html, customElement, query, state, PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext } from '@umbraco-cms/backoffice/modal';
|
||||
import { Subject, debounceTime } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
import _ from 'lodash';
|
||||
|
||||
@customElement('umb-scripts-workspace-edit')
|
||||
export class UmbScriptsWorkspaceEditElement extends UmbLitElement {
|
||||
#name: string | undefined = '';
|
||||
@state()
|
||||
private get _name() {
|
||||
return this.#name;
|
||||
}
|
||||
|
||||
private set _name(value) {
|
||||
this.#name = value?.replace('.js', '');
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
@state()
|
||||
private _content?: string | null = '';
|
||||
|
||||
@state()
|
||||
private _path?: string | null = '';
|
||||
|
||||
@state()
|
||||
private _dirName?: string | null = '';
|
||||
|
||||
@state()
|
||||
private _ready?: boolean = false;
|
||||
|
||||
@query('umb-code-editor')
|
||||
private _codeEditor?: UmbCodeEditorElement;
|
||||
|
||||
#scriptsWorkspaceContext?: UmbScriptsWorkspaceContext;
|
||||
private _modalContext?: UmbModalManagerContext;
|
||||
|
||||
#isNew = false;
|
||||
|
||||
private inputQuery$ = new Subject<string>();
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => {
|
||||
this._modalContext = instance;
|
||||
});
|
||||
|
||||
this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => {
|
||||
this.#scriptsWorkspaceContext = workspaceContext as UmbScriptsWorkspaceContext;
|
||||
this.observe(this.#scriptsWorkspaceContext.name, (name) => {
|
||||
this._name = name;
|
||||
});
|
||||
|
||||
this.observe(this.#scriptsWorkspaceContext.content, (content) => {
|
||||
this._content = content;
|
||||
});
|
||||
|
||||
this.observe(this.#scriptsWorkspaceContext.path, (path) => {
|
||||
this._path = path;
|
||||
});
|
||||
|
||||
this.observe(this.#scriptsWorkspaceContext.isNew, (isNew) => {
|
||||
this.#isNew = !!isNew;
|
||||
});
|
||||
|
||||
this.observe(this.#scriptsWorkspaceContext.isCodeEditorReady, (isReady) => {
|
||||
this._ready = isReady;
|
||||
});
|
||||
|
||||
this.inputQuery$.pipe(debounceTime(250)).subscribe((nameInputValue: string) => {
|
||||
this.#scriptsWorkspaceContext?.setName(`${nameInputValue}.js`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected willUpdate(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
|
||||
if (_changedProperties.has('_path')) {
|
||||
this._dirName = this._path?.substring(0, this._path?.lastIndexOf('/'));
|
||||
}
|
||||
}
|
||||
|
||||
#onNameInput(event: Event) {
|
||||
const target = event.target as UUIInputElement;
|
||||
const value = target.value as string;
|
||||
this.inputQuery$.next(value);
|
||||
}
|
||||
|
||||
#onCodeEditorInput(event: Event) {
|
||||
const target = event.target as UmbCodeEditorElement;
|
||||
const value = target.code as string;
|
||||
this.#scriptsWorkspaceContext?.setContent(value);
|
||||
}
|
||||
|
||||
#renderCodeEditor() {
|
||||
return html`<umb-code-editor
|
||||
language="javascript"
|
||||
id="content"
|
||||
.code=${this._content ?? ''}
|
||||
@input=${this.#onCodeEditorInput}></umb-code-editor>`;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<umb-workspace-editor alias="Umb.Workspace.Scripts">
|
||||
<div id="workspace-header" slot="header">
|
||||
<uui-input
|
||||
placeholder="Enter name..."
|
||||
.value=${this._name}
|
||||
@input=${this.#onNameInput}
|
||||
label="template name"></uui-input>
|
||||
<small>Scripts/${this._dirName}${this._name}.js</small>
|
||||
</div>
|
||||
<uui-box>
|
||||
<!-- the div below in the header is to make the box display nicely with code editor -->
|
||||
<div slot="header"></div>
|
||||
${this._ready
|
||||
? this.#renderCodeEditor()
|
||||
: html`<div id="loader-container">
|
||||
<uui-loader></uui-loader>
|
||||
</div>`}
|
||||
</uui-box>
|
||||
<div slot="footer-info">
|
||||
<!-- TODO: Shortcuts Modal? -->
|
||||
<uui-button label="Show keyboard shortcuts">
|
||||
Keyboard Shortcuts
|
||||
<uui-keyboard-shortcut>
|
||||
<uui-key>ALT</uui-key>
|
||||
+
|
||||
<uui-key>shift</uui-key>
|
||||
+
|
||||
<uui-key>k</uui-key>
|
||||
</uui-keyboard-shortcut>
|
||||
</uui-button>
|
||||
</div>
|
||||
</umb-workspace-editor>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#loader-container {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
min-height: calc(100dvh - 260px);
|
||||
}
|
||||
|
||||
umb-code-editor {
|
||||
--editor-height: calc(100dvh - 260px);
|
||||
}
|
||||
|
||||
uui-box {
|
||||
min-height: calc(100dvh - 260px);
|
||||
margin: var(--uui-size-layout-1);
|
||||
--uui-box-default-padding: 0;
|
||||
/* remove header border bottom as code editor looks better in this box */
|
||||
--uui-color-divider-standalone: transparent;
|
||||
}
|
||||
|
||||
#workspace-header {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
uui-input {
|
||||
width: 100%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export default UmbScriptsWorkspaceEditElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-scripts-workspace-edit': UmbScriptsWorkspaceEditElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import { ScriptDetails, SCRIPTS_WORKSPACE_ALIAS } from '../config.js';
|
||||
import { UmbScriptsRepository } from '../repository/scripts.repository.js';
|
||||
import { createObservablePart, UmbBooleanState, UmbDeepState } from '@umbraco-cms/backoffice/observable-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
import { loadCodeEditor } from '@umbraco-cms/backoffice/code-editor';
|
||||
import { TextFileResponseModelBaseModel, UpdateScriptRequestModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
|
||||
export class UmbScriptsWorkspaceContext extends UmbWorkspaceContext<UmbScriptsRepository, ScriptDetails> {
|
||||
#data = new UmbDeepState<ScriptDetails | undefined>(undefined);
|
||||
data = this.#data.asObservable();
|
||||
name = createObservablePart(this.#data, (data) => data?.name);
|
||||
content = createObservablePart(this.#data, (data) => data?.content);
|
||||
path = createObservablePart(this.#data, (data) => data?.path);
|
||||
|
||||
#isCodeEditorReady = new UmbBooleanState(false);
|
||||
isCodeEditorReady = this.#isCodeEditorReady.asObservable();
|
||||
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
super(host, SCRIPTS_WORKSPACE_ALIAS, new UmbScriptsRepository(host));
|
||||
this.#loadCodeEditor();
|
||||
}
|
||||
|
||||
async #loadCodeEditor() {
|
||||
try {
|
||||
await loadCodeEditor();
|
||||
this.#isCodeEditorReady.next(true);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
getData() {
|
||||
return this.#data.getValue();
|
||||
}
|
||||
|
||||
setName(value: string) {
|
||||
this.#data.next({ ...this.#data.value, name: value });
|
||||
}
|
||||
|
||||
setContent(value: string) {
|
||||
this.#data.next({ ...this.#data.value, content: value });
|
||||
}
|
||||
|
||||
async load(entityKey: string) {
|
||||
const { data } = await this.repository.requestByKey(entityKey);
|
||||
if (data) {
|
||||
this.setIsNew(false);
|
||||
this.#data.next(data);
|
||||
}
|
||||
}
|
||||
|
||||
async create(parentKey: string) {
|
||||
const newScript: TextFileResponseModelBaseModel = {
|
||||
name: '',
|
||||
path: parentKey,
|
||||
content: '',
|
||||
};
|
||||
this.#data.next(newScript);
|
||||
this.setIsNew(true);
|
||||
}
|
||||
|
||||
getEntityId(): string | undefined {
|
||||
return this.getData()?.path;
|
||||
}
|
||||
|
||||
public async save() {
|
||||
const script = this.getData();
|
||||
|
||||
if (!script) {
|
||||
return Promise.reject('Something went wrong, there is no data for script you want to save...');
|
||||
}
|
||||
if (this.getIsNew()) {
|
||||
const createRequestBody = {
|
||||
name: script.name,
|
||||
content: script.content,
|
||||
parentPath: script.path + '/',
|
||||
};
|
||||
|
||||
this.repository.create(createRequestBody);
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (!script.path) return Promise.reject('There is no path');
|
||||
const updateRequestBody: UpdateScriptRequestModel = {
|
||||
name: script.name,
|
||||
existingPath: script.path,
|
||||
content: script.content,
|
||||
};
|
||||
this.repository.save(script.path, updateRequestBody);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
getEntityType(): string {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { UmbScriptsWorkspaceContext } from './scripts-workspace.context.js';
|
||||
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
import { UmbRoute, IRoutingInfo, PageComponent } from '@umbraco-cms/backoffice/router';
|
||||
import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
@customElement('umb-scripts-workspace')
|
||||
export class UmbScriptsWorkspaceElement extends UmbLitElement {
|
||||
#scriptsWorkspaceContext = new UmbScriptsWorkspaceContext(this);
|
||||
@state()
|
||||
_routes: UmbRoute[] = [
|
||||
{
|
||||
path: 'create/:parentKey',
|
||||
component: import('./scripts-workspace-edit.element.js'),
|
||||
setup: async (component: PageComponent, info: IRoutingInfo) => {
|
||||
const parentKey = info.match.params.parentKey;
|
||||
const decodePath = decodeURIComponent(parentKey);
|
||||
this.#scriptsWorkspaceContext.create(decodePath === 'null' ? '' : decodePath);
|
||||
|
||||
new UmbWorkspaceIsNewRedirectController(
|
||||
this,
|
||||
this.#scriptsWorkspaceContext,
|
||||
this.shadowRoot!.querySelector('umb-router-slot')!,
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'edit/:key',
|
||||
component: import('./scripts-workspace-edit.element.js'),
|
||||
setup: (component: PageComponent, info: IRoutingInfo) => {
|
||||
const key = info.match.params.key;
|
||||
const decodePath = decodeURIComponent(key).replace('-js', '.js');
|
||||
this.#scriptsWorkspaceContext.load(decodePath);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
render() {
|
||||
return html`<umb-router-slot .routes=${this._routes}></umb-router-slot>`;
|
||||
}
|
||||
|
||||
static styles = [UUITextStyles, css``];
|
||||
}
|
||||
|
||||
export default UmbScriptsWorkspaceElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-scripts-workspace': UmbScriptsWorkspaceElement;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UMB_APP } from '@umbraco-cms/backoffice/app';
|
||||
import { UMB_AUTH, type UmbLoggedInUser } from '@umbraco-cms/backoffice/auth';
|
||||
import { UMB_APP } from '@umbraco-cms/backoffice/context';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { css, CSSResultGroup, html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbModalContext } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
@@ -102,7 +102,7 @@ export class UmbAuthFlow {
|
||||
openIdConnectUrl: string,
|
||||
redirectUri: string,
|
||||
clientId = 'umbraco-back-office',
|
||||
scope = 'offline_access'
|
||||
scope = 'offline_access',
|
||||
) {
|
||||
this.#openIdConnectUrl = openIdConnectUrl;
|
||||
this.#redirectUri = redirectUri;
|
||||
@@ -115,7 +115,7 @@ export class UmbAuthFlow {
|
||||
this.#authorizationHandler = new RedirectRequestHandler(
|
||||
this.#storageBackend,
|
||||
new UmbNoHashQueryStringUtils(),
|
||||
window.location
|
||||
window.location,
|
||||
);
|
||||
|
||||
// set notifier to deliver responses
|
||||
@@ -156,7 +156,10 @@ export class UmbAuthFlow {
|
||||
*/
|
||||
async setInitialState() {
|
||||
// Ensure there is a connection to the server
|
||||
await this.fetchServiceConfiguration();
|
||||
if (!this.#configuration) {
|
||||
await this.fetchServiceConfiguration();
|
||||
}
|
||||
|
||||
const tokenResponseJson = await this.#storageBackend.getItem(TOKEN_RESPONSE_NAME);
|
||||
if (tokenResponseJson) {
|
||||
const response = new TokenResponse(JSON.parse(tokenResponseJson));
|
||||
@@ -216,7 +219,7 @@ export class UmbAuthFlow {
|
||||
extras: extras,
|
||||
},
|
||||
undefined,
|
||||
true
|
||||
true,
|
||||
);
|
||||
|
||||
this.#authorizationHandler.performAuthorizationRequest(this.#configuration, request);
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export * from './app.context.js';
|
||||
@@ -19,6 +19,9 @@
|
||||
"baseUrl": ".",
|
||||
"incremental": true,
|
||||
"paths": {
|
||||
// APPS
|
||||
"@umbraco-cms/backoffice/app": ["src/apps/app"],
|
||||
|
||||
"@umbraco-cms/backoffice/external/lit": ["src/external/lit"],
|
||||
"@umbraco-cms/backoffice/external/lodash": ["src/external/lodash"],
|
||||
"@umbraco-cms/backoffice/external/monaco-editor": ["src/external/monaco-editor"],
|
||||
@@ -40,7 +43,6 @@
|
||||
|
||||
// SHARED
|
||||
"@umbraco-cms/backoffice/auth": ["src/shared/auth"],
|
||||
"@umbraco-cms/backoffice/context": ["src/shared/context"],
|
||||
"@umbraco-cms/backoffice/events": ["src/shared/umb-events"],
|
||||
"@umbraco-cms/backoffice/icon": ["src/shared/icon-registry"],
|
||||
"@umbraco-cms/backoffice/models": ["src/shared/models"],
|
||||
@@ -75,6 +77,7 @@
|
||||
"@umbraco-cms/backoffice/tree": ["src/packages/core/tree"],
|
||||
"@umbraco-cms/backoffice/variant": ["src/packages/core/variant"],
|
||||
"@umbraco-cms/backoffice/workspace": ["src/packages/core/workspace"],
|
||||
"@umbraco-cms/backoffice/culture": ["src/packages/core/culture"],
|
||||
|
||||
"@umbraco-cms/backoffice/dictionary": ["./src/packages/dictionary/dictionary/index.ts"],
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ export default {
|
||||
imports: {
|
||||
'src/': './src/',
|
||||
|
||||
'@umbraco-cms/backoffice/app': './src/apps/app/index.ts',
|
||||
|
||||
'@umbraco-cms/backoffice/external/lit': './src/external/lit/index.ts',
|
||||
'@umbraco-cms/backoffice/external/lodash': './src/external/lodash/index.ts',
|
||||
'@umbraco-cms/backoffice/external/monaco-editor': './src/external/monaco-editor/index.ts',
|
||||
@@ -40,7 +42,6 @@ export default {
|
||||
'@umbraco-cms/backoffice/observable-api': './src/libs/observable-api/index.ts',
|
||||
|
||||
'@umbraco-cms/backoffice/auth': './src/shared/auth/index.ts',
|
||||
'@umbraco-cms/backoffice/context': './src/shared/context/index.ts',
|
||||
'@umbraco-cms/backoffice/events': './src/shared/umb-events/index.ts',
|
||||
'@umbraco-cms/backoffice/icon': './src/shared/icon-registry/index.ts',
|
||||
'@umbraco-cms/backoffice/models': './src/shared/models/index.ts',
|
||||
@@ -77,6 +78,7 @@ export default {
|
||||
'@umbraco-cms/backoffice/tree': './src/packages/core/tree/index.ts',
|
||||
'@umbraco-cms/backoffice/variant': './src/packages/core/variant/index.ts',
|
||||
'@umbraco-cms/backoffice/workspace': './src/packages/core/workspace/index.ts',
|
||||
'@umbraco-cms/backoffice/culture': './src/packages/core/culture/index.ts',
|
||||
|
||||
'@umbraco-cms/backoffice/dictionary': './src/packages/dictionary/dictionary/index.ts',
|
||||
|
||||
|
||||
Reference in New Issue
Block a user