mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
chore: deps update (#11968)
# Which Problems Are Solved This pr updates major and minor dependencies and is the first step on getting our dependabot alerts cut down. # How the Problems Are Solved Depedency updates across the board eg: - Upgrade Angular to v21 - Upgrade next.js to v16.2 - Upgrade tailwind to v4 in the login - Upgrade vitest to v4 in the login This is an uncompleted list refer to the changed files for a full overview of all the updates. # Additional Changes Migrated all control flow in the console to the modern control flow syntax. Fixed the dependsOn setting for the @zitadel/login:test-unit nx target. # Additional Context - Closes https://github.com/zitadel/zitadel/issues/11274 --------- Co-authored-by: Max Peintner <[email protected]>
This commit is contained in:
+15
-15
@@ -25,9 +25,9 @@
|
||||
"@headlessui/react": "^2.2.9",
|
||||
"@heroicons/react": "2.2.0",
|
||||
"@inkeep/cxkit-react": "^0.5.115",
|
||||
"@scalar/api-reference": "^1.44.23",
|
||||
"@shikijs/rehype": "^3.22.0",
|
||||
"@shikijs/types": "^3.22.0",
|
||||
"@scalar/api-reference": "^1.49.8",
|
||||
"@shikijs/rehype": "^3.23.0",
|
||||
"@shikijs/types": "^3.23.0",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"clsx": "2.1.1",
|
||||
"fumadocs-core": "16.6.15",
|
||||
@@ -36,41 +36,41 @@
|
||||
"fumadocs-ui": "16.6.15",
|
||||
"js-yaml": "^4.1.1",
|
||||
"lucide-react": "^0.574.0",
|
||||
"mixpanel-browser": "^2.74.0",
|
||||
"mixpanel-browser": "^2.77.0",
|
||||
"next": "16.1.6",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "^19.2.4",
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
"react-copy-to-clipboard": "^5.1.1",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-google-charts": "^5.2.1",
|
||||
"shiki": "^3.22.0",
|
||||
"shiki": "^3.23.0",
|
||||
"tailwind-merge": "^3.5.0",
|
||||
"vanilla-cookieconsent": "3.1.0",
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@tailwindcss/postcss": "^4.1.18",
|
||||
"@tailwindcss/postcss": "^4.2.2",
|
||||
"@tailwindcss/typography": "^0.5.19",
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "^25.2.3",
|
||||
"@types/node": "^25.5.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^8.57.0",
|
||||
"@typescript-eslint/parser": "^8.57.0",
|
||||
"eslint": "^10.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.58.0",
|
||||
"@typescript-eslint/parser": "^8.58.0",
|
||||
"eslint": "^10.1.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-mdx": "^3.7.0",
|
||||
"glob": "^13.0.5",
|
||||
"globals": "^17.3.0",
|
||||
"glob": "^13.0.6",
|
||||
"globals": "^17.4.0",
|
||||
"next-validate-link": "^1.6.4",
|
||||
"postcss": "^8.5.6",
|
||||
"postcss": "^8.5.8",
|
||||
"raw-loader": "^4.0.2",
|
||||
"remark-heading-id": "^1.0.1",
|
||||
"semver": "^7.7.4",
|
||||
"tailwindcss": "^4.1.18",
|
||||
"tailwindcss": "^4.2.2",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "^5.9.3",
|
||||
|
||||
Vendored
+1
-1
@@ -87,7 +87,7 @@ declare namespace NodeJS {
|
||||
/**
|
||||
* Optional: JSON string to configure the cache TTLs (in minutes) for specific backend API routes or global fallbacks.
|
||||
* Example: '{"defaultMinutes": 15, "longMinutes": 60, "getBrandingSettings": 120}'
|
||||
*
|
||||
*
|
||||
* Properties:
|
||||
* - \`defaultMinutes\`: The globally utilized default TTL in minutes (falls back to 15 if not set).
|
||||
* - \`longMinutes\`: The TTL utilized string for long-cached routes, like branding/translation (falls back to 60 if not set).
|
||||
|
||||
+45
-45
@@ -23,93 +23,93 @@
|
||||
"*": "prettier --write --ignore-unknown"
|
||||
},
|
||||
"dependencies": {
|
||||
"@connectrpc/connect": "^2.1.1",
|
||||
"@connectrpc/connect-node": "^2.1.1",
|
||||
"@headlessui/react": "^2.2.9",
|
||||
"@heroicons/react": "^2.2.0",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@opentelemetry/api-logs": "^0.211.0",
|
||||
"@opentelemetry/auto-instrumentations-node": "^0.69.0",
|
||||
"@opentelemetry/resource-detector-container": "^0.8.2",
|
||||
"@opentelemetry/resource-detector-gcp": "^0.46.0",
|
||||
"@opentelemetry/resources": "^2.5.0",
|
||||
"@opentelemetry/sdk-node": "^0.211.0",
|
||||
"@opentelemetry/winston-transport": "^0.21.0",
|
||||
"@opentelemetry/api": "^1.9.1",
|
||||
"@opentelemetry/api-logs": "^0.214.0",
|
||||
"@opentelemetry/auto-instrumentations-node": "^0.72.0",
|
||||
"@opentelemetry/resource-detector-container": "^0.8.5",
|
||||
"@opentelemetry/resource-detector-gcp": "^0.49.0",
|
||||
"@opentelemetry/resources": "^2.6.1",
|
||||
"@opentelemetry/sdk-node": "^0.214.0",
|
||||
"@opentelemetry/winston-transport": "^0.24.0",
|
||||
"@radix-ui/react-tooltip": "^1.2.8",
|
||||
"@tailwindcss/forms": "^0.5.11",
|
||||
"clsx": "^2.1.1",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"deepmerge": "^4.3.1",
|
||||
"escape-html": "^1.0.3",
|
||||
"lucide-react": "^0.562.0",
|
||||
"lucide-react": "^0.577.0",
|
||||
"moment": "^2.30.1",
|
||||
"next": "16.1.6",
|
||||
"next-intl": "^4.8.3",
|
||||
"next-themes": "^0.2.1",
|
||||
"next": "16.2.2",
|
||||
"next-intl": "^4.8.4",
|
||||
"next-themes": "^0.4.6",
|
||||
"nice-grpc": "^2.1.14",
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4",
|
||||
"react-hook-form": "^7.71.1",
|
||||
"react-hook-form": "^7.72.0",
|
||||
"server-only": "^0.0.1",
|
||||
"tinycolor2": "^1.6.0",
|
||||
"uuid": "^13.0.0",
|
||||
"@connectrpc/connect-node": "^2.1.1",
|
||||
"@connectrpc/connect": "^2.1.1",
|
||||
"winston": "^3.17.0"
|
||||
"winston": "^3.19.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^10.0.0",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@faker-js/faker": "^9.9.0",
|
||||
"@next/eslint-plugin-next": "16.1.6",
|
||||
"@opentelemetry/sdk-trace-base": "^2.5.0",
|
||||
"@opentelemetry/sdk-trace-node": "^2.5.0",
|
||||
"@next/eslint-plugin-next": "16.2.2",
|
||||
"@opentelemetry/sdk-trace-base": "^2.6.1",
|
||||
"@opentelemetry/sdk-trace-node": "^2.6.1",
|
||||
"@otplib/core": "^12.0.1",
|
||||
"@otplib/plugin-crypto": "^12.0.1",
|
||||
"@otplib/plugin-thirty-two": "^12.0.1",
|
||||
"@playwright/test": "^1.58.0",
|
||||
"@playwright/test": "^1.59.0",
|
||||
"@tailwindcss/postcss": "^4.2.2",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@types/escape-html": "^1.0.4",
|
||||
"@types/node": "^22.19.7",
|
||||
"@types/node": "^25.5.0",
|
||||
"@types/node-forge": "^1.3.14",
|
||||
"@types/react": "19.2.7",
|
||||
"@types/react": "19.2.14",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"@types/tinycolor2": "^1.4.6",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.57.0",
|
||||
"@typescript-eslint/parser": "^8.57.0",
|
||||
"@vercel/git-hooks": "1.0.0",
|
||||
"@types/uuid": "^11.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.58.0",
|
||||
"@typescript-eslint/parser": "^8.58.0",
|
||||
"@vercel/git-hooks": "^1.0.0",
|
||||
"@vitejs/plugin-react": "^4.7.0",
|
||||
"@zitadel/client": "workspace:*",
|
||||
"@zitadel/proto": "workspace:*",
|
||||
"autoprefixer": "^10.4.23",
|
||||
"concurrently": "^9.2.1",
|
||||
"dotenv-cli": "^8.0.0",
|
||||
"env-cmd": "^10.1.0",
|
||||
"esbuild": "^0.27.3",
|
||||
"eslint": "^10.0.0",
|
||||
"dotenv-cli": "^11.0.0",
|
||||
"env-cmd": "^11.0.0",
|
||||
"esbuild": "^0.27.4",
|
||||
"eslint": "^10.1.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
"eslint-plugin-cypress": "^4.2.0",
|
||||
"eslint-plugin-cypress": "^4.3.0",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"gaxios": "^7.1.3",
|
||||
"globals": "^17.0.0",
|
||||
"gaxios": "^7.1.4",
|
||||
"globals": "^17.4.0",
|
||||
"grpc-tools": "^1.13.1",
|
||||
"jsdom": "^26.1.0",
|
||||
"lint-staged": "15.5.1",
|
||||
"node-forge": "^1.3.3",
|
||||
"nodemon": "^3.1.11",
|
||||
"postcss": "^8.5.6",
|
||||
"lint-staged": "^16.4.0",
|
||||
"node-forge": "^1.4.0",
|
||||
"nodemon": "^3.1.14",
|
||||
"postcss": "^8.5.8",
|
||||
"prettier": "^3.8.1",
|
||||
"prettier-plugin-organize-imports": "^4.3.0",
|
||||
"prettier-plugin-tailwindcss": "^0.7.2",
|
||||
"sass": "^1.97.3",
|
||||
"start-server-and-test": "^2.1.3",
|
||||
"tailwindcss": "3.4.14",
|
||||
"testcontainers": "^11.11.0",
|
||||
"ts-proto": "^2.11.1",
|
||||
"sass": "^1.98.0",
|
||||
"start-server-and-test": "^3.0.0",
|
||||
"tailwindcss": "^4.2.2",
|
||||
"testcontainers": "^11.13.0",
|
||||
"ts-proto": "^2.11.6",
|
||||
"typescript": "^5.9.3",
|
||||
"vite-tsconfig-paths": "^5.1.4",
|
||||
"vitest": "^2.1.9"
|
||||
"vitest": "^4.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
"@tailwindcss/postcss": {},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
},
|
||||
"build-vercel": {
|
||||
"description": "Builds the Next.js Login application for Vercel deployment",
|
||||
"cache": true,
|
||||
"cache": false,
|
||||
"dependsOn": ["^build"],
|
||||
"inputs": [
|
||||
"default",
|
||||
@@ -54,7 +54,7 @@
|
||||
"!{projectRoot}/acceptance/**/*",
|
||||
"!{projectRoot}/dockerized/**/*"
|
||||
],
|
||||
"outputs": ["{projectRoot}/.next", "!{projectRoot}/.next/cache", "!{projectRoot}/.next/standalone"]
|
||||
"outputs": ["{projectRoot}/.next/!(cache|standalone)/**"]
|
||||
},
|
||||
"lint": {
|
||||
"description": "Runs all linters",
|
||||
@@ -77,7 +77,7 @@
|
||||
},
|
||||
"test-unit": {
|
||||
"description": "Runs unit tests using Vitest",
|
||||
"dependsOn": ["^build"]
|
||||
"dependsOn": ["build"]
|
||||
},
|
||||
"test-dockerized": {
|
||||
"description": "Runs dockerized integration tests (OpenTelemetry and custom CA certificate tests)",
|
||||
|
||||
@@ -50,7 +50,7 @@ export default async function Page(props: { searchParams: Promise<Record<string
|
||||
|
||||
{postErrorRedirectUrl && (
|
||||
<Link href={postErrorRedirectUrl}>
|
||||
<Button className="w-full rounded-md bg-primary-light-500 px-4 py-3 text-center transition-all hover:bg-primary-light-400 dark:bg-primary-dark-500 dark:hover:bg-primary-dark-400">
|
||||
<Button className="bg-primary-light-500 hover:bg-primary-light-400 dark:bg-primary-dark-500 dark:hover:bg-primary-dark-400 w-full rounded-md px-4 py-3 text-center transition-all">
|
||||
<Translated i18nKey="accountNotFound.backToLogin" namespace="idp" />
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
@@ -50,7 +50,7 @@ export default async function Page(props: { searchParams: Promise<Record<string
|
||||
|
||||
{postErrorRedirectUrl && (
|
||||
<Link href={postErrorRedirectUrl}>
|
||||
<Button className="w-full rounded-md bg-primary-light-500 px-4 py-3 text-center transition-all hover:bg-primary-light-400 dark:bg-primary-dark-500 dark:hover:bg-primary-dark-400">
|
||||
<Button className="bg-primary-light-500 hover:bg-primary-light-400 dark:bg-primary-dark-500 dark:hover:bg-primary-dark-400 w-full rounded-md px-4 py-3 text-center transition-all">
|
||||
<Translated i18nKey="registrationFailed.backToLogin" namespace="idp" />
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
@@ -51,7 +51,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
|
||||
<Suspense
|
||||
fallback={
|
||||
<BackgroundWrapper
|
||||
className={`relative flex min-h-screen flex-col justify-center bg-background-light-600 dark:bg-background-dark-600`}
|
||||
className={`bg-background-light-600 dark:bg-background-dark-600 relative flex min-h-screen flex-col justify-center`}
|
||||
>
|
||||
<div className="relative mx-auto w-full max-w-[440px] py-8">
|
||||
<Skeleton>
|
||||
@@ -66,7 +66,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
|
||||
>
|
||||
<LanguageProvider>
|
||||
<BackgroundWrapper
|
||||
className={`relative flex min-h-screen flex-col justify-center bg-background-light-600 dark:bg-background-dark-600`}
|
||||
className={`bg-background-light-600 dark:bg-background-dark-600 relative flex min-h-screen flex-col justify-center`}
|
||||
>
|
||||
<div className="relative mx-auto w-full max-w-[1100px] py-8">
|
||||
<div>{children}</div>
|
||||
|
||||
@@ -71,7 +71,7 @@ export default async function Page(props: { searchParams: Promise<Record<string
|
||||
)}
|
||||
|
||||
{loginSettings?.allowExternalIdp && !!identityProviders?.length && (
|
||||
<div className="w-full pb-4 pt-6">
|
||||
<div className="w-full pt-6 pb-4">
|
||||
<SignInWithIdp
|
||||
identityProviders={identityProviders}
|
||||
requestId={requestId}
|
||||
|
||||
@@ -22,7 +22,7 @@ export function AddressBar({ domain }: Props) {
|
||||
</svg>
|
||||
</div>
|
||||
<div className="flex space-x-1 text-sm font-medium">
|
||||
<div className="max-w-[150px] overflow-hidden text-ellipsis px-2 text-gray-500">
|
||||
<div className="max-w-[150px] overflow-hidden px-2 text-ellipsis text-gray-500">
|
||||
<span className="whitespace-nowrap">{domain}</span>
|
||||
</div>
|
||||
{pathname ? (
|
||||
|
||||
@@ -26,8 +26,8 @@ export function Alert({ children, type = AlertType.ALERT }: Props) {
|
||||
[neutral]: type === AlertType.INFO,
|
||||
})}
|
||||
>
|
||||
{type === AlertType.ALERT && <ExclamationTriangleIcon className="ml-2 mr-2 h-5 w-5 flex-shrink-0" />}
|
||||
{type === AlertType.INFO && <InformationCircleIcon className="ml-2 mr-2 h-5 w-5 flex-shrink-0" />}
|
||||
{type === AlertType.ALERT && <ExclamationTriangleIcon className="mr-2 ml-2 h-5 w-5 flex-shrink-0" />}
|
||||
{type === AlertType.INFO && <InformationCircleIcon className="mr-2 ml-2 h-5 w-5 flex-shrink-0" />}
|
||||
<span className="w-full text-sm">{children}</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -26,7 +26,7 @@ export function AppAvatar({ appName, imageUrl, shadow }: AvatarProps) {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`dark:group-focus:ring-offset-blue dark:text-blue pointer-events-none flex h-[100px] w-[100px] cursor-default items-center justify-center rounded-full bg-primary-light-500 text-primary-light-contrast-500 transition-colors duration-200 hover:bg-primary-light-400 group-focus:outline-none group-focus:ring-2 group-focus:ring-primary-light-200 dark:bg-primary-dark-300 dark:text-primary-dark-contrast-300 hover:dark:bg-primary-dark-500 dark:group-focus:ring-primary-dark-400 ${
|
||||
className={`dark:group-focus:ring-offset-blue dark:text-blue bg-primary-light-500 text-primary-light-contrast-500 hover:bg-primary-light-400 group-focus:ring-primary-light-200 dark:bg-primary-dark-300 dark:text-primary-dark-contrast-300 hover:dark:bg-primary-dark-500 dark:group-focus:ring-primary-dark-400 pointer-events-none flex h-[100px] w-[100px] cursor-default items-center justify-center rounded-full transition-colors duration-200 group-focus:ring-2 group-focus:outline-none ${
|
||||
shadow ? "shadow" : ""
|
||||
}`}
|
||||
style={resolvedTheme === "light" ? avatarStyleLight : avatarStyleDark}
|
||||
@@ -36,7 +36,7 @@ export function AppAvatar({ appName, imageUrl, shadow }: AvatarProps) {
|
||||
height={48}
|
||||
width={48}
|
||||
alt="avatar"
|
||||
className="h-full w-full rounded-full border border-divider-light dark:border-divider-dark"
|
||||
className="border-divider-light dark:border-divider-dark h-full w-full rounded-full border"
|
||||
src={imageUrl}
|
||||
/>
|
||||
) : (
|
||||
|
||||
@@ -181,7 +181,7 @@ export const PASSWORD = (alreadyAdded: boolean, link: string) => {
|
||||
|
||||
function Setup() {
|
||||
return (
|
||||
<div className="absolute right-2 top-0 transform">
|
||||
<div className="absolute top-0 right-2 transform">
|
||||
<StateBadge evenPadding={true} state={BadgeState.Success}>
|
||||
<CheckIcon className="h-4 w-4" />
|
||||
</StateBadge>
|
||||
|
||||
@@ -29,11 +29,11 @@ export function AuthenticationMethodRadio({
|
||||
value={method}
|
||||
data-testid={method + "-radio"}
|
||||
className={({ focus, checked }) =>
|
||||
`${focus ? "ring-2 ring-primary-light-500 ring-opacity-60 dark:ring-white/20" : ""} ${
|
||||
`${focus ? "ring-primary-light-500 ring-opacity-60 ring-2 dark:ring-white/20" : ""} ${
|
||||
checked
|
||||
? "bg-background-light-400 ring-2 ring-primary-light-500 dark:bg-background-dark-400 dark:ring-primary-dark-500"
|
||||
? "bg-background-light-400 ring-primary-light-500 dark:bg-background-dark-400 dark:ring-primary-dark-500 ring-2"
|
||||
: "bg-background-light-400 dark:bg-background-dark-400"
|
||||
} boder-divider-light relative flex h-full flex-1 cursor-pointer rounded-lg border px-5 py-4 hover:shadow-lg focus:outline-none dark:border-divider-dark dark:hover:bg-white/10`
|
||||
} boder-divider-light dark:border-divider-dark relative flex h-full flex-1 cursor-pointer rounded-lg border px-5 py-4 hover:shadow-lg focus:outline-none dark:hover:bg-white/10`
|
||||
}
|
||||
>
|
||||
<div className="flex w-full flex-col items-center text-sm">
|
||||
|
||||
@@ -54,7 +54,7 @@ export function Avatar({ size = "base", name, loginName, imageUrl, shadow }: Ava
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`dark:group-focus:ring-offset-blue dark:text-blue pointer-events-none flex h-full w-full flex-shrink-0 cursor-default items-center justify-center bg-primary-light-500 text-primary-light-contrast-500 transition-colors duration-200 hover:bg-primary-light-400 group-focus:outline-none group-focus:ring-2 group-focus:ring-primary-light-200 dark:bg-primary-dark-300 dark:text-primary-dark-contrast-300 hover:dark:bg-primary-dark-500 dark:group-focus:ring-primary-dark-400 ${avatarRoundness} ${
|
||||
className={`dark:group-focus:ring-offset-blue dark:text-blue bg-primary-light-500 text-primary-light-contrast-500 hover:bg-primary-light-400 group-focus:ring-primary-light-200 dark:bg-primary-dark-300 dark:text-primary-dark-contrast-300 hover:dark:bg-primary-dark-500 dark:group-focus:ring-primary-dark-400 pointer-events-none flex h-full w-full flex-shrink-0 cursor-default items-center justify-center transition-colors duration-200 group-focus:ring-2 group-focus:outline-none ${avatarRoundness} ${
|
||||
shadow ? "shadow" : ""
|
||||
} ${
|
||||
size === "large"
|
||||
@@ -72,7 +72,7 @@ export function Avatar({ size = "base", name, loginName, imageUrl, shadow }: Ava
|
||||
height={48}
|
||||
width={48}
|
||||
alt="avatar"
|
||||
className={`h-full w-full border border-divider-light dark:border-divider-dark ${avatarRoundness}`}
|
||||
className={`border-divider-light dark:border-divider-dark h-full w-full border ${avatarRoundness}`}
|
||||
src={imageUrl}
|
||||
/>
|
||||
) : (
|
||||
|
||||
@@ -56,7 +56,7 @@ export const Boundary = ({
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={clsx("absolute -top-2 flex space-x-1 text-[9px] uppercase leading-4 tracking-widest", {
|
||||
className={clsx("absolute -top-2 flex space-x-1 text-[9px] leading-4 tracking-widest uppercase", {
|
||||
"left-3 lg:left-5": size === "small",
|
||||
"left-4 lg:left-9": size === "default",
|
||||
})}
|
||||
|
||||
@@ -31,7 +31,7 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Che
|
||||
disabled={disabled}
|
||||
type="checkbox"
|
||||
className={classNames(
|
||||
"form-checkbox rounded border-gray-300 text-primary-light-500 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 focus:ring-offset-0 dark:text-primary-dark-500",
|
||||
"form-checkbox text-primary-light-500 focus:ring-opacity-50 dark:text-primary-dark-500 rounded border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-offset-0",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -83,7 +83,7 @@ export function ChooseSecondFactorToSetup({
|
||||
</div>
|
||||
{!force && (
|
||||
<button
|
||||
className="text-sm transition-all hover:text-primary-light-500 dark:hover:text-primary-dark-500"
|
||||
className="hover:text-primary-light-500 dark:hover:text-primary-dark-500 text-sm transition-all"
|
||||
onClick={async () => {
|
||||
const skipResponse = await skipMFAAndContinueWithNextUrl({
|
||||
userId,
|
||||
|
||||
@@ -48,7 +48,7 @@ export function ConsentScreen({
|
||||
<div className="flex w-full flex-col items-center space-y-4 pt-4">
|
||||
<ul className="w-full list-disc space-y-2">
|
||||
{scopes?.length === 0 && (
|
||||
<span className="flex w-full flex-row items-center rounded-md border border-divider-light bg-background-light-400 px-4 py-2 text-sm transition-all dark:bg-background-dark-400">
|
||||
<span className="border-divider-light bg-background-light-400 dark:bg-background-dark-400 flex w-full flex-row items-center rounded-md border px-4 py-2 text-sm transition-all">
|
||||
<Translated i18nKey="device.scope.openid" namespace="device" />
|
||||
</span>
|
||||
)}
|
||||
@@ -62,7 +62,7 @@ export function ConsentScreen({
|
||||
return (
|
||||
<li
|
||||
key={s}
|
||||
className="flex w-full flex-row items-center rounded-md border border-divider-light bg-background-light-400 px-4 py-2 text-sm transition-all dark:bg-background-dark-400"
|
||||
className="border-divider-light bg-background-light-400 dark:bg-background-dark-400 flex w-full flex-row items-center rounded-md border px-4 py-2 text-sm transition-all"
|
||||
>
|
||||
<span>{resolvedDescription}</span>
|
||||
</li>
|
||||
|
||||
@@ -69,7 +69,7 @@ export function DynamicTheme({
|
||||
{hasLeftRightStructure && (
|
||||
<div className="flex flex-col items-start space-y-4 text-left">
|
||||
{/* Apply larger styling to the content */}
|
||||
<div className="space-y-6 [&_h1]:text-left [&_h1]:text-4xl [&_h1]:leading-tight [&_h1]:text-gray-900 [&_h1]:dark:text-white [&_h1]:lg:text-4xl [&_p]:text-left [&_p]:leading-relaxed [&_p]:text-gray-700 [&_p]:dark:text-gray-300">
|
||||
<div className="space-y-6 [&_h1]:text-left [&_h1]:text-4xl [&_h1]:leading-tight [&_h1]:text-gray-900 [&_h1]:lg:text-4xl [&_h1]:dark:text-white [&_p]:text-left [&_p]:leading-relaxed [&_p]:text-gray-700 [&_p]:dark:text-gray-300">
|
||||
{leftContent}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,7 @@ export const BaseButton = forwardRef<HTMLButtonElement, SignInWithIdentityProvid
|
||||
ref={ref}
|
||||
disabled={formStatus.pending}
|
||||
className={clsx(
|
||||
`flex flex-1 cursor-pointer flex-row items-center px-4 text-sm text-text-light-500 outline-none transition-all hover:border-black focus:border-primary-light-500 dark:text-text-dark-500 hover:dark:border-white focus:dark:border-primary-dark-500`,
|
||||
`text-text-light-500 focus:border-primary-light-500 dark:text-text-dark-500 focus:dark:border-primary-dark-500 flex flex-1 cursor-pointer flex-row items-center px-4 text-sm transition-all outline-none hover:border-black hover:dark:border-white`,
|
||||
buttonRoundness,
|
||||
idpButtonAppearance,
|
||||
`bg-background-light-400 dark:bg-background-dark-500`, // Keep background as fallback for non-glass themes
|
||||
|
||||
@@ -59,7 +59,7 @@ export const TextInput = forwardRef<HTMLInputElement, TextInputProps>(
|
||||
const actualRoundness = roundness || getDefaultInputRoundness();
|
||||
|
||||
return (
|
||||
<label className="relative flex flex-col text-12px text-input-light-label dark:text-input-dark-label">
|
||||
<label className="text-12px text-input-light-label dark:text-input-dark-label relative flex flex-col">
|
||||
<span className={`mb-1 leading-3 ${error ? "text-warn-light-500 dark:text-warn-dark-500" : ""}`}>
|
||||
{label} {required && "*"}
|
||||
</span>
|
||||
@@ -80,7 +80,7 @@ export const TextInput = forwardRef<HTMLInputElement, TextInputProps>(
|
||||
{suffix && (
|
||||
<span
|
||||
className={clsx(
|
||||
"absolute bottom-[22px] right-[3px] z-30 translate-y-1/2 transform bg-background-light-500 p-2 dark:bg-background-dark-500",
|
||||
"bg-background-light-500 dark:bg-background-dark-500 absolute right-[3px] bottom-[22px] z-30 translate-y-1/2 transform p-2",
|
||||
// Extract just the roundness part for the suffix (no padding)
|
||||
actualRoundness.split(" ")[0], // Take only the first part (rounded-full, rounded-md, etc.)
|
||||
)}
|
||||
@@ -89,7 +89,7 @@ export const TextInput = forwardRef<HTMLInputElement, TextInputProps>(
|
||||
</span>
|
||||
)}
|
||||
|
||||
<div className="leading-14.5px h-14.5px flex flex-row items-center text-12px text-warn-light-500 dark:text-warn-dark-500">
|
||||
<div className="leading-14.5px h-14.5px text-12px text-warn-light-500 dark:text-warn-dark-500 flex flex-row items-center">
|
||||
<span>{error ? error : " "}</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -45,19 +45,19 @@ export function LanguageSwitcher({ languages }: { languages: Lang[] }) {
|
||||
<Listbox value={selected} onChange={handleChange}>
|
||||
<ListboxButton
|
||||
className={clsx(
|
||||
`relative block w-full py-1.5 pl-3 pr-8 text-left text-sm/6 text-black dark:text-white ${switcherRoundness}`,
|
||||
`relative block w-full py-1.5 pr-8 pl-3 text-left text-sm/6 text-black dark:text-white ${switcherRoundness}`,
|
||||
cardAppearance,
|
||||
"focus:outline-none data-[focus]:outline-2 data-[focus]:-outline-offset-2 data-[focus]:outline-white/25",
|
||||
)}
|
||||
>
|
||||
{selected.name}
|
||||
<ChevronDownIcon className="group pointer-events-none absolute right-2.5 top-2.5 size-4" aria-hidden="true" />
|
||||
<ChevronDownIcon className="group pointer-events-none absolute top-2.5 right-2.5 size-4" aria-hidden="true" />
|
||||
</ListboxButton>
|
||||
<ListboxOptions
|
||||
anchor="bottom"
|
||||
transition
|
||||
className={clsx(
|
||||
`w-[var(--button-width)] rounded-md border border-black/5 bg-background-light-500 p-1 [--anchor-gap:var(--spacing-1)] focus:outline-none dark:border-white/5 dark:bg-background-dark-500`,
|
||||
`bg-background-light-500 dark:bg-background-dark-500 w-[var(--button-width)] rounded-md border border-black/5 p-1 [--anchor-gap:var(--spacing-1)] focus:outline-none dark:border-white/5`,
|
||||
"transition duration-100 ease-in data-[leave]:data-[closed]:opacity-0",
|
||||
)}
|
||||
>
|
||||
@@ -65,7 +65,7 @@ export function LanguageSwitcher({ languages }: { languages: Lang[] }) {
|
||||
<ListboxOption
|
||||
key={lang.code}
|
||||
value={lang}
|
||||
className={`group flex cursor-default select-none items-center gap-2 px-3 py-1.5 data-[focus]:bg-black/10 dark:data-[focus]:bg-white/10 ${switcherRoundness}`}
|
||||
className={`group flex cursor-default items-center gap-2 px-3 py-1.5 select-none data-[focus]:bg-black/10 dark:data-[focus]:bg-white/10 ${switcherRoundness}`}
|
||||
>
|
||||
<CheckIcon className="invisible size-4 group-data-[selected]:visible" />
|
||||
<div className="text-sm/6 text-black dark:text-white">{lang.name}</div>
|
||||
|
||||
@@ -95,7 +95,7 @@ export function LDAPUsernamePasswordForm({
|
||||
data-testid="username-text-input"
|
||||
/>
|
||||
|
||||
<div className={`${error && "transform-gpu animate-shake"}`}>
|
||||
<div className={`${error && "animate-shake transform-gpu"}`}>
|
||||
<TextInput
|
||||
type="password"
|
||||
autoComplete="password"
|
||||
|
||||
@@ -223,7 +223,7 @@ export function LoginOTP({ host, loginName, sessionId, requestId, organization,
|
||||
aria-label="Resend OTP Code"
|
||||
disabled={loading}
|
||||
type="button"
|
||||
className="ml-4 cursor-pointer text-primary-light-500 hover:text-primary-light-400 disabled:cursor-default disabled:text-gray-400 dark:text-primary-dark-500 hover:dark:text-primary-dark-400 dark:disabled:text-gray-700"
|
||||
className="text-primary-light-500 hover:text-primary-light-400 dark:text-primary-dark-500 hover:dark:text-primary-dark-400 ml-4 cursor-pointer disabled:cursor-default disabled:text-gray-400 dark:disabled:text-gray-700"
|
||||
onClick={async () => {
|
||||
setLoading(true);
|
||||
const response = await updateSessionForOTPChallenge();
|
||||
|
||||
@@ -29,7 +29,7 @@ function CheckIcon({ title }: { title: string }) {
|
||||
function CrossIcon({ title }: { title: string }) {
|
||||
return (
|
||||
<svg
|
||||
className="las la-times mr-2 h-6 w-6 flex-none text-lg text-warn-light-500 dark:text-warn-dark-500"
|
||||
className="las la-times text-warn-light-500 dark:text-warn-dark-500 mr-2 h-6 w-6 flex-none text-lg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
|
||||
@@ -112,7 +112,7 @@ export function PasswordForm({ loginSettings, loginName, organization, defaultOr
|
||||
<>
|
||||
{samlData && <AutoSubmitForm url={samlData.url} fields={samlData.fields} />}
|
||||
<form className="w-full">
|
||||
<div className={`${error && "transform-gpu animate-shake"}`}>
|
||||
<div className={`${error && "animate-shake transform-gpu"}`}>
|
||||
<TextInput
|
||||
type="password"
|
||||
autoComplete="password"
|
||||
@@ -123,7 +123,7 @@ export function PasswordForm({ loginSettings, loginName, organization, defaultOr
|
||||
/>
|
||||
{!loginSettings?.hidePasswordReset && (
|
||||
<button
|
||||
className="text-sm transition-all hover:text-primary-light-500 dark:hover:text-primary-dark-500"
|
||||
className="hover:text-primary-light-500 dark:hover:text-primary-dark-500 text-sm transition-all"
|
||||
onClick={() => resetPasswordAndContinue()}
|
||||
type="button"
|
||||
disabled={loading}
|
||||
|
||||
@@ -32,7 +32,7 @@ export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className="mt-4 flex flex-row items-center text-sm text-text-light-secondary-500 dark:text-text-dark-secondary-500">
|
||||
<p className="text-text-light-secondary-500 dark:text-text-dark-secondary-500 mt-4 flex flex-row items-center text-sm">
|
||||
<Translated i18nKey="agreeTo" namespace="register" />
|
||||
{legal?.helpLink && (
|
||||
<span>
|
||||
@@ -73,7 +73,7 @@ export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
|
||||
/>
|
||||
|
||||
<div className="mr-4 w-[28rem]">
|
||||
<p className="text-sm text-text-light-500 dark:text-text-dark-500">
|
||||
<p className="text-text-light-500 dark:text-text-dark-500 text-sm">
|
||||
<Link href={legal.tosLink} className="underline" target="_blank">
|
||||
<Translated i18nKey="termsOfService" namespace="register" />
|
||||
</Link>
|
||||
@@ -99,7 +99,7 @@ export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
|
||||
/>
|
||||
|
||||
<div className="mr-4 w-[28rem]">
|
||||
<p className="text-sm text-text-light-500 dark:text-text-dark-500">
|
||||
<p className="text-text-light-500 dark:text-text-dark-500 text-sm">
|
||||
<Link href={legal.privacyPolicyLink} className="underline" target="_blank">
|
||||
<Translated i18nKey="privacyPolicy" namespace="register" />
|
||||
</Link>
|
||||
|
||||
@@ -159,7 +159,7 @@ export function RegisterForm({
|
||||
{/* show chooser if both methods are allowed */}
|
||||
{loginSettings && loginSettings.allowLocalAuthentication && loginSettings.passkeysType == PasskeysType.ALLOWED && (
|
||||
<>
|
||||
<p className="ztdl-p mb-6 mt-4 block text-left">
|
||||
<p className="ztdl-p mt-4 mb-6 block text-left">
|
||||
<Translated i18nKey="selectMethod" namespace="register" />
|
||||
</p>
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ const SelfServiceItem = ({ name, link }: { name: string; link: string }) => {
|
||||
<Link
|
||||
prefetch={false}
|
||||
href={link}
|
||||
className="group flex w-full flex-row items-center rounded-md border border-divider-light bg-background-light-400 px-4 py-2 transition-all hover:shadow-lg dark:bg-background-dark-400 dark:hover:bg-white/10"
|
||||
className="group border-divider-light bg-background-light-400 dark:bg-background-dark-400 flex w-full flex-row items-center rounded-md border px-4 py-2 transition-all hover:shadow-lg dark:hover:bg-white/10"
|
||||
>
|
||||
{name}
|
||||
</Link>
|
||||
|
||||
@@ -47,7 +47,7 @@ export function SessionClearItem({ session, reload }: { session: Session; reload
|
||||
reload();
|
||||
});
|
||||
}}
|
||||
className="group flex flex-row items-center rounded-md border border-divider-light bg-background-light-400 px-4 py-2 transition-all hover:shadow-lg dark:bg-background-dark-400 dark:hover:bg-white/10"
|
||||
className="group border-divider-light bg-background-light-400 dark:bg-background-dark-400 flex flex-row items-center rounded-md border px-4 py-2 transition-all hover:shadow-lg dark:hover:bg-white/10"
|
||||
>
|
||||
<div className="pr-4">
|
||||
<Avatar
|
||||
@@ -59,9 +59,9 @@ export function SessionClearItem({ session, reload }: { session: Session; reload
|
||||
|
||||
<div className="flex flex-col items-start overflow-hidden">
|
||||
<span className="">{session.factors?.user?.displayName}</span>
|
||||
<span className="text-ellipsis text-xs opacity-80">{session.factors?.user?.loginName}</span>
|
||||
<span className="text-xs text-ellipsis opacity-80">{session.factors?.user?.loginName}</span>
|
||||
{valid ? (
|
||||
<span className="text-ellipsis text-xs opacity-80">
|
||||
<span className="text-xs text-ellipsis opacity-80">
|
||||
{verifiedAt && (
|
||||
<Translated
|
||||
i18nKey="verifiedAt"
|
||||
@@ -72,7 +72,7 @@ export function SessionClearItem({ session, reload }: { session: Session; reload
|
||||
</span>
|
||||
) : (
|
||||
verifiedAt && (
|
||||
<span className="text-ellipsis text-xs opacity-80">
|
||||
<span className="text-xs text-ellipsis opacity-80">
|
||||
expired {session.expirationDate && moment(timestampDate(session.expirationDate)).fromNow()}
|
||||
</span>
|
||||
)
|
||||
@@ -81,7 +81,7 @@ export function SessionClearItem({ session, reload }: { session: Session; reload
|
||||
|
||||
<span className="flex-grow"></span>
|
||||
<div className="relative flex flex-row items-center">
|
||||
<div className="mr-6 flex hidden items-center justify-center rounded-full bg-[#ff0000]/10 px-2 py-[2px] text-xs text-warn-light-500 transition-all group-hover:block dark:bg-[#ff0000]/10 dark:text-warn-dark-500">
|
||||
<div className="text-warn-light-500 dark:text-warn-dark-500 mr-6 flex hidden items-center justify-center rounded-full bg-[#ff0000]/10 px-2 py-[2px] text-xs transition-all group-hover:block dark:bg-[#ff0000]/10">
|
||||
<Translated i18nKey="clear" namespace="logout" />
|
||||
</div>
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ export function SessionItem({ session, reload, requestId }: { session: Session;
|
||||
}
|
||||
}
|
||||
}}
|
||||
className="group flex flex-row items-center rounded-md border border-divider-light bg-background-light-400 px-4 py-2 transition-all hover:shadow-lg dark:bg-background-dark-400 dark:hover:bg-white/10"
|
||||
className="group border-divider-light bg-background-light-400 dark:bg-background-dark-400 flex flex-row items-center rounded-md border px-4 py-2 transition-all hover:shadow-lg dark:hover:bg-white/10"
|
||||
>
|
||||
<div className="pr-4">
|
||||
<Avatar
|
||||
@@ -104,15 +104,15 @@ export function SessionItem({ session, reload, requestId }: { session: Session;
|
||||
|
||||
<div className="flex flex-col items-start overflow-hidden">
|
||||
<span className="">{session.factors?.user?.displayName}</span>
|
||||
<span className="text-ellipsis text-xs opacity-80">{session.factors?.user?.loginName}</span>
|
||||
<span className="text-xs text-ellipsis opacity-80">{session.factors?.user?.loginName}</span>
|
||||
{valid ? (
|
||||
<span className="text-ellipsis text-xs opacity-80">
|
||||
<span className="text-xs text-ellipsis opacity-80">
|
||||
<Translated i18nKey="verified" namespace="accounts" />{" "}
|
||||
{verifiedAt && moment(timestampDate(verifiedAt)).fromNow()}
|
||||
</span>
|
||||
) : (
|
||||
verifiedAt && (
|
||||
<span className="text-ellipsis text-xs opacity-80">
|
||||
<span className="text-xs text-ellipsis opacity-80">
|
||||
<Translated i18nKey="expired" namespace="accounts" />{" "}
|
||||
{session.expirationDate && moment(timestampDate(session.expirationDate)).fromNow()}
|
||||
</span>
|
||||
@@ -129,7 +129,7 @@ export function SessionItem({ session, reload, requestId }: { session: Session;
|
||||
)}
|
||||
|
||||
<XCircleIcon
|
||||
className="h-5 w-5 opacity-50 transition-all hover:opacity-100 group-hover:block sm:hidden"
|
||||
className="h-5 w-5 opacity-50 transition-all group-hover:block hover:opacity-100 sm:hidden"
|
||||
onClick={async (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -143,7 +143,7 @@ export function SessionItem({ session, reload, requestId }: { session: Session;
|
||||
{valid && session.expirationDate && (
|
||||
<Tooltip.Portal>
|
||||
<Tooltip.Content
|
||||
className="z-50 select-none rounded-md border bg-background-light-500 px-3 py-2 text-xs text-black shadow-xl dark:border-white/20 dark:bg-background-dark-500 dark:text-white"
|
||||
className="bg-background-light-500 dark:bg-background-dark-500 z-50 rounded-md border px-3 py-2 text-xs text-black shadow-xl select-none dark:border-white/20 dark:text-white"
|
||||
sideOffset={5}
|
||||
>
|
||||
Expires {moment(timestampDate(session.expirationDate)).fromNow()}
|
||||
|
||||
@@ -186,7 +186,7 @@ export function SetPasswordForm({
|
||||
aria-label="Resend OTP Code"
|
||||
disabled={loading}
|
||||
type="button"
|
||||
className="ml-4 cursor-pointer text-primary-light-500 hover:text-primary-light-400 disabled:cursor-default disabled:text-gray-400 dark:text-primary-dark-500 hover:dark:text-primary-dark-400 dark:disabled:text-gray-700"
|
||||
className="text-primary-light-500 hover:text-primary-light-400 dark:text-primary-dark-500 hover:dark:text-primary-dark-400 ml-4 cursor-pointer disabled:cursor-default disabled:text-gray-400 dark:disabled:text-gray-700"
|
||||
onClick={() => {
|
||||
resendCode();
|
||||
}}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ReactNode } from "react";
|
||||
|
||||
export function Skeleton({ children }: { children?: ReactNode }) {
|
||||
return (
|
||||
<div className="skeleton flex flex-row items-center justify-center rounded-lg bg-background-light-600 px-8 py-12 dark:bg-background-dark-600">
|
||||
<div className="skeleton bg-background-light-600 dark:bg-background-dark-600 flex flex-row items-center justify-center rounded-lg px-8 py-12">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@ export const Spinner: FC<{ className?: string }> = ({ className = "" }) => {
|
||||
return (
|
||||
<svg
|
||||
role="status"
|
||||
className={`${className} inline-block animate-spin fill-primary-light-500 text-black/10 dark:fill-primary-dark-500 dark:text-white/10`}
|
||||
className={`${className} fill-primary-light-500 dark:fill-primary-dark-500 inline-block animate-spin text-black/10 dark:text-white/10`}
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
@@ -17,7 +17,7 @@ export const Tab = ({ path, item: { slug, text } }: { path: string; item: Item }
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className={clsx("mr-2 mt-2 rounded-lg px-3 py-1 text-sm font-medium", {
|
||||
className={clsx("mt-2 mr-2 rounded-lg px-3 py-1 text-sm font-medium", {
|
||||
"bg-gray-700 text-gray-100 hover:bg-gray-500 hover:text-white": !isActive,
|
||||
"bg-blue-500 text-white": isActive,
|
||||
})}
|
||||
|
||||
@@ -54,7 +54,8 @@ export const ThemeWrapper = ({ children, branding }: Props) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, [branding?.themeMode, setNextTheme]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [branding?.themeMode]);
|
||||
|
||||
return <div>{children}</div>;
|
||||
};
|
||||
|
||||
@@ -106,7 +106,7 @@ export function TotpRegister({ uri, loginName, sessionId, requestId, organizatio
|
||||
{uri && (
|
||||
<>
|
||||
<QRCodeSVG className="my-4 h-40 w-40 rounded-md bg-white p-2" value={uri} />
|
||||
<div className="my-2 mb-4 flex w-96 rounded-lg border border-divider-light px-4 py-2 pr-2 text-sm dark:border-divider-dark">
|
||||
<div className="border-divider-light dark:border-divider-dark my-2 mb-4 flex w-96 rounded-lg border px-4 py-2 pr-2 text-sm">
|
||||
<Link href={uri} target="_blank" className="flex-1 overflow-x-auto">
|
||||
{uri}
|
||||
</Link>
|
||||
|
||||
@@ -40,12 +40,12 @@ export function UserAvatar({ loginName, displayName, showDropdown, searchParams
|
||||
<div>
|
||||
<Avatar size="small" name={displayName ?? loginName ?? ""} loginName={loginName ?? ""} />
|
||||
</div>
|
||||
<span className="ml-4 max-w-[250px] overflow-hidden text-ellipsis pr-4 text-14px">{loginName}</span>
|
||||
<span className="text-14px ml-4 max-w-[250px] overflow-hidden pr-4 text-ellipsis">{loginName}</span>
|
||||
<span className="flex-grow"></span>
|
||||
{showDropdown && (
|
||||
<Link
|
||||
href={"/accounts?" + params}
|
||||
className={`ml-4 mr-1 flex items-center justify-center p-1 transition-all hover:bg-black/10 dark:hover:bg-white/10 ${userAvatarRoundness}`}
|
||||
className={`mr-1 ml-4 flex items-center justify-center p-1 transition-all hover:bg-black/10 dark:hover:bg-white/10 ${userAvatarRoundness}`}
|
||||
>
|
||||
<ChevronDownIcon className="h-4 w-4" />
|
||||
</Link>
|
||||
|
||||
@@ -115,7 +115,7 @@ export function UsernameForm({
|
||||
/>
|
||||
{allowRegister && (
|
||||
<button
|
||||
className="text-sm transition-all hover:text-primary-light-500 dark:hover:text-primary-dark-500"
|
||||
className="hover:text-primary-light-500 dark:hover:text-primary-dark-500 text-sm transition-all"
|
||||
onClick={() => {
|
||||
const registerParams = new URLSearchParams();
|
||||
if (organization) {
|
||||
|
||||
@@ -153,7 +153,7 @@ export function VerifyForm({ userId, loginName, organization, requestId, code, i
|
||||
aria-label="Resend Code"
|
||||
disabled={loading}
|
||||
type="button"
|
||||
className="ml-4 cursor-pointer text-primary-light-500 hover:text-primary-light-400 disabled:cursor-default disabled:text-gray-400 dark:text-primary-dark-500 hover:dark:text-primary-dark-400 dark:disabled:text-gray-700"
|
||||
className="text-primary-light-500 hover:text-primary-light-400 dark:text-primary-dark-500 hover:dark:text-primary-dark-400 ml-4 cursor-pointer disabled:cursor-default disabled:text-gray-400 dark:disabled:text-gray-700"
|
||||
onClick={() => {
|
||||
resendCode();
|
||||
}}
|
||||
|
||||
@@ -130,7 +130,7 @@ describe("processIDPCallback", () => {
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetAllMocks();
|
||||
|
||||
// Import mocked modules
|
||||
const { headers } = await import("next/headers");
|
||||
@@ -937,7 +937,7 @@ describe("validateIDPLinkingPermissions", () => {
|
||||
let validateIDPLinkingPermissions: any;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetAllMocks();
|
||||
|
||||
// Import mocked modules
|
||||
const { getLoginSettings, getActiveIdentityProviders } = await import("../zitadel");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
// https://github.com/tailwindlabs/tailwindcss/discussions/16173
|
||||
@import "tailwindcss";
|
||||
@config "../../tailwind.config.mjs";
|
||||
|
||||
@layer base {
|
||||
h1,
|
||||
@@ -9,7 +9,7 @@
|
||||
}
|
||||
|
||||
.ztdl-p {
|
||||
@apply text-sm text-text-light-secondary-500 dark:text-text-dark-secondary-500;
|
||||
@apply text-text-light-secondary-500 dark:text-text-dark-secondary-500 text-sm;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"$schema": "https://openapi.vercel.sh/vercel.json",
|
||||
"buildCommand": "pnpm nx run @zitadel/login:build-vercel"
|
||||
"buildCommand": "NX_DAEMON=false NX_DISABLE_DB=true pnpm nx run @zitadel/login:build-vercel"
|
||||
}
|
||||
+43
-44
@@ -13,78 +13,77 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^20.3.16",
|
||||
"@angular/cdk": "^20.2.14",
|
||||
"@angular/common": "^20.3.16",
|
||||
"@angular/compiler": "^20.3.16",
|
||||
"@angular/core": "^20.3.16",
|
||||
"@angular/forms": "^20.3.16",
|
||||
"@angular/material": "^20.2.14",
|
||||
"@angular/material-moment-adapter": "^20.2.14",
|
||||
"@angular/platform-browser": "^20.3.16",
|
||||
"@angular/platform-browser-dynamic": "^20.3.16",
|
||||
"@angular/router": "^20.3.16",
|
||||
"@angular/service-worker": "^20.3.16",
|
||||
"@angular/animations": "^21.2.6",
|
||||
"@angular/cdk": "^21.2.4",
|
||||
"@angular/common": "^21.2.6",
|
||||
"@angular/compiler": "^21.2.6",
|
||||
"@angular/core": "^21.2.6",
|
||||
"@angular/forms": "^21.2.6",
|
||||
"@angular/material": "^21.2.4",
|
||||
"@angular/material-moment-adapter": "^21.2.4",
|
||||
"@angular/platform-browser": "^21.2.6",
|
||||
"@angular/platform-browser-dynamic": "^21.2.6",
|
||||
"@angular/router": "^21.2.6",
|
||||
"@angular/service-worker": "^21.2.6",
|
||||
"@bufbuild/protobuf": "^2.11.0",
|
||||
"@connectrpc/connect": "~2.0.4",
|
||||
"@connectrpc/connect-web": "~2.0.4",
|
||||
"@ctrl/ngx-codemirror": "^6.1.0",
|
||||
"@fortawesome/angular-fontawesome": "^3.0.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||
"@netlify/build-info": "^10.3.0",
|
||||
"@ng-icons/core": "^32.5.0",
|
||||
"@ng-icons/heroicons": "^32.5.0",
|
||||
"@connectrpc/connect": "^2.1.1",
|
||||
"@connectrpc/connect-web": "^2.1.1",
|
||||
"@ctrl/ngx-codemirror": "^7.0.0",
|
||||
"@fortawesome/angular-fontawesome": "^4.0.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^7.2.0",
|
||||
"@fortawesome/free-brands-svg-icons": "^7.2.0",
|
||||
"@netlify/build-info": "^10.4.0",
|
||||
"@ng-icons/core": "^33.2.0",
|
||||
"@ng-icons/heroicons": "^33.2.0",
|
||||
"@ngx-translate/core": "^17.0.0",
|
||||
"@tanstack/angular-query-experimental": "^5.90.24",
|
||||
"@tanstack/angular-query-experimental": "^5.96.1",
|
||||
"angular-oauth2-oidc": "^20.0.2",
|
||||
"angularx-qrcode": "^20.0.0",
|
||||
"angularx-qrcode": "^21.0.5",
|
||||
"buffer": "^6.0.3",
|
||||
"codemirror": "^5.65.20",
|
||||
"codemirror": "^5.65.21",
|
||||
"file-saver": "^2.0.5",
|
||||
"flag-icons": "^7.5.0",
|
||||
"google-protobuf": "~3.21.4",
|
||||
"grpc-web": "~1.5.0",
|
||||
"google-protobuf": "^4.0.2",
|
||||
"grpc-web": "^2.0.2",
|
||||
"i18n-iso-countries": "^7.14.0",
|
||||
"libphonenumber-js": "^1.12.35",
|
||||
"libphonenumber-js": "^1.12.41",
|
||||
"material-design-icons-iconfont": "^6.7.0",
|
||||
"moment": "^2.30.1",
|
||||
"ngx-color": "^9.0.0",
|
||||
"ngx-color": "^10.1.0",
|
||||
"opentype.js": "^1.3.4",
|
||||
"posthog-js": "^1.335.3",
|
||||
"posthog-js": "^1.364.5",
|
||||
"rxjs": "^7.8.2",
|
||||
"tinycolor2": "^1.6.0",
|
||||
"tslib": "^2.8.1",
|
||||
"uuid": "^10.0.0",
|
||||
"uuid": "^13.0.0",
|
||||
"zone.js": "~0.15.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-eslint/eslint-plugin": "21.3.0",
|
||||
"@angular-eslint/eslint-plugin-template": "21.3.0",
|
||||
"@angular-eslint/template-parser": "21.3.0",
|
||||
"@angular/build": "^20.3.15",
|
||||
"@angular/cli": "^20.3.15",
|
||||
"@angular/compiler-cli": "^20.3.16",
|
||||
"@angular/language-service": "^20.3.16",
|
||||
"@eslint/js": "^10.0.0",
|
||||
"@angular/build": "^21.2.6",
|
||||
"@angular/cli": "^21.2.6",
|
||||
"@angular/compiler-cli": "^21.2.6",
|
||||
"@angular/language-service": "^21.2.6",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/google-protobuf": "~3.15.12",
|
||||
"@types/google-protobuf": "^3.15.12",
|
||||
"@types/jasmine": "~5.1.15",
|
||||
"@types/jasminewd2": "~2.0.13",
|
||||
"@types/jsonwebtoken": "^9.0.10",
|
||||
"@types/node": "^22.19.7",
|
||||
"@types/node": "^25.5.0",
|
||||
"@types/opentype.js": "^1.3.9",
|
||||
"@types/qrcode": "^1.5.6",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.57.0",
|
||||
"@typescript-eslint/parser": "^8.57.0",
|
||||
"@types/uuid": "^11.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.58.0",
|
||||
"@typescript-eslint/parser": "^8.58.0",
|
||||
"@zitadel/client": "workspace:*",
|
||||
"@zitadel/proto": "workspace:*",
|
||||
"eslint": "^10.0.0",
|
||||
"eslint": "^10.1.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"globals": "^17.0.0",
|
||||
"globals": "^17.4.0",
|
||||
"jasmine-core": "~5.12.1",
|
||||
"jasmine-spec-reporter": "~7.0.0",
|
||||
"karma": "^6.4.4",
|
||||
@@ -92,7 +91,7 @@
|
||||
"karma-coverage": "^2.2.1",
|
||||
"karma-coverage-istanbul-reporter": "^3.0.3",
|
||||
"karma-jasmine": "^5.1.0",
|
||||
"karma-jasmine-html-reporter": "^2.1.0",
|
||||
"karma-jasmine-html-reporter": "^2.2.0",
|
||||
"prettier": "^3.8.1",
|
||||
"prettier-plugin-organize-imports": "^4.3.0",
|
||||
"typescript": "5.9.2"
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<div class="main-container">
|
||||
<ng-container *ngIf="authService.user | async as user">
|
||||
@if (authService.user | async; as user) {
|
||||
<cnsl-header
|
||||
[org]="activeOrganizationQuery.data()"
|
||||
[user]="user"
|
||||
[isDarkTheme]="componentCssClass === 'dark-theme'"
|
||||
(changedActiveOrg)="changedOrg()"
|
||||
/>
|
||||
|
||||
<cnsl-nav
|
||||
id="mainnav"
|
||||
class="nav"
|
||||
@@ -15,7 +14,7 @@
|
||||
[user]="user"
|
||||
[isDarkTheme]="componentCssClass === 'dark-theme'"
|
||||
></cnsl-nav>
|
||||
</ng-container>
|
||||
}
|
||||
|
||||
<div class="router-container" [@routeAnimations]="prepareRoute(outlet)">
|
||||
<div class="outlet">
|
||||
|
||||
@@ -1,40 +1,41 @@
|
||||
<div class="feature-row" *ngIf="toggleState$ | async as toggleState">
|
||||
<span>{{ 'SETTING.FEATURES.' + (toggleStateKey | uppercase) | translate }}</span>
|
||||
<div class="row">
|
||||
<mat-button-toggle-group
|
||||
class="theme-toggle"
|
||||
class="buttongroup"
|
||||
[(ngModel)]="toggleState.enabled"
|
||||
(change)="toggleChange.emit(toggleState)"
|
||||
name="displayview"
|
||||
>
|
||||
<mat-button-toggle [value]="false">
|
||||
<div class="toggle-row">
|
||||
<span>{{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
|
||||
|
||||
<div
|
||||
*ngIf="!toggleState.enabled && (isInherited$ | async)"
|
||||
class="current-dot"
|
||||
matTooltip="{{ 'SETTING.FEATURES.INHERITEDINDICATOR_DESCRIPTION.DISABLED' | translate }}"
|
||||
></div>
|
||||
</div>
|
||||
</mat-button-toggle>
|
||||
<mat-button-toggle [value]="true">
|
||||
<div class="toggle-row">
|
||||
<span>{{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
|
||||
<div
|
||||
*ngIf="toggleState.enabled && (isInherited$ | async)"
|
||||
class="current-dot"
|
||||
matTooltip="{{ 'SETTING.FEATURES.INHERITEDINDICATOR_DESCRIPTION.ENABLED' | translate }}"
|
||||
></div>
|
||||
</div>
|
||||
</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
@if (toggleState$ | async; as toggleState) {
|
||||
<div class="feature-row">
|
||||
<span>{{ 'SETTING.FEATURES.' + (toggleStateKey | uppercase) | translate }}</span>
|
||||
<div class="row">
|
||||
<mat-button-toggle-group
|
||||
class="theme-toggle"
|
||||
class="buttongroup"
|
||||
[(ngModel)]="toggleState.enabled"
|
||||
(change)="toggleChange.emit(toggleState)"
|
||||
name="displayview"
|
||||
>
|
||||
<mat-button-toggle [value]="false">
|
||||
<div class="toggle-row">
|
||||
<span>{{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}</span>
|
||||
@if (!toggleState.enabled && (isInherited$ | async)) {
|
||||
<div
|
||||
class="current-dot"
|
||||
matTooltip="{{ 'SETTING.FEATURES.INHERITEDINDICATOR_DESCRIPTION.DISABLED' | translate }}"
|
||||
></div>
|
||||
}
|
||||
</div>
|
||||
</mat-button-toggle>
|
||||
<mat-button-toggle [value]="true">
|
||||
<div class="toggle-row">
|
||||
<span>{{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}</span>
|
||||
@if (toggleState.enabled && (isInherited$ | async)) {
|
||||
<div
|
||||
class="current-dot"
|
||||
matTooltip="{{ 'SETTING.FEATURES.INHERITEDINDICATOR_DESCRIPTION.ENABLED' | translate }}"
|
||||
></div>
|
||||
}
|
||||
</div>
|
||||
</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
</div>
|
||||
<ng-content></ng-content>
|
||||
@if ('SETTING.FEATURES.' + (toggleStateKey | uppercase) + '_DESCRIPTION' | translate; as i18nDescription) {
|
||||
<cnsl-info-section class="feature-info">{{ i18nDescription }}</cnsl-info-section>
|
||||
}
|
||||
</div>
|
||||
<ng-content></ng-content>
|
||||
<cnsl-info-section
|
||||
class="feature-info"
|
||||
*ngIf="'SETTING.FEATURES.' + (toggleStateKey | uppercase) + '_DESCRIPTION' | translate as i18nDescription"
|
||||
>{{ i18nDescription }}</cnsl-info-section
|
||||
>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AsyncPipe, NgIf, UpperCasePipe } from '@angular/common';
|
||||
import { AsyncPipe, UpperCasePipe } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
@@ -23,7 +23,6 @@ import { map } from 'rxjs/operators';
|
||||
MatTooltipModule,
|
||||
InfoSectionModule,
|
||||
AsyncPipe,
|
||||
NgIf,
|
||||
],
|
||||
})
|
||||
export class FeatureToggleComponent<TKey extends ToggleStateKeys, TValue extends ToggleStates[TKey]> {
|
||||
|
||||
@@ -18,15 +18,21 @@
|
||||
</button>
|
||||
</ng-template>
|
||||
|
||||
<cnsl-card *ngIf="toggleStates$ | async as toggleStates">
|
||||
<div class="features">
|
||||
<cnsl-feature-toggle
|
||||
*ngFor="let key of FEATURE_KEYS"
|
||||
[toggleStateKey]="key"
|
||||
[toggleState]="toggleStates[key]"
|
||||
(toggleChange)="saveFeature(key, $event)"
|
||||
></cnsl-feature-toggle>
|
||||
<cnsl-login-v2-feature-toggle [toggleState]="toggleStates.loginV2" (toggleChanged)="saveFeature('loginV2', $event)" />
|
||||
</div>
|
||||
</cnsl-card>
|
||||
@if (toggleStates$ | async; as toggleStates) {
|
||||
<cnsl-card>
|
||||
<div class="features">
|
||||
@for (key of FEATURE_KEYS; track key) {
|
||||
<cnsl-feature-toggle
|
||||
[toggleStateKey]="key"
|
||||
[toggleState]="toggleStates[key]"
|
||||
(toggleChange)="saveFeature(key, $event)"
|
||||
></cnsl-feature-toggle>
|
||||
}
|
||||
<cnsl-login-v2-feature-toggle
|
||||
[toggleState]="toggleStates.loginV2"
|
||||
(toggleChanged)="saveFeature('loginV2', $event)"
|
||||
/>
|
||||
</div>
|
||||
</cnsl-card>
|
||||
}
|
||||
</div>
|
||||
|
||||
+31
-23
@@ -4,32 +4,40 @@
|
||||
<input cnslInput type="text" placeholder="" #nameInput [formControl]="myControl" [matAutocomplete]="auto" />
|
||||
|
||||
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
|
||||
<mat-option *ngIf="isLoading()" class="is-loading">
|
||||
<mat-spinner diameter="30"></mat-spinner>
|
||||
</mat-option>
|
||||
<mat-option *ngFor="let framework of filteredOptions | async" [value]="framework.id">
|
||||
<div class="framework-option">
|
||||
<div class="framework-option-column">
|
||||
<div class="img-wrapper">
|
||||
<img class="dark-only" *ngIf="framework.imgSrcDark" [src]="framework.imgSrcDark" />
|
||||
<img class="light-only" *ngIf="framework.imgSrcLight" [src]="framework.imgSrcLight" />
|
||||
@if (isLoading()) {
|
||||
<mat-option class="is-loading">
|
||||
<mat-spinner diameter="30"></mat-spinner>
|
||||
</mat-option>
|
||||
}
|
||||
@for (framework of filteredOptions | async; track framework) {
|
||||
<mat-option [value]="framework.id">
|
||||
<div class="framework-option">
|
||||
<div class="framework-option-column">
|
||||
<div class="img-wrapper">
|
||||
@if (framework.imgSrcDark) {
|
||||
<img class="dark-only" [src]="framework.imgSrcDark" />
|
||||
}
|
||||
@if (framework.imgSrcLight) {
|
||||
<img class="light-only" [src]="framework.imgSrcLight" />
|
||||
}
|
||||
</div>
|
||||
<span class="fill-space"></span>
|
||||
<span>{{ framework.title }}</span>
|
||||
</div>
|
||||
<span class="fill-space"></span>
|
||||
|
||||
<span>{{ framework.title }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</mat-option>
|
||||
<mat-option *ngIf="withCustom" [value]="'other'">
|
||||
<div class="framework-option">
|
||||
<div class="framework-option-column">
|
||||
<div class="img-wrapper"></div>
|
||||
<span class="fill-space"></span>
|
||||
|
||||
<span>{{ 'QUICKSTART.FRAMEWORK_OTHER' | translate }}</span>
|
||||
</mat-option>
|
||||
}
|
||||
@if (withCustom) {
|
||||
<mat-option [value]="'other'">
|
||||
<div class="framework-option">
|
||||
<div class="framework-option-column">
|
||||
<div class="img-wrapper"></div>
|
||||
<span class="fill-space"></span>
|
||||
<span>{{ 'QUICKSTART.FRAMEWORK_OTHER' | translate }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-option>
|
||||
</mat-option>
|
||||
}
|
||||
</mat-autocomplete>
|
||||
</cnsl-form-field>
|
||||
</form>
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
<div class="framework-change-wrapper">
|
||||
<div class="framework-card-wrapper">
|
||||
<div class="framework-card card" *ngIf="framework | async as framework; else frameworkFallback">
|
||||
<div>
|
||||
<img class="dark-only" *ngIf="framework.imgSrcDark" [src]="framework.imgSrcDark" />
|
||||
<img class="light-only" *ngIf="framework.imgSrcLight" [src]="framework.imgSrcLight" />
|
||||
@if (framework | async; as framework) {
|
||||
<div class="framework-card card">
|
||||
<div>
|
||||
@if (framework.imgSrcDark) {
|
||||
<img class="dark-only" [src]="framework.imgSrcDark" />
|
||||
}
|
||||
@if (framework.imgSrcLight) {
|
||||
<img class="light-only" [src]="framework.imgSrcLight" />
|
||||
}
|
||||
</div>
|
||||
<span>{{ framework.title }}</span>
|
||||
</div>
|
||||
<span>{{ framework.title }}</span>
|
||||
</div>
|
||||
|
||||
<ng-template #frameworkFallback>
|
||||
} @else {
|
||||
<div class="framework-card card">
|
||||
<span>{{ 'QUICKSTART.SELECT_FRAMEWORK' | translate }}</span>
|
||||
</div>
|
||||
</ng-template>
|
||||
}
|
||||
|
||||
<button (click)="openDialog()" mat-stroked-button>
|
||||
{{ 'ACTIONS.CHANGE' | translate }}
|
||||
|
||||
@@ -21,23 +21,35 @@
|
||||
<span class="left cnsl-secondary-text">
|
||||
{{ 'APP.GRANT' | translate }}
|
||||
</span>
|
||||
<span class="right" *ngIf="configuration.grantTypesList && configuration.grantTypesList.length > 0">
|
||||
[<span *ngFor="let element of configuration.grantTypesList ?? []; index as i">
|
||||
{{ 'APP.OIDC.GRANT.' + element | translate }}
|
||||
{{ i < configuration.grantTypesList.length - 1 ? ', ' : '' }} </span
|
||||
>]
|
||||
</span>
|
||||
@if (configuration.grantTypesList && configuration.grantTypesList.length > 0) {
|
||||
<span class="right">
|
||||
[
|
||||
@for (element of configuration.grantTypesList ?? []; track element; let i = $index) {
|
||||
<span>
|
||||
{{ 'APP.OIDC.GRANT.' + element | translate }}
|
||||
{{ i < configuration.grantTypesList.length - 1 ? ', ' : '' }}
|
||||
</span>
|
||||
}
|
||||
]
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
<div class="row">
|
||||
<span class="left cnsl-secondary-text">
|
||||
{{ 'APP.OIDC.RESPONSETYPE' | translate }}
|
||||
</span>
|
||||
<span class="right" *ngIf="configuration.responseTypesList && configuration.responseTypesList.length > 0">
|
||||
[<span *ngFor="let element of configuration.responseTypesList ?? []; index as i">
|
||||
{{ 'APP.OIDC.RESPONSE.' + element | translate }}
|
||||
{{ i < configuration.responseTypesList.length - 1 ? ', ' : '' }} </span
|
||||
>]
|
||||
</span>
|
||||
@if (configuration.responseTypesList && configuration.responseTypesList.length > 0) {
|
||||
<span class="right">
|
||||
[
|
||||
@for (element of configuration.responseTypesList ?? []; track element; let i = $index) {
|
||||
<span>
|
||||
{{ 'APP.OIDC.RESPONSE.' + element | translate }}
|
||||
{{ i < configuration.responseTypesList.length - 1 ? ', ' : '' }}
|
||||
</span>
|
||||
}
|
||||
]
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
@@ -25,7 +24,7 @@ export type Framework = FrameworkDefinition & {
|
||||
selector: 'cnsl-oidc-app-configuration',
|
||||
templateUrl: './oidc-configuration.component.html',
|
||||
styleUrls: ['./oidc-configuration.component.scss'],
|
||||
imports: [TranslateModule, RouterModule, CommonModule, MatButtonModule],
|
||||
imports: [TranslateModule, RouterModule, MatButtonModule],
|
||||
})
|
||||
export class OIDCConfigurationComponent {
|
||||
@Input() public name?: string;
|
||||
|
||||
@@ -13,11 +13,15 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="quickstart-card-wrapper">
|
||||
<ng-container *ngFor="let framework of frameworks.slice(0, 18)">
|
||||
@for (framework of frameworks.slice(0, 18); track framework) {
|
||||
<a [routerLink]="['/projects', 'app-create']" [queryParams]="{ framework: framework.id }" class="quickstart-card card">
|
||||
<img class="dark-only" *ngIf="framework.imgSrcDark" [src]="framework.imgSrcDark" alt="{{ framework.title }}" />
|
||||
<img class="light-only" *ngIf="framework.imgSrcLight" [src]="framework.imgSrcLight" alt="{{ framework.title }}" />
|
||||
@if (framework.imgSrcDark) {
|
||||
<img class="dark-only" [src]="framework.imgSrcDark" alt="{{ framework.title }}" />
|
||||
}
|
||||
@if (framework.imgSrcLight) {
|
||||
<img class="light-only" [src]="framework.imgSrcLight" alt="{{ framework.title }}" />
|
||||
}
|
||||
</a>
|
||||
</ng-container>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
@@ -27,7 +26,7 @@ export type Framework = FrameworkDefinition & {
|
||||
selector: 'cnsl-quickstart',
|
||||
templateUrl: './quickstart.component.html',
|
||||
styleUrls: ['./quickstart.component.scss'],
|
||||
imports: [TranslateModule, RouterModule, CommonModule, MatButtonModule],
|
||||
imports: [TranslateModule, RouterModule, MatButtonModule],
|
||||
})
|
||||
export class QuickstartComponent {
|
||||
public frameworks: FrameworkDefinition[] = frameworkDefinition
|
||||
|
||||
@@ -1,51 +1,56 @@
|
||||
<div class="accounts-card" *ngIf="user$ | async as user">
|
||||
<cnsl-avatar
|
||||
(click)="editUserProfile()"
|
||||
class="avatar"
|
||||
[ngClass]="{ 'iam-user': iamuser }"
|
||||
[forColor]="user.preferredLoginName"
|
||||
[avatarUrl]="user.human?.profile?.avatarUrl || ''"
|
||||
[name]="user.human?.profile?.displayName ?? ''"
|
||||
[size]="80"
|
||||
>
|
||||
</cnsl-avatar>
|
||||
|
||||
<span class="u-name">{{ user?.human?.profile?.displayName ? user?.human?.profile?.displayName : 'A' }}</span>
|
||||
<span class="u-email" *ngIf="user?.preferredLoginName">{{ user?.preferredLoginName }}</span>
|
||||
|
||||
<button (click)="editUserProfile()" mat-stroked-button>{{ 'USER.EDITACCOUNT' | translate }}</button>
|
||||
<div class="l-accounts">
|
||||
<mat-progress-bar *ngIf="(sessions$ | async) === null" color="primary" mode="indeterminate"></mat-progress-bar>
|
||||
<a class="row" *ngFor="let session of sessions$ | async" (click)="selectAccount(session.loginName)">
|
||||
<cnsl-avatar
|
||||
*ngIf="session && session.displayName"
|
||||
class="small-avatar"
|
||||
[avatarUrl]="session.avatarUrl || ''"
|
||||
[name]="session.displayName"
|
||||
[forColor]="session.loginName"
|
||||
[size]="32"
|
||||
>
|
||||
</cnsl-avatar>
|
||||
|
||||
<div class="col">
|
||||
<span class="user-title">{{ session.displayName ? session.displayName : session.userName }} </span>
|
||||
<span class="loginname">{{ session.loginName }}</span>
|
||||
<span class="state inactive" *ngIf="$any(session.authState) === UserState.USER_STATE_INACTIVE">{{
|
||||
'USER.STATE.' + session.authState | translate
|
||||
}}</span>
|
||||
</div>
|
||||
<mat-icon>keyboard_arrow_right</mat-icon>
|
||||
</a>
|
||||
<a class="row" (click)="selectNewAccount()">
|
||||
<div class="icon-wrapper">
|
||||
<i class="las la-user-plus"></i>
|
||||
</div>
|
||||
<span class="col">
|
||||
<span class="user-title">{{ 'USER.ADDACCOUNT' | translate }}</span>
|
||||
</span>
|
||||
<mat-icon>keyboard_arrow_right</mat-icon>
|
||||
</a>
|
||||
@if (user$ | async; as user) {
|
||||
<div class="accounts-card">
|
||||
<cnsl-avatar
|
||||
(click)="editUserProfile()"
|
||||
class="avatar"
|
||||
[ngClass]="{ 'iam-user': iamuser }"
|
||||
[forColor]="user.preferredLoginName"
|
||||
[avatarUrl]="user.human?.profile?.avatarUrl || ''"
|
||||
[name]="user.human?.profile?.displayName ?? ''"
|
||||
[size]="80"
|
||||
>
|
||||
</cnsl-avatar>
|
||||
<span class="u-name">{{ user?.human?.profile?.displayName ? user?.human?.profile?.displayName : 'A' }}</span>
|
||||
@if (user?.preferredLoginName) {
|
||||
<span class="u-email">{{ user?.preferredLoginName }}</span>
|
||||
}
|
||||
<button (click)="editUserProfile()" mat-stroked-button>{{ 'USER.EDITACCOUNT' | translate }}</button>
|
||||
<div class="l-accounts">
|
||||
@if ((sessions$ | async) === null) {
|
||||
<mat-progress-bar color="primary" mode="indeterminate"></mat-progress-bar>
|
||||
}
|
||||
@for (session of sessions$ | async; track session) {
|
||||
<a class="row" (click)="selectAccount(session.loginName)">
|
||||
@if (session && session.displayName) {
|
||||
<cnsl-avatar
|
||||
class="small-avatar"
|
||||
[avatarUrl]="session.avatarUrl || ''"
|
||||
[name]="session.displayName"
|
||||
[forColor]="session.loginName"
|
||||
[size]="32"
|
||||
>
|
||||
</cnsl-avatar>
|
||||
}
|
||||
<div class="col">
|
||||
<span class="user-title">{{ session.displayName ? session.displayName : session.userName }} </span>
|
||||
<span class="loginname">{{ session.loginName }}</span>
|
||||
@if ($any(session.authState) === UserState.USER_STATE_INACTIVE) {
|
||||
<span class="state inactive">{{ 'USER.STATE.' + session.authState | translate }}</span>
|
||||
}
|
||||
</div>
|
||||
<mat-icon>keyboard_arrow_right</mat-icon>
|
||||
</a>
|
||||
}
|
||||
<a class="row" (click)="selectNewAccount()">
|
||||
<div class="icon-wrapper">
|
||||
<i class="las la-user-plus"></i>
|
||||
</div>
|
||||
<span class="col">
|
||||
<span class="user-title">{{ 'USER.ADDACCOUNT' | translate }}</span>
|
||||
</span>
|
||||
<mat-icon>keyboard_arrow_right</mat-icon>
|
||||
</a>
|
||||
</div>
|
||||
<button (click)="logout()" color="warn" mat-stroked-button>{{ 'MENU.LOGOUT' | translate }}</button>
|
||||
</div>
|
||||
|
||||
<button (click)="logout()" color="warn" mat-stroked-button>{{ 'MENU.LOGOUT' | translate }}</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,62 +1,81 @@
|
||||
<div
|
||||
*ngIf="type !== ActionKeysType.ORGSWITCHER && (isHandset$ | async) === false"
|
||||
class="action-keys-wrapper"
|
||||
[ngSwitch]="type"
|
||||
[ngClass]="{ 'without-margin': withoutMargin, 'no-contrast-mode': doNotUseContrast }"
|
||||
>
|
||||
<div *ngSwitchCase="ActionKeysType.CLEAR" class="action-keys-row">
|
||||
<div class="action-key esc">
|
||||
<div class="key-overlay"></div>
|
||||
<span>ESC</span>
|
||||
</div>
|
||||
@if (type !== ActionKeysType.ORGSWITCHER && (isHandset$ | async) === false) {
|
||||
<div class="action-keys-wrapper" [ngClass]="{ 'without-margin': withoutMargin, 'no-contrast-mode': doNotUseContrast }">
|
||||
@switch (type) {
|
||||
@case (ActionKeysType.CLEAR) {
|
||||
<div class="action-keys-row">
|
||||
<div class="action-key esc">
|
||||
<div class="key-overlay"></div>
|
||||
<span>ESC</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@case (ActionKeysType.ADD) {
|
||||
<div class="action-keys-row" data-e2e="action-key-add">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>N</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@case (ActionKeysType.DELETE) {
|
||||
<div class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
@if (isMacLike || isIOS) {
|
||||
<span>⌘</span>
|
||||
} @else {
|
||||
<span>crtl</span>
|
||||
}
|
||||
</div>
|
||||
+
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>BS</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@case (ActionKeysType.DEACTIVATE) {
|
||||
<div class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
@if (isMacLike || isIOS) {
|
||||
<span>⌘</span>
|
||||
} @else {
|
||||
<span>crtl</span>
|
||||
}
|
||||
</div>
|
||||
+
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>↓</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@case (ActionKeysType.REACTIVATE) {
|
||||
<div class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
@if (isMacLike || isIOS) {
|
||||
<span>⌘</span>
|
||||
} @else {
|
||||
<span>crtl</span>
|
||||
}
|
||||
</div>
|
||||
+
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>↑</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@case (ActionKeysType.FILTER) {
|
||||
<div class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>F</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div *ngSwitchCase="ActionKeysType.ADD" class="action-keys-row" data-e2e="action-key-add">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>N</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="ActionKeysType.DELETE" class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span *ngIf="isMacLike || isIOS; else otherOS">⌘</span>
|
||||
</div>
|
||||
+
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>BS</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="ActionKeysType.DEACTIVATE" class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span *ngIf="isMacLike || isIOS; else otherOS">⌘</span>
|
||||
</div>
|
||||
+
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>↓</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="ActionKeysType.REACTIVATE" class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span *ngIf="isMacLike || isIOS; else otherOS">⌘</span>
|
||||
</div>
|
||||
+
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>↑</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="ActionKeysType.FILTER" class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>F</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #otherOS>
|
||||
<span>crtl</span>
|
||||
</ng-template>
|
||||
}
|
||||
|
||||
+5
-3
@@ -24,9 +24,11 @@
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'ACTIONSTWO.EXECUTION.TABLE.TARGET' | translate }}</th>
|
||||
<td mat-cell *cnslCellDef="let row; dataSource: dataSource">
|
||||
<div class="target-key">
|
||||
<cnsl-project-role-chip *ngFor="let target of row.mappedTargets; trackBy: trackTarget" [roleName]="target.name">
|
||||
{{ target.name }}
|
||||
</cnsl-project-role-chip>
|
||||
@for (target of row.mappedTargets; track trackTarget($index, target)) {
|
||||
<cnsl-project-role-chip [roleName]="target.name">
|
||||
{{ target.name }}
|
||||
</cnsl-project-role-chip>
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
+10
-6
@@ -3,12 +3,16 @@
|
||||
<input #input cnslInput type="text" placeholder="" [formControl]="control" [matAutocomplete]="autocomplete" />
|
||||
|
||||
<mat-autocomplete requireSelection #autocomplete="matAutocomplete">
|
||||
<mat-option *ngIf="items === undefined" class="is-loading">
|
||||
<mat-spinner diameter="30"></mat-spinner>
|
||||
</mat-option>
|
||||
<mat-option *ngFor="let item of items | filter: input | async" [value]="item">
|
||||
<span>{{ item }}</span>
|
||||
</mat-option>
|
||||
@if (items === undefined) {
|
||||
<mat-option class="is-loading">
|
||||
<mat-spinner diameter="30"></mat-spinner>
|
||||
</mat-option>
|
||||
}
|
||||
@for (item of items | filter: input | async; track item) {
|
||||
<mat-option [value]="item">
|
||||
<span>{{ item }}</span>
|
||||
</mat-option>
|
||||
}
|
||||
</mat-autocomplete>
|
||||
|
||||
<ng-content></ng-content>
|
||||
|
||||
+1
-3
@@ -1,5 +1,5 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, Pipe, PipeTransform } from '@angular/core';
|
||||
import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
|
||||
import { AsyncPipe } from '@angular/common';
|
||||
import { FormFieldModule } from 'src/app/modules/form-field/form-field.module';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
import { LabelModule } from 'src/app/modules/label/label.module';
|
||||
@@ -39,8 +39,6 @@ class Filter implements PipeTransform {
|
||||
MatOptionModule,
|
||||
MatProgressSpinnerModule,
|
||||
TranslateModule,
|
||||
NgIf,
|
||||
NgForOf,
|
||||
ReactiveFormsModule,
|
||||
],
|
||||
})
|
||||
|
||||
+69
-78
@@ -1,79 +1,70 @@
|
||||
<form *ngIf="form$ | async as form" [formGroup]="form.form" class="form-grid" (ngSubmit)="submit(form)">
|
||||
<ng-container *ngIf="form.case === 'request' || form.case === 'response'">
|
||||
<p class="cnsl-secondary-text">{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.REQ_RESP_DESCRIPTION' | translate }}</p>
|
||||
|
||||
<div class="emailVerified">
|
||||
<mat-checkbox [formControl]="form.form.controls.all">
|
||||
<div class="execution-condition-text">
|
||||
<span>{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.ALL.TITLE' | translate }}</span>
|
||||
<span class="description cnsl-secondary-text">{{
|
||||
'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.ALL.DESCRIPTION' | translate
|
||||
}}</span>
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
@if (form$ | async; as form) {
|
||||
<form [formGroup]="form.form" class="form-grid" (ngSubmit)="submit(form)">
|
||||
@if (form.case === 'request' || form.case === 'response') {
|
||||
<p class="cnsl-secondary-text">{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.REQ_RESP_DESCRIPTION' | translate }}</p>
|
||||
<div class="emailVerified">
|
||||
<mat-checkbox [formControl]="form.form.controls.all">
|
||||
<div class="execution-condition-text">
|
||||
<span>{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.ALL.TITLE' | translate }}</span>
|
||||
<span class="description cnsl-secondary-text">{{
|
||||
'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.ALL.DESCRIPTION' | translate
|
||||
}}</span>
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<p class="condition-description">{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_SERVICE.TITLE' | translate }}</p>
|
||||
<cnsl-actions-two-add-action-autocomplete-input
|
||||
label="ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_SERVICE.DESCRIPTION"
|
||||
[items]="listExecutionServicesQuery.data()"
|
||||
[control]="form.form.controls.service"
|
||||
></cnsl-actions-two-add-action-autocomplete-input>
|
||||
<p class="condition-description">{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_METHOD.TITLE' | translate }}</p>
|
||||
<cnsl-actions-two-add-action-autocomplete-input
|
||||
label="ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_METHOD.DESCRIPTION"
|
||||
[items]="filteredExecutionMethods()"
|
||||
[control]="form.form.controls.method"
|
||||
></cnsl-actions-two-add-action-autocomplete-input>
|
||||
}
|
||||
@if (form.case === 'function') {
|
||||
<cnsl-actions-two-add-action-autocomplete-input
|
||||
label="ACTIONSTWO.EXECUTION.DIALOG.CONDITION.FUNCTIONNAME.TITLE"
|
||||
[items]="listExecutionFunctionsQuery.data()"
|
||||
[control]="form.form.controls.name"
|
||||
>
|
||||
<span class="name-hint cnsl-secondary-text" cnslHint>{{
|
||||
'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.FUNCTIONNAME.DESCRIPTION' | translate
|
||||
}}</span>
|
||||
</cnsl-actions-two-add-action-autocomplete-input>
|
||||
}
|
||||
@if (form.case === 'event') {
|
||||
<div class="emailVerified">
|
||||
<mat-checkbox [formControl]="form.form.controls.all">
|
||||
<div class="execution-condition-text">
|
||||
<span>{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.ALL.TITLE' | translate }}</span>
|
||||
<span class="description cnsl-secondary-text">{{
|
||||
'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.ALL_EVENTS' | translate
|
||||
}}</span>
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<p class="condition-description">{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_GROUP.TITLE' | translate }}</p>
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_GROUP.DESCRIPTION' | translate }}</cnsl-label>
|
||||
<input cnslInput type="text" placeholder="" [formControl]="form.form.controls.group" />
|
||||
</cnsl-form-field>
|
||||
<p class="condition-description">{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_EVENT.TITLE' | translate }}</p>
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_EVENT.DESCRIPTION' | translate }}</cnsl-label>
|
||||
<input cnslInput type="text" placeholder="" [formControl]="form.form.controls.event" />
|
||||
</cnsl-form-field>
|
||||
}
|
||||
<div class="actions">
|
||||
<button mat-stroked-button (click)="back.emit()">
|
||||
{{ 'ACTIONS.BACK' | translate }}
|
||||
</button>
|
||||
<button [disabled]="form.form.invalid" color="primary" mat-raised-button type="submit">
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p class="condition-description">{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_SERVICE.TITLE' | translate }}</p>
|
||||
<cnsl-actions-two-add-action-autocomplete-input
|
||||
label="ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_SERVICE.DESCRIPTION"
|
||||
[items]="listExecutionServicesQuery.data()"
|
||||
[control]="form.form.controls.service"
|
||||
></cnsl-actions-two-add-action-autocomplete-input>
|
||||
|
||||
<p class="condition-description">{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_METHOD.TITLE' | translate }}</p>
|
||||
|
||||
<cnsl-actions-two-add-action-autocomplete-input
|
||||
label="ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_METHOD.DESCRIPTION"
|
||||
[items]="filteredExecutionMethods()"
|
||||
[control]="form.form.controls.method"
|
||||
></cnsl-actions-two-add-action-autocomplete-input>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="form.case === 'function'">
|
||||
<cnsl-actions-two-add-action-autocomplete-input
|
||||
label="ACTIONSTWO.EXECUTION.DIALOG.CONDITION.FUNCTIONNAME.TITLE"
|
||||
[items]="listExecutionFunctionsQuery.data()"
|
||||
[control]="form.form.controls.name"
|
||||
>
|
||||
<span class="name-hint cnsl-secondary-text" cnslHint>{{
|
||||
'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.FUNCTIONNAME.DESCRIPTION' | translate
|
||||
}}</span>
|
||||
</cnsl-actions-two-add-action-autocomplete-input>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="form.case === 'event'">
|
||||
<div class="emailVerified">
|
||||
<mat-checkbox [formControl]="form.form.controls.all">
|
||||
<div class="execution-condition-text">
|
||||
<span>{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.ALL.TITLE' | translate }}</span>
|
||||
<span class="description cnsl-secondary-text">{{
|
||||
'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.ALL_EVENTS' | translate
|
||||
}}</span>
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<p class="condition-description">{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_GROUP.TITLE' | translate }}</p>
|
||||
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_GROUP.DESCRIPTION' | translate }}</cnsl-label>
|
||||
<input cnslInput type="text" placeholder="" [formControl]="form.form.controls.group" />
|
||||
</cnsl-form-field>
|
||||
|
||||
<p class="condition-description">{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_EVENT.TITLE' | translate }}</p>
|
||||
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.EXECUTION.DIALOG.CONDITION.SELECT_EVENT.DESCRIPTION' | translate }}</cnsl-label>
|
||||
<input cnslInput type="text" placeholder="" [formControl]="form.form.controls.event" />
|
||||
</cnsl-form-field>
|
||||
</ng-container>
|
||||
|
||||
<div class="actions">
|
||||
<button mat-stroked-button (click)="back.emit()">
|
||||
{{ 'ACTIONS.BACK' | translate }}
|
||||
</button>
|
||||
<button [disabled]="form.form.invalid" color="primary" mat-raised-button type="submit">
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
}
|
||||
|
||||
+31
-24
@@ -1,28 +1,35 @@
|
||||
<h2 *ngIf="!data.execution" mat-dialog-title>{{ 'ACTIONSTWO.EXECUTION.DIALOG.CREATE_TITLE' | translate }}</h2>
|
||||
<h2 *ngIf="data.execution" mat-dialog-title>{{ 'ACTIONSTWO.EXECUTION.DIALOG.UPDATE_TITLE' | translate }}</h2>
|
||||
@if (!data.execution) {
|
||||
<h2 mat-dialog-title>{{ 'ACTIONSTWO.EXECUTION.DIALOG.CREATE_TITLE' | translate }}</h2>
|
||||
}
|
||||
@if (data.execution) {
|
||||
<h2 mat-dialog-title>{{ 'ACTIONSTWO.EXECUTION.DIALOG.UPDATE_TITLE' | translate }}</h2>
|
||||
}
|
||||
|
||||
<mat-dialog-content>
|
||||
<div class="framework-change-block" [ngSwitch]="page()">
|
||||
<cnsl-actions-two-add-action-type
|
||||
*ngSwitchCase="Page.Type"
|
||||
[initialValue]="typeSignal()"
|
||||
(back)="back()"
|
||||
(continue)="typeSignal.set($event); continue()"
|
||||
></cnsl-actions-two-add-action-type>
|
||||
|
||||
<cnsl-actions-two-add-action-condition
|
||||
*ngSwitchCase="Page.Condition"
|
||||
[conditionType]="typeSignal()"
|
||||
(back)="back()"
|
||||
(continue)="conditionSignal.set({ conditionType: { case: typeSignal(), value: $event } }); continue()"
|
||||
></cnsl-actions-two-add-action-condition>
|
||||
|
||||
<cnsl-actions-two-add-action-target
|
||||
*ngSwitchCase="Page.Target"
|
||||
(back)="back()"
|
||||
[hideBackButton]="!!data.execution"
|
||||
(continue)="targetsSignal.set($event); continue()"
|
||||
[preselectedTargetIds]="preselectedTargetIds"
|
||||
></cnsl-actions-two-add-action-target>
|
||||
<div class="framework-change-block">
|
||||
@switch (page()) {
|
||||
@case (Page.Type) {
|
||||
<cnsl-actions-two-add-action-type
|
||||
[initialValue]="typeSignal()"
|
||||
(back)="back()"
|
||||
(continue)="typeSignal.set($event); continue()"
|
||||
></cnsl-actions-two-add-action-type>
|
||||
}
|
||||
@case (Page.Condition) {
|
||||
<cnsl-actions-two-add-action-condition
|
||||
[conditionType]="typeSignal()"
|
||||
(back)="back()"
|
||||
(continue)="conditionSignal.set({ conditionType: { case: typeSignal(), value: $event } }); continue()"
|
||||
></cnsl-actions-two-add-action-condition>
|
||||
}
|
||||
@case (Page.Target) {
|
||||
<cnsl-actions-two-add-action-target
|
||||
(back)="back()"
|
||||
[hideBackButton]="!!data.execution"
|
||||
(continue)="targetsSignal.set($event); continue()"
|
||||
[preselectedTargetIds]="preselectedTargetIds"
|
||||
></cnsl-actions-two-add-action-target>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</mat-dialog-content>
|
||||
|
||||
+1
-2
@@ -9,7 +9,7 @@ import {
|
||||
ConditionType,
|
||||
} from './actions-two-add-action-condition/actions-two-add-action-condition.component';
|
||||
import { ActionsTwoAddActionTargetComponent } from './actions-two-add-action-target/actions-two-add-action-target.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { Condition, Execution } from '@zitadel/proto/zitadel/action/v2/execution_pb';
|
||||
import { Subject } from 'rxjs';
|
||||
import { SetExecutionRequestSchema } from '@zitadel/proto/zitadel/action/v2/action_service_pb';
|
||||
@@ -54,7 +54,6 @@ export type ActionTwoAddActionDialogResult = MessageInitShape<typeof SetExecutio
|
||||
templateUrl: './actions-two-add-action-dialog.component.html',
|
||||
styleUrls: ['./actions-two-add-action-dialog.component.scss'],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule,
|
||||
MatDialogModule,
|
||||
TranslateModule,
|
||||
|
||||
+72
-72
@@ -1,72 +1,72 @@
|
||||
<form *ngIf="form$ | async as form" class="form-grid" [formGroup]="form" (ngSubmit)="submit()">
|
||||
<p class="target-description">{{ 'ACTIONSTWO.EXECUTION.DIALOG.TARGET.DESCRIPTION' | translate }}</p>
|
||||
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.EXECUTION.DIALOG.TARGET.TARGET.DESCRIPTION' | translate }}</cnsl-label>
|
||||
<input
|
||||
cnslInput
|
||||
#trigger="matAutocompleteTrigger"
|
||||
#input
|
||||
type="text"
|
||||
[formControl]="form.controls.autocomplete"
|
||||
[matAutocomplete]="autoservice"
|
||||
(keydown.enter)="handleEnter($event, form); input.blur(); trigger.closePanel()"
|
||||
/>
|
||||
<mat-autocomplete #autoservice="matAutocomplete">
|
||||
<mat-option *ngIf="targets().state === 'loading'" class="is-loading">
|
||||
<mat-spinner diameter="30"></mat-spinner>
|
||||
</mat-option>
|
||||
<mat-option
|
||||
*ngFor="let target of selectableTargets(); trackBy: trackTarget"
|
||||
#option
|
||||
(click)="addTarget(target, form); option.deselect()"
|
||||
[value]="target.name"
|
||||
>
|
||||
{{ target.name }}
|
||||
</mat-option>
|
||||
</mat-autocomplete>
|
||||
</cnsl-form-field>
|
||||
|
||||
<table mat-table cdkDropList (cdkDropListDropped)="drop($event, form)" [dataSource]="dataSource" [trackBy]="trackTarget">
|
||||
<ng-container matColumnDef="order">
|
||||
<th mat-header-cell *matHeaderCellDef>Reorder</th>
|
||||
<td mat-cell *cnslCellDef="let row; let i = index; dataSource: dataSource">
|
||||
<i class="las la-bars"></i>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef>Name</th>
|
||||
<td mat-cell *cnslCellDef="let row; dataSource: dataSource">
|
||||
<cnsl-project-role-chip [roleName]="row.name">{{ row.name }}</cnsl-project-role-chip>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="deleteAction" stickyEnd>
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *cnslCellDef="let i = index; dataSource: dataSource">
|
||||
<cnsl-table-actions>
|
||||
<button
|
||||
actions
|
||||
matTooltip="{{ 'ACTIONS.REMOVE' | translate }}"
|
||||
color="warn"
|
||||
(click)="removeTarget(i, form)"
|
||||
mat-icon-button
|
||||
>
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
</cnsl-table-actions>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="['order', 'name', 'deleteAction']"></tr>
|
||||
<tr class="drag-row" cdkDrag mat-row *matRowDef="let row; columns: ['order', 'name', 'deleteAction']"></tr>
|
||||
</table>
|
||||
|
||||
<div class="actions">
|
||||
<button *ngIf="!hideBackButton" mat-stroked-button (click)="back.emit()">
|
||||
{{ 'ACTIONS.BACK' | translate }}
|
||||
</button>
|
||||
<span class="fill-space"></span>
|
||||
<button color="primary" [disabled]="form.invalid" mat-raised-button type="submit">
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@if (form$ | async; as form) {
|
||||
<form class="form-grid" [formGroup]="form" (ngSubmit)="submit()">
|
||||
<p class="target-description">{{ 'ACTIONSTWO.EXECUTION.DIALOG.TARGET.DESCRIPTION' | translate }}</p>
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.EXECUTION.DIALOG.TARGET.TARGET.DESCRIPTION' | translate }}</cnsl-label>
|
||||
<input
|
||||
cnslInput
|
||||
#trigger="matAutocompleteTrigger"
|
||||
#input
|
||||
type="text"
|
||||
[formControl]="form.controls.autocomplete"
|
||||
[matAutocomplete]="autoservice"
|
||||
(keydown.enter)="handleEnter($event, form); input.blur(); trigger.closePanel()"
|
||||
/>
|
||||
<mat-autocomplete #autoservice="matAutocomplete">
|
||||
@if (targets().state === 'loading') {
|
||||
<mat-option class="is-loading">
|
||||
<mat-spinner diameter="30"></mat-spinner>
|
||||
</mat-option>
|
||||
}
|
||||
@for (target of selectableTargets(); track trackTarget($index, target)) {
|
||||
<mat-option #option (click)="addTarget(target, form); option.deselect()" [value]="target.name">
|
||||
{{ target.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-autocomplete>
|
||||
</cnsl-form-field>
|
||||
<table mat-table cdkDropList (cdkDropListDropped)="drop($event, form)" [dataSource]="dataSource" [trackBy]="trackTarget">
|
||||
<ng-container matColumnDef="order">
|
||||
<th mat-header-cell *matHeaderCellDef>Reorder</th>
|
||||
<td mat-cell *cnslCellDef="let row; let i = index; dataSource: dataSource">
|
||||
<i class="las la-bars"></i>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef>Name</th>
|
||||
<td mat-cell *cnslCellDef="let row; dataSource: dataSource">
|
||||
<cnsl-project-role-chip [roleName]="row.name">{{ row.name }}</cnsl-project-role-chip>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="deleteAction" stickyEnd>
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *cnslCellDef="let i = index; dataSource: dataSource">
|
||||
<cnsl-table-actions>
|
||||
<button
|
||||
actions
|
||||
matTooltip="{{ 'ACTIONS.REMOVE' | translate }}"
|
||||
color="warn"
|
||||
(click)="removeTarget(i, form)"
|
||||
mat-icon-button
|
||||
>
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
</cnsl-table-actions>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="['order', 'name', 'deleteAction']"></tr>
|
||||
<tr class="drag-row" cdkDrag mat-row *matRowDef="let row; columns: ['order', 'name', 'deleteAction']"></tr>
|
||||
</table>
|
||||
<div class="actions">
|
||||
@if (!hideBackButton) {
|
||||
<button mat-stroked-button (click)="back.emit()">
|
||||
{{ 'ACTIONS.BACK' | translate }}
|
||||
</button>
|
||||
}
|
||||
<span class="fill-space"></span>
|
||||
<button color="primary" [disabled]="form.invalid" mat-raised-button type="submit">
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output, signal } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
@@ -20,7 +19,7 @@ import { ConditionType } from '../actions-two-add-action-condition/actions-two-a
|
||||
selector: 'cnsl-actions-two-add-action-type',
|
||||
templateUrl: './actions-two-add-action-type.component.html',
|
||||
styleUrls: ['./actions-two-add-action-type.component.scss'],
|
||||
imports: [TranslateModule, MatRadioModule, RouterModule, ReactiveFormsModule, FormsModule, CommonModule, MatButtonModule],
|
||||
imports: [TranslateModule, MatRadioModule, RouterModule, ReactiveFormsModule, FormsModule, MatButtonModule],
|
||||
})
|
||||
export class ActionsTwoAddActionTypeComponent {
|
||||
protected readonly typeForm: ReturnType<typeof this.buildActionTypeForm> = this.buildActionTypeForm();
|
||||
|
||||
+62
-63
@@ -2,71 +2,70 @@
|
||||
<mat-dialog-content>
|
||||
<p class="target-description">{{ 'ACTIONSTWO.TARGET.CREATE.DESCRIPTION' | translate }}</p>
|
||||
|
||||
<form *ngIf="targetForm" class="form-grid" [formGroup]="targetForm" (ngSubmit)="closeWithResult()">
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.TARGET.CREATE.NAME' | translate }}</cnsl-label>
|
||||
<input cnslInput type="text" placeholder="" formControlName="name" />
|
||||
<span class="name-hint cnsl-secondary-text" cnslHint>{{
|
||||
'ACTIONSTWO.TARGET.CREATE.NAME_DESCRIPTION' | translate
|
||||
}}</span>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.TARGET.CREATE.ENDPOINT' | translate }}</cnsl-label>
|
||||
<input cnslInput type="text" placeholder="" formControlName="endpoint" />
|
||||
<span class="name-hint cnsl-secondary-text" cnslHint>{{
|
||||
'ACTIONSTWO.TARGET.CREATE.ENDPOINT_DESCRIPTION' | translate
|
||||
}}</span>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.TARGET.CREATE.TYPE' | translate }}</cnsl-label>
|
||||
<mat-select [formControl]="targetForm.controls.type" name="type">
|
||||
<mat-option *ngFor="let type of targetTypes" [value]="type">
|
||||
{{ 'ACTIONSTWO.TARGET.CREATE.TYPES.' + type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<span class="name-hint cnsl-secondary-text types-description">
|
||||
{{ 'ACTIONSTWO.TARGET.CREATE.TYPES_DESCRIPTION' | translate }}
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.TARGET.CREATE.PAYLOAD_TYPE' | translate }}</cnsl-label>
|
||||
<mat-select [formControl]="targetForm.controls.payloadType" name="payloadType">
|
||||
<mat-option *ngFor="let type of payloadTypes" [value]="type">
|
||||
{{ 'ACTIONSTWO.TARGET.CREATE.PAYLOAD_TYPES.' + type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<span class="name-hint cnsl-secondary-text types-description">
|
||||
{{ 'ACTIONSTWO.TARGET.CREATE.PAYLOAD_TYPE_DESCRIPTION' | translate }}
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.TARGET.CREATE.TIMEOUT' | translate }}</cnsl-label>
|
||||
<input cnslInput type="number" placeholder="10" [formControl]="targetForm.controls.timeout" />
|
||||
<span class="name-hint cnsl-secondary-text" cnslHint>{{
|
||||
'ACTIONSTWO.TARGET.CREATE.TIMEOUT_DESCRIPTION' | translate
|
||||
}}</span>
|
||||
</cnsl-form-field>
|
||||
|
||||
<mat-checkbox
|
||||
*ngIf="targetForm.controls.type.value === 'restWebhook' || targetForm.controls.type.value === 'restCall'"
|
||||
class="target-checkbox"
|
||||
[formControl]="targetForm.controls.interruptOnError"
|
||||
>
|
||||
<div class="target-condition-text">
|
||||
<span>{{ 'ACTIONSTWO.TARGET.CREATE.INTERRUPT_ON_ERROR' | translate }}</span>
|
||||
<span class="description cnsl-secondary-text">{{
|
||||
'ACTIONSTWO.TARGET.CREATE.INTERRUPT_ON_ERROR_DESCRIPTION' | translate
|
||||
@if (targetForm) {
|
||||
<form class="form-grid" [formGroup]="targetForm" (ngSubmit)="closeWithResult()">
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.TARGET.CREATE.NAME' | translate }}</cnsl-label>
|
||||
<input cnslInput type="text" placeholder="" formControlName="name" />
|
||||
<span class="name-hint cnsl-secondary-text" cnslHint>{{
|
||||
'ACTIONSTWO.TARGET.CREATE.NAME_DESCRIPTION' | translate
|
||||
}}</span>
|
||||
<span [style.color]="'var(--warn)'" class="description cnsl-secondary-text"
|
||||
>{{ 'ACTIONSTWO.TARGET.CREATE.INTERRUPT_ON_ERROR_WARNING' | translate }}
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.TARGET.CREATE.ENDPOINT' | translate }}</cnsl-label>
|
||||
<input cnslInput type="text" placeholder="" formControlName="endpoint" />
|
||||
<span class="name-hint cnsl-secondary-text" cnslHint>{{
|
||||
'ACTIONSTWO.TARGET.CREATE.ENDPOINT_DESCRIPTION' | translate
|
||||
}}</span>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.TARGET.CREATE.TYPE' | translate }}</cnsl-label>
|
||||
<mat-select [formControl]="targetForm.controls.type" name="type">
|
||||
@for (type of targetTypes; track type) {
|
||||
<mat-option [value]="type">
|
||||
{{ 'ACTIONSTWO.TARGET.CREATE.TYPES.' + type | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<span class="name-hint cnsl-secondary-text types-description">
|
||||
{{ 'ACTIONSTWO.TARGET.CREATE.TYPES_DESCRIPTION' | translate }}
|
||||
</span>
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
</form>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.TARGET.CREATE.PAYLOAD_TYPE' | translate }}</cnsl-label>
|
||||
<mat-select [formControl]="targetForm.controls.payloadType" name="payloadType">
|
||||
@for (type of payloadTypes; track type) {
|
||||
<mat-option [value]="type">
|
||||
{{ 'ACTIONSTWO.TARGET.CREATE.PAYLOAD_TYPES.' + type | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<span class="name-hint cnsl-secondary-text types-description">
|
||||
{{ 'ACTIONSTWO.TARGET.CREATE.PAYLOAD_TYPE_DESCRIPTION' | translate }}
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'ACTIONSTWO.TARGET.CREATE.TIMEOUT' | translate }}</cnsl-label>
|
||||
<input cnslInput type="number" placeholder="10" [formControl]="targetForm.controls.timeout" />
|
||||
<span class="name-hint cnsl-secondary-text" cnslHint>{{
|
||||
'ACTIONSTWO.TARGET.CREATE.TIMEOUT_DESCRIPTION' | translate
|
||||
}}</span>
|
||||
</cnsl-form-field>
|
||||
@if (targetForm.controls.type.value === 'restWebhook' || targetForm.controls.type.value === 'restCall') {
|
||||
<mat-checkbox class="target-checkbox" [formControl]="targetForm.controls.interruptOnError">
|
||||
<div class="target-condition-text">
|
||||
<span>{{ 'ACTIONSTWO.TARGET.CREATE.INTERRUPT_ON_ERROR' | translate }}</span>
|
||||
<span class="description cnsl-secondary-text">{{
|
||||
'ACTIONSTWO.TARGET.CREATE.INTERRUPT_ON_ERROR_DESCRIPTION' | translate
|
||||
}}</span>
|
||||
<span [style.color]="'var(--warn)'" class="description cnsl-secondary-text"
|
||||
>{{ 'ACTIONSTWO.TARGET.CREATE.INTERRUPT_ON_ERROR_WARNING' | translate }}
|
||||
</span>
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
}
|
||||
</form>
|
||||
}
|
||||
</mat-dialog-content>
|
||||
<div>
|
||||
<mat-dialog-actions class="actions">
|
||||
|
||||
+1
-2
@@ -2,7 +2,7 @@ import { Component, Inject } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { FormBuilder, FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { InputModule } from '../../input/input.module';
|
||||
@@ -21,7 +21,6 @@ type TargetTypes = ActionTwoAddTargetDialogComponent['targetTypes'][number];
|
||||
templateUrl: './actions-two-add-target-dialog.component.html',
|
||||
styleUrls: ['./actions-two-add-target-dialog.component.scss'],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule,
|
||||
MatDialogModule,
|
||||
ReactiveFormsModule,
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
<cnsl-form-field class="form-field">
|
||||
<cnsl-label>{{ 'USER.MACHINE.TYPE' | translate }}</cnsl-label>
|
||||
<mat-select [(ngModel)]="type">
|
||||
<mat-option *ngFor="let t of types" [value]="t">
|
||||
{{ 'USER.MACHINE.KEYTYPES.' + t | translate }}
|
||||
</mat-option>
|
||||
@for (t of types; track t) {
|
||||
<mat-option [value]="t">
|
||||
{{ 'USER.MACHINE.KEYTYPES.' + t | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
@@ -16,10 +18,12 @@
|
||||
<input cnslInput [matDatepicker]="picker" [min]="startDate" [formControl]="dateControl" />
|
||||
<mat-datepicker-toggle style="top: 0" cnslSuffix [for]="picker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker [startAt]="startDate"></mat-datepicker>
|
||||
<span cnslError *ngIf="dateControl && dateControl.errors && dateControl.errors['matDatepickerMin']?.min">
|
||||
{{ 'USER.MACHINE.CHOOSEDATEAFTER' | translate }}:
|
||||
{{ dateControl.errors['matDatepickerMin'].min.toDate() | localizedDate: 'EEE dd. MMM' }}
|
||||
</span>
|
||||
@if (dateControl && dateControl.errors && dateControl.errors['matDatepickerMin']?.min) {
|
||||
<span cnslError>
|
||||
{{ 'USER.MACHINE.CHOOSEDATEAFTER' | translate }}:
|
||||
{{ dateControl.errors['matDatepickerMin'].min.toDate() | localizedDate: 'EEE dd. MMM' }}
|
||||
</span>
|
||||
}
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
|
||||
@@ -5,17 +5,18 @@
|
||||
<div mat-dialog-content>
|
||||
<p class="desc cnsl-secondary-text">{{ 'ORG_DETAIL.MEMBER.ADDDESCRIPTION' | translate }}</p>
|
||||
|
||||
<ng-container *ngIf="showCreationTypeSelector">
|
||||
@if (showCreationTypeSelector) {
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-label>{{ 'MEMBER.CREATIONTYPE' | translate }}</cnsl-label>
|
||||
<mat-select [(ngModel)]="creationType" (selectionChange)="loadRoles()">
|
||||
<mat-option *ngFor="let type of creationTypes" [value]="type.type" [disabled]="(type.disabled$ | async) === false">
|
||||
{{ 'MEMBER.CREATIONTYPES.' + type.type | translate }}
|
||||
</mat-option>
|
||||
@for (type of creationTypes; track type) {
|
||||
<mat-option [value]="type.type" [disabled]="(type.disabled$ | async) === false">
|
||||
{{ 'MEMBER.CREATIONTYPES.' + type.type | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<ng-container *ngIf="creationType === CreationType.PROJECT_OWNED || creationType === CreationType.PROJECT_GRANTED">
|
||||
@if (creationType === CreationType.PROJECT_OWNED || creationType === CreationType.PROJECT_GRANTED) {
|
||||
<p>{{ 'PROJECT.GRANT.CREATE.SEL_PROJECT' | translate }}</p>
|
||||
<cnsl-search-project-autocomplete
|
||||
class="block"
|
||||
@@ -29,26 +30,22 @@
|
||||
"
|
||||
>
|
||||
</cnsl-search-project-autocomplete>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
}
|
||||
}
|
||||
|
||||
<cnsl-search-user-autocomplete [users]="preselectedUsers" (selectionChanged)="users = $any($event)">
|
||||
</cnsl-search-user-autocomplete>
|
||||
|
||||
<div class="roles-selection">
|
||||
<mat-checkbox
|
||||
class="role-cb"
|
||||
*ngFor="let role of memberRoleOptions"
|
||||
color="primary"
|
||||
(change)="toggleRole(role)"
|
||||
[checked]="roles.includes(role)"
|
||||
>
|
||||
<div class="role-cb-content">
|
||||
<div class="cnsl-chip-dot" [style.background]="getColor(role)"></div>
|
||||
<span data-e2e="role-checkbox">{{ role | roletransform }}</span>
|
||||
<i class="info-hover las la-question-circle" matTooltip="{{ 'MEMBERROLES.' + role | translate }}"></i>
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
@for (role of memberRoleOptions; track role) {
|
||||
<mat-checkbox class="role-cb" color="primary" (change)="toggleRole(role)" [checked]="roles.includes(role)">
|
||||
<div class="role-cb-content">
|
||||
<div class="cnsl-chip-dot" [style.background]="getColor(role)"></div>
|
||||
<span data-e2e="role-checkbox">{{ role | roletransform }}</span>
|
||||
<i class="info-hover las la-question-circle" matTooltip="{{ 'MEMBERROLES.' + role | translate }}"></i>
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
|
||||
+9
-13
@@ -2,19 +2,15 @@
|
||||
<div mat-dialog-content>
|
||||
<p class="desc">{{ 'MEMBER.EDITFOR' | translate: { value: data.user } }}</p>
|
||||
<div class="roles-selection">
|
||||
<mat-checkbox
|
||||
class="role-cb"
|
||||
*ngFor="let role of allRoles"
|
||||
color="primary"
|
||||
(change)="toggleRole(role)"
|
||||
[checked]="selectedRoles.includes(role)"
|
||||
>
|
||||
<div class="role-cb-content">
|
||||
<div class="cnsl-chip-dot" [style.background]="getColor(role)"></div>
|
||||
<span>{{ role | roletransform }}</span>
|
||||
<i class="info-hover las la-question-circle" matTooltip="{{ 'MEMBERROLES.' + role | translate }}"></i>
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
@for (role of allRoles; track role) {
|
||||
<mat-checkbox class="role-cb" color="primary" (change)="toggleRole(role)" [checked]="selectedRoles.includes(role)">
|
||||
<div class="role-cb-content">
|
||||
<div class="cnsl-chip-dot" [style.background]="getColor(role)"></div>
|
||||
<span>{{ role | roletransform }}</span>
|
||||
<i class="info-hover las la-question-circle" matTooltip="{{ 'MEMBERROLES.' + role | translate }}"></i>
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
<input cnslInput [matDatepicker]="picker" [min]="startDate" [formControl]="dateControl" />
|
||||
<mat-datepicker-toggle style="top: 0" cnslSuffix [for]="picker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker startView="year" [startAt]="startDate"></mat-datepicker>
|
||||
<span cnslError *ngIf="dateControl && dateControl.errors && dateControl.errors['matDatepickerMin']?.min">
|
||||
{{ 'USER.PERSONALACCESSTOKEN.ADD.CHOOSEDATEAFTER' | translate }}:
|
||||
{{ dateControl.errors['matDatepickerMin'].min.toDate() | localizedDate: 'EEE dd. MMM' }}
|
||||
</span>
|
||||
@if (dateControl && dateControl.errors && dateControl.errors['matDatepickerMin']?.min) {
|
||||
<span cnslError>
|
||||
{{ 'USER.PERSONALACCESSTOKEN.ADD.CHOOSEDATEAFTER' | translate }}:
|
||||
{{ dateControl.errors['matDatepickerMin'].min.toDate() | localizedDate: 'EEE dd. MMM' }}
|
||||
</span>
|
||||
}
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
|
||||
+38
-31
@@ -1,5 +1,5 @@
|
||||
<div class="auth-method-radio-button-wrapper" [ngClass]="{ compact: compact }">
|
||||
<ng-container *ngFor="let method of authMethods; index as i">
|
||||
@for (method of authMethods; track method; let i = $index) {
|
||||
<input
|
||||
type="radio"
|
||||
[disabled]="method.disabled"
|
||||
@@ -13,43 +13,50 @@
|
||||
[ngClass]="{ compact: compact, first: i === 0, last: i === authMethods.length - 1 }"
|
||||
[for]="method.key"
|
||||
>
|
||||
<div
|
||||
class="recommended"
|
||||
[ngClass]="{ not: method.notRecommended }"
|
||||
*ngIf="method.recommended || method.notRecommended"
|
||||
>
|
||||
{{ (method.recommended ? 'APP.OIDC.RECOMMENDED' : 'APP.OIDC.NOTRECOMMENDED') | translate }}
|
||||
</div>
|
||||
|
||||
@if (method.recommended || method.notRecommended) {
|
||||
<div class="recommended" [ngClass]="{ not: method.notRecommended }">
|
||||
{{ (method.recommended ? 'APP.OIDC.RECOMMENDED' : 'APP.OIDC.NOTRECOMMENDED') | translate }}
|
||||
</div>
|
||||
}
|
||||
<div class="cnsl-radio-header" [ngStyle]="{ background: method.background }">
|
||||
<span>{{ method.prefix }}</span>
|
||||
<div class="current" *ngIf="current === method.key">{{ 'APP.OIDC.CURRENT' | translate }}</div>
|
||||
@if (current === method.key) {
|
||||
<div class="current">{{ 'APP.OIDC.CURRENT' | translate }}</div>
|
||||
}
|
||||
</div>
|
||||
<p>{{ method.titleI18nKey | translate }}</p>
|
||||
<p class="type-desc cnsl-secondary-text">{{ method.descI18nKey | translate }}</p>
|
||||
<span class="fill-space"></span>
|
||||
<div class="app-specs cnsl-secondary-text">
|
||||
<div class="row" *ngIf="isOIDC && method && method.responseType !== undefined">
|
||||
<span class="row-entry">{{ 'APP.OIDC.RESPONSETYPE' | translate }}</span>
|
||||
<span>{{ 'APP.OIDC.RESPONSE.' + method.responseType.toString() | translate }}</span>
|
||||
</div>
|
||||
<div class="row" *ngIf="isOIDC && method.grantType !== undefined">
|
||||
<span class="row-entry">{{ 'APP.GRANT' | translate }}</span>
|
||||
<span
|
||||
><span class="space" *ngFor="let grant of method.grantType">{{
|
||||
'APP.OIDC.GRANT.' + grant.toString() | translate
|
||||
}}</span></span
|
||||
>
|
||||
</div>
|
||||
<div class="row" *ngIf="isOIDC && method.authMethod !== undefined">
|
||||
<span class="row-entry">{{ 'APP.AUTHMETHOD' | translate }}</span>
|
||||
<span>{{ 'APP.OIDC.AUTHMETHOD.' + method.authMethod.toString() | translate }}</span>
|
||||
</div>
|
||||
<div class="row" *ngIf="!isOIDC && method.apiAuthMethod !== undefined">
|
||||
<span class="row-entry">{{ 'APP.AUTHMETHOD' | translate }}</span>
|
||||
<span>{{ 'APP.API.AUTHMETHOD.' + method.apiAuthMethod.toString() | translate }}</span>
|
||||
</div>
|
||||
@if (isOIDC && method && method.responseType !== undefined) {
|
||||
<div class="row">
|
||||
<span class="row-entry">{{ 'APP.OIDC.RESPONSETYPE' | translate }}</span>
|
||||
<span>{{ 'APP.OIDC.RESPONSE.' + method.responseType.toString() | translate }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (isOIDC && method.grantType !== undefined) {
|
||||
<div class="row">
|
||||
<span class="row-entry">{{ 'APP.GRANT' | translate }}</span>
|
||||
<span>
|
||||
@for (grant of method.grantType; track grant) {
|
||||
<span class="space">{{ 'APP.OIDC.GRANT.' + grant.toString() | translate }}</span>
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
@if (isOIDC && method.authMethod !== undefined) {
|
||||
<div class="row">
|
||||
<span class="row-entry">{{ 'APP.AUTHMETHOD' | translate }}</span>
|
||||
<span>{{ 'APP.OIDC.AUTHMETHOD.' + method.authMethod.toString() | translate }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (!isOIDC && method.apiAuthMethod !== undefined) {
|
||||
<div class="row">
|
||||
<span class="row-entry">{{ 'APP.AUTHMETHOD' | translate }}</span>
|
||||
<span>{{ 'APP.API.AUTHMETHOD.' + method.apiAuthMethod.toString() | translate }}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</label>
|
||||
</ng-container>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="app-type-radio-button-wrapper">
|
||||
<ng-container *ngFor="let type of types">
|
||||
@for (type of types; track type) {
|
||||
<input class="app" type="radio" (change)="emitChange()" [value]="type" [(ngModel)]="selected" [id]="type.prefix" />
|
||||
<label class="cnsl-type-radio-button" [for]="type.prefix">
|
||||
<div class="cnsl-type-radio-header" [ngStyle]="{ background: type.background }">
|
||||
@@ -8,7 +8,9 @@
|
||||
<p>{{ type.titleI18nKey | translate }}</p>
|
||||
<p class="type-desc cnsl-secondary-text">{{ type.descI18nKey | translate }}</p>
|
||||
<span class="fill-space"></span>
|
||||
<span class="cnsl-type-protocol state" *ngIf="type.protocol">{{ type.protocol }}</span>
|
||||
@if (type.protocol) {
|
||||
<span class="cnsl-type-protocol state">{{ type.protocol }}</span>
|
||||
}
|
||||
</label>
|
||||
</ng-container>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -13,11 +13,12 @@
|
||||
}"
|
||||
[ngClass]="{ active: active }"
|
||||
>
|
||||
<ng-container *ngIf="isMachine; else human">
|
||||
@if (isMachine) {
|
||||
<i class="machine-icon las la-robot"></i>
|
||||
</ng-container>
|
||||
<ng-template #human>
|
||||
} @else {
|
||||
<span class="dontcloseonclick">{{ credentials }}</span>
|
||||
<img class="dontcloseonclick" *ngIf="avatarUrl" [src]="avatarUrl" (error)="errorHandler($event)" />
|
||||
</ng-template>
|
||||
@if (avatarUrl) {
|
||||
<img class="dontcloseonclick" [src]="avatarUrl" (error)="errorHandler($event)" />
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -1,19 +1,37 @@
|
||||
<div class="card" [ngClass]="{ nomargin: nomargin, warn: warn }" data-e2e="app-card">
|
||||
<div *ngIf="title || description" class="header" [ngClass]="{ 'bottom-margin': expanded }">
|
||||
<div *ngIf="title" class="row">
|
||||
<h2 class="title" data-e2e="app-card-title">{{ title }}</h2>
|
||||
<span class="fill-space"></span>
|
||||
<ng-content select="[card-actions]"></ng-content>
|
||||
<button class="button" type="button" matTooltip="Expand or collapse" mat-icon-button (click)="expanded = !expanded">
|
||||
<mat-icon *ngIf="!expanded">keyboard_arrow_down</mat-icon>
|
||||
<mat-icon *ngIf="expanded">keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
@if (title || description) {
|
||||
<div class="header" [ngClass]="{ 'bottom-margin': expanded }">
|
||||
@if (title) {
|
||||
<div class="row">
|
||||
<h2 class="title" data-e2e="app-card-title">{{ title }}</h2>
|
||||
<span class="fill-space"></span>
|
||||
<ng-content select="[card-actions]"></ng-content>
|
||||
<button
|
||||
class="button"
|
||||
type="button"
|
||||
matTooltip="Expand or collapse"
|
||||
mat-icon-button
|
||||
(click)="expanded = !expanded"
|
||||
>
|
||||
@if (!expanded) {
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
}
|
||||
@if (expanded) {
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
@if (description) {
|
||||
<p class="desc cnsl-secondary-text">
|
||||
{{ description }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<p *ngIf="description" class="desc cnsl-secondary-text">
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-content" *ngIf="expanded">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
}
|
||||
@if (expanded) {
|
||||
<div class="card-content">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -3,49 +3,63 @@
|
||||
</div>
|
||||
|
||||
<div class="scroll-container">
|
||||
<li class="item" *ngFor="let hist of data | async; index as histindex">
|
||||
<span *ngIf="hist.values[0].dates[0]" class="date">
|
||||
{{ hist.values[0].dates[0] | timestampToDate | localizedDate: 'dd. MMM yyyy' }}
|
||||
</span>
|
||||
<div class="item" *ngFor="let dayelement of hist.values; index as i">
|
||||
<div class="row">
|
||||
<cnsl-avatar
|
||||
matTooltip="{{ dayelement.editorDisplayName }}"
|
||||
*ngIf="dayelement.editorDisplayName; else spacer"
|
||||
class="avatar"
|
||||
[name]="dayelement.editorDisplayName"
|
||||
[size]="32"
|
||||
[forColor]="dayelement?.editorPreferredLoginName ?? 'A'"
|
||||
[avatarUrl]="dayelement.editorAvatarUrl || ''"
|
||||
>
|
||||
</cnsl-avatar>
|
||||
<ng-template #spacer>
|
||||
<div class="spacer"></div>
|
||||
</ng-template>
|
||||
<div class="change-actions">
|
||||
<div class="change-action" *ngFor="let action of dayelement.eventTypes; index as j">
|
||||
<div>
|
||||
<span class="msg">{{ action.localizedMessage }}</span>
|
||||
<span
|
||||
class="block"
|
||||
matTooltip="{{ dayelement.dates[j] | timestampToDate | localizedDate: 'dd. MM yyyy, HH:mm:ss.SSS' }}"
|
||||
>{{ dayelement.dates[j] | timestampToDate | localizedDate: 'HH:mm' }}</span
|
||||
@for (hist of data | async; track hist; let histindex = $index) {
|
||||
<li class="item">
|
||||
@if (hist.values[0].dates[0]) {
|
||||
<span class="date">
|
||||
{{ hist.values[0].dates[0] | timestampToDate | localizedDate: 'dd. MMM yyyy' }}
|
||||
</span>
|
||||
}
|
||||
@for (dayelement of hist.values; track dayelement; let i = $index) {
|
||||
<div class="item">
|
||||
<div class="row">
|
||||
@if (dayelement.editorDisplayName) {
|
||||
<cnsl-avatar
|
||||
matTooltip="{{ dayelement.editorDisplayName }}"
|
||||
class="avatar"
|
||||
[name]="dayelement.editorDisplayName"
|
||||
[size]="32"
|
||||
[forColor]="dayelement?.editorPreferredLoginName ?? 'A'"
|
||||
[avatarUrl]="dayelement.editorAvatarUrl || ''"
|
||||
>
|
||||
</cnsl-avatar>
|
||||
} @else {
|
||||
<div class="spacer"></div>
|
||||
}
|
||||
<div class="change-actions">
|
||||
@for (action of dayelement.eventTypes; track action; let j = $index) {
|
||||
<div class="change-action">
|
||||
<div>
|
||||
<span class="msg">{{ action.localizedMessage }}</span>
|
||||
<span
|
||||
class="block"
|
||||
matTooltip="{{ dayelement.dates[j] | timestampToDate | localizedDate: 'dd. MM yyyy, HH:mm:ss.SSS' }}"
|
||||
>{{ dayelement.dates[j] | timestampToDate | localizedDate: 'HH:mm' }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
<div class="ch-sp-wrapper">
|
||||
<mat-spinner *ngIf="loading | async" diameter="25"></mat-spinner>
|
||||
@if (loading | async) {
|
||||
<mat-spinner diameter="25"></mat-spinner>
|
||||
}
|
||||
</div>
|
||||
|
||||
<button (click)="more()" class="load-more-button" *ngIf="!bottom" mat-stroked-button>
|
||||
{{ 'CHANGES.LOADMORE' | translate }}
|
||||
</button>
|
||||
@if (!bottom) {
|
||||
<button (click)="more()" class="load-more-button" mat-stroked-button>
|
||||
{{ 'CHANGES.LOADMORE' | translate }}
|
||||
</button>
|
||||
}
|
||||
|
||||
<div *ngIf="bottom" class="end-container">
|
||||
<span class="cnsl-secondary-text">{{ 'CHANGES.BOTTOM' | translate }}</span>
|
||||
</div>
|
||||
@if (bottom) {
|
||||
<div class="end-container">
|
||||
<span class="cnsl-secondary-text">{{ 'CHANGES.BOTTOM' | translate }}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<div class="contributor-groups">
|
||||
<div class="contributor-people">
|
||||
<div class="contributor-img-list" [ngClass]="{ 'padd-left': totalResult > 0 }" [@cardAnimation]="totalResult">
|
||||
<mat-spinner class="spinner" diameter="20" *ngIf="loading"></mat-spinner>
|
||||
<ng-container *ngIf="totalResult < 10; else compact">
|
||||
<ng-container *ngFor="let member of membersSubject | async; index as i">
|
||||
@if (loading) {
|
||||
<mat-spinner class="spinner" diameter="20"></mat-spinner>
|
||||
}
|
||||
@if (totalResult < 10) {
|
||||
@for (member of membersSubject | async; track member; let i = $index) {
|
||||
<div
|
||||
@animate
|
||||
(click)="emitShowDetail()"
|
||||
@@ -12,24 +14,23 @@
|
||||
[ngStyle]="{ 'z-index': 20 - i }"
|
||||
data-e2e="member-avatar"
|
||||
>
|
||||
<cnsl-avatar
|
||||
*ngIf="member && member.userType === UserType.TYPE_HUMAN; else cog"
|
||||
class="contributor-avatar dontcloseonclick"
|
||||
[avatarUrl]="member.avatarUrl || ''"
|
||||
[name]="member.displayName"
|
||||
[forColor]="member.preferredLoginName"
|
||||
[size]="32"
|
||||
>
|
||||
</cnsl-avatar>
|
||||
<ng-template #cog>
|
||||
@if (member && member.userType === UserType.TYPE_HUMAN) {
|
||||
<cnsl-avatar
|
||||
class="contributor-avatar dontcloseonclick"
|
||||
[avatarUrl]="member.avatarUrl || ''"
|
||||
[name]="member.displayName"
|
||||
[forColor]="member.preferredLoginName"
|
||||
[size]="32"
|
||||
>
|
||||
</cnsl-avatar>
|
||||
} @else {
|
||||
<cnsl-avatar [forColor]="member.preferredLoginName" [isMachine]="true">
|
||||
<i class="las la-robot"></i>
|
||||
</cnsl-avatar>
|
||||
</ng-template>
|
||||
}
|
||||
</div>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ng-template #compact>
|
||||
}
|
||||
} @else {
|
||||
<div
|
||||
(click)="emitShowDetail()"
|
||||
class="contributor-avatar-circle"
|
||||
@@ -37,7 +38,7 @@
|
||||
>
|
||||
<span>{{ totalResult }}</span>
|
||||
</div>
|
||||
</ng-template>
|
||||
}
|
||||
<button
|
||||
class="add-img"
|
||||
[ngClass]="{ 'no-margin': totalResult === 0 }"
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
<button (click)="close()" mat-icon-button matTooltip="{{ 'ACTIONS.CLOSE' | translate }}">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
<span class="abort">{{ title }}</span
|
||||
><span class="abort-2" *ngIf="createSteps > 1"
|
||||
>{{ 'ACTIONS.STEP' | translate }} {{ currentCreateStep }} {{ 'ACTIONS.OF' | translate }} {{ createSteps }}</span
|
||||
>
|
||||
<span class="abort">{{ title }}</span>
|
||||
@if (createSteps > 1) {
|
||||
<span class="abort-2"
|
||||
>{{ 'ACTIONS.STEP' | translate }} {{ currentCreateStep }} {{ 'ACTIONS.OF' | translate }} {{ createSteps }}</span
|
||||
>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="create-layout-content">
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
<div class="detail-layout-top-view">
|
||||
<div>
|
||||
<div class="back-row">
|
||||
<a *ngIf="hasBackButton" cnslBack mat-icon-button>
|
||||
<mat-icon class="icon">arrow_back</mat-icon>
|
||||
</a>
|
||||
@if (hasBackButton) {
|
||||
<a cnslBack mat-icon-button>
|
||||
<mat-icon class="icon">arrow_back</mat-icon>
|
||||
</a>
|
||||
}
|
||||
<div>
|
||||
<h1>{{ title }}</h1>
|
||||
<ng-content select="[sub]"></ng-content>
|
||||
|
||||
@@ -1,76 +1,87 @@
|
||||
<h2 class="title" mat-dialog-title>{{ 'IAM.EVENTS.DIALOG.TITLE' | translate }}</h2>
|
||||
<div mat-dialog-content>
|
||||
<div class="event-data-column" *ngIf="event && (event | toobject) as event">
|
||||
<div class="data-row" *ngIf="event && event.type && event.type.localized && event.type.localized.localizedMessage">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.TYPE' | translate }}</span>
|
||||
<span>{{ event.type.localized.localizedMessage }}</span>
|
||||
</div>
|
||||
|
||||
<div class="data-row" *ngIf="event && event.creationDate">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.CREATIONDATE' | translate }}</span>
|
||||
<span>{{ event.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="data-row" *ngIf="event && event.aggregate && event.aggregate.id">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.AGGREGATEID' | translate }}</span>
|
||||
<span>{{ event.aggregate.id }}</span>
|
||||
</div>
|
||||
|
||||
<div class="data-row" *ngIf="event && event.aggregate && event.aggregate.resourceOwner">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.RESOURCEOWNER' | translate }}</span>
|
||||
<span>{{ event.aggregate.resourceOwner }}</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="data-row"
|
||||
*ngIf="
|
||||
@if (event && (event | toobject); as event) {
|
||||
<div class="event-data-column">
|
||||
@if (event && event.type && event.type.localized && event.type.localized.localizedMessage) {
|
||||
<div class="data-row">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.TYPE' | translate }}</span>
|
||||
<span>{{ event.type.localized.localizedMessage }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (event && event.creationDate) {
|
||||
<div class="data-row">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.CREATIONDATE' | translate }}</span>
|
||||
<span>{{ event.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (event && event.aggregate && event.aggregate.id) {
|
||||
<div class="data-row">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.AGGREGATEID' | translate }}</span>
|
||||
<span>{{ event.aggregate.id }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (event && event.aggregate && event.aggregate.resourceOwner) {
|
||||
<div class="data-row">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.RESOURCEOWNER' | translate }}</span>
|
||||
<span>{{ event.aggregate.resourceOwner }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (
|
||||
event &&
|
||||
event.aggregate &&
|
||||
event.aggregate.type &&
|
||||
event.aggregate.type.localized &&
|
||||
event.aggregate.type.localized.localizedMessage
|
||||
"
|
||||
>
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.AGGREGATETYPE' | translate }}</span>
|
||||
<span class="state aggregate-type">{{ event.aggregate.type.localized.localizedMessage }}</span>
|
||||
) {
|
||||
<div class="data-row">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.AGGREGATETYPE' | translate }}</span>
|
||||
<span class="state aggregate-type">{{ event.aggregate.type.localized.localizedMessage }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (event && event.editor?.userId) {
|
||||
<div class="data-row">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.EDITORID' | translate }}</span>
|
||||
<span>{{ event.editor?.userId }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (event && event.editor?.displayName) {
|
||||
<div class="data-row">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.EDITOR' | translate }}</span>
|
||||
<span>{{ event.editor?.displayName }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (event && event.sequence) {
|
||||
<div class="data-row">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.SEQUENCE' | translate }}</span>
|
||||
<span>{{ event.sequence }}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="data-row" *ngIf="event && event.editor?.userId">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.EDITORID' | translate }}</span>
|
||||
<span>{{ event.editor?.userId }}</span>
|
||||
@if (opened$ | async) {
|
||||
<div class="code">
|
||||
@if (event) {
|
||||
<ngx-codemirror
|
||||
[ngModel]="event | topayload | json"
|
||||
[options]="{
|
||||
height: 'auto',
|
||||
readOnly: true,
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
indentWithTabs: false,
|
||||
tabSize: 2,
|
||||
theme: 'material',
|
||||
mode: {
|
||||
name: 'javascript',
|
||||
json: true,
|
||||
statementIndent: 2,
|
||||
},
|
||||
}"
|
||||
></ngx-codemirror>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="data-row" *ngIf="event && event.editor?.displayName">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.EDITOR' | translate }}</span>
|
||||
<span>{{ event.editor?.displayName }}</span>
|
||||
</div>
|
||||
|
||||
<div class="data-row" *ngIf="event && event.sequence">
|
||||
<span class="label cnsl-secondary-text">{{ 'IAM.EVENTS.SEQUENCE' | translate }}</span>
|
||||
<span>{{ event.sequence }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="code" *ngIf="opened$ | async">
|
||||
<ngx-codemirror
|
||||
*ngIf="event"
|
||||
[ngModel]="event | topayload | json"
|
||||
[options]="{
|
||||
height: 'auto',
|
||||
readOnly: true,
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
indentWithTabs: false,
|
||||
tabSize: 2,
|
||||
theme: 'material',
|
||||
mode: {
|
||||
name: 'javascript',
|
||||
json: true,
|
||||
statementIndent: 2,
|
||||
},
|
||||
}"
|
||||
></ngx-codemirror>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
<button mat-stroked-button (click)="closeDialog()">
|
||||
|
||||
+123
-94
@@ -14,110 +14,139 @@
|
||||
</div>
|
||||
|
||||
<div mat-dialog-content cdkFocusInitial autofocus>
|
||||
<div *ngIf="showNew && !(dns || http)">
|
||||
<p class="domain-desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION' | translate }}</p>
|
||||
<p class="domain-desc">
|
||||
{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_HTML' | translate }}
|
||||
@if (showNew && !(dns || http)) {
|
||||
<div>
|
||||
<p class="domain-desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION' | translate }}</p>
|
||||
<p class="domain-desc">
|
||||
{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_HTML' | translate }}
|
||||
</p>
|
||||
<p class="domain-desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_DNS' | translate }}</p>
|
||||
<p class="domain-desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_SKIP' | translate }}</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (showNew && !(dns || http)) {
|
||||
<cnsl-info-section [type]="InfoSectionType.WARN" class="desc">{{
|
||||
'ORG.PAGES.ORGDOMAIN.VERIFICATION_VALIDATION_DESC' | translate
|
||||
}}</cnsl-info-section>
|
||||
}
|
||||
|
||||
@if (!showNew && !(dns || http)) {
|
||||
<p class="desc">
|
||||
{{
|
||||
'ORG.PAGES.ORGDOMAIN.VERIFICATION_VALIDATION_ONGOING'
|
||||
| translate: { value: domain?.validationType == 1 ? 'HTTP' : 'DNS' }
|
||||
}}
|
||||
</p>
|
||||
<p class="domain-desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_DNS' | translate }}</p>
|
||||
<p class="domain-desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_SKIP' | translate }}</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
<cnsl-info-section [type]="InfoSectionType.WARN" *ngIf="showNew && !(dns || http)" class="desc">{{
|
||||
'ORG.PAGES.ORGDOMAIN.VERIFICATION_VALIDATION_DESC' | translate
|
||||
}}</cnsl-info-section>
|
||||
|
||||
<p *ngIf="!showNew && !(dns || http)" class="desc">
|
||||
{{
|
||||
'ORG.PAGES.ORGDOMAIN.VERIFICATION_VALIDATION_ONGOING'
|
||||
| translate: { value: domain?.validationType == 1 ? 'HTTP' : 'DNS' }
|
||||
}}
|
||||
</p>
|
||||
|
||||
<ng-container *ngIf="showNew">
|
||||
<div *ngIf="http">
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_HTTP_DESC' | translate: { value: domain?.domainName } }}</p>
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_HTTP_URL_LABEL' | translate }}</p>
|
||||
<div class="domain-entry" *ngIf="http.url">
|
||||
<p>{{ http.url }}</p>
|
||||
<button
|
||||
color="primary"
|
||||
[disabled]="copied === data.clientSecret"
|
||||
matTooltip="copy to clipboard"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="http.url"
|
||||
(copiedValue)="copied = $event"
|
||||
mat-icon-button
|
||||
>
|
||||
<i *ngIf="copied !== http.url" class="las la-clipboard"></i>
|
||||
<i *ngIf="copied === http.url" class="las la-clipboard-check"></i>
|
||||
</button>
|
||||
@if (showNew) {
|
||||
@if (http) {
|
||||
<div>
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_HTTP_DESC' | translate: { value: domain?.domainName } }}</p>
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_HTTP_URL_LABEL' | translate }}</p>
|
||||
@if (http.url) {
|
||||
<div class="domain-entry">
|
||||
<p>{{ http.url }}</p>
|
||||
<button
|
||||
color="primary"
|
||||
[disabled]="copied === data.clientSecret"
|
||||
matTooltip="copy to clipboard"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="http.url"
|
||||
(copiedValue)="copied = $event"
|
||||
mat-icon-button
|
||||
>
|
||||
@if (copied !== http.url) {
|
||||
<i class="las la-clipboard"></i>
|
||||
}
|
||||
@if (copied === http.url) {
|
||||
<i class="las la-clipboard-check"></i>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_HTTP_FILE_LABEL' | translate }}</p>
|
||||
<button mat-stroked-button (click)="saveFile()" color="primary">{{ 'ORG.PAGES.DOWNLOAD_FILE' | translate }}</button>
|
||||
</div>
|
||||
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_HTTP_FILE_LABEL' | translate }}</p>
|
||||
<button mat-stroked-button (click)="saveFile()" color="primary">{{ 'ORG.PAGES.DOWNLOAD_FILE' | translate }}</button>
|
||||
</div>
|
||||
|
||||
<div *ngIf="dns">
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_DNS_DESC' | translate: { value: domain?.domainName } }}</p>
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_DNS_HOST_LABEL' | translate }}</p>
|
||||
<div class="domain-line">
|
||||
<div class="domain-entry" *ngIf="dns.token">
|
||||
<p>{{ dnsChallenge }}</p>
|
||||
<button
|
||||
color="primary"
|
||||
[disabled]="copied === data.clientSecret"
|
||||
matTooltip="copy to clipboard"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="dnsChallenge"
|
||||
(copiedValue)="copied = $event"
|
||||
mat-icon-button
|
||||
>
|
||||
<i *ngIf="copied !== dnsChallenge" class="las la-clipboard"></i>
|
||||
<i *ngIf="copied === dnsChallenge" class="las la-clipboard-check"></i>
|
||||
</button>
|
||||
}
|
||||
@if (dns) {
|
||||
<div>
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_DNS_DESC' | translate: { value: domain?.domainName } }}</p>
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_DNS_HOST_LABEL' | translate }}</p>
|
||||
<div class="domain-line">
|
||||
@if (dns.token) {
|
||||
<div class="domain-entry">
|
||||
<p>{{ dnsChallenge }}</p>
|
||||
<button
|
||||
color="primary"
|
||||
[disabled]="copied === data.clientSecret"
|
||||
matTooltip="copy to clipboard"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="dnsChallenge"
|
||||
(copiedValue)="copied = $event"
|
||||
mat-icon-button
|
||||
>
|
||||
@if (copied !== dnsChallenge) {
|
||||
<i class="las la-clipboard"></i>
|
||||
}
|
||||
@if (copied === dnsChallenge) {
|
||||
<i class="las la-clipboard-check"></i>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
<span>.{{ domain?.domainName }}</span>
|
||||
</div>
|
||||
<span>.{{ domain?.domainName }}</span>
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_DNS_CHALLENGE_LABEL' | translate }}</p>
|
||||
@if (dns.token) {
|
||||
<div class="domain-entry">
|
||||
<p>{{ dns.token }}</p>
|
||||
<button
|
||||
color="primary"
|
||||
[disabled]="copied === data.clientSecret"
|
||||
matTooltip="copy to clipboard"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="dns.token"
|
||||
(copiedValue)="copied = $event"
|
||||
mat-icon-button
|
||||
>
|
||||
@if (copied !== dns.token) {
|
||||
<i class="las la-clipboard"></i>
|
||||
}
|
||||
@if (copied === dns.token) {
|
||||
<i class="las la-clipboard-check"></i>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_DNS_CHALLENGE_LABEL' | translate }}</p>
|
||||
<div class="domain-entry" *ngIf="dns.token">
|
||||
<p>{{ dns.token }}</p>
|
||||
<button
|
||||
color="primary"
|
||||
[disabled]="copied === data.clientSecret"
|
||||
matTooltip="copy to clipboard"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="dns.token"
|
||||
(copiedValue)="copied = $event"
|
||||
mat-icon-button
|
||||
>
|
||||
<i *ngIf="copied !== dns.token" class="las la-clipboard"></i>
|
||||
<i *ngIf="copied === dns.token" class="las la-clipboard-check"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
<button
|
||||
*ngIf="!showNew || dns || http"
|
||||
color="primary"
|
||||
type="submit"
|
||||
mat-raised-button
|
||||
class="verify-button"
|
||||
(click)="validate()"
|
||||
>
|
||||
{{ 'ACTIONS.VERIFY' | translate }}
|
||||
</button>
|
||||
<mat-spinner class="spinner" *ngIf="validating" diameter="20" mode="indeterminate"></mat-spinner>
|
||||
@if (!showNew || dns || http) {
|
||||
<button color="primary" type="submit" mat-raised-button class="verify-button" (click)="validate()">
|
||||
{{ 'ACTIONS.VERIFY' | translate }}
|
||||
</button>
|
||||
}
|
||||
@if (validating) {
|
||||
<mat-spinner class="spinner" diameter="20" mode="indeterminate"></mat-spinner>
|
||||
}
|
||||
|
||||
<button *ngIf="!showNew" mat-stroked-button color="primary" (click)="showNew = true">
|
||||
{{ 'ORG.PAGES.ORGDOMAIN.RESETMETHOD' | translate }}
|
||||
</button>
|
||||
@if (!showNew) {
|
||||
<button mat-stroked-button color="primary" (click)="showNew = true">
|
||||
{{ 'ORG.PAGES.ORGDOMAIN.RESETMETHOD' | translate }}
|
||||
</button>
|
||||
}
|
||||
|
||||
<div>
|
||||
<button color="primary" *ngIf="showNew && !(dns || http)" mat-raised-button (click)="loadHttpToken()">HTTP</button>
|
||||
<button color="primary" *ngIf="showNew && !(dns || http)" mat-raised-button (click)="loadDnsToken()">DNS</button>
|
||||
@if (showNew && !(dns || http)) {
|
||||
<button color="primary" mat-raised-button (click)="loadHttpToken()">HTTP</button>
|
||||
}
|
||||
@if (showNew && !(dns || http)) {
|
||||
<button color="primary" mat-raised-button (click)="loadDnsToken()">DNS</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
<button mat-stroked-button (click)="closeDialog()">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<ng-container *ngIf="['org.write$'] | hasRole as canwrite$">
|
||||
@if (['org.write$'] | hasRole; as canwrite$) {
|
||||
<div class="domain-top-view">
|
||||
<div>
|
||||
<div class="domain-title-row">
|
||||
@@ -15,7 +15,6 @@
|
||||
<p class="domain-desc cnsl-secondary-text">{{ 'ORG.DOMAINS.DESCRIPTION' | translate }}</p>
|
||||
</div>
|
||||
<span class="fill-space"></span>
|
||||
|
||||
<button
|
||||
[disabled]="(canwrite$ | async) === false"
|
||||
matTooltip="Add domain"
|
||||
@@ -31,39 +30,40 @@
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<cnsl-card *ngFor="let domain of domains" class="domain-card">
|
||||
<div class="domain">
|
||||
<span class="title">{{ domain.domainName }}</span>
|
||||
|
||||
<i matTooltip="verified" *ngIf="domain.isVerified" class="verified las la-check-circle"></i>
|
||||
<i matTooltip="primary" *ngIf="domain.isPrimary" class="primary las la-star"></i>
|
||||
<a
|
||||
*ngIf="domain.isVerified && !domain.isPrimary && (canwrite$ | async)"
|
||||
class="primaryset"
|
||||
(click)="setPrimary(domain)"
|
||||
>{{ 'ORG.DOMAINS.SETPRIMARY' | translate }}</a
|
||||
>
|
||||
|
||||
<span class="fill-space"></span>
|
||||
<button
|
||||
mat-icon-button
|
||||
[disabled]="(canwrite$ | async) === false || domain.isVerified"
|
||||
*ngIf="verifyOrgDomains"
|
||||
(click)="verifyDomain(domain)"
|
||||
>
|
||||
<i class="las la-pen"></i>
|
||||
</button>
|
||||
<button
|
||||
class="domain-rem-button"
|
||||
[disabled]="(canwrite$ | async) === false || domain.isPrimary"
|
||||
matTooltip="Remove domain"
|
||||
color="warn"
|
||||
mat-icon-button
|
||||
(click)="removeDomain(domain.domainName)"
|
||||
>
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</cnsl-card>
|
||||
</ng-container>
|
||||
@for (domain of domains; track domain) {
|
||||
<cnsl-card class="domain-card">
|
||||
<div class="domain">
|
||||
<span class="title">{{ domain.domainName }}</span>
|
||||
@if (domain.isVerified) {
|
||||
<i matTooltip="verified" class="verified las la-check-circle"></i>
|
||||
}
|
||||
@if (domain.isPrimary) {
|
||||
<i matTooltip="primary" class="primary las la-star"></i>
|
||||
}
|
||||
@if (domain.isVerified && !domain.isPrimary && (canwrite$ | async)) {
|
||||
<a class="primaryset" (click)="setPrimary(domain)">{{ 'ORG.DOMAINS.SETPRIMARY' | translate }}</a>
|
||||
}
|
||||
<span class="fill-space"></span>
|
||||
@if (verifyOrgDomains) {
|
||||
<button
|
||||
mat-icon-button
|
||||
[disabled]="(canwrite$ | async) === false || domain.isVerified"
|
||||
(click)="verifyDomain(domain)"
|
||||
>
|
||||
<i class="las la-pen"></i>
|
||||
</button>
|
||||
}
|
||||
<button
|
||||
class="domain-rem-button"
|
||||
[disabled]="(canwrite$ | async) === false || domain.isPrimary"
|
||||
matTooltip="Remove domain"
|
||||
color="warn"
|
||||
mat-icon-button
|
||||
(click)="removeDomain(domain.domainName)"
|
||||
>
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</cnsl-card>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +1,80 @@
|
||||
<div *ngIf="currentMap">
|
||||
<form [formGroup]="form">
|
||||
<ng-container *ngFor="let key of current$ | async | keyvalue">
|
||||
<div *ngIf="key.key !== 'isDefault'" class="edit-text-block">
|
||||
<div class="edit-text-flex" *ngIf="default$ | async as defaultmap">
|
||||
<cnsl-form-field class="edit-text-formfield">
|
||||
<cnsl-label>{{ key.key }}</cnsl-label>
|
||||
<textarea
|
||||
class="edit-text-area"
|
||||
cnslInput
|
||||
[formControlName]="key.key"
|
||||
[placeholder]="$any(defaultmap[key.key])"
|
||||
[name]="key.key"
|
||||
[ngClass]="{ defaulttext: form.get(key.key)?.value === '' }"
|
||||
></textarea>
|
||||
<div class="edit-text-chips" *ngIf="warnText[key.key] === undefined">
|
||||
<ng-container *ngFor="let chip of chips">
|
||||
<div
|
||||
class="chip"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="chip.value"
|
||||
(copiedValue)="copied = $event"
|
||||
(click)="addChip(key.key, chip.value)"
|
||||
>
|
||||
<span class="key">{{ chip.key | translate }}</span>
|
||||
<span class="value">{{ chip.value }}</span>
|
||||
<i *ngIf="copied !== chip.value" class="las la-clipboard"></i>
|
||||
<i *ngIf="copied === chip.value" class="las la-clipboard-check"></i>
|
||||
@if (currentMap) {
|
||||
<div>
|
||||
<form [formGroup]="form">
|
||||
@for (key of current$ | async | keyvalue; track key) {
|
||||
@if (key.key !== 'isDefault') {
|
||||
<div class="edit-text-block">
|
||||
@if (default$ | async; as defaultmap) {
|
||||
<div class="edit-text-flex">
|
||||
<cnsl-form-field class="edit-text-formfield">
|
||||
<cnsl-label>{{ key.key }}</cnsl-label>
|
||||
<textarea
|
||||
class="edit-text-area"
|
||||
cnslInput
|
||||
[formControlName]="key.key"
|
||||
[placeholder]="$any(defaultmap[key.key])"
|
||||
[name]="key.key"
|
||||
[ngClass]="{ defaulttext: form.get(key.key)?.value === '' }"
|
||||
></textarea>
|
||||
@if (warnText[key.key] === undefined) {
|
||||
<div class="edit-text-chips">
|
||||
@for (chip of chips; track chip) {
|
||||
<div
|
||||
class="chip"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="chip.value"
|
||||
(copiedValue)="copied = $event"
|
||||
(click)="addChip(key.key, chip.value)"
|
||||
>
|
||||
<span class="key">{{ chip.key | translate }}</span>
|
||||
<span class="value">{{ chip.value }}</span>
|
||||
@if (copied !== chip.value) {
|
||||
<i class="las la-clipboard"></i>
|
||||
}
|
||||
@if (copied === chip.value) {
|
||||
<i class="las la-clipboard-check"></i>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</cnsl-form-field>
|
||||
<div class="edit-text-actions">
|
||||
<button
|
||||
matTooltip="{{ 'ACTIONS.RESETDEFAULT' | translate }}"
|
||||
mat-icon-button
|
||||
[disabled]="form.get(key.key)?.value === defaultmap[key.key] || disabled"
|
||||
(click)="form.get(key.key)?.setValue(defaultmap[key.key])"
|
||||
(mouseenter)="
|
||||
form.get(key.key)?.value !== defaultmap[key.key] && setWarnText(key.key, $any(defaultmap[key.key]))
|
||||
"
|
||||
(mouseleave)="setWarnText(key.key, undefined)"
|
||||
>
|
||||
<i class="las la-history"></i>
|
||||
</button>
|
||||
<button
|
||||
matTooltip="{{ 'ACTIONS.RESETCURRENT' | translate }}"
|
||||
mat-icon-button
|
||||
[disabled]="form.get(key.key)?.value === currentMap[key.key] || disabled"
|
||||
(click)="form.get(key.key)?.setValue(currentMap[key.key])"
|
||||
(mouseenter)="
|
||||
form.get(key.key)?.value !== currentMap[key.key] && setWarnText(key.key, $any(currentMap[key.key]))
|
||||
"
|
||||
(mouseleave)="setWarnText(key.key, undefined)"
|
||||
>
|
||||
<i class="las la-undo"></i>
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</cnsl-form-field>
|
||||
<div class="edit-text-actions">
|
||||
<button
|
||||
matTooltip="{{ 'ACTIONS.RESETDEFAULT' | translate }}"
|
||||
mat-icon-button
|
||||
[disabled]="form.get(key.key)?.value === defaultmap[key.key] || disabled"
|
||||
(click)="form.get(key.key)?.setValue(defaultmap[key.key])"
|
||||
(mouseenter)="
|
||||
form.get(key.key)?.value !== defaultmap[key.key] && setWarnText(key.key, $any(defaultmap[key.key]))
|
||||
"
|
||||
(mouseleave)="setWarnText(key.key, undefined)"
|
||||
>
|
||||
<i class="las la-history"></i>
|
||||
</button>
|
||||
<button
|
||||
matTooltip="{{ 'ACTIONS.RESETCURRENT' | translate }}"
|
||||
mat-icon-button
|
||||
[disabled]="form.get(key.key)?.value === currentMap[key.key] || disabled"
|
||||
(click)="form.get(key.key)?.setValue(currentMap[key.key])"
|
||||
(mouseenter)="
|
||||
form.get(key.key)?.value !== currentMap[key.key] && setWarnText(key.key, $any(currentMap[key.key]))
|
||||
"
|
||||
(mouseleave)="setWarnText(key.key, undefined)"
|
||||
>
|
||||
<i class="las la-undo"></i>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<cnsl-info-section *ngIf="warnText[key.key] !== undefined" class="edit-text-info" [type]="InfoSectionType.WARN">
|
||||
{{ 'ACTIONS.RESETTO' | translate }} <cite>'{{ warnText[key.key] }}'</cite></cnsl-info-section
|
||||
>
|
||||
</ng-container>
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
@if (warnText[key.key] !== undefined) {
|
||||
<cnsl-info-section class="edit-text-info" [type]="InfoSectionType.WARN">
|
||||
{{ 'ACTIONS.RESETTO' | translate }} <cite>'{{ warnText[key.key] }}'</cite></cnsl-info-section
|
||||
>
|
||||
}
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -22,49 +22,57 @@
|
||||
<ng-container matColumnDef="editor">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'IAM.EVENTS.EDITOR' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let event">
|
||||
<ng-container *ngIf="event | toobject as event">
|
||||
<div class="editor-row" *ngIf="event.editor as editor">
|
||||
<!-- <cnsl-avatar
|
||||
@if (event | toobject; as event) {
|
||||
@if (event.editor; as editor) {
|
||||
<div class="editor-row">
|
||||
<!-- <cnsl-avatar
|
||||
*ngIf="editor && editor.displayName; else cog"
|
||||
class="avatar"
|
||||
[name]="editor.displayName"
|
||||
[avatarUrl]="editor.avatarUrl || ''"
|
||||
[forColor]="editor.preferredLoginName ?? editor.displayName"
|
||||
[size]="32"
|
||||
>
|
||||
>
|
||||
</cnsl-avatar>
|
||||
<ng-template #cog>
|
||||
<cnsl-avatar [forColor]="editor?.preferredLoginName ?? 'franz'" [isMachine]="true">
|
||||
<i class="las la-robot"></i>
|
||||
</cnsl-avatar> </ng-template
|
||||
> -->
|
||||
<span class="name" *ngIf="editor.displayName">{{ editor.displayName }}</span>
|
||||
<span class="state" *ngIf="editor.service">{{ editor.service }}</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
> -->
|
||||
@if (editor.displayName) {
|
||||
<span class="name">{{ editor.displayName }}</span>
|
||||
}
|
||||
@if (editor.service) {
|
||||
<span class="state">{{ editor.service }}</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="aggregate">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'IAM.EVENTS.AGGREGATE' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let event">
|
||||
<ng-container *ngIf="event | toobject as event">
|
||||
@if (event | toobject; as event) {
|
||||
<div class="aggregate-row">
|
||||
<span class="id">{{ event.aggregate.id }}</span
|
||||
><span class="state" *ngIf="event.aggregate?.type?.localized?.localizedMessage">{{
|
||||
event.aggregate.type.localized.localizedMessage
|
||||
}}</span>
|
||||
<span class="id">{{ event.aggregate.id }}</span>
|
||||
@if (event.aggregate?.type?.localized?.localizedMessage) {
|
||||
<span class="state">{{ event.aggregate.type.localized.localizedMessage }}</span>
|
||||
}
|
||||
</div>
|
||||
</ng-container>
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="resourceOwner">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'IAM.EVENTS.RESOURCEOWNER' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let event">
|
||||
<ng-container *ngIf="event | toobject as event">
|
||||
<span *ngIf="event.aggregate.resourceOwner">{{ event.aggregate.resourceOwner }}</span>
|
||||
</ng-container>
|
||||
@if (event | toobject; as event) {
|
||||
@if (event.aggregate.resourceOwner) {
|
||||
<span>{{ event.aggregate.resourceOwner }}</span>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
@@ -73,9 +81,9 @@
|
||||
{{ 'IAM.EVENTS.SEQUENCE' | translate }}
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let event">
|
||||
<ng-container *ngIf="event | toobject as event">
|
||||
@if (event | toobject; as event) {
|
||||
{{ event.sequence }}
|
||||
</ng-container>
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
@@ -84,32 +92,34 @@
|
||||
{{ 'IAM.EVENTS.CREATIONDATE' | translate }}
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let event">
|
||||
<ng-container *ngIf="event | toobject as event">
|
||||
@if (event | toobject; as event) {
|
||||
<span>{{ event?.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm:ss' }}</span>
|
||||
</ng-container>
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="type">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'IAM.EVENTS.TYPE' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let event" data-e2e="event-type-cell">
|
||||
<ng-container *ngIf="event | toobject as event">
|
||||
<span *ngIf="event.type?.localized?.localizedMessage">{{ event.type.localized.localizedMessage }}</span>
|
||||
</ng-container>
|
||||
@if (event | toobject; as event) {
|
||||
@if (event.type?.localized?.localizedMessage) {
|
||||
<span>{{ event.type.localized.localizedMessage }}</span>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="payload">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'IAM.EVENTS.PAYLOAD' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let event">
|
||||
<ng-container *ngIf="event | topayload as payload">
|
||||
@if (event | topayload; as payload) {
|
||||
<span>{{ payload | json }}</span>
|
||||
<div class="btn-wrapper">
|
||||
<button class="open-in-dialog-btn" mat-icon-button (click)="openDialog(event)">
|
||||
<mat-icon svgIcon="mdi_arrow_expand"></mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<div class="cnsl-action-button">
|
||||
<i class="las la-filter no-margin"></i>
|
||||
<span>{{ 'ACTIONS.FILTER' | translate }}</span>
|
||||
<span *ngIf="queryCount" class="filter-count">{{ queryCount }}</span>
|
||||
@if (queryCount) {
|
||||
<span class="filter-count">{{ queryCount }}</span>
|
||||
}
|
||||
<cnsl-action-keys
|
||||
[doNotUseContrast]="true"
|
||||
[type]="ActionKeysType.FILTER"
|
||||
@@ -37,190 +39,211 @@
|
||||
{{ 'ACTIONS.APPLY' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
<form *ngIf="form" [formGroup]="form" (ngSubmit)="emitChange()">
|
||||
<div *ngIf="isLoading" class="sp_wrapper"><mat-spinner diameter="20"></mat-spinner></div>
|
||||
<div class="filter-events-section">
|
||||
<div class="checkbox-wrapper">
|
||||
<mat-checkbox id="userFilterSet" name="userFilterSet" class="cb" formControlName="userFilterSet"
|
||||
>{{ 'IAM.EVENTS.FILTERS.USER.CHECKBOX' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="filter-events-sub" *ngIf="userFilterSet?.value">
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.USER.IDLABEL' | translate }}</cnsl-label>
|
||||
<input cnslInput id="editorUserId" name="editorUserId" formControlName="editorUserId" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-events-section">
|
||||
<div class="checkbox-wrapper">
|
||||
<mat-checkbox id="aggregateFilterSet" name="aggregateFilterSet" class="cb" formControlName="aggregateFilterSet"
|
||||
>{{ 'IAM.EVENTS.FILTERS.AGGREGATE.CHECKBOX' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="filter-events-sub" *ngIf="aggregateFilterSet?.value">
|
||||
<cnsl-form-field class="aggregate-type-select">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.AGGREGATE.TYPELABEL' | translate }}</cnsl-label>
|
||||
|
||||
<mat-select
|
||||
id="aggregateTypesList"
|
||||
name="aggregateTypesList"
|
||||
formControlName="aggregateTypesList"
|
||||
[multiple]="true"
|
||||
>
|
||||
<mat-select-trigger>
|
||||
<span *ngIf="aggregateTypesList?.value && aggregateTypesList?.value.length">{{
|
||||
aggregateTypesList?.value[0]?.localized?.localizedMessage || ''
|
||||
}}</span>
|
||||
<small *ngIf="(aggregateTypesList?.value?.length || 0) > 1" class="cnsl-secondary-text">
|
||||
(+{{ (aggregateTypesList?.value?.length || 0) - 1 }}
|
||||
{{ aggregateTypesList?.value?.length === 2 ? 'other' : 'others' }})
|
||||
</small>
|
||||
</mat-select-trigger>
|
||||
<mat-option *ngFor="let aggregate of aggregateTypes" [value]="aggregate">
|
||||
<span *ngIf="aggregate.localized && aggregate.localized.localizedMessage">
|
||||
{{ aggregate.localized.localizedMessage }}
|
||||
</span>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.AGGREGATE.IDLABEL' | translate }}</cnsl-label>
|
||||
<input id="aggregateId" formControlName="aggregateId" cnslInput name="aggregateId" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-events-section">
|
||||
<div class="checkbox-wrapper">
|
||||
<mat-checkbox
|
||||
id="eventTypesFilterSet"
|
||||
name="eventTypesFilterSet"
|
||||
class="cb"
|
||||
formControlName="eventTypesFilterSet"
|
||||
data-e2e="event-type-filter-checkbox"
|
||||
>{{ 'IAM.EVENTS.FILTERS.TYPE.CHECKBOX' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="filter-events-sub" *ngIf="eventTypesFilterSet?.value">
|
||||
<cnsl-form-field class="event-types-select">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.TYPE.TYPELABEL' | translate }}</cnsl-label>
|
||||
|
||||
<mat-select id="eventTypesList" formControlName="eventTypesList" [multiple]="true">
|
||||
<mat-select-trigger>
|
||||
<span *ngIf="eventTypesList?.value && eventTypesList?.value.length">{{
|
||||
eventTypesList?.value[0]?.localized?.localizedMessage || ''
|
||||
}}</span>
|
||||
<small *ngIf="(eventTypesList?.value?.length || 0) > 1" class="cnsl-secondary-text">
|
||||
(+{{ (eventTypesList?.value?.length || 0) - 1 }}
|
||||
{{ eventTypesList?.value?.length === 2 ? 'other' : 'others' }})
|
||||
</small>
|
||||
</mat-select-trigger>
|
||||
<mat-option *ngFor="let eventType of eventTypes" [value]="eventType">
|
||||
<ng-container *ngIf="eventType.localized && eventType.localized.localizedMessage">
|
||||
{{ eventType.localized.localizedMessage }}
|
||||
</ng-container>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-events-section">
|
||||
<div class="checkbox-wrapper">
|
||||
<mat-checkbox
|
||||
id="resourceOwnerFilterSet"
|
||||
name="resourceOwnerFilterSet"
|
||||
class="cb"
|
||||
formControlName="resourceOwnerFilterSet"
|
||||
>{{ 'IAM.EVENTS.FILTERS.RESOURCEOWNER.CHECKBOX' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="filter-events-sub" *ngIf="resourceOwnerFilterSet?.value">
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.RESOURCEOWNER.LABEL' | translate }}</cnsl-label>
|
||||
<input cnslInput id="resourceOwner" name="resourceOwner" formControlName="resourceOwner" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-events-section">
|
||||
<div class="checkbox-wrapper">
|
||||
<mat-checkbox id="sequenceFilterSet" name="sequenceFilterSet" class="cb" formControlName="sequenceFilterSet"
|
||||
>{{ 'IAM.EVENTS.FILTERS.SEQUENCE.CHECKBOX' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="filter-events-sub" *ngIf="sequenceFilterSet?.value">
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.SEQUENCE.LABEL' | translate }}</cnsl-label>
|
||||
<input cnslInput id="sequence" name="sequence" formControlName="sequence" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-events-section">
|
||||
<mat-radio-group aria-label="Select an option" class="filter-events-sub" formControlName="creationDateFilterType">
|
||||
<mat-radio-button [value]="CreationDateFilterType.FROM">
|
||||
{{ 'IAM.EVENTS.FILTERS.CREATIONDATE.RADIO_FROM' | translate }}
|
||||
</mat-radio-button>
|
||||
<mat-radio-button [value]="CreationDateFilterType.RANGE">
|
||||
{{ 'IAM.EVENTS.FILTERS.CREATIONDATE.RADIO_RANGE' | translate }}
|
||||
</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
<div class="filter-events-sub">
|
||||
<ng-container *ngIf="creationDateFilterType!.value === CreationDateFilterType.FROM">
|
||||
<mat-form-field class="datetime-input">
|
||||
<input
|
||||
class="datetime"
|
||||
matInput
|
||||
type="datetime-local"
|
||||
name="creationDateFrom"
|
||||
[value]="creationDateFrom!.value | date: 'yyyy-MM-dd HH:mm:ss'"
|
||||
(change)="creationDateFrom = $event.target"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="creationDateFilterType!.value === CreationDateFilterType.RANGE">
|
||||
<div class="datetime-range">
|
||||
<mat-form-field class="datetime-input">
|
||||
<cnsl-label
|
||||
>{{ 'IAM.EVENTS.FILTERS.CREATIONDATE.LABEL_SINCE' | translate }}
|
||||
<input
|
||||
matInput
|
||||
type="datetime-local"
|
||||
name="creationDateSince"
|
||||
[value]="creationDateSince!.value | date: 'yyyy-MM-dd HH:mm:ss'"
|
||||
(change)="creationDateSince = $event.target"
|
||||
/>
|
||||
</cnsl-label>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="datetime-input">
|
||||
<cnsl-label
|
||||
>{{ 'IAM.EVENTS.FILTERS.CREATIONDATE.LABEL_UNTIL' | translate }}
|
||||
<input
|
||||
matInput
|
||||
type="datetime-local"
|
||||
name="creationDateUntil"
|
||||
[value]="creationDateUntil!.value | date: 'yyyy-MM-dd HH:mm:ss'"
|
||||
(change)="creationDateUntil = $event.target"
|
||||
/>
|
||||
</cnsl-label>
|
||||
</mat-form-field>
|
||||
@if (form) {
|
||||
<form [formGroup]="form" (ngSubmit)="emitChange()">
|
||||
@if (isLoading) {
|
||||
<div class="sp_wrapper"><mat-spinner diameter="20"></mat-spinner></div>
|
||||
}
|
||||
<div class="filter-events-section">
|
||||
<div class="checkbox-wrapper">
|
||||
<mat-checkbox id="userFilterSet" name="userFilterSet" class="cb" formControlName="userFilterSet"
|
||||
>{{ 'IAM.EVENTS.FILTERS.USER.CHECKBOX' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
@if (userFilterSet?.value) {
|
||||
<div class="filter-events-sub">
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.USER.IDLABEL' | translate }}</cnsl-label>
|
||||
<input cnslInput id="editorUserId" name="editorUserId" formControlName="editorUserId" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
</ng-container>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-events-section">
|
||||
<cnsl-form-field class="aggregate-type-select">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.SORT' | translate }}</cnsl-label>
|
||||
|
||||
<mat-select id="isAsc" formControlName="isAsc">
|
||||
<mat-option [value]="false"> {{ 'IAM.EVENTS.FILTERS.DESC' | translate }} </mat-option>
|
||||
<mat-option [value]="true">{{ 'IAM.EVENTS.FILTERS.ASC' | translate }} </mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
</form>
|
||||
<div class="filter-events-section">
|
||||
<div class="checkbox-wrapper">
|
||||
<mat-checkbox id="aggregateFilterSet" name="aggregateFilterSet" class="cb" formControlName="aggregateFilterSet"
|
||||
>{{ 'IAM.EVENTS.FILTERS.AGGREGATE.CHECKBOX' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
@if (aggregateFilterSet?.value) {
|
||||
<div class="filter-events-sub">
|
||||
<cnsl-form-field class="aggregate-type-select">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.AGGREGATE.TYPELABEL' | translate }}</cnsl-label>
|
||||
<mat-select
|
||||
id="aggregateTypesList"
|
||||
name="aggregateTypesList"
|
||||
formControlName="aggregateTypesList"
|
||||
[multiple]="true"
|
||||
>
|
||||
<mat-select-trigger>
|
||||
@if (aggregateTypesList?.value && aggregateTypesList?.value.length) {
|
||||
<span>{{ aggregateTypesList?.value[0]?.localized?.localizedMessage || '' }}</span>
|
||||
}
|
||||
@if ((aggregateTypesList?.value?.length || 0) > 1) {
|
||||
<small class="cnsl-secondary-text">
|
||||
(+{{ (aggregateTypesList?.value?.length || 0) - 1 }}
|
||||
{{ aggregateTypesList?.value?.length === 2 ? 'other' : 'others' }})
|
||||
</small>
|
||||
}
|
||||
</mat-select-trigger>
|
||||
@for (aggregate of aggregateTypes; track aggregate) {
|
||||
<mat-option [value]="aggregate">
|
||||
@if (aggregate.localized && aggregate.localized.localizedMessage) {
|
||||
<span>
|
||||
{{ aggregate.localized.localizedMessage }}
|
||||
</span>
|
||||
}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.AGGREGATE.IDLABEL' | translate }}</cnsl-label>
|
||||
<input id="aggregateId" formControlName="aggregateId" cnslInput name="aggregateId" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="filter-events-section">
|
||||
<div class="checkbox-wrapper">
|
||||
<mat-checkbox
|
||||
id="eventTypesFilterSet"
|
||||
name="eventTypesFilterSet"
|
||||
class="cb"
|
||||
formControlName="eventTypesFilterSet"
|
||||
data-e2e="event-type-filter-checkbox"
|
||||
>{{ 'IAM.EVENTS.FILTERS.TYPE.CHECKBOX' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
@if (eventTypesFilterSet?.value) {
|
||||
<div class="filter-events-sub">
|
||||
<cnsl-form-field class="event-types-select">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.TYPE.TYPELABEL' | translate }}</cnsl-label>
|
||||
<mat-select id="eventTypesList" formControlName="eventTypesList" [multiple]="true">
|
||||
<mat-select-trigger>
|
||||
@if (eventTypesList?.value && eventTypesList?.value.length) {
|
||||
<span>{{ eventTypesList?.value[0]?.localized?.localizedMessage || '' }}</span>
|
||||
}
|
||||
@if ((eventTypesList?.value?.length || 0) > 1) {
|
||||
<small class="cnsl-secondary-text">
|
||||
(+{{ (eventTypesList?.value?.length || 0) - 1 }}
|
||||
{{ eventTypesList?.value?.length === 2 ? 'other' : 'others' }})
|
||||
</small>
|
||||
}
|
||||
</mat-select-trigger>
|
||||
@for (eventType of eventTypes; track eventType) {
|
||||
<mat-option [value]="eventType">
|
||||
@if (eventType.localized && eventType.localized.localizedMessage) {
|
||||
{{ eventType.localized.localizedMessage }}
|
||||
}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="filter-events-section">
|
||||
<div class="checkbox-wrapper">
|
||||
<mat-checkbox
|
||||
id="resourceOwnerFilterSet"
|
||||
name="resourceOwnerFilterSet"
|
||||
class="cb"
|
||||
formControlName="resourceOwnerFilterSet"
|
||||
>{{ 'IAM.EVENTS.FILTERS.RESOURCEOWNER.CHECKBOX' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
@if (resourceOwnerFilterSet?.value) {
|
||||
<div class="filter-events-sub">
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.RESOURCEOWNER.LABEL' | translate }}</cnsl-label>
|
||||
<input cnslInput id="resourceOwner" name="resourceOwner" formControlName="resourceOwner" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="filter-events-section">
|
||||
<div class="checkbox-wrapper">
|
||||
<mat-checkbox id="sequenceFilterSet" name="sequenceFilterSet" class="cb" formControlName="sequenceFilterSet"
|
||||
>{{ 'IAM.EVENTS.FILTERS.SEQUENCE.CHECKBOX' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
@if (sequenceFilterSet?.value) {
|
||||
<div class="filter-events-sub">
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.SEQUENCE.LABEL' | translate }}</cnsl-label>
|
||||
<input cnslInput id="sequence" name="sequence" formControlName="sequence" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="filter-events-section">
|
||||
<mat-radio-group
|
||||
aria-label="Select an option"
|
||||
class="filter-events-sub"
|
||||
formControlName="creationDateFilterType"
|
||||
>
|
||||
<mat-radio-button [value]="CreationDateFilterType.FROM">
|
||||
{{ 'IAM.EVENTS.FILTERS.CREATIONDATE.RADIO_FROM' | translate }}
|
||||
</mat-radio-button>
|
||||
<mat-radio-button [value]="CreationDateFilterType.RANGE">
|
||||
{{ 'IAM.EVENTS.FILTERS.CREATIONDATE.RADIO_RANGE' | translate }}
|
||||
</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
<div class="filter-events-sub">
|
||||
@if (creationDateFilterType!.value === CreationDateFilterType.FROM) {
|
||||
<mat-form-field class="datetime-input">
|
||||
<input
|
||||
class="datetime"
|
||||
matInput
|
||||
type="datetime-local"
|
||||
name="creationDateFrom"
|
||||
[value]="creationDateFrom!.value | date: 'yyyy-MM-dd HH:mm:ss'"
|
||||
(change)="creationDateFrom = $event.target"
|
||||
/>
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (creationDateFilterType!.value === CreationDateFilterType.RANGE) {
|
||||
<div class="datetime-range">
|
||||
<mat-form-field class="datetime-input">
|
||||
<cnsl-label
|
||||
>{{ 'IAM.EVENTS.FILTERS.CREATIONDATE.LABEL_SINCE' | translate }}
|
||||
<input
|
||||
matInput
|
||||
type="datetime-local"
|
||||
name="creationDateSince"
|
||||
[value]="creationDateSince!.value | date: 'yyyy-MM-dd HH:mm:ss'"
|
||||
(change)="creationDateSince = $event.target"
|
||||
/>
|
||||
</cnsl-label>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="datetime-input">
|
||||
<cnsl-label
|
||||
>{{ 'IAM.EVENTS.FILTERS.CREATIONDATE.LABEL_UNTIL' | translate }}
|
||||
<input
|
||||
matInput
|
||||
type="datetime-local"
|
||||
name="creationDateUntil"
|
||||
[value]="creationDateUntil!.value | date: 'yyyy-MM-dd HH:mm:ss'"
|
||||
(change)="creationDateUntil = $event.target"
|
||||
/>
|
||||
</cnsl-label>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-events-section">
|
||||
<cnsl-form-field class="aggregate-type-select">
|
||||
<cnsl-label>{{ 'IAM.EVENTS.FILTERS.SORT' | translate }}</cnsl-label>
|
||||
<mat-select id="isAsc" formControlName="isAsc">
|
||||
<mat-option [value]="false"> {{ 'IAM.EVENTS.FILTERS.DESC' | translate }} </mat-option>
|
||||
<mat-option [value]="true">{{ 'IAM.EVENTS.FILTERS.ASC' | translate }} </mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
@@ -8,19 +8,22 @@
|
||||
(change)="changeCheckbox(SubQuery.NAME, $event)"
|
||||
>{{ 'FILTER.ORGNAME' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.NAME) as eq">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="eq.getMethod()" (selectionChange)="setMethod(eq, $event)">
|
||||
<mat-option *ngFor="let method of methods" [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="eq.getName()" (change)="setValue(SubQuery.NAME, eq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.NAME); as eq) {
|
||||
<div class="subquery">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="eq.getMethod()" (selectionChange)="setMethod(eq, $event)">
|
||||
@for (method of methods; track method) {
|
||||
<mat-option [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="eq.getName()" (change)="setValue(SubQuery.NAME, eq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="name-query">
|
||||
@@ -31,19 +34,22 @@
|
||||
(change)="changeCheckbox(SubQuery.STATE, $event)"
|
||||
>{{ 'FILTER.STATE' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.STATE) as sq">
|
||||
<span class="nomethod cnsl-secondary-text">
|
||||
{{ 'FILTER.METHODS.1' | translate }}
|
||||
</span>
|
||||
|
||||
<cnsl-form-field class="filter-select-value">
|
||||
<mat-select [value]="sq.getState()" (selectionChange)="setValue(SubQuery.STATE, sq, $event)">
|
||||
<mat-option *ngFor="let state of states" [value]="state">
|
||||
{{ 'USER.STATE.' + state | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.STATE); as sq) {
|
||||
<div class="subquery">
|
||||
<span class="nomethod cnsl-secondary-text">
|
||||
{{ 'FILTER.METHODS.1' | translate }}
|
||||
</span>
|
||||
<cnsl-form-field class="filter-select-value">
|
||||
<mat-select [value]="sq.getState()" (selectionChange)="setValue(SubQuery.STATE, sq, $event)">
|
||||
@for (state of states; track state) {
|
||||
<mat-option [value]="state">
|
||||
{{ 'USER.STATE.' + state | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -55,33 +61,37 @@
|
||||
(change)="changeCheckbox(SubQuery.DOMAIN, $event)"
|
||||
>{{ 'FILTER.PRIMARYDOMAIN' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.DOMAIN) as dq">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="dq.getMethod()" (selectionChange)="setMethod(dq, $event)">
|
||||
<mat-option *ngFor="let method of methods" [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="dq.getDomain()" (change)="setValue(SubQuery.DOMAIN, dq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.DOMAIN); as dq) {
|
||||
<div class="subquery">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="dq.getMethod()" (selectionChange)="setMethod(dq, $event)">
|
||||
@for (method of methods; track method) {
|
||||
<mat-option [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="dq.getDomain()" (change)="setValue(SubQuery.DOMAIN, dq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="id-query">
|
||||
<mat-checkbox id="id" class="cb" [checked]="getSubFilter(SubQuery.ID)" (change)="changeCheckbox(SubQuery.ID, $event)"
|
||||
>{{ 'FILTER.ORGID' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.ID) as idq">
|
||||
<span class="nomethod cnsl-secondary-text">
|
||||
{{ 'FILTER.METHODS.1' | translate }}
|
||||
</span>
|
||||
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="idq.getId()" (change)="setValue(SubQuery.ID, idq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.ID); as idq) {
|
||||
<div class="subquery">
|
||||
<span class="nomethod cnsl-secondary-text">
|
||||
{{ 'FILTER.METHODS.1' | translate }}
|
||||
</span>
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="idq.getId()" (change)="setValue(SubQuery.ID, idq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</cnsl-filter>
|
||||
|
||||
@@ -8,19 +8,22 @@
|
||||
(change)="changeCheckbox(SubQuery.NAME, $event)"
|
||||
>{{ 'FILTER.PROJECTNAME' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.NAME) as eq">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="eq.getMethod()" (selectionChange)="setMethod(eq, $event)">
|
||||
<mat-option *ngFor="let method of methods" [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="eq.getName()" (change)="setValue(SubQuery.NAME, eq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.NAME); as eq) {
|
||||
<div class="subquery">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="eq.getMethod()" (selectionChange)="setMethod(eq, $event)">
|
||||
@for (method of methods; track method) {
|
||||
<mat-option [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="eq.getName()" (change)="setValue(SubQuery.NAME, eq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</cnsl-filter>
|
||||
|
||||
@@ -8,24 +8,27 @@
|
||||
(change)="changeCheckbox(SubQuery.DISPLAYNAME, $event)"
|
||||
>{{ 'FILTER.DISPLAYNAME' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.DISPLAYNAME) as dnq">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="dnq.getMethod()" (selectionChange)="setMethod(dnq, $event)">
|
||||
<mat-option *ngFor="let method of methods" [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input
|
||||
cnslInput
|
||||
name="value"
|
||||
[value]="dnq.getDisplayName()"
|
||||
(change)="setValue(SubQuery.DISPLAYNAME, dnq, $event)"
|
||||
/>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.DISPLAYNAME); as dnq) {
|
||||
<div class="subquery">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="dnq.getMethod()" (selectionChange)="setMethod(dnq, $event)">
|
||||
@for (method of methods; track method) {
|
||||
<mat-option [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input
|
||||
cnslInput
|
||||
name="value"
|
||||
[value]="dnq.getDisplayName()"
|
||||
(change)="setValue(SubQuery.DISPLAYNAME, dnq, $event)"
|
||||
/>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="usernane-query">
|
||||
@@ -36,19 +39,22 @@
|
||||
(change)="changeCheckbox(SubQuery.USERNAME, $event)"
|
||||
>{{ 'FILTER.USERNAME' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.USERNAME) as unq">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="unq.getMethod()" (selectionChange)="setMethod(unq, $event)">
|
||||
<mat-option *ngFor="let method of methods" [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="unq.getUserName()" (change)="setValue(SubQuery.USERNAME, unq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.USERNAME); as unq) {
|
||||
<div class="subquery">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="unq.getMethod()" (selectionChange)="setMethod(unq, $event)">
|
||||
@for (method of methods; track method) {
|
||||
<mat-option [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="unq.getUserName()" (change)="setValue(SubQuery.USERNAME, unq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="email-query">
|
||||
@@ -59,19 +65,22 @@
|
||||
(change)="changeCheckbox(SubQuery.ORGNAME, $event)"
|
||||
>{{ 'FILTER.ORGNAME' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.ORGNAME) as onq">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="onq.getMethod()" (selectionChange)="setMethod(onq, $event)">
|
||||
<mat-option *ngFor="let method of methods" [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="onq.getOrgName()" (change)="setValue(SubQuery.ORGNAME, onq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.ORGNAME); as onq) {
|
||||
<div class="subquery">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="onq.getMethod()" (selectionChange)="setMethod(onq, $event)">
|
||||
@for (method of methods; track method) {
|
||||
<mat-option [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="onq.getOrgName()" (change)="setValue(SubQuery.ORGNAME, onq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="email-query">
|
||||
@@ -82,24 +91,27 @@
|
||||
(change)="changeCheckbox(SubQuery.PROJECTNAME, $event)"
|
||||
>{{ 'FILTER.PROJECTNAME' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.PROJECTNAME) as pnq">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="pnq.getMethod()" (selectionChange)="setMethod(pnq, $event)">
|
||||
<mat-option *ngFor="let method of methods" [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input
|
||||
cnslInput
|
||||
name="value"
|
||||
[value]="pnq.getProjectName()"
|
||||
(change)="setValue(SubQuery.PROJECTNAME, pnq, $event)"
|
||||
/>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.PROJECTNAME); as pnq) {
|
||||
<div class="subquery">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="pnq.getMethod()" (selectionChange)="setMethod(pnq, $event)">
|
||||
@for (method of methods; track method) {
|
||||
<mat-option [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input
|
||||
cnslInput
|
||||
name="value"
|
||||
[value]="pnq.getProjectName()"
|
||||
(change)="setValue(SubQuery.PROJECTNAME, pnq, $event)"
|
||||
/>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</cnsl-filter>
|
||||
|
||||
@@ -8,19 +8,22 @@
|
||||
(change)="changeCheckbox(SubQuery.STATE, $event)"
|
||||
>{{ 'FILTER.STATE' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.STATE) as sq">
|
||||
<span class="nomethod cnsl-secondary-text">
|
||||
{{ 'FILTER.METHODS.1' | translate }}
|
||||
</span>
|
||||
|
||||
<cnsl-form-field class="filter-select-value">
|
||||
<mat-select [value]="sq.getState()" (selectionChange)="setValue(SubQuery.STATE, sq, $event)">
|
||||
<mat-option *ngFor="let state of states" [value]="state">
|
||||
{{ 'USER.STATE.' + state | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.STATE); as sq) {
|
||||
<div class="subquery">
|
||||
<span class="nomethod cnsl-secondary-text">
|
||||
{{ 'FILTER.METHODS.1' | translate }}
|
||||
</span>
|
||||
<cnsl-form-field class="filter-select-value">
|
||||
<mat-select [value]="sq.getState()" (selectionChange)="setValue(SubQuery.STATE, sq, $event)">
|
||||
@for (state of states; track state) {
|
||||
<mat-option [value]="state">
|
||||
{{ 'USER.STATE.' + state | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="name-query">
|
||||
@@ -31,24 +34,27 @@
|
||||
(change)="changeCheckbox(SubQuery.DISPLAYNAME, $event)"
|
||||
>{{ 'FILTER.DISPLAYNAME' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.DISPLAYNAME) as dnq">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="dnq.getMethod()" (selectionChange)="setMethod(dnq, $event)">
|
||||
<mat-option *ngFor="let method of methods" [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input
|
||||
cnslInput
|
||||
name="value"
|
||||
[value]="dnq.getDisplayName()"
|
||||
(change)="setValue(SubQuery.DISPLAYNAME, dnq, $event)"
|
||||
/>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.DISPLAYNAME); as dnq) {
|
||||
<div class="subquery">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="dnq.getMethod()" (selectionChange)="setMethod(dnq, $event)">
|
||||
@for (method of methods; track method) {
|
||||
<mat-option [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input
|
||||
cnslInput
|
||||
name="value"
|
||||
[value]="dnq.getDisplayName()"
|
||||
(change)="setValue(SubQuery.DISPLAYNAME, dnq, $event)"
|
||||
/>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="email-query">
|
||||
@@ -59,19 +65,22 @@
|
||||
(change)="changeCheckbox(SubQuery.EMAIL, $event)"
|
||||
>{{ 'FILTER.EMAIL' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.EMAIL) as eq">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="eq.getMethod()" (selectionChange)="setMethod(eq, $event)">
|
||||
<mat-option *ngFor="let method of methods" [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="eq.getEmailAddress()" (change)="setValue(SubQuery.EMAIL, eq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.EMAIL); as eq) {
|
||||
<div class="subquery">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="eq.getMethod()" (selectionChange)="setMethod(eq, $event)">
|
||||
@for (method of methods; track method) {
|
||||
<mat-option [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="eq.getEmailAddress()" (change)="setValue(SubQuery.EMAIL, eq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="usernane-query">
|
||||
@@ -82,19 +91,22 @@
|
||||
(change)="changeCheckbox(SubQuery.USERNAME, $event)"
|
||||
>{{ 'FILTER.USERNAME' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="subquery" *ngIf="getSubFilter(SubQuery.USERNAME) as unq">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="unq.getMethod()" (selectionChange)="setMethod(unq, $event)">
|
||||
<mat-option *ngFor="let method of methods" [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="unq.getUserName()" (change)="setValue(SubQuery.USERNAME, unq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
@if (getSubFilter(SubQuery.USERNAME); as unq) {
|
||||
<div class="subquery">
|
||||
<cnsl-form-field class="filter-select-method">
|
||||
<mat-select [value]="unq.getMethod()" (selectionChange)="setMethod(unq, $event)">
|
||||
@for (method of methods; track method) {
|
||||
<mat-option [value]="method">
|
||||
{{ 'FILTER.METHODS.' + method | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="filter-input-value">
|
||||
<input cnslInput name="value" [value]="unq.getUserName()" (change)="setValue(SubQuery.USERNAME, unq, $event)" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</cnsl-filter>
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
<div class="cnsl-action-button">
|
||||
<i class="las la-filter no-margin"></i>
|
||||
<span>{{ 'ACTIONS.FILTER' | translate }}</span>
|
||||
<span *ngIf="queryCount" class="filter-count">{{ queryCount }}</span>
|
||||
@if (queryCount) {
|
||||
<span class="filter-count">{{ queryCount }}</span>
|
||||
}
|
||||
<cnsl-action-keys [doNotUseContrast]="true" [type]="ActionKeysType.FILTER" (actionTriggered)="toggleFilter()">
|
||||
</cnsl-action-keys>
|
||||
</div>
|
||||
|
||||
@@ -1,35 +1,43 @@
|
||||
<div class="footer-wrapper">
|
||||
<div class="footer-row">
|
||||
<div class="footer-links" *ngIf="authService.privacypolicy$ | async as pP">
|
||||
<a target="_blank" *ngIf="pP?.tosLink" rel="noreferrer" [href]="pP?.tosLink" external>
|
||||
<span>{{ 'FOOTER.LINKS.TOS' | translate }}</span>
|
||||
<i class="las la-external-link-alt"></i>
|
||||
</a>
|
||||
<a target="_blank" *ngIf="pP?.privacyLink" rel="noreferrer" [href]="pP?.privacyLink" external>
|
||||
<span>{{ 'FOOTER.LINKS.PP' | translate }}</span>
|
||||
<i class="las la-external-link-alt"></i>
|
||||
</a>
|
||||
</div>
|
||||
@if (authService.privacypolicy$ | async; as pP) {
|
||||
<div class="footer-links">
|
||||
@if (pP?.tosLink) {
|
||||
<a target="_blank" rel="noreferrer" [href]="pP?.tosLink" external>
|
||||
<span>{{ 'FOOTER.LINKS.TOS' | translate }}</span>
|
||||
<i class="las la-external-link-alt"></i>
|
||||
</a>
|
||||
}
|
||||
@if (pP?.privacyLink) {
|
||||
<a target="_blank" rel="noreferrer" [href]="pP?.privacyLink" external>
|
||||
<span>{{ 'FOOTER.LINKS.PP' | translate }}</span>
|
||||
<i class="las la-external-link-alt"></i>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="footer-socials" *ngIf="authService.labelpolicy$ | async as lP">
|
||||
<ng-container *ngIf="lP?.disableWatermark === false">
|
||||
<a target="_blank" rel="noreferrer" href="https://github.com/zitadel">
|
||||
<i class="text-3xl lab la-github"></i>
|
||||
</a>
|
||||
<a target="_blank" rel="noreferrer" href="https://twitter.com/zitadel">
|
||||
<fa-icon [icon]="faXTwitter" size="xl"></fa-icon>
|
||||
</a>
|
||||
<a target="_blank" rel="noreferrer" href="https://www.linkedin.com/company/zitadel/">
|
||||
<i class="text-3xl lab la-linkedin"></i>
|
||||
</a>
|
||||
<a target="_blank" rel="noreferrer" href="https://zitadel.com/chat">
|
||||
<i class="text-3xl lab la-discord"></i>
|
||||
</a>
|
||||
<a target="_blank" rel="noreferrer" href="https://www.youtube.com/channel/UCUAWJUNYaRn1yIVrZxEfsuA">
|
||||
<i class="text-3xl lab la-youtube"></i>
|
||||
</a>
|
||||
</ng-container>
|
||||
</div>
|
||||
@if (authService.labelpolicy$ | async; as lP) {
|
||||
<div class="footer-socials">
|
||||
@if (lP?.disableWatermark === false) {
|
||||
<a target="_blank" rel="noreferrer" href="https://github.com/zitadel">
|
||||
<i class="text-3xl lab la-github"></i>
|
||||
</a>
|
||||
<a target="_blank" rel="noreferrer" href="https://twitter.com/zitadel">
|
||||
<fa-icon [icon]="faXTwitter" size="xl"></fa-icon>
|
||||
</a>
|
||||
<a target="_blank" rel="noreferrer" href="https://www.linkedin.com/company/zitadel/">
|
||||
<i class="text-3xl lab la-linkedin"></i>
|
||||
</a>
|
||||
<a target="_blank" rel="noreferrer" href="https://zitadel.com/chat">
|
||||
<i class="text-3xl lab la-discord"></i>
|
||||
</a>
|
||||
<a target="_blank" rel="noreferrer" href="https://www.youtube.com/channel/UCUAWJUNYaRn1yIVrZxEfsuA">
|
||||
<i class="text-3xl lab la-youtube"></i>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="theme">
|
||||
<cnsl-theme-setting></cnsl-theme-setting>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<ng-template #labelTemplate>
|
||||
<label class="cnsl-label-wrapper" [attr.for]="_control.id" [attr.aria-owns]="_control.id">
|
||||
<ng-content select="cnsl-label"></ng-content>
|
||||
<span *ngIf="_control.required && !hideRequiredMarker" aria-hidden="true" class="cnsl-form-field-required-marker"
|
||||
>*</span
|
||||
>
|
||||
@if (_control.required && !hideRequiredMarker) {
|
||||
<span aria-hidden="true" class="cnsl-form-field-required-marker">*</span>
|
||||
}
|
||||
</label>
|
||||
</ng-template>
|
||||
|
||||
@@ -13,17 +13,25 @@
|
||||
<ng-content></ng-content>
|
||||
<ng-content select="cnslSuffix"></ng-content>
|
||||
</div>
|
||||
<ng-container *ngIf="help$ && help$ | async as help">
|
||||
<div [ngSwitch]="help.type" class="cnsl-form-field-subscript-wrapper">
|
||||
<div *ngSwitchCase="'hints'" class="cnsl-form-field-hint-wrapper" [@transitionMessages]="_subscriptAnimationState">
|
||||
<ng-content select="cnsl-hint"></ng-content>
|
||||
</div>
|
||||
<div *ngSwitchCase="'errors'" class="cnsl-form-field-error-wrapper" [@transitionMessages]="_subscriptAnimationState">
|
||||
<span cnslError *ngFor="let err of help.validationErrors">
|
||||
{{ err.i18nKey | translate: err.params }}
|
||||
</span>
|
||||
<ng-content select="cnsl-error"></ng-content>
|
||||
</div>
|
||||
@if (help$ && help$ | async; as help) {
|
||||
<div class="cnsl-form-field-subscript-wrapper">
|
||||
@switch (help.type) {
|
||||
@case ('hints') {
|
||||
<div class="cnsl-form-field-hint-wrapper" [@transitionMessages]="_subscriptAnimationState">
|
||||
<ng-content select="cnsl-hint"></ng-content>
|
||||
</div>
|
||||
}
|
||||
@case ('errors') {
|
||||
<div class="cnsl-form-field-error-wrapper" [@transitionMessages]="_subscriptAnimationState">
|
||||
@for (err of help.validationErrors; track err) {
|
||||
<span cnslError>
|
||||
{{ err.i18nKey | translate: err.params }}
|
||||
</span>
|
||||
}
|
||||
<ng-content select="cnsl-error"></ng-content>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</ng-container>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -1,44 +1,41 @@
|
||||
<mat-toolbar class="header-wrapper">
|
||||
<div class="header-content">
|
||||
<div *ngIf="authService.labelPolicyLoading$ | async; else logo" class="logo-placeholder">
|
||||
<mat-spinner [diameter]="20"></mat-spinner>
|
||||
</div>
|
||||
<ng-template #logo>
|
||||
<a class="title custom" [routerLink]="['/']" *ngIf="authService.labelpolicy$ | async as lP; else defaultHome">
|
||||
<img
|
||||
class="logo"
|
||||
alt="home logo"
|
||||
*ngIf="isDarkTheme; else customlighttheme"
|
||||
[src]="lP.iconUrlDark ? lP.iconUrlDark : './assets/images/zitadel-logo-solo-light.svg'"
|
||||
(error)="errorHandler($event, './assets/images/zitadel-logo-solo-light.svg')"
|
||||
/>
|
||||
<ng-template #customlighttheme>
|
||||
<img
|
||||
alt="home logo"
|
||||
class="logo"
|
||||
[src]="lP.iconUrl ? lP.iconUrl : './assets/images/zitadel-logo-solo-dark.svg'"
|
||||
(error)="errorHandler($event, './assets/images/zitadel-logo-solo-dark.svg')"
|
||||
/>
|
||||
</ng-template>
|
||||
</a>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #defaultHome>
|
||||
<a class="title" [routerLink]="(authService.zitadelPermissions | async)?.length ? ['/'] : ['/users', 'me']">
|
||||
<img
|
||||
class="logo"
|
||||
alt="zitadel logo"
|
||||
*ngIf="isDarkTheme; else lighttheme"
|
||||
src="./assets/images/zitadel-logo-solo-light.svg"
|
||||
/>
|
||||
<ng-template #lighttheme>
|
||||
<img alt="zitadel logo" class="logo" src="./assets/images/zitadel-logo-solo-dark.svg" />
|
||||
</ng-template>
|
||||
</a>
|
||||
</ng-template>
|
||||
@if (authService.labelPolicyLoading$ | async) {
|
||||
<div class="logo-placeholder">
|
||||
<mat-spinner [diameter]="20"></mat-spinner>
|
||||
</div>
|
||||
} @else {
|
||||
@if (authService.labelpolicy$ | async; as lP) {
|
||||
<a class="title custom" [routerLink]="['/']">
|
||||
@if (isDarkTheme) {
|
||||
<img
|
||||
class="logo"
|
||||
alt="home logo"
|
||||
[src]="lP.iconUrlDark ? lP.iconUrlDark : './assets/images/zitadel-logo-solo-light.svg'"
|
||||
(error)="errorHandler($event, './assets/images/zitadel-logo-solo-light.svg')"
|
||||
/>
|
||||
} @else {
|
||||
<img
|
||||
alt="home logo"
|
||||
class="logo"
|
||||
[src]="lP.iconUrl ? lP.iconUrl : './assets/images/zitadel-logo-solo-dark.svg'"
|
||||
(error)="errorHandler($event, './assets/images/zitadel-logo-solo-dark.svg')"
|
||||
/>
|
||||
}
|
||||
</a>
|
||||
} @else {
|
||||
<a class="title" [routerLink]="(authService.zitadelPermissions | async)?.length ? ['/'] : ['/users', 'me']">
|
||||
@if (isDarkTheme) {
|
||||
<img class="logo" alt="zitadel logo" src="./assets/images/zitadel-logo-solo-light.svg" />
|
||||
} @else {
|
||||
<img alt="zitadel logo" class="logo" src="./assets/images/zitadel-logo-solo-dark.svg" />
|
||||
}
|
||||
</a>
|
||||
}
|
||||
}
|
||||
|
||||
<ng-container *ngFor="let bread of breadcrumbService.breadcrumbs$ | async as bc; index as i">
|
||||
<ng-container *ngIf="bread.type === BreadcrumbType.INSTANCE">
|
||||
@if (bread.type === BreadcrumbType.INSTANCE) {
|
||||
<ng-template cnslHasRole [hasRole]="['iam.read']">
|
||||
<svg
|
||||
class="slash hide-on-small"
|
||||
@@ -53,16 +50,15 @@
|
||||
>
|
||||
<path d="M16.88 3.549L7.12 20.451"></path>
|
||||
</svg>
|
||||
|
||||
<div class="breadcrumb-context hide-on-small">
|
||||
<a matRipple [matRippleUnbounded]="false" class="breadcrumb-link" [routerLink]="bread.routerLink">
|
||||
{{ 'MENU.INSTANCE' | translate }}
|
||||
</a>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
}
|
||||
|
||||
<ng-container *ngIf="bread.type === BreadcrumbType.ORG">
|
||||
@if (bread.type === BreadcrumbType.ORG) {
|
||||
<svg
|
||||
class="slash"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -76,20 +72,13 @@
|
||||
>
|
||||
<path d="M16.88 3.549L7.12 20.451"></path>
|
||||
</svg>
|
||||
|
||||
<div class="org-context">
|
||||
<a
|
||||
*ngIf="org() as org"
|
||||
matRipple
|
||||
[matRippleUnbounded]="false"
|
||||
class="org-link"
|
||||
id="orglink"
|
||||
[routerLink]="['/org']"
|
||||
>
|
||||
{{ org.name ? org.name : 'NO NAME' }}</a
|
||||
>
|
||||
|
||||
<div class="org-context-wrapper" *ngIf="org">
|
||||
@if (org(); as org) {
|
||||
<a matRipple [matRippleUnbounded]="false" class="org-link" id="orglink" [routerLink]="['/org']">
|
||||
{{ org.name ? org.name : 'NO NAME' }}</a
|
||||
>
|
||||
}
|
||||
<div class="org-context-wrapper">
|
||||
<button
|
||||
cdkOverlayOrigin
|
||||
#trigger="cdkOverlayOrigin"
|
||||
@@ -113,7 +102,6 @@
|
||||
[type]="ActionKeysType.ORGSWITCHER"
|
||||
></cnsl-action-keys>
|
||||
</button>
|
||||
|
||||
<ng-template
|
||||
cdkConnectedOverlay
|
||||
[cdkConnectedOverlayOrigin]="trigger"
|
||||
@@ -125,20 +113,21 @@
|
||||
(backdropClick)="showOrgContext = false"
|
||||
(detach)="showOrgContext = false"
|
||||
>
|
||||
<cnsl-org-context
|
||||
class="context_card"
|
||||
*ngIf="showOrgContext && org() as org"
|
||||
(closedCard)="showOrgContext = false"
|
||||
[org]="org"
|
||||
(setOrg)="setActiveOrg($event)"
|
||||
>
|
||||
</cnsl-org-context>
|
||||
@if (showOrgContext && org(); as org) {
|
||||
<cnsl-org-context
|
||||
class="context_card"
|
||||
(closedCard)="showOrgContext = false"
|
||||
[org]="org"
|
||||
(setOrg)="setActiveOrg($event)"
|
||||
>
|
||||
</cnsl-org-context>
|
||||
}
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
}
|
||||
|
||||
<ng-container *ngIf="bread.type !== BreadcrumbType.INSTANCE && bread.type !== BreadcrumbType.ORG">
|
||||
@if (bread.type !== BreadcrumbType.INSTANCE && bread.type !== BreadcrumbType.ORG) {
|
||||
<svg
|
||||
class="slash"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -152,7 +141,6 @@
|
||||
>
|
||||
<path d="M16.88 3.549L7.12 20.451"></path>
|
||||
</svg>
|
||||
|
||||
<div class="breadcrumb-context">
|
||||
<a
|
||||
matRipple
|
||||
@@ -161,58 +149,54 @@
|
||||
[ngClass]="{ maxwidth: bc.length > 1 }"
|
||||
[routerLink]="bread.routerLink"
|
||||
>
|
||||
<ng-container *ngIf="i !== bc.length - 1; else defLabel">
|
||||
@if (i !== bc.length - 1) {
|
||||
<span class="desk">{{ bread.name }}</span>
|
||||
<span class="mob">...</span>
|
||||
</ng-container>
|
||||
<ng-template #defLabel>
|
||||
} @else {
|
||||
<span>{{ bread.name }}</span>
|
||||
</ng-template>
|
||||
}
|
||||
</a>
|
||||
</div>
|
||||
</ng-container>
|
||||
}
|
||||
</ng-container>
|
||||
|
||||
<span class="fill-space"></span>
|
||||
|
||||
<ng-container *ngIf="authService.privacypolicy$ | async as pP">
|
||||
<a class="custom-link" *ngIf="pP.customLink" href="{{ pP.customLink }}" mat-stroked-button target="_blank">
|
||||
{{ pP.customLinkText }}
|
||||
</a>
|
||||
@if (authService.privacypolicy$ | async; as pP) {
|
||||
@if (pP.customLink) {
|
||||
<a class="custom-link" href="{{ pP.customLink }}" mat-stroked-button target="_blank">
|
||||
{{ pP.customLinkText }}
|
||||
</a>
|
||||
}
|
||||
@if (pP.docsLink) {
|
||||
<a class="doc-link" href="{{ pP.docsLink }}" mat-stroked-button target="_blank">
|
||||
{{ 'MENU.DOCUMENTATION' | translate }}
|
||||
</a>
|
||||
}
|
||||
}
|
||||
|
||||
<a class="doc-link" *ngIf="pP.docsLink" href="{{ pP.docsLink }}" mat-stroked-button target="_blank">
|
||||
{{ 'MENU.DOCUMENTATION' | translate }}
|
||||
</a>
|
||||
</ng-container>
|
||||
@if (!isOnMe) {
|
||||
<div class="system-rel">
|
||||
@if (!isOnInstance && (['iam.read$', 'iam.write$'] | hasRole | async)) {
|
||||
<a id="systembutton" [routerLink]="['/instance']" class="iam-settings" mat-stroked-button>
|
||||
<div class="cnsl-action-button">
|
||||
<span class="iam-label">{{ 'MENU.INSTANCE' | translate }}</span>
|
||||
<i class="las la-cog"></i>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
@if (isOnInstance && (['org.read'] | hasRole | async)) {
|
||||
<a id="orgbutton" [routerLink]="['/org']" class="org-settings" mat-stroked-button>
|
||||
<div class="cnsl-action-button">
|
||||
<span class="iam-label">{{ 'MENU.ORGANIZATION' | translate }}</span>
|
||||
<i class="las la-cog"></i>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="system-rel" *ngIf="!isOnMe">
|
||||
<a
|
||||
id="systembutton"
|
||||
*ngIf="!isOnInstance && (['iam.read$', 'iam.write$'] | hasRole | async)"
|
||||
[routerLink]="['/instance']"
|
||||
class="iam-settings"
|
||||
mat-stroked-button
|
||||
>
|
||||
<div class="cnsl-action-button">
|
||||
<span class="iam-label">{{ 'MENU.INSTANCE' | translate }}</span>
|
||||
<i class="las la-cog"></i>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
id="orgbutton"
|
||||
*ngIf="isOnInstance && (['org.read'] | hasRole | async)"
|
||||
[routerLink]="['/org']"
|
||||
class="org-settings"
|
||||
mat-stroked-button
|
||||
>
|
||||
<div class="cnsl-action-button">
|
||||
<span class="iam-label">{{ 'MENU.ORGANIZATION' | translate }}</span>
|
||||
<i class="las la-cog"></i>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="user && user.id">
|
||||
@if (user && user.id) {
|
||||
<div class="account-card-wrapper">
|
||||
<button
|
||||
cdkOverlayOrigin
|
||||
@@ -244,15 +228,16 @@
|
||||
(backdropClick)="showAccount = false"
|
||||
(detach)="showAccount = false"
|
||||
>
|
||||
<cnsl-accounts-card
|
||||
class="a_card"
|
||||
*ngIf="showAccount"
|
||||
(closedCard)="showAccount = false"
|
||||
[user]="user"
|
||||
[iamuser]="['iam.write$'] | hasRole | async"
|
||||
>
|
||||
</cnsl-accounts-card>
|
||||
@if (showAccount) {
|
||||
<cnsl-accounts-card
|
||||
class="a_card"
|
||||
(closedCard)="showAccount = false"
|
||||
[user]="user"
|
||||
[iamuser]="['iam.write$'] | hasRole | async"
|
||||
>
|
||||
</cnsl-accounts-card>
|
||||
}
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
}
|
||||
</div>
|
||||
</mat-toolbar>
|
||||
|
||||
@@ -13,16 +13,12 @@
|
||||
<span>{{ 'IDP.AVAILABILITY' | translate }}</span>
|
||||
</th>
|
||||
<td class="pointer availability" mat-cell *matCellDef="let idp">
|
||||
<i
|
||||
matTooltip="{{ 'IDP.AVAILABLE' | translate }}"
|
||||
*ngIf="isEnabled(idp) && idp.state === IDPState.IDP_STATE_ACTIVE"
|
||||
class="idp-available las la-check-circle"
|
||||
></i>
|
||||
<i
|
||||
matTooltip="{{ 'IDP.AVAILABLEBUTINACTIVE' | translate }}"
|
||||
*ngIf="isEnabled(idp) && idp.state === IDPState.IDP_STATE_INACTIVE"
|
||||
class="idp-not-available las la-check-circle"
|
||||
></i>
|
||||
@if (isEnabled(idp) && idp.state === IDPState.IDP_STATE_ACTIVE) {
|
||||
<i matTooltip="{{ 'IDP.AVAILABLE' | translate }}" class="idp-available las la-check-circle"></i>
|
||||
}
|
||||
@if (isEnabled(idp) && idp.state === IDPState.IDP_STATE_INACTIVE) {
|
||||
<i matTooltip="{{ 'IDP.AVAILABLEBUTINACTIVE' | translate }}" class="idp-not-available las la-check-circle"></i>
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
@@ -36,59 +32,87 @@
|
||||
<ng-container matColumnDef="type">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'IDP.TYPE' | translate }}</th>
|
||||
<td class="pointer" mat-cell *matCellDef="let idp">
|
||||
<div [ngSwitch]="idp.type">
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_AZURE_AD">
|
||||
<img class="idp-logo" src="./assets/images/idp/ms.svg" alt="azure ad" />
|
||||
Microsoft
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_GOOGLE">
|
||||
<img class="idp-logo" src="./assets/images/idp/google.png" alt="google" />
|
||||
Google
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_GITHUB">
|
||||
<img class="idp-logo dark" src="./assets/images/idp/github-dark.svg" alt="github" />
|
||||
<img class="idp-logo light" src="./assets/images/idp/github.svg" alt="github" />
|
||||
GitHub
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_OIDC">
|
||||
<mat-icon class="idp-icon" svgIcon="mdi_openid" alt="oidc" />
|
||||
Generic OIDC
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_OAUTH">
|
||||
<img class="idp-logo" src="./assets/images/idp/oauth.svg" alt="oauth" />
|
||||
Generic OAuth
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_JWT">
|
||||
<mat-icon class="idp-icon" svgIcon="mdi_jwt" alt="jwt" />
|
||||
Generic JWT
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_GITLAB">
|
||||
<img class="idp-logo" src="./assets/images/idp/gitlab.svg" alt="gitlab" />
|
||||
Gitlab
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_GITLAB_SELF_HOSTED">
|
||||
<img class="idp-logo" src="./assets/images/idp/gitlab.svg" alt="gitlab self hosted" />
|
||||
Gitlab Self Hosted
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_GITHUB_ES">
|
||||
<img class="idp-logo dark" src="./assets/images/idp/github-dark.svg" alt="github" />
|
||||
<img class="idp-logo light" src="./assets/images/idp/github.svg" alt="github" />
|
||||
GitHub Enterprise Server
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_LDAP">
|
||||
<i class="idp-icon las la-building"></i>
|
||||
Active Directory / LDAP
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_APPLE">
|
||||
<img class="idp-logo apple dark" src="./assets/images/idp/apple-dark.svg" alt="apple" />
|
||||
<img class="idp-logo apple light" src="./assets/images/idp/apple.svg" alt="apple" />
|
||||
Apple
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_SAML">
|
||||
<img class="idp-logo" src="./assets/images/idp/saml-icon.svg" alt="saml" />
|
||||
SAML
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchDefault>coming soon</div>
|
||||
<div>
|
||||
@switch (idp.type) {
|
||||
@case (ProviderType.PROVIDER_TYPE_AZURE_AD) {
|
||||
<div class="idp-table-provider-type">
|
||||
<img class="idp-logo" src="./assets/images/idp/ms.svg" alt="azure ad" />
|
||||
Microsoft
|
||||
</div>
|
||||
}
|
||||
@case (ProviderType.PROVIDER_TYPE_GOOGLE) {
|
||||
<div class="idp-table-provider-type">
|
||||
<img class="idp-logo" src="./assets/images/idp/google.png" alt="google" />
|
||||
Google
|
||||
</div>
|
||||
}
|
||||
@case (ProviderType.PROVIDER_TYPE_GITHUB) {
|
||||
<div class="idp-table-provider-type">
|
||||
<img class="idp-logo dark" src="./assets/images/idp/github-dark.svg" alt="github" />
|
||||
<img class="idp-logo light" src="./assets/images/idp/github.svg" alt="github" />
|
||||
GitHub
|
||||
</div>
|
||||
}
|
||||
@case (ProviderType.PROVIDER_TYPE_OIDC) {
|
||||
<div class="idp-table-provider-type">
|
||||
<mat-icon class="idp-icon" svgIcon="mdi_openid" alt="oidc" />
|
||||
Generic OIDC
|
||||
</div>
|
||||
}
|
||||
@case (ProviderType.PROVIDER_TYPE_OAUTH) {
|
||||
<div class="idp-table-provider-type">
|
||||
<img class="idp-logo" src="./assets/images/idp/oauth.svg" alt="oauth" />
|
||||
Generic OAuth
|
||||
</div>
|
||||
}
|
||||
@case (ProviderType.PROVIDER_TYPE_JWT) {
|
||||
<div class="idp-table-provider-type">
|
||||
<mat-icon class="idp-icon" svgIcon="mdi_jwt" alt="jwt" />
|
||||
Generic JWT
|
||||
</div>
|
||||
}
|
||||
@case (ProviderType.PROVIDER_TYPE_GITLAB) {
|
||||
<div class="idp-table-provider-type">
|
||||
<img class="idp-logo" src="./assets/images/idp/gitlab.svg" alt="gitlab" />
|
||||
Gitlab
|
||||
</div>
|
||||
}
|
||||
@case (ProviderType.PROVIDER_TYPE_GITLAB_SELF_HOSTED) {
|
||||
<div class="idp-table-provider-type">
|
||||
<img class="idp-logo" src="./assets/images/idp/gitlab.svg" alt="gitlab self hosted" />
|
||||
Gitlab Self Hosted
|
||||
</div>
|
||||
}
|
||||
@case (ProviderType.PROVIDER_TYPE_GITHUB_ES) {
|
||||
<div class="idp-table-provider-type">
|
||||
<img class="idp-logo dark" src="./assets/images/idp/github-dark.svg" alt="github" />
|
||||
<img class="idp-logo light" src="./assets/images/idp/github.svg" alt="github" />
|
||||
GitHub Enterprise Server
|
||||
</div>
|
||||
}
|
||||
@case (ProviderType.PROVIDER_TYPE_LDAP) {
|
||||
<div class="idp-table-provider-type">
|
||||
<i class="idp-icon las la-building"></i>
|
||||
Active Directory / LDAP
|
||||
</div>
|
||||
}
|
||||
@case (ProviderType.PROVIDER_TYPE_APPLE) {
|
||||
<div class="idp-table-provider-type">
|
||||
<img class="idp-logo apple dark" src="./assets/images/idp/apple-dark.svg" alt="apple" />
|
||||
<img class="idp-logo apple light" src="./assets/images/idp/apple.svg" alt="apple" />
|
||||
Apple
|
||||
</div>
|
||||
}
|
||||
@case (ProviderType.PROVIDER_TYPE_SAML) {
|
||||
<div class="idp-table-provider-type">
|
||||
<img class="idp-logo" src="./assets/images/idp/saml-icon.svg" alt="saml" />
|
||||
SAML
|
||||
</div>
|
||||
}
|
||||
@default {
|
||||
<div class="idp-table-provider-type">coming soon</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
@@ -132,71 +156,75 @@
|
||||
<th class="idp-table-actions" mat-header-cell *matHeaderCellDef></th>
|
||||
<td class="idp-table-actions" mat-cell *matCellDef="let idp">
|
||||
<cnsl-table-actions>
|
||||
<button
|
||||
actions
|
||||
*ngIf="!isEnabled(idp)"
|
||||
[disabled]="
|
||||
([
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.idp.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'org.idp.write'
|
||||
: '',
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
"
|
||||
mat-icon-button
|
||||
matTooltip="{{ 'IDP.SETAVAILABLE' | translate }}"
|
||||
(click)="addIdp(idp); $event.stopPropagation()"
|
||||
>
|
||||
<i class="las la-check-circle"></i>
|
||||
</button>
|
||||
<button
|
||||
actions
|
||||
*ngIf="isEnabled(idp)"
|
||||
[disabled]="
|
||||
([
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.idp.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'org.idp.write'
|
||||
: '',
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
"
|
||||
mat-icon-button
|
||||
matTooltip="{{ 'IDP.SETUNAVAILABLE' | translate }}"
|
||||
(click)="removeIdp(idp); $event.stopPropagation()"
|
||||
>
|
||||
<i class="las la-times-circle"></i>
|
||||
</button>
|
||||
<button
|
||||
actions
|
||||
*ngIf="
|
||||
(serviceType === PolicyComponentServiceType.MGMT && idp.owner === IDPOwnerType.IDP_OWNER_TYPE_ORG) ||
|
||||
(serviceType === PolicyComponentServiceType.ADMIN && idp.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM)
|
||||
"
|
||||
[disabled]="
|
||||
(serviceType === PolicyComponentServiceType.MGMT && idp?.providerType === IDPOwnerType.IDP_OWNER_TYPE_ORG) ||
|
||||
([
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.idp.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'org.idp.write'
|
||||
: '',
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
"
|
||||
mat-icon-button
|
||||
color="warn"
|
||||
matTooltip="{{ 'ACTIONS.REMOVE' | translate }}"
|
||||
(click)="deleteIdp(idp); $event.stopPropagation()"
|
||||
>
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
@if (!isEnabled(idp)) {
|
||||
<button
|
||||
actions
|
||||
[disabled]="
|
||||
([
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.idp.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'org.idp.write'
|
||||
: '',
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
"
|
||||
mat-icon-button
|
||||
matTooltip="{{ 'IDP.SETAVAILABLE' | translate }}"
|
||||
(click)="addIdp(idp); $event.stopPropagation()"
|
||||
>
|
||||
<i class="las la-check-circle"></i>
|
||||
</button>
|
||||
}
|
||||
@if (isEnabled(idp)) {
|
||||
<button
|
||||
actions
|
||||
[disabled]="
|
||||
([
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.idp.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'org.idp.write'
|
||||
: '',
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
"
|
||||
mat-icon-button
|
||||
matTooltip="{{ 'IDP.SETUNAVAILABLE' | translate }}"
|
||||
(click)="removeIdp(idp); $event.stopPropagation()"
|
||||
>
|
||||
<i class="las la-times-circle"></i>
|
||||
</button>
|
||||
}
|
||||
@if (
|
||||
(serviceType === PolicyComponentServiceType.MGMT && idp.owner === IDPOwnerType.IDP_OWNER_TYPE_ORG) ||
|
||||
(serviceType === PolicyComponentServiceType.ADMIN && idp.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM)
|
||||
) {
|
||||
<button
|
||||
actions
|
||||
[disabled]="
|
||||
(serviceType === PolicyComponentServiceType.MGMT &&
|
||||
idp?.providerType === IDPOwnerType.IDP_OWNER_TYPE_ORG) ||
|
||||
([
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.idp.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'org.idp.write'
|
||||
: '',
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
"
|
||||
mat-icon-button
|
||||
color="warn"
|
||||
matTooltip="{{ 'ACTIONS.REMOVE' | translate }}"
|
||||
(click)="deleteIdp(idp); $event.stopPropagation()"
|
||||
>
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
}
|
||||
</cnsl-table-actions>
|
||||
</td>
|
||||
</ng-container>
|
||||
@@ -206,10 +234,12 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div *ngIf="(loading$ | async) === false && !dataSource?.data?.length" class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'IDP.EMPTY' | translate }}</span>
|
||||
</div>
|
||||
@if ((loading$ | async) === false && !dataSource?.data?.length) {
|
||||
<div class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'IDP.EMPTY' | translate }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<cnsl-paginator
|
||||
#paginator
|
||||
|
||||
@@ -1,32 +1,19 @@
|
||||
<span class="title" mat-dialog-title>{{ data.titleKey | translate: data.titleParam }}</span>
|
||||
<span class="title" mat-dialog-title>{{ data.titleKey | translate }}</span>
|
||||
|
||||
<div mat-dialog-content>
|
||||
<div class="icon-wrapper" *ngIf="data.icon">
|
||||
<i class="icon {{ data.icon }}"></i>
|
||||
</div>
|
||||
<p class="desc cnsl-secondary-text">{{ data.descriptionKey | translate: data.descriptionParam }}</p>
|
||||
|
||||
<cnsl-info-section *ngIf="data.infoSectionKey" [type]="InfoSectionType.INFO">{{
|
||||
data.warnSectionKey | translate
|
||||
}}</cnsl-info-section>
|
||||
|
||||
<p *ngIf="data.hintKey" class="desc cnsl-secondary-text">{{ data.hintKey | translate: { value: data.confirmation } }}</p>
|
||||
|
||||
<cnsl-form-field *ngIf="data.confirmation && data.confirmationKey" class="formfield">
|
||||
<cnsl-label>{{ data.confirmationKey | translate: { value: data.confirmation } }}</cnsl-label>
|
||||
<input cnslInput [(ngModel)]="confirm" data-e2e="confirm-dialog-input" />
|
||||
</cnsl-form-field>
|
||||
<p class="desc cnsl-secondary-text">{{ data.descriptionKey | translate }}</p>
|
||||
</div>
|
||||
|
||||
<div mat-dialog-actions class="action">
|
||||
<button *ngIf="data.cancelKey" mat-stroked-button (click)="closeDialog()">
|
||||
<button mat-stroked-button (click)="dialogRef.close(false)">
|
||||
{{ data.cancelKey | translate }}
|
||||
</button>
|
||||
<span class="fill-space"></span>
|
||||
<button
|
||||
color="primary"
|
||||
[disabled]="data.confirmation && confirm !== data.confirmation"
|
||||
mat-raised-button
|
||||
class="ok-button"
|
||||
(click)="closeDialogWithSuccess()"
|
||||
(click)="dialogRef.close(true)"
|
||||
data-e2e="confirm-dialog-button"
|
||||
>
|
||||
{{ data.confirmKey | translate }}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { InfoDialogComponent } from './info-dialog.component';
|
||||
|
||||
describe('InfoDialogComponent', () => {
|
||||
let component: InfoDialogComponent;
|
||||
let fixture: ComponentFixture<InfoDialogComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [InfoDialogComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(InfoDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,27 +1,28 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
||||
|
||||
import { InfoSectionType } from '../info-section/info-section.component';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
|
||||
export type InfoDialogData = {
|
||||
confirmKey: string;
|
||||
cancelKey: string;
|
||||
titleKey: string;
|
||||
descriptionKey: string;
|
||||
};
|
||||
|
||||
export type InfoDialogResult = boolean;
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-info-dialog',
|
||||
templateUrl: './info-dialog.component.html',
|
||||
styleUrls: ['./info-dialog.component.scss'],
|
||||
standalone: false,
|
||||
imports: [TranslateModule, MatDialogModule, MatButtonModule],
|
||||
})
|
||||
export class InfoDialogComponent {
|
||||
public confirm: string = '';
|
||||
InfoSectionType: any = InfoSectionType;
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<InfoDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
) {}
|
||||
protected readonly InfoSectionType = InfoSectionType;
|
||||
|
||||
public closeDialog(): void {
|
||||
this.dialogRef.close(false);
|
||||
}
|
||||
|
||||
public closeDialogWithSuccess(): void {
|
||||
this.dialogRef.close(true);
|
||||
}
|
||||
protected readonly dialogRef = inject<MatDialogRef<InfoDialogComponent>>(MatDialogRef);
|
||||
protected readonly data = inject<InfoDialogData>(MAT_DIALOG_DATA);
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { InfoSectionModule } from '../info-section/info-section.module';
|
||||
import { InputModule } from '../input/input.module';
|
||||
import { InfoDialogComponent } from './info-dialog.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [InfoDialogComponent],
|
||||
imports: [CommonModule, FormsModule, MatDialogModule, TranslateModule, InfoSectionModule, MatButtonModule, InputModule],
|
||||
})
|
||||
export class InfoDialogModule {}
|
||||
@@ -1,24 +1,27 @@
|
||||
<div class="context_intro_overlay">
|
||||
<div class="overlay-info-row">
|
||||
<span class="info"
|
||||
>INFO <span *ngIf="data.number && data.count">{{ data.number }}/{{ data.count }}</span></span
|
||||
>
|
||||
>INFO
|
||||
@if (data.number && data.count) {
|
||||
<span>{{ data.number }}/{{ data.count }}</span>
|
||||
}
|
||||
</span>
|
||||
<button mat-icon-button (click)="workflowService.reset()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<p>{{ data.i18nText | translate }}</p>
|
||||
<div class="overlay-actions">
|
||||
<button
|
||||
(click)="workflowService.nextStep()"
|
||||
*ngIf="workflowService.nextPossible && !workflowService.isLast"
|
||||
mat-stroked-button
|
||||
>
|
||||
{{ 'ACTIONS.NEXT' | translate }}
|
||||
</button>
|
||||
@if (workflowService.nextPossible && !workflowService.isLast) {
|
||||
<button (click)="workflowService.nextStep()" mat-stroked-button>
|
||||
{{ 'ACTIONS.NEXT' | translate }}
|
||||
</button>
|
||||
}
|
||||
|
||||
<button *ngIf="workflowService.isLast" (click)="workflowService.nextStep()" color="primary" mat-raised-button>
|
||||
{{ 'ACTIONS.FINISHED' | translate }}
|
||||
</button>
|
||||
@if (workflowService.isLast) {
|
||||
<button (click)="workflowService.nextStep()" color="primary" mat-raised-button>
|
||||
{{ 'ACTIONS.FINISHED' | translate }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,308 +1,363 @@
|
||||
<div class="info-row" *ngIf="user">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'USER.PAGES.STATE' | translate }}</p>
|
||||
<p
|
||||
*ngIf="user?.state"
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: user.state === UserState.USER_STATE_ACTIVE,
|
||||
inactive: user.state === UserState.USER_STATE_INACTIVE,
|
||||
}"
|
||||
>
|
||||
{{ (isV2(user) ? 'USER.STATEV2.' : 'USER.STATE.') + user.state | translate }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'USER.ID' | translate }}</p>
|
||||
<p *ngIf="userId" class="info-row-desc">{{ userId }}</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'USER.DETAILS.DATECREATED' | translate }}</p>
|
||||
<p *ngIf="creationDate" class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'USER.DETAILS.DATECHANGED' | translate }}</p>
|
||||
<p *ngIf="changeDate" class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper width">
|
||||
<p class="info-row-title">{{ 'USER.PAGES.LOGINMETHODS' | translate }}</p>
|
||||
<div class="copy-row" *ngFor="let login of loginMethods">
|
||||
<button
|
||||
[disabled]="copied === login"
|
||||
[matTooltip]="(copied !== login ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="login"
|
||||
(copiedValue)="copied = $event"
|
||||
data-e2e="copy-loginname"
|
||||
>
|
||||
{{ login }}
|
||||
</button>
|
||||
@if (user) {
|
||||
<div class="info-row">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'USER.PAGES.STATE' | translate }}</p>
|
||||
@if (user?.state) {
|
||||
<p
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: user.state === UserState.USER_STATE_ACTIVE,
|
||||
inactive: user.state === UserState.USER_STATE_INACTIVE,
|
||||
}"
|
||||
>
|
||||
{{ (isV2(user) ? 'USER.STATEV2.' : 'USER.STATE.') + user.state | translate }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'USER.ID' | translate }}</p>
|
||||
@if (userId) {
|
||||
<p class="info-row-desc">{{ userId }}</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'USER.DETAILS.DATECREATED' | translate }}</p>
|
||||
@if (creationDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'USER.DETAILS.DATECHANGED' | translate }}</p>
|
||||
@if (changeDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper width">
|
||||
<p class="info-row-title">{{ 'USER.PAGES.LOGINMETHODS' | translate }}</p>
|
||||
@for (login of loginMethods; track login) {
|
||||
<div class="copy-row">
|
||||
<button
|
||||
[disabled]="copied === login"
|
||||
[matTooltip]="(copied !== login ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="login"
|
||||
(copiedValue)="copied = $event"
|
||||
data-e2e="copy-loginname"
|
||||
>
|
||||
{{ login }}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="info-row" *ngIf="instance">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'IAM.PAGES.STATE' | translate }}</p>
|
||||
<p
|
||||
*ngIf="instance?.state"
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: instance.state === State.STATE_RUNNING,
|
||||
inactive: instance.state === State.STATE_STOPPED || instance.state === State.STATE_STOPPING,
|
||||
}"
|
||||
>
|
||||
{{ 'IAM.STATE.' + instance.state | translate }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'INSTANCEID' | translate }}</p>
|
||||
<p *ngIf="instance?.id" class="info-row-desc">{{ instance.id }}</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'NAME' | translate }}</p>
|
||||
<p *ngIf="instance?.name" class="info-row-desc">{{ instance.name }}</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'VERSION' | translate }}</p>
|
||||
<p *ngIf="instance?.version" class="info-row-desc">{{ instance.version }}</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper width">
|
||||
<p class="info-row-title">{{ 'IAM.PAGES.DOMAINLIST' | translate }}</p>
|
||||
<div class="copy-row" *ngFor="let domain of instance?.domainsList">
|
||||
<button
|
||||
[disabled]="copied === domain.domain"
|
||||
[matTooltip]="(copied !== domain.domain ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="domain.domain"
|
||||
(copiedValue)="copied = $event"
|
||||
>
|
||||
{{ domain.domain }}
|
||||
</button>
|
||||
@if (instance) {
|
||||
<div class="info-row">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'IAM.PAGES.STATE' | translate }}</p>
|
||||
@if (instance?.state) {
|
||||
<p
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: instance.state === State.STATE_RUNNING,
|
||||
inactive: instance.state === State.STATE_STOPPED || instance.state === State.STATE_STOPPING,
|
||||
}"
|
||||
>
|
||||
{{ 'IAM.STATE.' + instance.state | translate }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'INSTANCEID' | translate }}</p>
|
||||
@if (instance?.id) {
|
||||
<p class="info-row-desc">{{ instance.id }}</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'NAME' | translate }}</p>
|
||||
@if (instance?.name) {
|
||||
<p class="info-row-desc">{{ instance.name }}</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'VERSION' | translate }}</p>
|
||||
@if (instance?.version) {
|
||||
<p class="info-row-desc">{{ instance.version }}</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper width">
|
||||
<p class="info-row-title">{{ 'IAM.PAGES.DOMAINLIST' | translate }}</p>
|
||||
@for (domain of instance?.domainsList; track domain) {
|
||||
<div class="copy-row">
|
||||
<button
|
||||
[disabled]="copied === domain.domain"
|
||||
[matTooltip]="(copied !== domain.domain ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="domain.domain"
|
||||
(copiedValue)="copied = $event"
|
||||
>
|
||||
{{ domain.domain }}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.CREATIONDATE' | translate }}</p>
|
||||
@if (instance?.details?.creationDate; as creationDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.DATECHANGED' | translate }}</p>
|
||||
@if (instance?.details?.changeDate; as changeDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.CREATIONDATE' | translate }}</p>
|
||||
<p *ngIf="instance?.details?.creationDate as creationDate" class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.DATECHANGED' | translate }}</p>
|
||||
<p *ngIf="instance?.details?.changeDate as changeDate" class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-row" *ngIf="org">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.STATE' | translate }}</p>
|
||||
<p
|
||||
*ngIf="org?.state"
|
||||
class="state"
|
||||
[ngClass]="{ active: org.state === OrgState.ORG_STATE_ACTIVE, inactive: org.state === OrgState.ORG_STATE_INACTIVE }"
|
||||
>
|
||||
{{ 'ORG.STATE.' + org.state | translate }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.ID' | translate }}</p>
|
||||
<p *ngIf="org?.id" class="info-row-desc">{{ org.id }}</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper width">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.PRIMARYDOMAIN' | translate }}</p>
|
||||
<div class="copy-row" *ngIf="org.primaryDomain">
|
||||
<button
|
||||
[disabled]="copied === org.primaryDomain"
|
||||
[matTooltip]="(copied !== org.primaryDomain ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="org.primaryDomain"
|
||||
(copiedValue)="copied = $event"
|
||||
>
|
||||
{{ org.primaryDomain }}
|
||||
</button>
|
||||
@if (org) {
|
||||
<div class="info-row">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.STATE' | translate }}</p>
|
||||
@if (org?.state) {
|
||||
<p
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: org.state === OrgState.ORG_STATE_ACTIVE,
|
||||
inactive: org.state === OrgState.ORG_STATE_INACTIVE,
|
||||
}"
|
||||
>
|
||||
{{ 'ORG.STATE.' + org.state | translate }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.ID' | translate }}</p>
|
||||
@if (org?.id) {
|
||||
<p class="info-row-desc">{{ org.id }}</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper width">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.PRIMARYDOMAIN' | translate }}</p>
|
||||
@if (org.primaryDomain) {
|
||||
<div class="copy-row">
|
||||
<button
|
||||
[disabled]="copied === org.primaryDomain"
|
||||
[matTooltip]="(copied !== org.primaryDomain ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="org.primaryDomain"
|
||||
(copiedValue)="copied = $event"
|
||||
>
|
||||
{{ org.primaryDomain }}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.CREATIONDATE' | translate }}</p>
|
||||
@if (org?.details?.creationDate; as creationDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.DATECHANGED' | translate }}</p>
|
||||
@if (org?.details?.changeDate; as changeDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.CREATIONDATE' | translate }}</p>
|
||||
<p *ngIf="org?.details?.creationDate as creationDate" class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@if (project) {
|
||||
<div class="info-row">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.STATE.TITLE' | translate }}</p>
|
||||
@if (project?.state) {
|
||||
<p
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: project.state === ProjectState.PROJECT_STATE_ACTIVE,
|
||||
inactive: project.state === ProjectState.PROJECT_STATE_INACTIVE,
|
||||
}"
|
||||
>
|
||||
{{ 'PROJECT.STATE.' + project.state | translate }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.ID' | translate }}</p>
|
||||
@if (project?.id) {
|
||||
<p class="info-row-desc">{{ project.id }}</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.CREATEDON' | translate }}</p>
|
||||
@if (project?.details?.creationDate; as creationDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.LASTMODIFIED' | translate }}</p>
|
||||
@if (project?.details?.changeDate; as changeDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.DATECHANGED' | translate }}</p>
|
||||
<p *ngIf="org?.details?.changeDate as changeDate" class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@if (grantedProject) {
|
||||
<div class="info-row">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.STATE.TITLE' | translate }}</p>
|
||||
@if (grantedProject?.state) {
|
||||
<p
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: grantedProject.state === ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE,
|
||||
inactive: grantedProject.state === ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE,
|
||||
}"
|
||||
>
|
||||
{{ 'PROJECT.STATE.' + grantedProject.state | translate }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.ID' | translate }}</p>
|
||||
@if (grantedProject?.projectId) {
|
||||
<p class="info-row-desc">{{ grantedProject.projectId }}</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.GRANT.GRANTID' | translate }}</p>
|
||||
@if (grantedProject?.grantId) {
|
||||
<p class="info-row-desc">{{ grantedProject.grantId }}</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.CREATEDON' | translate }}</p>
|
||||
@if (grantedProject?.details?.creationDate; as creationDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.LASTMODIFIED' | translate }}</p>
|
||||
@if (grantedProject?.details?.changeDate; as changeDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="info-row" *ngIf="project">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.STATE.TITLE' | translate }}</p>
|
||||
<p
|
||||
*ngIf="project?.state"
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: project.state === ProjectState.PROJECT_STATE_ACTIVE,
|
||||
inactive: project.state === ProjectState.PROJECT_STATE_INACTIVE,
|
||||
}"
|
||||
>
|
||||
{{ 'PROJECT.STATE.' + project.state | translate }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.ID' | translate }}</p>
|
||||
<p *ngIf="project?.id" class="info-row-desc">{{ project.id }}</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.CREATEDON' | translate }}</p>
|
||||
<p *ngIf="project?.details?.creationDate as creationDate" class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.LASTMODIFIED' | translate }}</p>
|
||||
<p *ngIf="project?.details?.changeDate as changeDate" class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-row" *ngIf="grantedProject">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.STATE.TITLE' | translate }}</p>
|
||||
<p
|
||||
*ngIf="grantedProject?.state"
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: grantedProject.state === ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE,
|
||||
inactive: grantedProject.state === ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE,
|
||||
}"
|
||||
>
|
||||
{{ 'PROJECT.STATE.' + grantedProject.state | translate }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.ID' | translate }}</p>
|
||||
<p *ngIf="grantedProject?.projectId" class="info-row-desc">{{ grantedProject.projectId }}</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.GRANT.GRANTID' | translate }}</p>
|
||||
<p *ngIf="grantedProject?.grantId" class="info-row-desc">{{ grantedProject.grantId }}</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.CREATEDON' | translate }}</p>
|
||||
<p *ngIf="grantedProject?.details?.creationDate as creationDate" class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.LASTMODIFIED' | translate }}</p>
|
||||
<p *ngIf="grantedProject?.details?.changeDate as changeDate" class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="app">
|
||||
@if (app) {
|
||||
<div class="info-row">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'APP.PAGES.STATE' | translate }}</p>
|
||||
<p
|
||||
*ngIf="app?.state"
|
||||
class="state"
|
||||
[ngClass]="{ active: app.state === AppState.APP_STATE_ACTIVE, inactive: app.state === AppState.APP_STATE_INACTIVE }"
|
||||
>
|
||||
{{ 'APP.PAGES.DETAIL.STATE.' + app.state | translate }}
|
||||
</p>
|
||||
@if (app?.state) {
|
||||
<p
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: app.state === AppState.APP_STATE_ACTIVE,
|
||||
inactive: app.state === AppState.APP_STATE_INACTIVE,
|
||||
}"
|
||||
>
|
||||
{{ 'APP.PAGES.DETAIL.STATE.' + app.state | translate }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="info-wrapper" *ngIf="app?.apiConfig?.authMethodType as authMethodType">
|
||||
<p class="info-row-title">{{ 'APP.AUTHMETHOD' | translate }}</p>
|
||||
<p class="info-row-desc">
|
||||
{{ 'APP.API.AUTHMETHOD.' + authMethodType | translate }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper" *ngIf="app?.oidcConfig?.authMethodType as authMethodType">
|
||||
<p class="info-row-title">{{ 'APP.AUTHMETHOD' | translate }}</p>
|
||||
<p class="info-row-desc">
|
||||
{{ 'APP.OIDC.AUTHMETHOD.' + authMethodType | translate }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@if (app?.apiConfig?.authMethodType; as authMethodType) {
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'APP.AUTHMETHOD' | translate }}</p>
|
||||
<p class="info-row-desc">
|
||||
{{ 'APP.API.AUTHMETHOD.' + authMethodType | translate }}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
@if (app?.oidcConfig?.authMethodType; as authMethodType) {
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'APP.AUTHMETHOD' | translate }}</p>
|
||||
<p class="info-row-desc">
|
||||
{{ 'APP.OIDC.AUTHMETHOD.' + authMethodType | translate }}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'APP.PAGES.ID' | translate }}</p>
|
||||
<p *ngIf="app?.id" class="info-row-desc">{{ app.id }}</p>
|
||||
@if (app?.id) {
|
||||
<p class="info-row-desc">{{ app.id }}</p>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'APP.PAGES.DATECREATED' | translate }}</p>
|
||||
<p *ngIf="app?.details?.creationDate as creationDate" class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@if (app?.details?.creationDate; as creationDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'APP.PAGES.DATECHANGED' | translate }}</p>
|
||||
<p *ngIf="app?.details?.changeDate as changeDate" class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@if (app?.details?.changeDate; as changeDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper" *ngIf="app">
|
||||
<p class="info-row-title">{{ 'APP.OIDC.INFO.CLIENTID' | translate }}</p>
|
||||
<div class="copy-row" *ngIf="app.oidcConfig?.clientId">
|
||||
<button
|
||||
*ngIf="app.oidcConfig?.clientId as clientId"
|
||||
[disabled]="copied === clientId"
|
||||
[matTooltip]="(copied !== clientId ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="clientId"
|
||||
(copiedValue)="copied = $event"
|
||||
>
|
||||
{{ clientId }}
|
||||
</button>
|
||||
@if (app) {
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'APP.OIDC.INFO.CLIENTID' | translate }}</p>
|
||||
@if (app.oidcConfig?.clientId) {
|
||||
<div class="copy-row">
|
||||
@if (app.oidcConfig?.clientId; as clientId) {
|
||||
<button
|
||||
[disabled]="copied === clientId"
|
||||
[matTooltip]="(copied !== clientId ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="clientId"
|
||||
(copiedValue)="copied = $event"
|
||||
>
|
||||
{{ clientId }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (app.apiConfig?.clientId) {
|
||||
<div class="copy-row">
|
||||
@if (app.apiConfig?.clientId; as clientId) {
|
||||
<button
|
||||
[disabled]="copied === clientId"
|
||||
[matTooltip]="(copied !== clientId ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="clientId"
|
||||
(copiedValue)="copied = $event"
|
||||
>
|
||||
{{ clientId }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="copy-row" *ngIf="app.apiConfig?.clientId">
|
||||
<button
|
||||
*ngIf="app.apiConfig?.clientId as clientId"
|
||||
[disabled]="copied === clientId"
|
||||
[matTooltip]="(copied !== clientId ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="clientId"
|
||||
(copiedValue)="copied = $event"
|
||||
>
|
||||
{{ clientId }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</ng-container>
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user