Merge branch 'main' into celery-2-dramatiq
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
188
web/package-lock.json
generated
188
web/package-lock.json
generated
@ -22,7 +22,7 @@
|
||||
"@floating-ui/dom": "^1.6.11",
|
||||
"@formatjs/intl-listformat": "^7.7.11",
|
||||
"@fortawesome/fontawesome-free": "^6.7.2",
|
||||
"@goauthentik/api": "^2025.6.2-1750636159",
|
||||
"@goauthentik/api": "^2025.6.2-1750801939",
|
||||
"@lit/context": "^1.1.2",
|
||||
"@lit/localize": "^0.12.2",
|
||||
"@lit/reactive-element": "^2.0.4",
|
||||
@ -34,7 +34,7 @@
|
||||
"@openlayers-elements/maps": "^0.4.0",
|
||||
"@patternfly/elements": "^4.1.0",
|
||||
"@patternfly/patternfly": "^4.224.2",
|
||||
"@sentry/browser": "^9.30.0",
|
||||
"@sentry/browser": "^9.31.0",
|
||||
"@spotlightjs/spotlight": "^3.0.1",
|
||||
"@webcomponents/webcomponentsjs": "^2.8.0",
|
||||
"base64-js": "^1.5.1",
|
||||
@ -126,7 +126,7 @@
|
||||
"storybook-addon-mock": "^5.0.0",
|
||||
"turnstile-types": "^1.2.3",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.34.1",
|
||||
"typescript-eslint": "^8.35.0",
|
||||
"vite-plugin-lit-css": "^2.0.0",
|
||||
"vite-tsconfig-paths": "^5.0.1",
|
||||
"wireit": "^0.14.12"
|
||||
@ -1731,9 +1731,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/api": {
|
||||
"version": "2025.6.2-1750636159",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2025.6.2-1750636159.tgz",
|
||||
"integrity": "sha512-LPseyRzzi5Wk/cP8suRYUhwe/sGdIsGIcaXUkl13jprkJCUXEfuLcfAgdJka2MnIPaMyBDv7oYxJ0IhV/sidEg=="
|
||||
"version": "2025.6.2-1750801939",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2025.6.2-1750801939.tgz",
|
||||
"integrity": "sha512-3s0pE6enhLEWVMD+zClORktBhUAw1vO/lCG0ATqm6xqbTfqGxPYWj5XMzYuX7+a2axxn1BFE134afWmdzDhThw=="
|
||||
},
|
||||
"node_modules/@goauthentik/core": {
|
||||
"resolved": "packages/core",
|
||||
@ -4561,75 +4561,75 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@sentry-internal/browser-utils": {
|
||||
"version": "9.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.30.0.tgz",
|
||||
"integrity": "sha512-e6ZlN8oWheCB0YJSGlBNUlh6UPnY5Ecj1P+/cgeKBhNm7c3bIx4J50485hB8LQsu+b7Q11L2o/wucZ//Pb6FCg==",
|
||||
"version": "9.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.31.0.tgz",
|
||||
"integrity": "sha512-rviu/jUmeQbY4rSO8l4pubOtRIhFtH5Gu/ryRNMTlpJRdomp4uxddqthHUDH5g6xCXZsMTyJEIdx0aTqbgr/GQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "9.30.0"
|
||||
"@sentry/core": "9.31.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/feedback": {
|
||||
"version": "9.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.30.0.tgz",
|
||||
"integrity": "sha512-qAZ7xxLqZM7GlEvmSUmTHnoueg+fc7esMQD4vH8pS7HI3n9C5MjGn3HHlndRpD8lL7iUUQ0TPZQgU6McbzMDyw==",
|
||||
"version": "9.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.31.0.tgz",
|
||||
"integrity": "sha512-Ygi/8UZ7p2B4DhXQjZDtOc45vNUHkfk2XETBTBGkByEQkE8vygzSiKhgRcnVpzwq+8xKFMRy+PxvpcCo+PNQew==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "9.30.0"
|
||||
"@sentry/core": "9.31.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay": {
|
||||
"version": "9.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.30.0.tgz",
|
||||
"integrity": "sha512-+6wkqQGLJuFUzvGRzbh3iIhFGyxQx/Oxc0ODDKmz9ag2xYRjCYb3UUQXmQX9navAF0HXUsq8ajoJPm2L1ZyWVg==",
|
||||
"version": "9.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.31.0.tgz",
|
||||
"integrity": "sha512-V5rvcO/xSj8JMw4ZnZT2cBYC+UOuIiZ2Flj4EoIurxMrTgowE1uMXUBA32EBfuB5/vQSJXB6W5uAudhk7LjBPQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "9.30.0",
|
||||
"@sentry/core": "9.30.0"
|
||||
"@sentry-internal/browser-utils": "9.31.0",
|
||||
"@sentry/core": "9.31.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay-canvas": {
|
||||
"version": "9.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.30.0.tgz",
|
||||
"integrity": "sha512-I4MxS27rfV7vnOU29L80y4baZ4I1XqpnYvC/yLN7C17nA8eDCufQ8WVomli41y8JETnfcxlm68z7CS0sO4RCSA==",
|
||||
"version": "9.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.31.0.tgz",
|
||||
"integrity": "sha512-VGqfvQCIuXQZeecrBf8bd4sj8lYGzUA/2CffTAkad1nB1Onyz0Kzo54qLWemivCxA3ufHf6DCpNA3Loa/0ywFQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/replay": "9.30.0",
|
||||
"@sentry/core": "9.30.0"
|
||||
"@sentry-internal/replay": "9.31.0",
|
||||
"@sentry/core": "9.31.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/browser": {
|
||||
"version": "9.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.30.0.tgz",
|
||||
"integrity": "sha512-sRyW6A9nIieTTI26MYXk1DmWEhmphTjZevusNWla+vvUigCmSjuH+xZw19w43OyvF3bu261Skypnm/mAalOTwg==",
|
||||
"version": "9.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.31.0.tgz",
|
||||
"integrity": "sha512-DzG72JJTqHzE0Qo2fHeHm3xgFs97InaSQStmTMxOA59yPqvAXbweNPcsgCNu1q76+jZyaJcoy1qOwahnLuEVDg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "9.30.0",
|
||||
"@sentry-internal/feedback": "9.30.0",
|
||||
"@sentry-internal/replay": "9.30.0",
|
||||
"@sentry-internal/replay-canvas": "9.30.0",
|
||||
"@sentry/core": "9.30.0"
|
||||
"@sentry-internal/browser-utils": "9.31.0",
|
||||
"@sentry-internal/feedback": "9.31.0",
|
||||
"@sentry-internal/replay": "9.31.0",
|
||||
"@sentry-internal/replay-canvas": "9.31.0",
|
||||
"@sentry/core": "9.31.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "9.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.30.0.tgz",
|
||||
"integrity": "sha512-JfEpeQ8a1qVJEb9DxpFTFy1J1gkNdlgKAPiqYGNnm4yQbnfl2Kb/iEo1if70FkiHc52H8fJwISEF90pzMm6lPg==",
|
||||
"version": "9.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.31.0.tgz",
|
||||
"integrity": "sha512-6JeoPGvBgT9m2YFIf2CrW+KrrOYzUqb9+Xwr/Dw25kPjVKy+WJjWqK8DKCNLgkBA22OCmSOmHuRwFR0YxGVdZQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@ -7415,17 +7415,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.1.tgz",
|
||||
"integrity": "sha512-STXcN6ebF6li4PxwNeFnqF8/2BNDvBupf2OPx2yWNzr6mKNGF7q49VM00Pz5FaomJyqvbXpY6PhO+T9w139YEQ==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.0.tgz",
|
||||
"integrity": "sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "8.34.1",
|
||||
"@typescript-eslint/type-utils": "8.34.1",
|
||||
"@typescript-eslint/utils": "8.34.1",
|
||||
"@typescript-eslint/visitor-keys": "8.34.1",
|
||||
"@typescript-eslint/scope-manager": "8.35.0",
|
||||
"@typescript-eslint/type-utils": "8.35.0",
|
||||
"@typescript-eslint/utils": "8.35.0",
|
||||
"@typescript-eslint/visitor-keys": "8.35.0",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^7.0.0",
|
||||
"natural-compare": "^1.4.0",
|
||||
@ -7439,7 +7439,7 @@
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@typescript-eslint/parser": "^8.34.1",
|
||||
"@typescript-eslint/parser": "^8.35.0",
|
||||
"eslint": "^8.57.0 || ^9.0.0",
|
||||
"typescript": ">=4.8.4 <5.9.0"
|
||||
}
|
||||
@ -7455,16 +7455,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "8.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.1.tgz",
|
||||
"integrity": "sha512-4O3idHxhyzjClSMJ0a29AcoK0+YwnEqzI6oz3vlRf3xw0zbzt15MzXwItOlnr5nIth6zlY2RENLsOPvhyrKAQA==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.35.0.tgz",
|
||||
"integrity": "sha512-6sMvZePQrnZH2/cJkwRpkT7DxoAWh+g6+GFRK6bV3YQo7ogi3SX5rgF6099r5Q53Ma5qeT7LGmOmuIutF4t3lA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.34.1",
|
||||
"@typescript-eslint/types": "8.34.1",
|
||||
"@typescript-eslint/typescript-estree": "8.34.1",
|
||||
"@typescript-eslint/visitor-keys": "8.34.1",
|
||||
"@typescript-eslint/scope-manager": "8.35.0",
|
||||
"@typescript-eslint/types": "8.35.0",
|
||||
"@typescript-eslint/typescript-estree": "8.35.0",
|
||||
"@typescript-eslint/visitor-keys": "8.35.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@ -7480,14 +7480,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/project-service": {
|
||||
"version": "8.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.34.1.tgz",
|
||||
"integrity": "sha512-nuHlOmFZfuRwLJKDGQOVc0xnQrAmuq1Mj/ISou5044y1ajGNp2BNliIqp7F2LPQ5sForz8lempMFCovfeS1XoA==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.35.0.tgz",
|
||||
"integrity": "sha512-41xatqRwWZuhUMF/aZm2fcUsOFKNcG28xqRSS6ZVr9BVJtGExosLAm5A1OxTjRMagx8nJqva+P5zNIGt8RIgbQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/tsconfig-utils": "^8.34.1",
|
||||
"@typescript-eslint/types": "^8.34.1",
|
||||
"@typescript-eslint/tsconfig-utils": "^8.35.0",
|
||||
"@typescript-eslint/types": "^8.35.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@ -7502,14 +7502,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.34.1.tgz",
|
||||
"integrity": "sha512-beu6o6QY4hJAgL1E8RaXNC071G4Kso2MGmJskCFQhRhg8VOH/FDbC8soP8NHN7e/Hdphwp8G8cE6OBzC8o41ZA==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.35.0.tgz",
|
||||
"integrity": "sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.34.1",
|
||||
"@typescript-eslint/visitor-keys": "8.34.1"
|
||||
"@typescript-eslint/types": "8.35.0",
|
||||
"@typescript-eslint/visitor-keys": "8.35.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@ -7520,9 +7520,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/tsconfig-utils": {
|
||||
"version": "8.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.1.tgz",
|
||||
"integrity": "sha512-K4Sjdo4/xF9NEeA2khOb7Y5nY6NSXBnod87uniVYW9kHP+hNlDV8trUSFeynA2uxWam4gIWgWoygPrv9VMWrYg==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.0.tgz",
|
||||
"integrity": "sha512-04k/7247kZzFraweuEirmvUj+W3bJLI9fX6fbo1Qm2YykuBvEhRTPl8tcxlYO8kZZW+HIXfkZNoasVb8EV4jpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@ -7537,14 +7537,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "8.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.34.1.tgz",
|
||||
"integrity": "sha512-Tv7tCCr6e5m8hP4+xFugcrwTOucB8lshffJ6zf1mF1TbU67R+ntCc6DzLNKM+s/uzDyv8gLq7tufaAhIBYeV8g==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.35.0.tgz",
|
||||
"integrity": "sha512-ceNNttjfmSEoM9PW87bWLDEIaLAyR+E6BoYJQ5PfaDau37UGca9Nyq3lBk8Bw2ad0AKvYabz6wxc7DMTO2jnNA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "8.34.1",
|
||||
"@typescript-eslint/utils": "8.34.1",
|
||||
"@typescript-eslint/typescript-estree": "8.35.0",
|
||||
"@typescript-eslint/utils": "8.35.0",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^2.1.0"
|
||||
},
|
||||
@ -7561,9 +7561,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "8.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.1.tgz",
|
||||
"integrity": "sha512-rjLVbmE7HR18kDsjNIZQHxmv9RZwlgzavryL5Lnj2ujIRTeXlKtILHgRNmQ3j4daw7zd+mQgy+uyt6Zo6I0IGA==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.35.0.tgz",
|
||||
"integrity": "sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@ -7575,16 +7575,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.1.tgz",
|
||||
"integrity": "sha512-rjCNqqYPuMUF5ODD+hWBNmOitjBWghkGKJg6hiCHzUvXRy6rK22Jd3rwbP2Xi+R7oYVvIKhokHVhH41BxPV5mA==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.0.tgz",
|
||||
"integrity": "sha512-F+BhnaBemgu1Qf8oHrxyw14wq6vbL8xwWKKMwTMwYIRmFFY/1n/9T/jpbobZL8vp7QyEUcC6xGrnAO4ua8Kp7w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/project-service": "8.34.1",
|
||||
"@typescript-eslint/tsconfig-utils": "8.34.1",
|
||||
"@typescript-eslint/types": "8.34.1",
|
||||
"@typescript-eslint/visitor-keys": "8.34.1",
|
||||
"@typescript-eslint/project-service": "8.35.0",
|
||||
"@typescript-eslint/tsconfig-utils": "8.35.0",
|
||||
"@typescript-eslint/types": "8.35.0",
|
||||
"@typescript-eslint/visitor-keys": "8.35.0",
|
||||
"debug": "^4.3.4",
|
||||
"fast-glob": "^3.3.2",
|
||||
"is-glob": "^4.0.3",
|
||||
@ -7604,16 +7604,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "8.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.34.1.tgz",
|
||||
"integrity": "sha512-mqOwUdZ3KjtGk7xJJnLbHxTuWVn3GO2WZZuM+Slhkun4+qthLdXx32C8xIXbO1kfCECb3jIs3eoxK3eryk7aoQ==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.35.0.tgz",
|
||||
"integrity": "sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.7.0",
|
||||
"@typescript-eslint/scope-manager": "8.34.1",
|
||||
"@typescript-eslint/types": "8.34.1",
|
||||
"@typescript-eslint/typescript-estree": "8.34.1"
|
||||
"@typescript-eslint/scope-manager": "8.35.0",
|
||||
"@typescript-eslint/types": "8.35.0",
|
||||
"@typescript-eslint/typescript-estree": "8.35.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@ -7628,13 +7628,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "8.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.1.tgz",
|
||||
"integrity": "sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.0.tgz",
|
||||
"integrity": "sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.34.1",
|
||||
"@typescript-eslint/types": "8.35.0",
|
||||
"eslint-visitor-keys": "^4.2.1"
|
||||
},
|
||||
"engines": {
|
||||
@ -27217,15 +27217,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript-eslint": {
|
||||
"version": "8.34.1",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.34.1.tgz",
|
||||
"integrity": "sha512-XjS+b6Vg9oT1BaIUfkW3M3LvqZE++rbzAMEHuccCfO/YkP43ha6w3jTEMilQxMF92nVOYCcdjv1ZUhAa1D/0ow==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.35.0.tgz",
|
||||
"integrity": "sha512-uEnz70b7kBz6eg/j0Czy6K5NivaYopgxRjsnAJ2Fx5oTLo3wefTHIbL7AkQr1+7tJCRVpTs/wiM8JR/11Loq9A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "8.34.1",
|
||||
"@typescript-eslint/parser": "8.34.1",
|
||||
"@typescript-eslint/utils": "8.34.1"
|
||||
"@typescript-eslint/eslint-plugin": "8.35.0",
|
||||
"@typescript-eslint/parser": "8.35.0",
|
||||
"@typescript-eslint/utils": "8.35.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
|
||||
@ -93,7 +93,7 @@
|
||||
"@floating-ui/dom": "^1.6.11",
|
||||
"@formatjs/intl-listformat": "^7.7.11",
|
||||
"@fortawesome/fontawesome-free": "^6.7.2",
|
||||
"@goauthentik/api": "^2025.6.2-1750636159",
|
||||
"@goauthentik/api": "^2025.6.2-1750801939",
|
||||
"@lit/context": "^1.1.2",
|
||||
"@lit/localize": "^0.12.2",
|
||||
"@lit/reactive-element": "^2.0.4",
|
||||
@ -105,7 +105,7 @@
|
||||
"@openlayers-elements/maps": "^0.4.0",
|
||||
"@patternfly/elements": "^4.1.0",
|
||||
"@patternfly/patternfly": "^4.224.2",
|
||||
"@sentry/browser": "^9.30.0",
|
||||
"@sentry/browser": "^9.31.0",
|
||||
"@spotlightjs/spotlight": "^3.0.1",
|
||||
"@webcomponents/webcomponentsjs": "^2.8.0",
|
||||
"base64-js": "^1.5.1",
|
||||
@ -197,7 +197,7 @@
|
||||
"storybook-addon-mock": "^5.0.0",
|
||||
"turnstile-types": "^1.2.3",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.34.1",
|
||||
"typescript-eslint": "^8.35.0",
|
||||
"vite-plugin-lit-css": "^2.0.0",
|
||||
"vite-tsconfig-paths": "^5.0.1",
|
||||
"wireit": "^0.14.12"
|
||||
|
||||
@ -64,7 +64,7 @@ export const EntryPoint = /** @type {const} */ ({
|
||||
in: resolve(PackageRoot, "src", "flow", "index.entrypoint.ts"),
|
||||
out: resolve(DistDirectory, "flow", "FlowInterface"),
|
||||
},
|
||||
Standalone: {
|
||||
StandaloneAPI: {
|
||||
in: resolve(PackageRoot, "src", "standalone", "api-browser/index.entrypoint.ts"),
|
||||
out: resolve(DistDirectory, "standalone", "api-browser", "index"),
|
||||
},
|
||||
|
||||
@ -64,7 +64,7 @@ export class AdminOverviewPage extends AdminOverviewBase {
|
||||
}
|
||||
|
||||
quickActions: QuickAction[] = [
|
||||
[msg("Create a new application"), paramURL("/core/applications", { createForm: true })],
|
||||
[msg("Create a new application"), paramURL("/core/applications", { createWizard: true })],
|
||||
[msg("Check the logs"), paramURL("/events/log")],
|
||||
[msg("Explore integrations"), "https://goauthentik.io/integrations/", true],
|
||||
[msg("Manage users"), paramURL("/identity/users")],
|
||||
|
||||
@ -89,7 +89,7 @@ export class RecentEventsCard extends Table<Event> {
|
||||
|
||||
return super.renderEmpty(
|
||||
html`<ak-empty-state
|
||||
><span slot="header">${msg("No Events found.")}</span>
|
||||
><span>${msg("No Events found.")}</span>
|
||||
<div slot="body">${msg("No matching events could be found.")}</div>
|
||||
</ak-empty-state>`,
|
||||
);
|
||||
|
||||
@ -112,7 +112,7 @@ export class ApplicationViewPage extends AKElement {
|
||||
|
||||
renderApp(): TemplateResult {
|
||||
if (!this.application) {
|
||||
return html`<ak-empty-state loading header=${msg("Loading")}> </ak-empty-state>`;
|
||||
return html`<ak-empty-state default-label></ak-empty-state>`;
|
||||
}
|
||||
return html`<ak-tabs>
|
||||
${this.missingOutpost
|
||||
|
||||
@ -118,13 +118,12 @@ export class ApplicationEntitlementsPage extends Table<ApplicationEntitlement> {
|
||||
|
||||
renderEmpty(): TemplateResult {
|
||||
return super.renderEmpty(
|
||||
html`<ak-empty-state
|
||||
header=${msg("No app entitlements created.")}
|
||||
icon="pf-icon-module"
|
||||
>
|
||||
html`<ak-empty-state icon="pf-icon-module"
|
||||
><span>${msg("No app entitlements created.")}</span>
|
||||
|
||||
<div slot="body">
|
||||
${msg(
|
||||
"This application does currently not have any application entitlement defined.",
|
||||
"This application does currently not have any application entitlements defined.",
|
||||
)}
|
||||
</div>
|
||||
<div slot="primary"></div>
|
||||
|
||||
@ -116,7 +116,7 @@ export class ApplicationWizardBindingsStep extends ApplicationWizardStep {
|
||||
.content=${[]}
|
||||
></ak-select-table>
|
||||
<ak-empty-state icon="pf-icon-module"
|
||||
><span slot="header">${msg("No bound policies.")} </span>
|
||||
><span>${msg("No bound policies.")}</span>
|
||||
<div slot="body">${msg("No policies are currently bound to this object.")}</div>
|
||||
<div slot="primary">
|
||||
<button
|
||||
|
||||
@ -83,7 +83,7 @@ export class ApplicationWizardProviderChoiceStep extends WithLicenseSummary(Appl
|
||||
}}
|
||||
></ak-wizard-page-type-create>
|
||||
</form>`
|
||||
: html`<ak-empty-state loading header=${msg("Loading")}></ak-empty-state>`;
|
||||
: html`<ak-empty-state default-label></ak-empty-state>`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -109,10 +109,8 @@ export class EnterpriseLicenseListPage extends TablePage<License> {
|
||||
return super.renderEmpty(html`
|
||||
${inner
|
||||
? inner
|
||||
: html`<ak-empty-state
|
||||
icon=${this.pageIcon()}
|
||||
header="${msg("No licenses found.")}"
|
||||
>
|
||||
: html`<ak-empty-state icon=${this.pageIcon()}
|
||||
><span>${msg("No licenses found.")}</span>
|
||||
<div slot="body">
|
||||
${this.searchEnabled() ? this.renderEmptyClearSearch() : html``}
|
||||
</div>
|
||||
|
||||
@ -136,7 +136,7 @@ export class BoundStagesList extends Table<FlowStageBinding> {
|
||||
renderEmpty(): TemplateResult {
|
||||
return super.renderEmpty(
|
||||
html`<ak-empty-state icon="pf-icon-module">
|
||||
<span slot="header">${msg("No Stages bound")}</span>
|
||||
<span>${msg("No Stages bound")}</span>
|
||||
<div slot="body">${msg("No stages are currently bound to this flow.")}</div>
|
||||
<div slot="primary">
|
||||
<ak-stage-wizard
|
||||
|
||||
@ -199,7 +199,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
|
||||
renderEmpty(): TemplateResult {
|
||||
return super.renderEmpty(
|
||||
html`<ak-empty-state icon="pf-icon-module"
|
||||
><span slot="header">${msg("No Policies bound.")}</span>
|
||||
><span>${msg("No Policies bound.")}</span>
|
||||
<div slot="body">${msg("No policies are currently bound to this object.")}</div>
|
||||
<div slot="primary">
|
||||
<ak-policy-wizard
|
||||
|
||||
@ -42,7 +42,7 @@ export class ProviderViewPage extends AKElement {
|
||||
|
||||
renderProvider(): TemplateResult {
|
||||
if (!this.provider) {
|
||||
return html`<ak-empty-state loading fullHeight></ak-empty-state>`;
|
||||
return html`<ak-empty-state loading full-height></ak-empty-state>`;
|
||||
}
|
||||
switch (this.provider?.component) {
|
||||
case "ak-provider-saml-form":
|
||||
|
||||
@ -34,7 +34,7 @@ export class SourceViewPage extends AKElement {
|
||||
|
||||
renderSource(): TemplateResult {
|
||||
if (!this.source) {
|
||||
return html`<ak-empty-state loading fullHeight></ak-empty-state>`;
|
||||
return html`<ak-empty-state loading full-height></ak-empty-state>`;
|
||||
}
|
||||
switch (this.source?.component) {
|
||||
case "ak-source-kerberos-form":
|
||||
|
||||
@ -7,7 +7,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
|
||||
import { Table, TableColumn } from "@goauthentik/elements/table/Table";
|
||||
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { TemplateResult, html, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
import { AuthenticatorsApi, Device } from "@goauthentik/api";
|
||||
@ -104,8 +104,11 @@ export class UserDeviceTable extends Table<Device> {
|
||||
row(item: Device): TemplateResult[] {
|
||||
return [
|
||||
html`${item.name}`,
|
||||
html`${deviceTypeName(item)}
|
||||
${item.extraDescription ? ` - ${item.extraDescription}` : ""}`,
|
||||
html`<div>
|
||||
${deviceTypeName(item)}
|
||||
${item.extraDescription ? ` - ${item.extraDescription}` : ""}
|
||||
</div>
|
||||
${item.externalId ? html` <small>${item.externalId}</small> ` : nothing} `,
|
||||
html`${item.confirmed ? msg("Yes") : msg("No")}`,
|
||||
html`${item.created.getTime() > 0
|
||||
? html`<div>${formatElapsedTime(item.created)}</div>
|
||||
|
||||
@ -133,7 +133,7 @@ export class UserListPage extends WithBrandConfig(WithCapabilitiesConfig(TablePa
|
||||
async apiEndpoint(): Promise<PaginatedResponse<User>> {
|
||||
const users = await new CoreApi(DEFAULT_CONFIG).coreUsersList({
|
||||
...(await this.defaultEndpointConfig()),
|
||||
pathStartswith: getURLParam("path", ""),
|
||||
pathStartswith: this.activePath,
|
||||
isActive: this.hideDeactivated ? true : undefined,
|
||||
includeGroups: false,
|
||||
});
|
||||
|
||||
@ -94,7 +94,7 @@ export class ObjectChangelog extends Table<Event> {
|
||||
renderEmpty(): TemplateResult {
|
||||
return super.renderEmpty(
|
||||
html`<ak-empty-state
|
||||
><span slot="header">${msg("No Events found.")}</span>
|
||||
><span>${msg("No Events found.")}</span>
|
||||
<div slot="body">${msg("No matching events could be found.")}</div>
|
||||
</ak-empty-state>`,
|
||||
);
|
||||
|
||||
@ -67,7 +67,7 @@ export class UserEvents extends Table<Event> {
|
||||
renderEmpty(): TemplateResult {
|
||||
return super.renderEmpty(
|
||||
html`<ak-empty-state
|
||||
><span slot="header">${msg("No Events found.")}</span>
|
||||
><span>${msg("No Events found.")}</span>
|
||||
<div slot="body">${msg("No matching events could be found.")}</div>
|
||||
</ak-empty-state>`,
|
||||
);
|
||||
|
||||
@ -148,5 +148,31 @@ export class AKElement extends LitElement implements AKElementProps {
|
||||
return this.#styleRoot;
|
||||
}
|
||||
|
||||
protected hasSlotted(name: string | null) {
|
||||
const isNotNestedSlot = (start: Element) => {
|
||||
let node = start.parentNode;
|
||||
while (node && node !== this) {
|
||||
if (node instanceof Element && node.hasAttribute("slot")) {
|
||||
return false;
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// All child slots accessible from the component's LightDOM that match the request
|
||||
const allChildSlotRequests =
|
||||
typeof name === "string"
|
||||
? [...this.querySelectorAll(`[slot="${name}"]`)]
|
||||
: [...this.children].filter((child) => {
|
||||
const slotAttr = child.getAttribute("slot");
|
||||
return !slotAttr || slotAttr === "";
|
||||
});
|
||||
|
||||
// All child slots accessible from the LightDom that match the request *and* are not nested
|
||||
// within another slotted element.
|
||||
return allChildSlotRequests.filter((node) => isNotNestedSlot(node)).length > 0;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
|
||||
@ -3,38 +3,63 @@ import { AKElement } from "@goauthentik/elements/Base";
|
||||
import "@goauthentik/elements/Spinner";
|
||||
import { type SlottedTemplateResult, type Spread } from "@goauthentik/elements/types";
|
||||
import { spread } from "@open-wc/lit-helpers";
|
||||
import { SlotController } from "@patternfly/pfe-core/controllers/slot-controller.js";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { css, html, nothing } from "lit";
|
||||
import { css, html, nothing, render } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { classMap } from "lit/directives/class-map.js";
|
||||
|
||||
import PFEmptyState from "@patternfly/patternfly/components/EmptyState/empty-state.css";
|
||||
import PFTitle from "@patternfly/patternfly/components/Title/title.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
/**
|
||||
* Props for the EmptyState component
|
||||
*/
|
||||
export interface IEmptyState {
|
||||
/** Font Awesome icon class (e.g., "fa-user", "fa-folder") to display */
|
||||
icon?: string;
|
||||
|
||||
/** When true, will automatically show the loading spinner. Overrides `icon`. */
|
||||
loading?: boolean;
|
||||
|
||||
/**
|
||||
* When true, will automatically fill the header with the "Loading" message and show the loading
|
||||
* spinner. Overrides 'loading'.
|
||||
*/
|
||||
defaultLabel?: boolean;
|
||||
|
||||
/** Whether the empty state should take up the full height of its container */
|
||||
fullHeight?: boolean;
|
||||
header?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @element ak-empty-state
|
||||
* @class EmptyState
|
||||
*
|
||||
* A component for displaying empty states with optional icons, headings, body text, and actions.
|
||||
* Follows PatternFly design patterns for empty state presentations.
|
||||
*
|
||||
* ## Slots
|
||||
*
|
||||
* @slot - The main heading text for the empty state
|
||||
* @slot body - Descriptive text explaining the empty state or what the user can do
|
||||
* @slot primary - Primary action buttons or other interactive elements
|
||||
*
|
||||
*/
|
||||
@customElement("ak-empty-state")
|
||||
export class EmptyState extends AKElement implements IEmptyState {
|
||||
@property({ type: String })
|
||||
icon = "";
|
||||
public icon = "";
|
||||
|
||||
@property({ type: Boolean })
|
||||
loading = false;
|
||||
@property({ type: Boolean, reflect: true })
|
||||
public loading = false;
|
||||
|
||||
@property({ type: Boolean })
|
||||
fullHeight = false;
|
||||
@property({ type: Boolean, reflect: true, attribute: "default-label" })
|
||||
public defaultLabel = false;
|
||||
|
||||
@property()
|
||||
header?: string;
|
||||
|
||||
slots = new SlotController(this, "header", "body", "primary");
|
||||
@property({ type: Boolean, attribute: "full-height" })
|
||||
public fullHeight = false;
|
||||
|
||||
static get styles() {
|
||||
return [
|
||||
@ -50,32 +75,49 @@ export class EmptyState extends AKElement implements IEmptyState {
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
const showHeader = this.loading || this.slots.hasSlotted("header");
|
||||
const header = () =>
|
||||
this.slots.hasSlotted("header")
|
||||
? html`<slot name="header"></slot>`
|
||||
: html`<span>${msg("Loading")}</span>`;
|
||||
willUpdate() {
|
||||
if (this.defaultLabel && this.querySelector("span:not([slot])") === null) {
|
||||
render(html`<span>${msg("Loading")}</span>`, this);
|
||||
}
|
||||
}
|
||||
|
||||
return html`<div class="pf-c-empty-state ${this.fullHeight && "pf-m-full-height"}">
|
||||
<div class="pf-c-empty-state__content">
|
||||
${this.loading
|
||||
? html`<div class="pf-c-empty-state__icon">
|
||||
get localAriaLabel() {
|
||||
const result = this.querySelector("span:not([slot])");
|
||||
return result instanceof HTMLElement ? result.innerText || undefined : undefined;
|
||||
}
|
||||
|
||||
render() {
|
||||
const hasHeading = this.hasSlotted(null);
|
||||
const loading = this.loading || this.defaultLabel;
|
||||
const classes = {
|
||||
"pf-c-empty-state": true,
|
||||
"pf-m-full-height": this.fullHeight,
|
||||
};
|
||||
|
||||
return html`<div aria-label=${this.localAriaLabel ?? nothing} class="${classMap(classes)}">
|
||||
<div class="pf-c-empty-state__content" role="progressbar">
|
||||
${loading
|
||||
? html`<div part="spinner" class="pf-c-empty-state__icon">
|
||||
<ak-spinner size=${PFSize.XLarge}></ak-spinner>
|
||||
</div>`
|
||||
: html`<i
|
||||
part="icon"
|
||||
class="pf-icon fa ${this.icon ||
|
||||
"fa-question-circle"} pf-c-empty-state__icon"
|
||||
aria-hidden="true"
|
||||
></i>`}
|
||||
${showHeader ? html` <h1 class="pf-c-title pf-m-lg">${header()}</h1>` : nothing}
|
||||
${this.slots.hasSlotted("body")
|
||||
? html` <div class="pf-c-empty-state__body">
|
||||
${hasHeading
|
||||
? html` <h1 part="heading" class="pf-c-title pf-m-lg" id="empty-state-heading">
|
||||
<slot></slot>
|
||||
</h1>`
|
||||
: nothing}
|
||||
${this.hasSlotted("body")
|
||||
? html` <div part="body" class="pf-c-empty-state__body">
|
||||
<slot name="body"></slot>
|
||||
</div>`
|
||||
: nothing}
|
||||
${this.slots.hasSlotted("primary")
|
||||
? html` <div class="pf-c-empty-state__primary">
|
||||
${this.hasSlotted("primary")
|
||||
? html` <div part="primary" class="pf-c-empty-state__primary">
|
||||
<slot name="primary"></slot>
|
||||
</div>`
|
||||
: nothing}
|
||||
@ -84,10 +126,37 @@ export class EmptyState extends AKElement implements IEmptyState {
|
||||
}
|
||||
}
|
||||
|
||||
export function akEmptyState(properties: IEmptyState, content: SlottedTemplateResult = nothing) {
|
||||
const message =
|
||||
typeof content === "string" ? html`<span slot="body">${content}</span>` : content;
|
||||
return html`<ak-empty-state ${spread(properties as Spread)}>${message}</ak-empty-state>`;
|
||||
interface IEmptyStateContent {
|
||||
heading?: SlottedTemplateResult;
|
||||
body?: SlottedTemplateResult;
|
||||
primary?: SlottedTemplateResult;
|
||||
}
|
||||
|
||||
type ContentKey = keyof IEmptyStateContent;
|
||||
type ContentValue = SlottedTemplateResult | undefined;
|
||||
|
||||
/**
|
||||
* Generate `<ak-empty-state>` programmatically
|
||||
*
|
||||
* @param properties - properties to apply to the component.
|
||||
* @param content - strings or TemplateResults for the slots in `<ak-empty-state>`
|
||||
* @returns TemplateResult for the ak-empty-state element
|
||||
*
|
||||
*/
|
||||
export function akEmptyState(properties: IEmptyState = {}, content: IEmptyStateContent = {}) {
|
||||
// `heading` here is an Object.key of ILoadingOverlayContent, not the obsolete
|
||||
// slot-name.
|
||||
const stringToSlot = (name: string, c: ContentValue) =>
|
||||
name === "heading" ? html`<span>${c}</span>` : html`<span slot=${name}>${c}</span>`;
|
||||
|
||||
const stringToTemplate = (name: string, c: ContentValue) =>
|
||||
typeof c === "string" ? stringToSlot(name, c) : c;
|
||||
|
||||
const items = Object.entries(content)
|
||||
.map(([name, content]) => stringToTemplate(name, content))
|
||||
.filter(Boolean);
|
||||
|
||||
return html`<ak-empty-state ${spread(properties as Spread)}>${items}</ak-empty-state>`;
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
@ -5,30 +5,59 @@ import { spread } from "@open-wc/lit-helpers";
|
||||
|
||||
import { css, html, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
export interface ILoadingOverlay {
|
||||
/**
|
||||
* Whether this overlay should appear above all other overlays (z-index: 999)
|
||||
*/
|
||||
topmost?: boolean;
|
||||
|
||||
/**
|
||||
* Whether to show the loading spinner animation
|
||||
*/
|
||||
noSpinner?: boolean;
|
||||
|
||||
/**
|
||||
* Icon name to display instead of the default loading spinner
|
||||
*/
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @element ak-loading-overlay
|
||||
* @class LoadingOverlay
|
||||
*
|
||||
* A component for for showing a loading message above a darkening background, in order
|
||||
* to pause interaction while dynamically importing a major component.
|
||||
*
|
||||
* ## Slots
|
||||
*
|
||||
* @slot - The main heading text for the loading state
|
||||
* @slot body - Descriptive text explaining the loading state
|
||||
*
|
||||
*/
|
||||
@customElement("ak-loading-overlay")
|
||||
export class LoadingOverlay extends AKElement implements ILoadingOverlay {
|
||||
// Do not camelize: https://www.merriam-webster.com/dictionary/topmost
|
||||
@property({ type: Boolean, attribute: "topmost" })
|
||||
topmost = false;
|
||||
|
||||
@property({ type: Boolean })
|
||||
loading = true;
|
||||
@property({ type: Boolean, attribute: "no-spinner" })
|
||||
noSpinner = false;
|
||||
|
||||
@property({ type: String })
|
||||
icon = "";
|
||||
icon?: string;
|
||||
|
||||
static get styles() {
|
||||
return [
|
||||
PFBase,
|
||||
css`
|
||||
:host {
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
@ -46,20 +75,49 @@ export class LoadingOverlay extends AKElement implements ILoadingOverlay {
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<ak-empty-state ?loading=${this.loading} header="" icon=${this.icon}>
|
||||
<span slot="body"><slot></slot></span>
|
||||
// Nested slots. Can get a little cognitively heavy, so be careful if you're editing here...
|
||||
return html`<ak-empty-state ?loading=${!this.noSpinner} icon=${ifDefined(this.icon)}>
|
||||
${this.hasSlotted(null) ? html`<span><slot></slot></span>` : nothing}
|
||||
${this.hasSlotted("body")
|
||||
? html`<span slot="body"><slot name="body"></slot></span>`
|
||||
: nothing}
|
||||
</ak-empty-state>`;
|
||||
}
|
||||
}
|
||||
|
||||
interface ILoadingOverlayContent {
|
||||
heading?: SlottedTemplateResult;
|
||||
body?: SlottedTemplateResult;
|
||||
}
|
||||
|
||||
type ContentKey = keyof ILoadingOverlayContent;
|
||||
type ContentValue = SlottedTemplateResult | undefined;
|
||||
|
||||
/**
|
||||
* Function to create `<ak-loading-overlay>` programmatically
|
||||
*
|
||||
* @param properties - properties to apply to the component.
|
||||
* @param content - strings or TemplateResults for the slots in `<ak-loading-overlay>`
|
||||
* @returns TemplateResult for the ak-loading-overlay element
|
||||
*
|
||||
*/
|
||||
export function akLoadingOverlay(
|
||||
properties: ILoadingOverlay,
|
||||
content: SlottedTemplateResult = nothing,
|
||||
properties: ILoadingOverlay = {},
|
||||
content: ILoadingOverlayContent = {},
|
||||
) {
|
||||
const message = typeof content === "string" ? html`<span>${content}</span>` : content;
|
||||
return html`<ak-loading-overlay ${spread(properties as Spread)}
|
||||
>${message}</ak-loading-overlay
|
||||
>`;
|
||||
// `heading` here is an Object.key of ILoadingOverlayContent, not the obsolete
|
||||
// slot-name.
|
||||
const stringToSlot = (name: string, c: ContentValue) =>
|
||||
name === "heading" ? html`<span>${c}</span>` : html`<span slot=${name}>${c}</span>`;
|
||||
|
||||
const stringToTemplate = (name: string, c: ContentValue) =>
|
||||
typeof c === "string" ? stringToSlot(name, c) : c;
|
||||
|
||||
const items = Object.entries(content)
|
||||
.map(([name, content]) => stringToTemplate(name, content))
|
||||
.filter(Boolean);
|
||||
|
||||
return html`<ak-loading-overlay ${spread(properties as Spread)}>${items}</ak-loading-overlay>`;
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
@ -32,8 +32,8 @@ import {
|
||||
} from "./types.js";
|
||||
|
||||
function localeComparator(a: DualSelectPair, b: DualSelectPair) {
|
||||
const aSortBy = a[2] || a[0];
|
||||
const bSortBy = b[2] || b[0];
|
||||
const aSortBy = String(a[2] || a[0]);
|
||||
const bSortBy = String(b[2] || b[0]);
|
||||
|
||||
return aSortBy.localeCompare(bSortBy);
|
||||
}
|
||||
|
||||
@ -201,7 +201,7 @@ export abstract class AKChart<T> extends AKElement {
|
||||
${this.error
|
||||
? html`
|
||||
<ak-empty-state icon="fa-times"
|
||||
><span slot="header">${msg("Failed to fetch data.")}</span>
|
||||
><span>${msg("Failed to fetch data.")}</span>
|
||||
<p slot="body">${pluckErrorDetail(this.error)}</p>
|
||||
</ak-empty-state>
|
||||
`
|
||||
|
||||
@ -40,9 +40,7 @@ export class LogViewer extends Table<LogEvent> {
|
||||
|
||||
renderEmpty(): TemplateResult {
|
||||
return super.renderEmpty(
|
||||
html`<ak-empty-state
|
||||
><span slot="header">${msg("No log messages.")}</span>
|
||||
</ak-empty-state>`,
|
||||
html`<ak-empty-state><span>${msg("No log messages.")}</span> </ak-empty-state>`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -164,7 +164,7 @@ export class NotificationDrawer extends AKElement {
|
||||
|
||||
renderEmpty() {
|
||||
return html`<ak-empty-state
|
||||
><span slot="header">${msg("No notifications found.")}</span>
|
||||
><span>${msg("No notifications found.")}</span>
|
||||
<div slot="body">${msg("You don't have any notifications currently.")}</div>
|
||||
</ak-empty-state>`;
|
||||
}
|
||||
|
||||
@ -1,59 +0,0 @@
|
||||
import { Canvas, Description, Meta, Story, Title } from "@storybook/blocks";
|
||||
|
||||
import * as EmptyStateStories from "./EmptyState.stories";
|
||||
|
||||
<Meta of={EmptyStateStories} />
|
||||
|
||||
# EmptyState
|
||||
|
||||
The EmptyState is an in-page element to indicate that something is either loading or unavailable.
|
||||
When "loading" is true it displays a spinner, otherwise it displays a static icon. The default
|
||||
icon is a question mark in a circle.
|
||||
|
||||
It has two named slots, `body` and `primary`, to communicate further details about the current state
|
||||
this element is meant to display.
|
||||
|
||||
## Usage
|
||||
|
||||
```Typescript
|
||||
import "@goauthentik/elements/EmptyState.js";
|
||||
```
|
||||
|
||||
Note that the content of an alert _must_ be a valid HTML component; plain text does not work here.
|
||||
|
||||
```html
|
||||
<ak-empty-state icon="fa-eject"
|
||||
><span slot="primary">This would display in the "primary" slot</span></ak-empty-state
|
||||
>
|
||||
```
|
||||
|
||||
## Demo
|
||||
|
||||
### Default: Loading
|
||||
|
||||
The default state is _loading_
|
||||
|
||||
<Story of={EmptyStateStories.DefaultStory} />
|
||||
|
||||
### Done
|
||||
|
||||
<Story of={EmptyStateStories.DefaultAndLoadingDone} />
|
||||
|
||||
### Alternative "Done" Icon
|
||||
|
||||
This also shows the "header" attribute filled, which is rendered in a large, dark typeface.
|
||||
|
||||
<Story of={EmptyStateStories.DoneWithAlternativeIcon} />
|
||||
|
||||
### The Body Slot Filled
|
||||
|
||||
The body content slot is rendered in a lighter typeface at default size.
|
||||
|
||||
<Story of={EmptyStateStories.WithBodySlotFilled} />
|
||||
|
||||
### The Body and Primary Slot Filled
|
||||
|
||||
The primary content is rendered in the normal dark typeface at default size. It is also spaced
|
||||
significantly below the spinner itself.
|
||||
|
||||
<Story of={EmptyStateStories.WithBodyAndPrimarySlotsFilled} />
|
||||
@ -1,108 +1,254 @@
|
||||
import type { Meta, StoryObj } from "@storybook/web-components";
|
||||
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { TemplateResult, html, nothing } from "lit";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
import { EmptyState, type IEmptyState } from "../EmptyState.js";
|
||||
import "../EmptyState.js";
|
||||
import { type EmptyState, type IEmptyState, akEmptyState } from "../EmptyState.js";
|
||||
|
||||
const metadata: Meta<EmptyState> = {
|
||||
title: "Elements/<ak-empty-state>",
|
||||
type StoryArgs = IEmptyState & {
|
||||
headingText?: string | TemplateResult;
|
||||
bodyText?: string | TemplateResult;
|
||||
primaryButtonText?: string | TemplateResult;
|
||||
};
|
||||
|
||||
const metadata: Meta<StoryArgs> = {
|
||||
title: "Elements / <ak-empty-state>",
|
||||
component: "ak-empty-state",
|
||||
tags: ["autodocs"],
|
||||
parameters: {
|
||||
docs: {
|
||||
description: "Our empty state spinner",
|
||||
description: {
|
||||
component: `
|
||||
# Empty State Component
|
||||
|
||||
The EmptyState is an in-page element to indicate that something is either loading or unavailable.
|
||||
When "loading" is true it displays a spinner, otherwise it displays a static icon. The default
|
||||
icon is a question mark in a circle.
|
||||
|
||||
It has three named slots:
|
||||
|
||||
- The default slot: The heading (renders larger and more bold)
|
||||
- **body**: Any text to describe the state
|
||||
- **primary**: Action buttons or other interactive elements
|
||||
|
||||
For the loading attributes:
|
||||
|
||||
- The attribute \`loading\` will show the spinner
|
||||
- The attribute \`default\` will show the spinner and the default header of "Loading"
|
||||
|
||||
If either of these attributes is active and the element contains content not assigned to one of the
|
||||
named slots, it will be shown in the header. This overrides the default text of \`default\`. You
|
||||
do not need both attributes for \`default\` to work; it assumes loading.
|
||||
|
||||
`,
|
||||
},
|
||||
},
|
||||
layout: "padded",
|
||||
},
|
||||
argTypes: {
|
||||
icon: { control: "text" },
|
||||
loading: { control: "boolean" },
|
||||
fullHeight: { control: "boolean" },
|
||||
header: { control: "text" },
|
||||
icon: {
|
||||
control: "text",
|
||||
description: "Font Awesome icon class (without 'fa-' prefix)",
|
||||
},
|
||||
loading: {
|
||||
control: "boolean",
|
||||
description: "Show loading spinner instead of icon",
|
||||
},
|
||||
defaultLabel: {
|
||||
control: "boolean",
|
||||
description: "Show loading spinner instead of icon",
|
||||
},
|
||||
fullHeight: {
|
||||
control: "boolean",
|
||||
description: "Fill the full height of container",
|
||||
},
|
||||
headingText: {
|
||||
control: "text",
|
||||
description: "Text for heading slot (for demo purposes)",
|
||||
},
|
||||
bodyText: {
|
||||
control: "text",
|
||||
description: "Text for body slot (for demo purposes)",
|
||||
},
|
||||
primaryButtonText: {
|
||||
control: "text",
|
||||
description: "Text for primary button (for demo purposes)",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default metadata;
|
||||
|
||||
const container = (content: TemplateResult) =>
|
||||
html` <div style="background-color: #f0f0f0; padding: 1rem;">
|
||||
<style>
|
||||
ak-divider {
|
||||
display: inline-block;
|
||||
width: 32rem;
|
||||
max-width: 32rem;
|
||||
}</style
|
||||
>${content}
|
||||
</div>`;
|
||||
type Story = StoryObj<StoryArgs>;
|
||||
|
||||
export const DefaultStory: StoryObj = {
|
||||
const Template: Story = {
|
||||
args: {
|
||||
icon: undefined,
|
||||
loading: true,
|
||||
icon: "fa-circle-radiation",
|
||||
loading: false,
|
||||
defaultLabel: false,
|
||||
fullHeight: false,
|
||||
header: undefined,
|
||||
},
|
||||
render: (args) => html`
|
||||
<ak-empty-state
|
||||
icon=${ifDefined(args.icon)}
|
||||
?loading=${args.loading}
|
||||
?default=${args.defaultLabel}
|
||||
?full-height=${args.fullHeight}
|
||||
>
|
||||
${args.headingText ? html`<span>${args.headingText}</span>` : nothing}
|
||||
${args.bodyText ? html`<span slot="body">${args.bodyText}</span>` : nothing}
|
||||
${args.primaryButtonText
|
||||
? html`
|
||||
<button slot="primary" class="pf-c-button pf-m-primary">
|
||||
${args.primaryButtonText}
|
||||
</button>
|
||||
`
|
||||
: nothing}
|
||||
</ak-empty-state>
|
||||
`,
|
||||
};
|
||||
|
||||
render: ({ icon, loading, fullHeight, header }: IEmptyState) =>
|
||||
container(
|
||||
html` <ak-empty-state
|
||||
?loading=${loading}
|
||||
?fullHeight=${fullHeight}
|
||||
icon=${ifDefined(icon)}
|
||||
header=${ifDefined(header)}
|
||||
>
|
||||
</ak-empty-state>`,
|
||||
export const Basic: Story = {
|
||||
...Template,
|
||||
args: {
|
||||
icon: "fa-folder-open",
|
||||
headingText: "No files found",
|
||||
bodyText: "This folder is empty. Upload some files to get started.",
|
||||
},
|
||||
};
|
||||
|
||||
export const Empty: Story = {
|
||||
...Template,
|
||||
args: {
|
||||
icon: "",
|
||||
},
|
||||
render: () =>
|
||||
html`<p>Note that a completely empty <ak-empty-state> is just that: empty.</p>
|
||||
<ak-empty-state></ak-empty-state>`,
|
||||
};
|
||||
|
||||
export const WithAction: Story = {
|
||||
...Template,
|
||||
args: {
|
||||
icon: "fa-users",
|
||||
headingText: "No users yet",
|
||||
bodyText: "Get started by creating your first user account.",
|
||||
primaryButtonText: html`<button>Create User</button>`,
|
||||
},
|
||||
};
|
||||
|
||||
export const Loading: Story = {
|
||||
...Template,
|
||||
args: {
|
||||
loading: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const LoadingWithCustomMessage: Story = {
|
||||
...Template,
|
||||
args: {
|
||||
loading: true,
|
||||
headingText: html`<span>I <em>know</em> it's here, somewhere...</span>`,
|
||||
},
|
||||
};
|
||||
|
||||
export const LoadingWithDefaultMessage: Story = {
|
||||
...Template,
|
||||
args: {
|
||||
defaultLabel: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const LoadingDefaultWithOverride: Story = {
|
||||
...Template,
|
||||
args: {
|
||||
defaultLabel: true,
|
||||
headingText: html`<span>Have they got a chance? Eh. It would take a miracle.</span>`,
|
||||
},
|
||||
};
|
||||
|
||||
export const LoadingDefaultWithButton: Story = {
|
||||
...Template,
|
||||
args: {
|
||||
defaultLabel: true,
|
||||
primaryButtonText: html`<button>Cancel</button>`,
|
||||
},
|
||||
};
|
||||
|
||||
export const FullHeight: Story = {
|
||||
...Template,
|
||||
args: {
|
||||
icon: "fa-search",
|
||||
headingText: "No search results",
|
||||
bodyText: "Try adjusting your search criteria or browse our categories.",
|
||||
fullHeight: true,
|
||||
primaryButtonText: html`<button>Go back</button>`,
|
||||
},
|
||||
};
|
||||
|
||||
export const ProgrammaticUsage: Story = {
|
||||
...Template,
|
||||
args: {
|
||||
icon: "fa-beer",
|
||||
headingText: "Hold My Beer",
|
||||
bodyText: "I saw this in a cartoon once. I'm sure I can pull it off.",
|
||||
primaryButtonText: html`<button>Leave The Scene Immediately</button>`,
|
||||
},
|
||||
render: (args) =>
|
||||
akEmptyState(
|
||||
{
|
||||
icon: args.icon,
|
||||
},
|
||||
{
|
||||
heading: args.headingText,
|
||||
body: args.bodyText,
|
||||
primary: args.primaryButtonText
|
||||
? html`
|
||||
<button slot="primary" class="pf-c-button pf-m-primary">
|
||||
${args.primaryButtonText}
|
||||
</button>
|
||||
`
|
||||
: undefined,
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
export const DefaultAndLoadingDone = {
|
||||
...DefaultStory,
|
||||
args: { ...DefaultStory, ...{ loading: false } },
|
||||
};
|
||||
|
||||
export const DoneWithAlternativeIcon = {
|
||||
...DefaultStory,
|
||||
args: {
|
||||
...DefaultStory,
|
||||
...{ loading: false, icon: "fa-space-shuttle", header: "The final frontier" },
|
||||
},
|
||||
};
|
||||
|
||||
export const WithBodySlotFilled = {
|
||||
...DefaultStory,
|
||||
args: {
|
||||
...DefaultStory,
|
||||
...{ loading: false, icon: "fa-space-shuttle", header: "The final frontier" },
|
||||
},
|
||||
render: ({ icon, loading, fullHeight, header }: IEmptyState) =>
|
||||
container(html`
|
||||
<ak-empty-state
|
||||
?loading=${loading}
|
||||
?fullHeight=${fullHeight}
|
||||
icon=${ifDefined(icon)}
|
||||
header=${ifDefined(header)}
|
||||
>
|
||||
<span slot="body">This is the body content</span>
|
||||
export const IconShowcase: Story = {
|
||||
args: {},
|
||||
render: () => html`
|
||||
<div
|
||||
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1rem;"
|
||||
>
|
||||
<ak-empty-state icon="fa-users">
|
||||
<span>Users</span>
|
||||
<span slot="body">No users found</span>
|
||||
</ak-empty-state>
|
||||
`),
|
||||
};
|
||||
|
||||
export const WithBodyAndPrimarySlotsFilled = {
|
||||
...DefaultStory,
|
||||
args: {
|
||||
...DefaultStory,
|
||||
...{ loading: false, icon: "fa-space-shuttle", header: "The final frontier" },
|
||||
},
|
||||
render: ({ icon, loading, fullHeight, header }: IEmptyState) =>
|
||||
container(
|
||||
html` <ak-empty-state
|
||||
?loading=${loading}
|
||||
?fullHeight=${fullHeight}
|
||||
icon=${ifDefined(icon)}
|
||||
header=${ifDefined(header)}
|
||||
>
|
||||
<span slot="body">This is the body content slot</span>
|
||||
<span slot="primary">This is the primary content slot</span>
|
||||
</ak-empty-state>`,
|
||||
),
|
||||
<ak-empty-state icon="fa-database">
|
||||
<span>Database</span>
|
||||
<span slot="body">No records</span>
|
||||
</ak-empty-state>
|
||||
|
||||
<ak-empty-state icon="fa-envelope">
|
||||
<span>Messages</span>
|
||||
<span slot="body">No messages</span>
|
||||
</ak-empty-state>
|
||||
|
||||
<ak-empty-state icon="fa-chart-bar">
|
||||
<span>Analytics</span>
|
||||
<span slot="body">No data to display</span>
|
||||
</ak-empty-state>
|
||||
|
||||
<ak-empty-state icon="fa-cog">
|
||||
<span>Settings</span>
|
||||
<span slot="body">No configuration</span>
|
||||
</ak-empty-state>
|
||||
|
||||
<ak-empty-state icon="fa-shield-alt">
|
||||
<span>Security</span>
|
||||
<span slot="body">No alerts</span>
|
||||
</ak-empty-state>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
import { Canvas, Description, Meta, Story, Title } from "@storybook/blocks";
|
||||
|
||||
import * as LoadingOverlayStories from "./LoadingOverlay.stories";
|
||||
|
||||
<Meta of={LoadingOverlayStories} />
|
||||
|
||||
# LoadingOverlay
|
||||
|
||||
The LoadingOverlay is meant to cover the container element completely, hiding the content behind a
|
||||
dimming filter, while content loads.
|
||||
|
||||
It has a single named slot, "body" into which messages about the loading process can be included.
|
||||
|
||||
## Usage
|
||||
|
||||
```Typescript
|
||||
import "@goauthentik/elements/LoadingOverlay.js";
|
||||
```
|
||||
|
||||
Note that the content of an alert _must_ be a valid HTML component; plain text does not work here.
|
||||
|
||||
```html
|
||||
<ak-loading-overlay topmost>
|
||||
<span>This would display below the loading spinner</span>
|
||||
</ak-loading-overlay>
|
||||
```
|
||||
|
||||
## Demo
|
||||
|
||||
### Default
|
||||
|
||||
<Story of={LoadingOverlayStories.DefaultStory} />
|
||||
|
||||
### With a message
|
||||
|
||||
<Story of={LoadingOverlayStories.WithAMessage} />
|
||||
@ -1,74 +1,154 @@
|
||||
import type { Meta, StoryObj } from "@storybook/web-components";
|
||||
|
||||
import { LitElement, TemplateResult, css, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { html } from "lit";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
import { type ILoadingOverlay, LoadingOverlay } from "../LoadingOverlay.js";
|
||||
import "../LoadingOverlay.js";
|
||||
import { type ILoadingOverlay, LoadingOverlay, akLoadingOverlay } from "../LoadingOverlay.js";
|
||||
|
||||
const metadata: Meta<LoadingOverlay> = {
|
||||
title: "Elements/<ak-loading-overlay>",
|
||||
type StoryArgs = ILoadingOverlay & {
|
||||
headingText?: string;
|
||||
bodyText?: string;
|
||||
noSpinner: boolean;
|
||||
};
|
||||
|
||||
const metadata: Meta<StoryArgs> = {
|
||||
title: "Elements/ <ak-loading-overlay>",
|
||||
component: "ak-loading-overlay",
|
||||
tags: ["autodocs"],
|
||||
parameters: {
|
||||
docs: {
|
||||
description: "Our empty state spinner",
|
||||
description: {
|
||||
component: `
|
||||
# Loading Overlay Component
|
||||
|
||||
A full-screen overlay component that displays a loading state with optional heading and body content.
|
||||
|
||||
A variant of the EmptyState component that includes a protective background for load or import
|
||||
operations during which the user should be prevented from interacting with the page.
|
||||
|
||||
It has two named slots, both optional:
|
||||
|
||||
- **heading**: Main title (renders in an \`<h1>\`)
|
||||
- **body**: Any text to describe the state
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
topmost: { control: "boolean" },
|
||||
// @ts-ignore
|
||||
message: { control: "text" },
|
||||
topmost: {
|
||||
control: "boolean",
|
||||
description:
|
||||
"Whether this overlay should appear above all other overlays (z-index: 999)",
|
||||
defaultValue: false,
|
||||
},
|
||||
noSpinner: {
|
||||
control: "boolean",
|
||||
description: "Disable the loading spinner animation",
|
||||
defaultValue: false,
|
||||
},
|
||||
icon: {
|
||||
control: "text",
|
||||
description: "Icon name to display instead of the default loading spinner",
|
||||
},
|
||||
headingText: {
|
||||
control: "text",
|
||||
description: "Heading text displayed above the loading indicator",
|
||||
},
|
||||
bodyText: {
|
||||
control: "text",
|
||||
description: "Body text displayed below the loading indicator",
|
||||
},
|
||||
},
|
||||
decorators: [
|
||||
(story) => html`
|
||||
<div
|
||||
style="position: relative; height: 400px; width: 100%; border: 1px solid #ccc; background: #f5f5f5;"
|
||||
>
|
||||
<div style="padding: 20px;">
|
||||
<h3>Content Behind Overlay</h3>
|
||||
<p>authentik is awesome (or will be if something were actually loading)</p>
|
||||
<button>Sample Button</button>
|
||||
</div>
|
||||
${story()}
|
||||
</div>
|
||||
`,
|
||||
],
|
||||
};
|
||||
|
||||
export default metadata;
|
||||
|
||||
@customElement("ak-storybook-demo-container")
|
||||
export class Container extends LitElement {
|
||||
static get styles() {
|
||||
return css`
|
||||
:host {
|
||||
display: block;
|
||||
position: relative;
|
||||
height: 25vh;
|
||||
width: 75vw;
|
||||
}
|
||||
#main-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
`;
|
||||
}
|
||||
type Story = StoryObj<StoryArgs>;
|
||||
|
||||
@property({ type: Object, attribute: false })
|
||||
content!: TemplateResult;
|
||||
export const Default: Story = {
|
||||
render: () => html`<ak-loading-overlay></ak-loading-overlay>`,
|
||||
};
|
||||
|
||||
render() {
|
||||
return html` <div id="main-container">${this.content}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
export const DefaultStory: StoryObj = {
|
||||
export const WithHeading: Story = {
|
||||
args: {
|
||||
topmost: undefined,
|
||||
// @ts-ignore
|
||||
message: undefined,
|
||||
},
|
||||
|
||||
// @ts-ignore
|
||||
render: ({ topmost, message }: ILoadingOverlay) => {
|
||||
message = typeof message === "string" ? html`<span>${message}</span>` : message;
|
||||
const content = html` <ak-loading-overlay ?topmost=${topmost}
|
||||
>${message ?? ""}
|
||||
</ak-loading-overlay>`;
|
||||
return html`<ak-storybook-demo-container
|
||||
.content=${content}
|
||||
></ak-storybook-demo-container>`;
|
||||
headingText: "Loading Data",
|
||||
},
|
||||
render: (args) =>
|
||||
html`<ak-loading-overlay>
|
||||
<span>${args.headingText}</span>
|
||||
</ak-loading-overlay>`,
|
||||
};
|
||||
|
||||
export const WithAMessage: StoryObj = {
|
||||
...DefaultStory,
|
||||
args: { ...DefaultStory.args, message: html`<p>Overlay with a message</p>` },
|
||||
export const WithHeadingAndBody: Story = {
|
||||
args: {
|
||||
headingText: "Loading Data",
|
||||
bodyText: "Please wait while we fetch your information...",
|
||||
},
|
||||
render: (args) =>
|
||||
html`<ak-loading-overlay>
|
||||
<span>${args.headingText}</span>
|
||||
<span slot="body">${args.bodyText}</span>
|
||||
</ak-loading-overlay>`,
|
||||
};
|
||||
|
||||
export const NoSpinner: Story = {
|
||||
args: {
|
||||
headingText: "Static Message",
|
||||
bodyText: "This overlay shows without a spinner animation.",
|
||||
},
|
||||
render: (args) =>
|
||||
html`<ak-loading-overlay no-spinner>
|
||||
<span>${args.headingText}</span>
|
||||
<span slot="body">${args.bodyText}</span>
|
||||
</ak-loading-overlay>`,
|
||||
};
|
||||
|
||||
export const WithCustomIcon: Story = {
|
||||
args: {
|
||||
icon: "fa-info-circle",
|
||||
headingText: "Processing",
|
||||
bodyText: "Your request is being processed...",
|
||||
},
|
||||
render: (args) =>
|
||||
html`<ak-loading-overlay no-spinner icon=${ifDefined(args.icon)}>
|
||||
<span>${args.headingText}</span>
|
||||
<span slot="body">${args.bodyText}</span>
|
||||
</ak-loading-overlay>`,
|
||||
};
|
||||
|
||||
export const ProgrammaticUsage: Story = {
|
||||
args: {
|
||||
topmost: false,
|
||||
noSpinner: false,
|
||||
icon: "",
|
||||
headingText: "Programmatic Loading",
|
||||
bodyText: "This overlay was created using the akLoadingOverlay function.",
|
||||
},
|
||||
render: (args) =>
|
||||
akLoadingOverlay(
|
||||
{
|
||||
topmost: args.topmost,
|
||||
noSpinner: args.noSpinner,
|
||||
icon: args.icon || undefined,
|
||||
},
|
||||
{
|
||||
heading: args.headingText,
|
||||
body: args.bodyText,
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
@ -299,9 +299,7 @@ export abstract class Table<T> extends WithLicenseSummary(AKElement) implements
|
||||
return html`<tr role="row">
|
||||
<td role="cell" colspan="25">
|
||||
<div class="pf-l-bullseye">
|
||||
<ak-empty-state loading
|
||||
><span slot="header">${msg("Loading")}</span></ak-empty-state
|
||||
>
|
||||
<ak-empty-state default-label></ak-empty-state>
|
||||
</div>
|
||||
</td>
|
||||
</tr>`;
|
||||
@ -314,7 +312,7 @@ export abstract class Table<T> extends WithLicenseSummary(AKElement) implements
|
||||
<div class="pf-l-bullseye">
|
||||
${inner ??
|
||||
html`<ak-empty-state
|
||||
><span slot="header">${msg("No objects found.")}</span> >
|
||||
><span>${msg("No objects found.")}</span>
|
||||
<div slot="primary">${this.renderObjectCreate()}</div>
|
||||
</ak-empty-state>`}
|
||||
</div>
|
||||
@ -331,7 +329,7 @@ export abstract class Table<T> extends WithLicenseSummary(AKElement) implements
|
||||
if (!this.error) return nothing;
|
||||
|
||||
return html`<ak-empty-state icon="fa-ban"
|
||||
><span slot="header">${msg("Failed to fetch objects.")}</span>
|
||||
><span>${msg("Failed to fetch objects.")}</span>
|
||||
<div slot="body">${pluckErrorDetail(this.error)}</div>
|
||||
</ak-empty-state>`;
|
||||
}
|
||||
|
||||
@ -42,7 +42,8 @@ export abstract class TablePage<T> extends Table<T> {
|
||||
return super.renderEmpty(html`
|
||||
${inner
|
||||
? inner
|
||||
: html`<ak-empty-state icon=${this.pageIcon()} header="${msg("No objects found.")}">
|
||||
: html`<ak-empty-state icon=${this.pageIcon()}
|
||||
><span>${msg("No objects found.")}</span>
|
||||
<div slot="body">
|
||||
${this.searchEnabled() ? this.renderEmptyClearSearch() : html``}
|
||||
</div>
|
||||
|
||||
@ -19,11 +19,7 @@ describe("ak-empty-state", () => {
|
||||
});
|
||||
|
||||
it("should render the default loader", async () => {
|
||||
render(
|
||||
html`<ak-empty-state loading
|
||||
><span slot="header">${msg("Loading")}</span>
|
||||
</ak-empty-state>`,
|
||||
);
|
||||
render(html`<ak-empty-state default-label></ak-empty-state>`);
|
||||
|
||||
const empty = await $("ak-empty-state").$(">>>.pf-c-empty-state__icon");
|
||||
await expect(empty).toExist();
|
||||
@ -33,25 +29,17 @@ describe("ak-empty-state", () => {
|
||||
});
|
||||
|
||||
it("should handle standard boolean", async () => {
|
||||
render(
|
||||
html`<ak-empty-state loading
|
||||
><span slot="header">${msg("Loading")}</span>
|
||||
</ak-empty-state>`,
|
||||
);
|
||||
render(html`<ak-empty-state loading>Waiting</ak-empty-state>`);
|
||||
|
||||
const empty = await $("ak-empty-state").$(">>>.pf-c-empty-state__icon");
|
||||
await expect(empty).toExist();
|
||||
|
||||
const header = await $("ak-empty-state").$(">>>.pf-c-title");
|
||||
await expect(header).toHaveText("Loading");
|
||||
await expect(header).toHaveText("Waiting");
|
||||
});
|
||||
|
||||
it("should render a static empty state", async () => {
|
||||
render(
|
||||
html`<ak-empty-state
|
||||
><span slot="header">${msg("No messages found")}</span>
|
||||
</ak-empty-state>`,
|
||||
);
|
||||
render(html`<ak-empty-state><span>${msg("No messages found")}</span> </ak-empty-state>`);
|
||||
|
||||
const empty = await $("ak-empty-state").$(">>>.pf-c-empty-state__icon");
|
||||
await expect(empty).toExist();
|
||||
@ -64,7 +52,7 @@ describe("ak-empty-state", () => {
|
||||
it("should render a slotted message", async () => {
|
||||
render(
|
||||
html`<ak-empty-state
|
||||
><span slot="header">${msg("No messages found")}</span>
|
||||
><span>${msg("No messages found")}</span>
|
||||
<p slot="body">Try again with a different filter</p>
|
||||
</ak-empty-state>`,
|
||||
);
|
||||
|
||||
@ -115,9 +115,9 @@ export class UserSourceSettingsPage extends AKElement {
|
||||
${this.sourceSettings
|
||||
? html`
|
||||
${this.sourceSettings.length < 1
|
||||
? html`<ak-empty-state
|
||||
header=${msg("No services available.")}
|
||||
></ak-empty-state>`
|
||||
? html`<ak-empty-state>
|
||||
<span>${msg("No services available.")}</span></ak-empty-state
|
||||
>`
|
||||
: html`
|
||||
${this.sourceSettings.map((source) => {
|
||||
return html`<li class="pf-c-data-list__item">
|
||||
@ -139,7 +139,7 @@ export class UserSourceSettingsPage extends AKElement {
|
||||
})}
|
||||
`}
|
||||
`
|
||||
: html`<ak-empty-state loading header=${msg("Loading")}> </ak-empty-state>`}
|
||||
: html`<ak-empty-state default-label></ak-empty-state>`}
|
||||
</ul>`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,7 +304,7 @@ export class FlowExecutor
|
||||
|
||||
async renderChallenge(): Promise<TemplateResult> {
|
||||
if (!this.challenge) {
|
||||
return html`<ak-empty-state loading> </ak-empty-state>`;
|
||||
return html`<ak-empty-state loading default-label> </ak-empty-state>`;
|
||||
}
|
||||
switch (this.challenge?.component) {
|
||||
case "ak-stage-access-denied":
|
||||
|
||||
@ -24,7 +24,7 @@ export class SessionEnd extends BaseStage<SessionEndChallenge, unknown> {
|
||||
|
||||
render(): TemplateResult {
|
||||
if (!this.challenge) {
|
||||
return html`<ak-empty-state loading header=${msg("Loading")}> </ak-empty-state>`;
|
||||
return html`<ak-empty-state default-label></ak-empty-state>`;
|
||||
}
|
||||
return html`<header class="pf-c-login__main-header">
|
||||
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>
|
||||
|
||||
@ -17,10 +17,8 @@ export class DeviceCodeFinish extends BaseStage<
|
||||
if (!this.challenge) {
|
||||
return html`<ak-empty-state loading> </ak-empty-state>`;
|
||||
}
|
||||
return html`<ak-empty-state
|
||||
icon="fas fa-check"
|
||||
header=${msg("You may close this page now.")}
|
||||
>
|
||||
return html`<ak-empty-state icon="fas fa-check">
|
||||
<span>${msg("You may close this page now.")}</span>
|
||||
<span slot="body"> ${msg("You've successfully authenticated your device.")} </span>
|
||||
</ak-empty-state>`;
|
||||
}
|
||||
|
||||
@ -69,7 +69,8 @@ export class PlexLoginInit extends BaseStage<
|
||||
</header>
|
||||
<div class="pf-c-login__main-body">
|
||||
<form class="pf-c-form">
|
||||
<ak-empty-state loading header=${msg("Waiting for authentication...")}>
|
||||
<ak-empty-state loading
|
||||
><span>${msg("Waiting for authentication...")}></span>
|
||||
</ak-empty-state>
|
||||
<hr class="pf-c-divider" />
|
||||
<p>${msg("If no Plex popup opens, click the button below.")}</p>
|
||||
|
||||
@ -45,12 +45,12 @@ export class FlowErrorStage extends BaseStage<FlowErrorChallenge, FlowChallengeR
|
||||
</header>
|
||||
<div class="pf-c-login__main-body">
|
||||
<form class="pf-c-form">
|
||||
<ak-empty-state
|
||||
icon="fa-times"
|
||||
header=${this.challenge.error
|
||||
? this.challenge.error
|
||||
: msg("Something went wrong! Please try again later.")}
|
||||
>
|
||||
<ak-empty-state icon="fa-times"
|
||||
><span>
|
||||
${this.challenge.error
|
||||
? this.challenge.error
|
||||
: msg("Something went wrong! Please try again later.")}</span
|
||||
>
|
||||
<div slot="body">
|
||||
${this.challenge?.traceback
|
||||
? html`<div class="pf-c-form__group">
|
||||
|
||||
@ -28,10 +28,10 @@ export class FlowFrameStage extends BaseStage<FrameChallenge, FrameChallengeResp
|
||||
</header>
|
||||
<div class="pf-c-login__main-body">
|
||||
${this.challenge.loadingOverlay
|
||||
? html`<ak-empty-state
|
||||
loading
|
||||
header=${this.challenge.loadingText ?? undefined}
|
||||
>
|
||||
? html`<ak-empty-state loading
|
||||
>${this.challenge.loadingText
|
||||
? html`<span>${this.challenge.loadingText}}</span>`
|
||||
: nothing}
|
||||
</ak-empty-state>`
|
||||
: nothing}
|
||||
<iframe
|
||||
|
||||
@ -69,13 +69,11 @@ export class RedirectStage extends BaseStage<RedirectChallenge, FlowChallengeRes
|
||||
// As this wouldn't really be a redirect, show a message that the page can be closed
|
||||
// and try to close it ourselves
|
||||
if (!url.protocol.startsWith("http")) {
|
||||
return html`<ak-empty-state
|
||||
icon="fas fa-check"
|
||||
header=${msg("You may close this page now.")}
|
||||
>
|
||||
return html`<ak-empty-state icon="fas fa-check"
|
||||
><span>${msg("You may close this page now.")}</span>
|
||||
</ak-empty-state>`;
|
||||
}
|
||||
return html`<ak-empty-state loading header=${msg("Loading")}> </ak-empty-state>`;
|
||||
return html`<ak-empty-state default-label></ak-empty-state>`;
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
|
||||
@ -44,7 +44,8 @@ export class AccessDeniedStage extends BaseStage<
|
||||
>
|
||||
</div>
|
||||
</ak-form-static>
|
||||
<ak-empty-state icon="fa-times" header=${msg("Request has been denied.")}>
|
||||
<ak-empty-state icon="fa-times"
|
||||
><span>${msg("Request has been denied.")}</span>
|
||||
${this.challenge.errorMessage
|
||||
? html`
|
||||
<div slot="body">
|
||||
|
||||
@ -59,13 +59,12 @@ export class AuthenticatorValidateStageWebDuo extends BaseDeviceStage<
|
||||
}}
|
||||
>
|
||||
${this.renderUserInfo()}
|
||||
<ak-empty-state
|
||||
?loading="${this.authenticating}"
|
||||
header=${this.authenticating
|
||||
? msg("Sending Duo push notification...")
|
||||
: errorMessage.join(", ") || msg("Failed to authenticate")}
|
||||
icon="fas fa-times"
|
||||
>
|
||||
<ak-empty-state ?loading="${this.authenticating}" icon="fas fa-times"
|
||||
><span
|
||||
>${this.authenticating
|
||||
? msg("Sending Duo push notification...")
|
||||
: errorMessage.join(", ") || msg("Failed to authenticate")}</span
|
||||
>
|
||||
</ak-empty-state>
|
||||
<div class="pf-c-form__group pf-m-action">${this.renderReturnToDevicePicker()}</div>
|
||||
</form>
|
||||
|
||||
@ -106,13 +106,12 @@ export class AuthenticatorValidateStageWebAuthn extends BaseDeviceStage<
|
||||
return html`<div class="pf-c-login__main-body">
|
||||
<form class="pf-c-form">
|
||||
${this.renderUserInfo()}
|
||||
<ak-empty-state
|
||||
?loading="${this.authenticating}"
|
||||
header=${this.authenticating
|
||||
? msg("Authenticating...")
|
||||
: this.errorMessage || msg("Loading")}
|
||||
icon="fa-times"
|
||||
>
|
||||
<ak-empty-state ?loading="${this.authenticating}" icon="fa-times">
|
||||
<span
|
||||
>${this.authenticating
|
||||
? msg("Authenticating...")
|
||||
: this.errorMessage || msg("Loading")}</span
|
||||
>
|
||||
</ak-empty-state>
|
||||
<div class="pf-c-form__group pf-m-action">
|
||||
${!this.authenticating
|
||||
|
||||
@ -145,13 +145,12 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage<
|
||||
>
|
||||
</div>
|
||||
</ak-form-static>
|
||||
<ak-empty-state
|
||||
?loading="${this.registerRunning}"
|
||||
header=${this.registerRunning
|
||||
? msg("Registering...")
|
||||
: this.registerMessage || msg("Failed to register")}
|
||||
icon="fa-times"
|
||||
>
|
||||
<ak-empty-state ?loading="${this.registerRunning}" icon="fa-times">
|
||||
<span
|
||||
>${this.registerRunning
|
||||
? msg("Registering...")
|
||||
: this.registerMessage || msg("Failed to register")}
|
||||
</span>
|
||||
</ak-empty-state>
|
||||
${this.challenge?.responseErrors
|
||||
? html`<p class="pf-m-block">
|
||||
|
||||
@ -327,9 +327,9 @@ export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeRe
|
||||
// [hasError, isInteractive]
|
||||
// prettier-ignore
|
||||
return match([Boolean(this.error), Boolean(this.challenge?.interactive)])
|
||||
.with([true, P.any], () => akEmptyState({ icon: "fa-times", header: this.error }))
|
||||
.with([true, P.any], () => akEmptyState({ icon: "fa-times" }, { heading: this.error }))
|
||||
.with([false, true], () => html`${this.captchaFrame}`)
|
||||
.with([false, false], () => akEmptyState({ loading: true, header: msg("Verifying...") }))
|
||||
.with([false, false], () => akEmptyState({ loading: true }, { heading: msg("Verifying...") }))
|
||||
.exhaustive();
|
||||
}
|
||||
|
||||
|
||||
@ -356,8 +356,8 @@ export class RacInterface extends WithBrandConfig(Interface) {
|
||||
GuacClientState.WAITING,
|
||||
].includes(this.clientState);
|
||||
return html`
|
||||
<ak-loading-overlay ?loading=${isLoading} icon="fa fa-times">
|
||||
<span> ${message} </span>
|
||||
<ak-loading-overlay ?no-spinner=${!isLoading} icon="fa fa-times">
|
||||
<span>${message}</span>
|
||||
</ak-loading-overlay>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -32,11 +32,12 @@ export class Loading extends AKElement {
|
||||
}
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.dataset.akInterfaceRoot = this.tagName.toLowerCase();
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html` <section
|
||||
return html`<section
|
||||
class="ak-static-page pf-c-page__main-section pf-m-no-padding-mobile pf-m-xl"
|
||||
>
|
||||
<div class="pf-c-empty-state" style="height: 100vh;">
|
||||
|
||||
@ -105,7 +105,7 @@ export class LibraryPage extends AKElement {
|
||||
}
|
||||
|
||||
loading() {
|
||||
return html`<ak-empty-state loading header=${msg("Loading")}> </ak-empty-state>`;
|
||||
return html`<ak-empty-state default-label></ak-empty-state>`;
|
||||
}
|
||||
|
||||
running() {
|
||||
|
||||
@ -172,7 +172,7 @@ export class UserSettingsFlowExecutor
|
||||
level: MessageLevel.success,
|
||||
message: msg("Successfully updated details"),
|
||||
});
|
||||
return html`<ak-empty-state loading header=${msg("Loading")}> </ak-empty-state>`;
|
||||
return html`<ak-empty-state default-label></ak-empty-state>`;
|
||||
default:
|
||||
console.debug(
|
||||
`authentik/user/flows: unsupported stage type ${this.challenge.component}`,
|
||||
@ -193,7 +193,7 @@ export class UserSettingsFlowExecutor
|
||||
return html`<p>${msg("No settings flow configured.")}</p> `;
|
||||
}
|
||||
if (!this.challenge || this.loading) {
|
||||
return html`<ak-empty-state loading header=${msg("Loading")}> </ak-empty-state>`;
|
||||
return html`<ak-empty-state default-label></ak-empty-state>`;
|
||||
}
|
||||
return html` ${this.renderChallenge()} `;
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ export class UserSettingsPromptStage extends PromptStage {
|
||||
|
||||
render(): TemplateResult {
|
||||
if (!this.challenge) {
|
||||
return html`<ak-empty-state loading header=${msg("Loading")}> </ak-empty-state>`;
|
||||
return html`<ak-empty-state default-label></ak-empty-state>`;
|
||||
}
|
||||
return html`<div class="pf-c-login__main-body">
|
||||
<form
|
||||
|
||||
@ -13,7 +13,7 @@ import "@goauthentik/user/user-settings/mfa/MFADeviceForm";
|
||||
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
||||
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { TemplateResult, html, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
@ -130,8 +130,14 @@ export class MFADevicesPage extends Table<Device> {
|
||||
row(item: Device): TemplateResult[] {
|
||||
return [
|
||||
html`${item.name}`,
|
||||
html`${deviceTypeName(item)}
|
||||
${item.extraDescription ? ` - ${item.extraDescription}` : ""}`,
|
||||
html`<div>${deviceTypeName(item)}</div>
|
||||
${item.extraDescription
|
||||
? html`
|
||||
<pf-tooltip position="top" content=${item.externalId || ""}>
|
||||
<small>${item.extraDescription}</small>
|
||||
</pf-tooltip>
|
||||
`
|
||||
: nothing} `,
|
||||
html`${item.created.getTime() > 0
|
||||
? html`<div>${formatElapsedTime(item.created)}</div>
|
||||
<small>${item.created.toLocaleString()}</small>`
|
||||
|
||||
@ -8751,9 +8751,6 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s05849efeac672dc7">
|
||||
<source>No app entitlements created.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
</trans-unit>
|
||||
@ -9256,6 +9253,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@ -7263,9 +7263,6 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s05849efeac672dc7">
|
||||
<source>No app entitlements created.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
</trans-unit>
|
||||
@ -7766,6 +7763,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@ -8814,9 +8814,6 @@ Las vinculaciones a grupos o usuarios se comparan con el usuario del evento.</ta
|
||||
<trans-unit id="s05849efeac672dc7">
|
||||
<source>No app entitlements created.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
</trans-unit>
|
||||
@ -9317,6 +9314,9 @@ Las vinculaciones a grupos o usuarios se comparan con el usuario del evento.</ta
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@ -9231,10 +9231,6 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
|
||||
<source>No app entitlements created.</source>
|
||||
<target>Aucun droit applicatif créé.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
<target>Cette application n'a actuellement pas de droit applicatif défini.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
<target>Créer un droit</target>
|
||||
@ -9885,6 +9881,9 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@ -8966,6 +8966,7 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s66f572bec2bde9c4">
|
||||
<source>External applications that use <x id="0" equiv-text="${this.brandingTitle}"/> as an identity provider via protocols like OAuth2 and SAML. All applications are shown here, even ones you cannot access.</source>
|
||||
<target>Applicazioni esterne che utilizzano <x id="0" equiv-text="${this.brandingTitle}"/> come fornitore di identità tramite protocolli come OAuth2 e SAML. Qui sono mostrate tutte le applicazioni, anche quelle a cui non è possibile accedere..</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s58bec0ecd4f3ccd4">
|
||||
<source>Strict</source>
|
||||
@ -9231,10 +9232,6 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<source>No app entitlements created.</source>
|
||||
<target>Non sono stati creati entitlements per l'app.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
<target>Al momento, per questa applicazione non è definito alcun entitlement applicativo.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
<target>Crea Privilegio</target>
|
||||
@ -9763,111 +9760,150 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa30ba280de276758">
|
||||
<source>When enabled, the SAML response will be signed.</source>
|
||||
<target>Se abilitata, la risposta SAML verrà firmata.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2c42bb3c6f5420d2">
|
||||
<source>Client Certificates</source>
|
||||
<target>Certificati client</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s95901716c0629274">
|
||||
<source>Available Certificates</source>
|
||||
<target>Certificati disponibili</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdbf6b484fa1436b0">
|
||||
<source>Selected Certificates</source>
|
||||
<target>Certificati selezionati</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9300147e327fd8f6">
|
||||
<source>Client-certificate/mTLS authentication/enrollment.</source>
|
||||
<target>Autenticazione/registrazione tramite certificato client/mTLS.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sbf990ec848470f5c">
|
||||
<source>Certificate optional</source>
|
||||
<target>Certificato facoltativo</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s72e2876e9409b9eb">
|
||||
<source>If no certificate was provided, this stage will succeed and continue to the next stage.</source>
|
||||
<target>Se non è stato fornito alcun certificato, questa fase avrà esito positivo e si passerà alla fase successiva.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="se07d973901a6e6b9">
|
||||
<source>Certificate required</source>
|
||||
<target>Certificato richiesto</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s664c47df020ee414">
|
||||
<source>If no certificate was provided, this stage will stop flow execution.</source>
|
||||
<target>Se non è stato fornito alcun certificato, questa fase interromperà l'esecuzione del flusso.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sbe9da6dad795aa39">
|
||||
<source>Certificate authorities</source>
|
||||
<target>Autorità di certificazione</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="se3a6aa4f0ab7568e">
|
||||
<source>Configure the certificate authority client certificates are validated against. The certificate authority can also be configured on a brand, which allows for different certificate authorities for different domains.</source>
|
||||
<target>Configurare l'autorità di certificazione con cui vengono convalidati i certificati client. L'autorità di certificazione può anche essere configurata per un marchio, consentendo di utilizzare autorità di certificazione diverse per domini diversi.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sb8fdf5a09a969870">
|
||||
<source>Certificate attribute</source>
|
||||
<target>Attributo del certificato</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8069037a865037c9">
|
||||
<source>Configure the attribute of the certificate used to look for a user.</source>
|
||||
<target>Configura l'attributo del certificato utilizzato per cercare un utente.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sc185a8ad96f8eaa2">
|
||||
<source>User attribute</source>
|
||||
<target>Attributo utente</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4f9860fefb8fbe01">
|
||||
<source>Configure the attribute of the user used to look for a user.</source>
|
||||
<target>Configura l'attributo dell'utente utilizzato per cercare un utente.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s42b57339ad2f3ac7">
|
||||
<source>Delete Not Found Objects</source>
|
||||
<target>Elimina oggetti non trovati</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="se3b26b762110bda0">
|
||||
<source>Delete authentik users and groups which were previously supplied by this source, but are now missing from it.</source>
|
||||
<target>Elimina gli utenti e i gruppi authentik precedentemente forniti da questa fonte, ma che ora mancano.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s0a2cb398b54a6207">
|
||||
<source>Welcome.</source>
|
||||
<target>Benvenuto.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4e1d2cb86cf5ecd0">
|
||||
<source>Field which contains members of a group. The value of this field is matched against User membership attribute.</source>
|
||||
<target>Campo che contiene i membri di un gruppo. Il valore di questo campo viene confrontato con l'attributo di appartenenza dell'utente.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s6478025f3e0174fa">
|
||||
<source>User membership attribute</source>
|
||||
<target>Attributo di appartenenza dell'utente</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s344be99cf5d36407">
|
||||
<source>Attribute which matches the value of Group membership field.</source>
|
||||
<target>Attributo che corrisponde al valore del campo di appartenenza al gruppo.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sfa6b7b105640e457">
|
||||
<source>Additional User DN</source>
|
||||
<target>DN utente aggiuntivo</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s04bb32ec9f359507">
|
||||
<source>Additional Group DN</source>
|
||||
<target>DN di gruppo aggiuntivo</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sb7af25ce6e30d61a">
|
||||
<source>The currently selected policy engine mode is <x id="0" equiv-text="${policyEngineMode.label}"/>:</source>
|
||||
<target>La modalità del motore di policy attualmente selezionata è <x id="0" equiv-text="${policyEngineMode.label}"/>:</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="se1d2545eda4b1600">
|
||||
<source>Import Existing Certificate-Key Pair</source>
|
||||
<target>Importa coppia certificato-chiave esistente</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sb3d5c0a0501669df">
|
||||
<source>Generate New Certificate-Key Pair</source>
|
||||
<target>Genera nuova coppia certificato-chiave</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf9686d31d28fcf7d">
|
||||
<source>Show field content</source>
|
||||
<target>Mostra il contenuto del campo</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sb1b05a7573ab618c">
|
||||
<source>Hide field content</source>
|
||||
<target>Nascondi il contenuto del campo</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4f820625804ed29b">
|
||||
<source>Re-authenticate with Plex</source>
|
||||
<target>Riautenticare con Plex</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s0433d667ea6eec1a">
|
||||
<source>The name of an invitation must be a slug: only lower case letters, numbers, and the hyphen are permitted here.</source>
|
||||
<target>Il nome di un invito deve essere uno slug: sono consentiti solo lettere minuscole, numeri e trattini.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2e9d5ea88f02ae68">
|
||||
<source>Select the group of users which the alerts are sent to. </source>
|
||||
<target>Selezionare il gruppo di utenti a cui inviare gli avvisi.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="se630f2ccd39bf9e6">
|
||||
<source>If no group is selected and 'Send notification to event user' is disabled the rule is disabled. </source>
|
||||
<target>Se non viene selezionato alcun gruppo e l'opzione "Invia notifica all'utente dell'evento" è disabilitata, la regola è disabilitata.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s47966b2a708694e2">
|
||||
<source>Send notification to event user</source>
|
||||
<target>Invia notifica all'utente dell'evento</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd30f00ff2135589c">
|
||||
<source>When enabled, notification will be sent to the user that triggered the event in addition to any users in the group above. The event user will always be the first user, to send a notification only to the event user enabled 'Send once' in the notification transport.</source>
|
||||
<target>Se abilitata, la notifica verrà inviata all'utente che ha attivato l'evento, oltre a tutti gli utenti del gruppo sopra indicato. L'utente dell'evento sarà sempre il primo a inviare una notifica solo all'utente dell'evento che ha abilitato "Invia una volta" nel trasporto delle notifiche.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sbd65aeeb8a3b9bbc">
|
||||
<source>Maximum registration attempts</source>
|
||||
<target>Numero massimo di tentativi di registrazione</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
<target>Numero massimo di tentativi di registrazione consentiti. Se impostato su 0 tentativi, i tentativi non sono limitati.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@ -8721,9 +8721,6 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s05849efeac672dc7">
|
||||
<source>No app entitlements created.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
</trans-unit>
|
||||
@ -9224,6 +9221,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@ -8625,9 +8625,6 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
|
||||
<trans-unit id="s05849efeac672dc7">
|
||||
<source>No app entitlements created.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
</trans-unit>
|
||||
@ -9128,6 +9125,9 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@ -9048,9 +9048,6 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
|
||||
<trans-unit id="s05849efeac672dc7">
|
||||
<source>No app entitlements created.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
</trans-unit>
|
||||
@ -9551,6 +9548,9 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@ -9056,9 +9056,6 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s05849efeac672dc7">
|
||||
<source>No app entitlements created.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
</trans-unit>
|
||||
@ -9560,4 +9557,7 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body></file></xliff>
|
||||
|
||||
@ -9113,9 +9113,6 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s05849efeac672dc7">
|
||||
<source>No app entitlements created.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
</trans-unit>
|
||||
@ -9643,6 +9640,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@ -9112,9 +9112,6 @@ Gruplara/kullanıcılara yapılan bağlamalar, etkinliğin kullanıcısına kar
|
||||
<trans-unit id="s05849efeac672dc7">
|
||||
<source>No app entitlements created.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
</trans-unit>
|
||||
@ -9615,6 +9612,9 @@ Gruplara/kullanıcılara yapılan bağlamalar, etkinliğin kullanıcısına kar
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@ -5879,9 +5879,6 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s05849efeac672dc7">
|
||||
<source>No app entitlements created.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
</trans-unit>
|
||||
@ -6383,6 +6380,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
||||
@ -9232,10 +9232,6 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<source>No app entitlements created.</source>
|
||||
<target>未创建应用程序授权。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
<target>此应用程序目前没有定义任何应用程序授权。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
<target>创建授权</target>
|
||||
@ -9898,6 +9894,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@ -6964,9 +6964,6 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s05849efeac672dc7">
|
||||
<source>No app entitlements created.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
</trans-unit>
|
||||
@ -7467,6 +7464,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@ -8700,9 +8700,6 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s05849efeac672dc7">
|
||||
<source>No app entitlements created.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc8a8f29af6aa411">
|
||||
<source>This application does currently not have any application entitlement defined.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf0bd204ce3fea1de">
|
||||
<source>Create Entitlement</source>
|
||||
</trans-unit>
|
||||
@ -9203,6 +9200,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8495753cb15e8d8e">
|
||||
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sab4db6a3bd6abc1e">
|
||||
<source>This application does currently not have any application entitlements defined.</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
Reference in New Issue
Block a user