mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
<!-- Please inform yourself about the contribution guidelines on submitting a PR here: https://github.com/zitadel/zitadel/blob/main/CONTRIBUTING.md#submit-a-pull-request-pr. Take note of how PR/commit titles should be written and replace the template texts in the sections below. Don't remove any of the sections. It is important that the commit history clearly shows what is changed and why. Important: By submitting a contribution you agree to the terms from our Licensing Policy as described here: https://github.com/zitadel/zitadel/blob/main/LICENSING.md#community-contributions. --> # Which Problems Are Solved When creating a new Project Grant in the Zitadel console, the UI becomes extremely sluggish/unusable. The issue appears tied to the organization search dropdown attempting to load a very large dataset. # How the Problems Are Solved The refactored `SearchOrgAutocompleteComponent` uses server side filtering and ondemand loading using infinite scrolling. This makes sure on a subset of organizations is ever loaded on the client. # Additional Changes - Added tailwindcss for easier styling - Removed build warnings - Removed some of the SCSS syntax warnings # Additional Context - Closes #11121 --------- Co-authored-by: Max Peintner <[email protected]>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"plugins": {
|
||||
"@tailwindcss/postcss": {}
|
||||
}
|
||||
}
|
||||
+11
-36
@@ -22,9 +22,7 @@
|
||||
"base": "dist/console"
|
||||
},
|
||||
"index": "src/index.html",
|
||||
"polyfills": [
|
||||
"zone.js"
|
||||
],
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
@@ -37,23 +35,13 @@
|
||||
"output": "assets/docs/img/tech"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": [
|
||||
"./node_modules/tinycolor2/dist/tinycolor-min.js"
|
||||
],
|
||||
"styles": ["src/styles.scss", "src/tailwind.css"],
|
||||
"scripts": ["./node_modules/tinycolor2/dist/tinycolor-min.js"],
|
||||
"stylePreprocessorOptions": {
|
||||
"sass": {
|
||||
"silenceDeprecations": [
|
||||
"import",
|
||||
"mixed-decls"
|
||||
]
|
||||
"silenceDeprecations": ["import", "mixed-decls"]
|
||||
},
|
||||
"includePaths": [
|
||||
"node_modules",
|
||||
"."
|
||||
]
|
||||
"includePaths": ["node_modules", "."]
|
||||
},
|
||||
"allowedCommonJsDependencies": [
|
||||
"opentype.js",
|
||||
@@ -158,29 +146,18 @@
|
||||
"test": {
|
||||
"builder": "@angular/build:karma",
|
||||
"options": {
|
||||
"polyfills": [
|
||||
"zone.js",
|
||||
"zone.js/testing"
|
||||
],
|
||||
"polyfills": ["zone.js", "zone.js/testing"],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"assets": ["src/favicon.ico", "src/assets"],
|
||||
"styles": ["src/styles.scss"],
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-eslint/builder:lint",
|
||||
"options": {
|
||||
"lintFilePatterns": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.html"
|
||||
]
|
||||
"lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -188,9 +165,7 @@
|
||||
},
|
||||
"cli": {
|
||||
"analytics": false,
|
||||
"schematicCollections": [
|
||||
"@angular-eslint/schematics"
|
||||
],
|
||||
"schematicCollections": ["@angular-eslint/schematics"],
|
||||
"packageManager": "pnpm"
|
||||
},
|
||||
"schematics": {
|
||||
@@ -219,4 +194,4 @@
|
||||
"typeSeparator": "."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
"@types/opentype.js": "^1.3.9",
|
||||
"@types/qrcode": "^1.5.6",
|
||||
"@types/uuid": "^11.0.0",
|
||||
"@tailwindcss/postcss": "^4.2.2",
|
||||
"@typescript-eslint/eslint-plugin": "^8.58.0",
|
||||
"@typescript-eslint/parser": "^8.58.0",
|
||||
"@zitadel/client": "workspace:*",
|
||||
@@ -92,8 +93,10 @@
|
||||
"karma-coverage-istanbul-reporter": "^3.0.3",
|
||||
"karma-jasmine": "^5.1.0",
|
||||
"karma-jasmine-html-reporter": "^2.2.0",
|
||||
"prettier": "^3.8.1",
|
||||
"postcss": "^8.5.8",
|
||||
"prettier": "^3.8.3",
|
||||
"prettier-plugin-organize-imports": "^4.3.0",
|
||||
"tailwindcss": "^4.2.2",
|
||||
"typescript": "5.9.2"
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -13,8 +13,8 @@
|
||||
|
||||
$list-background-color: map-get($background, 300);
|
||||
$card-background-color: map-get($background, cards);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if($is-dark-theme, #fff, #000);
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if(sass($is-dark-theme): #fff; else: #000);
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
@@ -58,11 +58,11 @@
|
||||
}
|
||||
|
||||
.dark-only {
|
||||
display: if($is-dark-theme, block, none);
|
||||
display: if(sass($is-dark-theme): block; else: none);
|
||||
}
|
||||
|
||||
.light-only {
|
||||
display: if($is-dark-theme, none, block);
|
||||
display: if(sass($is-dark-theme): none; else: block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
$list-background-color: map-get($background, 300);
|
||||
$card-background-color: map-get($background, cards);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if($is-dark-theme, #fff, #000);
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if(sass($is-dark-theme): #fff; else: #000);
|
||||
|
||||
.framework-change-wrapper {
|
||||
.framework-card-wrapper {
|
||||
@@ -36,7 +36,7 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
// background-color: if($is-dark-theme, map-get($background, state), #e4e7e4);
|
||||
// background-color: if(sass($is-dark-theme): map-get($background, state); else: #e4e7e4);
|
||||
// box-shadow: 0 0 3px #0000001a;
|
||||
border: 1px solid rgba(#8795a1, 0.2);
|
||||
padding: 0 0.5rem;
|
||||
@@ -51,11 +51,11 @@
|
||||
}
|
||||
|
||||
.dark-only {
|
||||
display: if($is-dark-theme, block, none);
|
||||
display: if(sass($is-dark-theme): block; else: none);
|
||||
}
|
||||
|
||||
.light-only {
|
||||
display: if($is-dark-theme, none, block);
|
||||
display: if(sass($is-dark-theme): none; else: block);
|
||||
}
|
||||
|
||||
span {
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
<span class="left cnsl-secondary-text">
|
||||
{{ 'APP.GRANT' | translate }}
|
||||
</span>
|
||||
@if (configuration.grantTypesList && configuration.grantTypesList.length > 0) {
|
||||
@if (configuration.grantTypesList && configuration.grantTypesList.length) {
|
||||
<span class="right">
|
||||
[
|
||||
@for (element of configuration.grantTypesList ?? []; track element; let i = $index) {
|
||||
@for (element of configuration.grantTypesList; track element; let i = $index) {
|
||||
<span>
|
||||
{{ 'APP.OIDC.GRANT.' + element | translate }}
|
||||
{{ i < configuration.grantTypesList.length - 1 ? ', ' : '' }}
|
||||
@@ -38,10 +38,10 @@
|
||||
<span class="left cnsl-secondary-text">
|
||||
{{ 'APP.OIDC.RESPONSETYPE' | translate }}
|
||||
</span>
|
||||
@if (configuration.responseTypesList && configuration.responseTypesList.length > 0) {
|
||||
@if (configuration.responseTypesList && configuration.responseTypesList.length) {
|
||||
<span class="right">
|
||||
[
|
||||
@for (element of configuration.responseTypesList ?? []; track element; let i = $index) {
|
||||
@for (element of configuration.responseTypesList; track element; let i = $index) {
|
||||
<span>
|
||||
{{ 'APP.OIDC.RESPONSE.' + element | translate }}
|
||||
{{ i < configuration.responseTypesList.length - 1 ? ', ' : '' }}
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
$list-background-color: map-get($background, 300);
|
||||
$card-background-color: map-get($background, cards);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if($is-dark-theme, #fff, #000);
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if(sass($is-dark-theme): #fff; else: #000);
|
||||
|
||||
.quickstart-header {
|
||||
display: flex;
|
||||
@@ -86,11 +86,11 @@
|
||||
}
|
||||
|
||||
.dark-only {
|
||||
display: if($is-dark-theme, block, none);
|
||||
display: if(sass($is-dark-theme): block; else: none);
|
||||
}
|
||||
|
||||
.light-only {
|
||||
display: if($is-dark-theme, none, block);
|
||||
display: if(sass($is-dark-theme): none; else: block);
|
||||
}
|
||||
|
||||
span {
|
||||
|
||||
@@ -6,9 +6,9 @@ import { Directive, ElementRef, EventEmitter, HostListener, Output } from '@angu
|
||||
})
|
||||
export class ScrollableDirective {
|
||||
// when using this directive, add overflow-y scroll to css
|
||||
@Output() scrollPosition: EventEmitter<any> = new EventEmitter();
|
||||
@Output() scrollPosition: EventEmitter<'bottom' | 'top'> = new EventEmitter();
|
||||
|
||||
constructor(public el: ElementRef) {}
|
||||
constructor(private readonly el: ElementRef) {}
|
||||
|
||||
@HostListener('scroll', ['$event'])
|
||||
public onScroll(event: any): void {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
$foreground: map-get($theme, foreground);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$back: map-get($background, background);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
$secondary-text: map-get($foreground, secondary-text);
|
||||
|
||||
.accounts-card {
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
.action-keys-row {
|
||||
.key-overlay {
|
||||
z-index: 0;
|
||||
background: if($is-dark-theme, #fff, #000);
|
||||
background: if(sass($is-dark-theme): #fff; else: #000);
|
||||
opacity: 0.15;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -3,7 +3,7 @@
|
||||
$primary-color: map-get($primary, 500);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$background: map-get($theme, background);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
|
||||
.auth-method-radio-button-wrapper {
|
||||
display: flex;
|
||||
@@ -29,7 +29,7 @@
|
||||
box-sizing: border-box;
|
||||
|
||||
&:focus {
|
||||
border: 1px solid if($is-dark-theme, white, black);
|
||||
border: 1px solid if(sass($is-dark-theme): white; else: black);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
box-shadow: 0 0 6px rgb(0 0 0 / 10%);
|
||||
|
||||
.cnsl-radio-header span {
|
||||
color: if($is-dark-theme, white, white);
|
||||
color: if(sass($is-dark-theme): white; else: white);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
span {
|
||||
margin: 2rem;
|
||||
font-size: 30px;
|
||||
color: if($is-dark-theme, #00000050, #ffffff50);
|
||||
color: if(sass($is-dark-theme): #00000050; else: #ffffff50);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
$primary-color: map-get($primary, 500);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$background: map-get($theme, background);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
|
||||
input[type='radio'].app {
|
||||
appearance: none;
|
||||
@@ -20,7 +20,7 @@
|
||||
box-sizing: border-box;
|
||||
|
||||
&:focus {
|
||||
border: 1px solid if($is-dark-theme, white, black);
|
||||
border: 1px solid if(sass($is-dark-theme): white; else: black);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
box-shadow: 0 0 6px rgb(0 0 0 / 10%);
|
||||
|
||||
.cnsl-type-radio-header span {
|
||||
color: if($is-dark-theme, white, white);
|
||||
color: if(sass($is-dark-theme): white; else: white);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
span {
|
||||
margin: 2rem;
|
||||
font-size: 30px;
|
||||
color: if($is-dark-theme, #00000050, #ffffff50);
|
||||
color: if(sass($is-dark-theme): #00000050; else: #ffffff50);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
$background: map-get($theme, background);
|
||||
$card-background-color: map-get($background, cards);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if($is-dark-theme, #fff, #000);
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if(sass($is-dark-theme): #fff; else: #000);
|
||||
|
||||
.card {
|
||||
background-color: $card-background-color;
|
||||
@@ -57,7 +57,7 @@
|
||||
.cnsl-chip {
|
||||
height: auto;
|
||||
border: 1px solid $border-color;
|
||||
background: if($is-dark-theme, map-get($background, state), #e4e7e4) !important;
|
||||
background: if(sass($is-dark-theme): map-get($background, state) ; else: #e4e7e4) !important;
|
||||
|
||||
.cnsl-chip-content {
|
||||
display: flex;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
@mixin domain-verification-theme($theme) {
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
|
||||
.entry {
|
||||
margin: 0.5rem 0;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
min-height: 80px;
|
||||
|
||||
&.defaulttext {
|
||||
color: if($is-dark-theme, #ffffff50, #00000050);
|
||||
color: if(sass($is-dark-theme): #ffffff50; else: #00000050);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
$foreground: map-get($theme, foreground);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$card-background-color: map-get($background, cards);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
$primary: map-get($theme, primary);
|
||||
$primary-color: map-get($primary, 500);
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
$secondary-text: map-get($foreground, secondary-text);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
|
||||
$link-hover-color: if($is-dark-theme, map-get($primary, 200), $primary-color);
|
||||
$link-color: if($is-dark-theme, $lighter-primary-color, $primary-color);
|
||||
$link-hover-color: if(sass($is-dark-theme): map-get($primary, 200) ; else: $primary-color);
|
||||
$link-color: if(sass($is-dark-theme): $lighter-primary-color; else: $primary-color);
|
||||
|
||||
.filter-events-wrapper {
|
||||
border-radius: 0.5rem;
|
||||
@@ -38,7 +38,7 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 0.5rem 0.5rem 0.5rem;
|
||||
border-bottom: 2px solid if($is-dark-theme, #ffffff15, #00000015);
|
||||
border-bottom: 2px solid if(sass($is-dark-theme): #ffffff15; else: #00000015);
|
||||
|
||||
.filter-middle {
|
||||
margin: 0 1rem;
|
||||
@@ -73,7 +73,7 @@
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
padding: 0 0.5rem;
|
||||
background-color: if($is-dark-theme, #00000020, #00000008);
|
||||
background-color: if(sass($is-dark-theme): #00000020; else: #00000008);
|
||||
margin: 0 -0.5rem;
|
||||
|
||||
.aggregate-type-select .mat-mdc-select {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
$foreground: map-get($theme, foreground);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$back: map-get($background, background);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
|
||||
.cnsl-filter-button-wrapper {
|
||||
position: relative;
|
||||
@@ -48,7 +48,7 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 2px solid if($is-dark-theme, #ffffff15, #00000015);
|
||||
border-bottom: 2px solid if(sass($is-dark-theme): #ffffff15; else: #00000015);
|
||||
|
||||
.filter-middle {
|
||||
margin: 0 1rem;
|
||||
@@ -74,7 +74,7 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 0.5rem;
|
||||
background-color: if($is-dark-theme, #00000020, #00000008);
|
||||
background-color: if(sass($is-dark-theme): #00000020; else: #00000008);
|
||||
margin: 0 -0.5rem;
|
||||
|
||||
.nomethod {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$back: map-get($background, background);
|
||||
$secondary-text: map-get($foreground, secondary-text);
|
||||
$link-hover-color: if($is-dark-theme, $lighter-primary-color, $darker-primary-color);
|
||||
$link-hover-color: if(sass($is-dark-theme): $lighter-primary-color; else: $darker-primary-color);
|
||||
|
||||
.footer-wrapper {
|
||||
padding: 2rem;
|
||||
@@ -71,7 +71,7 @@
|
||||
.swisssvg {
|
||||
width: 14rem;
|
||||
margin: 1rem 0;
|
||||
color: if($is-dark-theme, #ffffff60, #00000060);
|
||||
color: if(sass($is-dark-theme): #ffffff60; else: #00000060);
|
||||
|
||||
.cross {
|
||||
fill: white;
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
// z-index: 502;
|
||||
|
||||
&:hover {
|
||||
background-color: if($is-dark-theme, #ffffff10, #00000010);
|
||||
background-color: if(sass($is-dark-theme): #ffffff10; else: #00000010);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 700px) {
|
||||
@@ -97,7 +97,7 @@
|
||||
transition: all ease 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-color: if($is-dark-theme, #ffffff10, #00000010);
|
||||
background-color: if(sass($is-dark-theme): #ffffff10; else: #00000010);
|
||||
}
|
||||
|
||||
.svgspan {
|
||||
@@ -146,7 +146,7 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: if($is-dark-theme, #ffffff10, #00000010);
|
||||
background-color: if(sass($is-dark-theme): #ffffff10; else: #00000010);
|
||||
}
|
||||
|
||||
.mob {
|
||||
@@ -274,7 +274,7 @@
|
||||
border-radius: 50%;
|
||||
transition: border ease 0.15s;
|
||||
padding: 0;
|
||||
border: 2px solid if($is-dark-theme, #ffffff80, #00000010);
|
||||
border: 2px solid if(sass($is-dark-theme): #ffffff80; else: #00000010);
|
||||
outline: none;
|
||||
background: none;
|
||||
|
||||
@@ -284,7 +284,7 @@
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
border: 2px solid if($is-dark-theme, #fff, map-get($primary, 200));
|
||||
border: 2px solid if(sass($is-dark-theme): #fff; else: map-get($primary, 200));
|
||||
}
|
||||
|
||||
.docs {
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@if ((loading$ | async) === false && !dataSource?.data?.length) {
|
||||
@if ((loading$ | async) === false && !dataSource.data.length) {
|
||||
<div class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'IDP.EMPTY' | translate }}</span>
|
||||
|
||||
@@ -26,11 +26,11 @@
|
||||
}
|
||||
|
||||
&.dark {
|
||||
display: if($is-dark-theme, block, none);
|
||||
display: if(sass($is-dark-theme): block; else: none);
|
||||
}
|
||||
|
||||
&.light {
|
||||
display: if($is-dark-theme, none, block);
|
||||
display: if(sass($is-dark-theme): none; else: block);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
$back: map-get($background, background);
|
||||
|
||||
.cnsl-overlay-backdrop {
|
||||
background-color: if($is-dark-theme, #00000080, #ffffff80);
|
||||
background-color: if(sass($is-dark-theme): #00000080; else: #ffffff80);
|
||||
backdrop-filter: blur(2px);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
padding: 1rem;
|
||||
font-size: 14px;
|
||||
width: 300px;
|
||||
border: 1px solid if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
border: 1px solid if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
|
||||
&::before {
|
||||
visibility: hidden;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="info-row">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'USER.PAGES.STATE' | translate }}</p>
|
||||
@if (user?.state) {
|
||||
@if (user.state) {
|
||||
<p
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
@@ -60,7 +60,7 @@
|
||||
<div class="info-row">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'IAM.PAGES.STATE' | translate }}</p>
|
||||
@if (instance?.state) {
|
||||
@if (instance.state) {
|
||||
<p
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
@@ -74,25 +74,25 @@
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'INSTANCEID' | translate }}</p>
|
||||
@if (instance?.id) {
|
||||
@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) {
|
||||
@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) {
|
||||
@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) {
|
||||
@for (domain of instance.domainsList; track domain) {
|
||||
<div class="copy-row">
|
||||
<button
|
||||
[disabled]="copied === domain.domain"
|
||||
@@ -108,7 +108,7 @@
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.CREATIONDATE' | translate }}</p>
|
||||
@if (instance?.details?.creationDate; as creationDate) {
|
||||
@if (instance.details?.creationDate; as creationDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@@ -116,7 +116,7 @@
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.DATECHANGED' | translate }}</p>
|
||||
@if (instance?.details?.changeDate; as changeDate) {
|
||||
@if (instance.details?.changeDate; as changeDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@@ -129,7 +129,7 @@
|
||||
<div class="info-row">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.STATE' | translate }}</p>
|
||||
@if (org?.state) {
|
||||
@if (org.state) {
|
||||
<p
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
@@ -143,7 +143,7 @@
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.ID' | translate }}</p>
|
||||
@if (org?.id) {
|
||||
@if (org.id) {
|
||||
<p class="info-row-desc">{{ org.id }}</p>
|
||||
}
|
||||
</div>
|
||||
@@ -165,7 +165,7 @@
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.CREATIONDATE' | translate }}</p>
|
||||
@if (org?.details?.creationDate; as creationDate) {
|
||||
@if (org.details?.creationDate; as creationDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@@ -173,7 +173,7 @@
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'ORG.PAGES.DATECHANGED' | translate }}</p>
|
||||
@if (org?.details?.changeDate; as changeDate) {
|
||||
@if (org.details?.changeDate; as changeDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@@ -186,7 +186,7 @@
|
||||
<div class="info-row">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.STATE.TITLE' | translate }}</p>
|
||||
@if (project?.state) {
|
||||
@if (project.state) {
|
||||
<p
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
@@ -200,13 +200,13 @@
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.ID' | translate }}</p>
|
||||
@if (project?.id) {
|
||||
@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) {
|
||||
@if (project.details?.creationDate; as creationDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@@ -214,7 +214,7 @@
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.LASTMODIFIED' | translate }}</p>
|
||||
@if (project?.details?.changeDate; as changeDate) {
|
||||
@if (project.details?.changeDate; as changeDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@@ -227,7 +227,7 @@
|
||||
<div class="info-row">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.STATE.TITLE' | translate }}</p>
|
||||
@if (grantedProject?.state) {
|
||||
@if (grantedProject.state) {
|
||||
<p
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
@@ -241,19 +241,19 @@
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.ID' | translate }}</p>
|
||||
@if (grantedProject?.projectId) {
|
||||
@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) {
|
||||
@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) {
|
||||
@if (grantedProject.details?.creationDate; as creationDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@@ -261,7 +261,7 @@
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'PROJECT.PAGES.LASTMODIFIED' | translate }}</p>
|
||||
@if (grantedProject?.details?.changeDate; as changeDate) {
|
||||
@if (grantedProject.details?.changeDate; as changeDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@@ -274,7 +274,7 @@
|
||||
<div class="info-row">
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'APP.PAGES.STATE' | translate }}</p>
|
||||
@if (app?.state) {
|
||||
@if (app.state) {
|
||||
<p
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
@@ -286,7 +286,7 @@
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
@if (app?.apiConfig?.authMethodType; as authMethodType) {
|
||||
@if (app.apiConfig?.authMethodType; as authMethodType) {
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'APP.AUTHMETHOD' | translate }}</p>
|
||||
<p class="info-row-desc">
|
||||
@@ -294,7 +294,7 @@
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
@if (app?.oidcConfig?.authMethodType; as authMethodType) {
|
||||
@if (app.oidcConfig?.authMethodType; as authMethodType) {
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'APP.AUTHMETHOD' | translate }}</p>
|
||||
<p class="info-row-desc">
|
||||
@@ -304,13 +304,13 @@
|
||||
}
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'APP.PAGES.ID' | translate }}</p>
|
||||
@if (app?.id) {
|
||||
@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>
|
||||
@if (app?.details?.creationDate; as creationDate) {
|
||||
@if (app.details?.creationDate; as creationDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ creationDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
@@ -318,46 +318,44 @@
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<p class="info-row-title">{{ 'APP.PAGES.DATECHANGED' | translate }}</p>
|
||||
@if (app?.details?.changeDate; as changeDate) {
|
||||
@if (app.details?.changeDate; as changeDate) {
|
||||
<p class="info-row-desc">
|
||||
{{ changeDate | timestampToDate | localizedDate: 'dd. MMMM yyyy, HH:mm' }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
@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="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>
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
}
|
||||
|
||||
.keyboard-shortcuts-group {
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
border: 1px solid $border-color;
|
||||
background-color: $card-background-color;
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
|
||||
.keyboard-shortcuts-action-key {
|
||||
.keyboard-shortcuts-key-overlay {
|
||||
background: if($is-dark-theme, #fff, #000);
|
||||
background: if(sass($is-dark-theme): #fff; else: #000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
.cnsl-form-field-disabled {
|
||||
.cnsl-label-wrapper {
|
||||
color: if($is-dark-theme, #ffffff80, #00000061);
|
||||
color: if(sass($is-dark-theme): #ffffff80; else: #00000061);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
padding: 2px;
|
||||
margin: -2px -9px -2px 8px;
|
||||
margin-left: 6px;
|
||||
background-color: if($is-dark-theme, #ffffff20, #00000020);
|
||||
background-color: if(sass($is-dark-theme): #ffffff20; else: #00000020);
|
||||
line-height: 18px;
|
||||
font-size: 11px;
|
||||
transition: background 0.2s ease;
|
||||
@@ -69,7 +69,7 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: if($is-dark-theme, #ffffff40, #00000010);
|
||||
background: if(sass($is-dark-theme): #ffffff40; else: #00000010);
|
||||
}
|
||||
|
||||
&.active {
|
||||
@@ -78,7 +78,7 @@
|
||||
|
||||
.c_label {
|
||||
.count {
|
||||
background-color: if($is-dark-theme, #00000020, #ffffff20);
|
||||
background-color: if(sass($is-dark-theme): #00000020; else: #ffffff20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
padding: 2px;
|
||||
margin: -2px -9px -2px 8px;
|
||||
margin-left: 6px;
|
||||
background-color: if($is-dark-theme, #ffffff20, #00000020);
|
||||
background-color: if(sass($is-dark-theme): #ffffff20; else: #00000020);
|
||||
line-height: 18px;
|
||||
font-size: 11px;
|
||||
transition: background 0.2s ease;
|
||||
@@ -100,7 +100,7 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: if($is-dark-theme, #ffffff40, #00000010);
|
||||
background: if(sass($is-dark-theme): #ffffff40; else: #00000010);
|
||||
}
|
||||
|
||||
&.active {
|
||||
@@ -110,7 +110,7 @@
|
||||
.c_label {
|
||||
.count {
|
||||
display: inline-block;
|
||||
background-color: if($is-dark-theme, #00000020, #ffffff20);
|
||||
background-color: if(sass($is-dark-theme): #00000020; else: #ffffff20);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,7 +136,7 @@
|
||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
|
||||
.slash {
|
||||
color: if($is-dark-theme, #525454, #d1d5d9);
|
||||
color: if(sass($is-dark-theme): #525454; else: #d1d5d9);
|
||||
}
|
||||
|
||||
.org-button {
|
||||
@@ -185,7 +185,7 @@
|
||||
margin-right: 0.5rem;
|
||||
width: 100px;
|
||||
min-width: 50px;
|
||||
background: if($is-dark-theme, #ffffff20, #00000010);
|
||||
background: if(sass($is-dark-theme): #ffffff20; else: #00000010);
|
||||
border: none;
|
||||
padding: 2px;
|
||||
border-radius: 50vw;
|
||||
@@ -193,7 +193,7 @@
|
||||
display: flex;
|
||||
|
||||
&:hover {
|
||||
background: if($is-dark-theme, #ffffff, $primary-color);
|
||||
background: if(sass($is-dark-theme): #ffffff; else: $primary-color);
|
||||
transition: background ease 0.15s;
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: if($is-dark-theme, #fff, #000);
|
||||
background: if(sass($is-dark-theme): #fff; else: #000);
|
||||
opacity: 0.15;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
width: 1.5rem;
|
||||
border-radius: 50vw;
|
||||
margin-right: 1rem;
|
||||
background-color: if($is-dark-theme, map-get($background, state), #e4e7e4);
|
||||
background-color: if(sass($is-dark-theme): map-get($background, state) ; else: #e4e7e4);
|
||||
box-shadow: 0 0 3px #0000001a;
|
||||
border: 1px solid rgba(#8795a1, 0.2);
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
$list-background-color: map-get($background, 300);
|
||||
$card-background-color: map-get($background, cards);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if($is-dark-theme, #fff, #000);
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if(sass($is-dark-theme): #fff; else: #000);
|
||||
|
||||
.onboarding-header {
|
||||
display: flex;
|
||||
@@ -141,7 +141,7 @@
|
||||
width: 1.5rem;
|
||||
border-radius: 50vw;
|
||||
margin-right: 1rem;
|
||||
background-color: if($is-dark-theme, map-get($background, state), #e4e7e4);
|
||||
background-color: if(sass($is-dark-theme): map-get($background, state) ; else: #e4e7e4);
|
||||
box-shadow: 0 0 3px #0000001a;
|
||||
border: 1px solid rgba(#8795a1, 0.2);
|
||||
|
||||
|
||||
@@ -87,11 +87,11 @@
|
||||
}
|
||||
|
||||
&.dark {
|
||||
display: if($is-dark-theme, block, none);
|
||||
display: if(sass($is-dark-theme): block; else: none);
|
||||
}
|
||||
|
||||
&.light {
|
||||
display: if($is-dark-theme, none, block);
|
||||
display: if(sass($is-dark-theme): none; else: block);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -69,11 +69,11 @@
|
||||
}
|
||||
|
||||
&.dark {
|
||||
display: if($is-dark-theme, block, none);
|
||||
display: if(sass($is-dark-theme): block; else: none);
|
||||
}
|
||||
|
||||
&.light {
|
||||
display: if($is-dark-theme, none, block);
|
||||
display: if(sass($is-dark-theme): none; else: block);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
@use '../../../label/label.component.scss' as label;
|
||||
|
||||
@mixin preview-theme($show-dark) {
|
||||
$theme: if($show-dark, $caos-dark-app-theme, $caos-light-app-theme);
|
||||
$theme: if(sass($show-dark): $caos-dark-app-theme; else: $caos-light-app-theme);
|
||||
|
||||
@include input.input-theme($theme);
|
||||
@include label.cnsl-label-theme($theme);
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@
|
||||
$is-dark-theme: map.get($theme, is-dark);
|
||||
$background: map.get($theme, background);
|
||||
$foreground: map.get($theme, foreground);
|
||||
$p-border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$p-border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
|
||||
.privatelabeling-policy {
|
||||
.header {
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
$list-background-color: map-get($background, 300);
|
||||
$card-background-color: map-get($background, cards);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if($is-dark-theme, #fff, #000);
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if(sass($is-dark-theme): #fff; else: #000);
|
||||
|
||||
.project-role-chip {
|
||||
display: flex;
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
<tr class="highlight" mat-row *matRowDef="let role; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
@if ((dataSource.loading$ | async) === false && !dataSource?.totalResult) {
|
||||
@if ((dataSource.loading$ | async) === false && !dataSource.totalResult) {
|
||||
<div class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'PROJECT.ROLE.EMPTY' | translate }}</span>
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
}
|
||||
|
||||
&.dark {
|
||||
display: if($is-dark-theme, block, none);
|
||||
display: if(sass($is-dark-theme): block; else: none);
|
||||
}
|
||||
|
||||
&.light {
|
||||
display: if($is-dark-theme, none, block);
|
||||
display: if(sass($is-dark-theme): none; else: block);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+51
-30
@@ -1,36 +1,57 @@
|
||||
<form>
|
||||
<cnsl-form-field class="full-width">
|
||||
<cnsl-form-field>
|
||||
<cnsl-label>{{ 'PROJECT.GRANT.CREATE.SEL_ORG_FORMFIELD' | translate }}</cnsl-label>
|
||||
<input
|
||||
cnslInput
|
||||
type="text"
|
||||
placeholder="Organization XY"
|
||||
#nameInput
|
||||
[formControl]="myControl"
|
||||
[matAutocomplete]="auto"
|
||||
data-e2e="add-org-input"
|
||||
/>
|
||||
|
||||
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)" [displayWith]="displayFn">
|
||||
@if (isLoading) {
|
||||
<mat-option class="is-loading">
|
||||
<mat-spinner diameter="30"></mat-spinner>
|
||||
</mat-option>
|
||||
<span class="tw:relative">
|
||||
<input
|
||||
cnslInput
|
||||
type="text"
|
||||
class="tw:max-w-125"
|
||||
[class.tw:pr-9]="query.isFetching()"
|
||||
[matAutocomplete]="auto"
|
||||
[formControl]="searchControl"
|
||||
name="name"
|
||||
data-e2e="add-org-input"
|
||||
#input
|
||||
(keyup)="searchSignal.set(input.value)"
|
||||
/>
|
||||
@if (query.isFetching()) {
|
||||
<span class="tw:absolute tw:inset-2 tw:flex tw:items-center tw:justify-end">
|
||||
<mat-spinner diameter="25" color="primary"></mat-spinner>
|
||||
</span>
|
||||
}
|
||||
@for (org of filteredOrgs; track org) {
|
||||
<mat-option [value]="org">
|
||||
<div class="org-option" data-e2e="org-option">
|
||||
<div class="org-option-column">
|
||||
<span>{{ org.name }}</span>
|
||||
<span class="fill-space"></span>
|
||||
<span class="smaller cnsl-secondary-text">{{ org.primaryDomain }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</mat-option>
|
||||
}
|
||||
</mat-autocomplete>
|
||||
<span class="org-autocomplete-target-desc">
|
||||
{{ 'PROJECT.GRANT.CREATE.SEL_ORG_DESC' | translate }}
|
||||
</span>
|
||||
<mat-autocomplete
|
||||
#auto="matAutocomplete"
|
||||
[displayWith]="displayOrg"
|
||||
[requireSelection]="true"
|
||||
[autoActiveFirstOption]="true"
|
||||
(optionSelected)="searchControl.value && selectionChanged.emit(searchControl.value)"
|
||||
>
|
||||
<div cnslScrollable class="tw:overflow-y-scroll tw:max-h-full" (scrollPosition)="onScroll($event)">
|
||||
@for (page of query.data()?.pages; track $index) {
|
||||
@for (org of page.result; track org.id) {
|
||||
<mat-option
|
||||
class="tw:max-w-full tw:relative"
|
||||
[value]="org"
|
||||
data-e2e="org-option"
|
||||
[matTooltip]="org.name"
|
||||
(mouseenter)="showTooltip.set(name.scrollWidth > name.clientWidth)"
|
||||
(mouseleave)="showTooltip.set(false)"
|
||||
[matTooltipDisabled]="!showTooltip()"
|
||||
>
|
||||
<div
|
||||
class="tw:absolute tw:inset-0 tw:flex tw:h-full tw:w-full tw:min-w-0 tw:flex-col tw:justify-center"
|
||||
data-e2e="org-option"
|
||||
>
|
||||
<span #name class="tw:block tw:mr-4 tw:ml-4 tw:truncate">{{ org.name }}</span>
|
||||
<span class="tw:block tw:mr-4 tw:ml-4 tw:truncate tw:text-[13px] tw:text-gray-500">{{
|
||||
org.primaryDomain
|
||||
}}</span>
|
||||
</div>
|
||||
</mat-option>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</mat-autocomplete>
|
||||
</cnsl-form-field>
|
||||
</form>
|
||||
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.org-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.org-option-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
|
||||
span {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.fill-space {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.smaller {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.org-autocomplete-target-desc {
|
||||
font-size: 14px;
|
||||
display: block;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { SearchOrgAutocompleteComponent } from './search-org-autocomplete.component';
|
||||
|
||||
describe('SearchOrgComponent', () => {
|
||||
let component: SearchOrgAutocompleteComponent;
|
||||
let fixture: ComponentFixture<SearchOrgAutocompleteComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [SearchOrgAutocompleteComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SearchOrgAutocompleteComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
+117
-67
@@ -1,85 +1,135 @@
|
||||
import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';
|
||||
import { UntypedFormControl } from '@angular/forms';
|
||||
import { MatAutocomplete, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
|
||||
import { debounceTime, from, map, Subject, switchMap, takeUntil, tap } from 'rxjs';
|
||||
import { TextQueryMethod } from 'src/app/proto/generated/zitadel/object_pb';
|
||||
import { Org, OrgNameQuery, OrgQuery, OrgState, OrgStateQuery } from 'src/app/proto/generated/zitadel/org_pb';
|
||||
import { AuthenticationService } from 'src/app/services/authentication.service';
|
||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { ChangeDetectionStrategy, Component, effect, inject, output, signal } from '@angular/core';
|
||||
import { NewAuthService } from 'src/app/services/new-auth.service';
|
||||
import { injectInfiniteQuery, keepPreviousData } from '@tanstack/angular-query-experimental';
|
||||
import { UserService } from 'src/app/services/user.service';
|
||||
import { AuthService, ListMyProjectOrgsRequestSchema } from '@zitadel/proto/zitadel/auth_pb';
|
||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { InputModule } from '../input/input.module';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { TextQueryMethod } from '@zitadel/proto/zitadel/object_pb';
|
||||
import { ScrollingModule } from '@angular/cdk/scrolling';
|
||||
import { Org, OrgFieldName, OrgState } from '@zitadel/proto/zitadel/org_pb';
|
||||
import { MessageInitShape } from '@bufbuild/protobuf';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { requiredValidator } from '../form-field/validators/validators';
|
||||
import { ScrollableDirective } from 'src/app/directives/scrollable/scrollable.directive';
|
||||
import { toObservable, toSignal } from '@angular/core/rxjs-interop';
|
||||
import { debounceTime } from 'rxjs';
|
||||
import { MatProgressSpinner } from '@angular/material/progress-spinner';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-search-org-autocomplete',
|
||||
templateUrl: './search-org-autocomplete.component.html',
|
||||
styleUrls: ['./search-org-autocomplete.component.scss'],
|
||||
standalone: false,
|
||||
standalone: true,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
ScrollingModule,
|
||||
MatInputModule,
|
||||
MatAutocompleteModule,
|
||||
ReactiveFormsModule,
|
||||
InputModule,
|
||||
TranslatePipe,
|
||||
FormsModule,
|
||||
MatTooltip,
|
||||
ScrollableDirective,
|
||||
MatProgressSpinner,
|
||||
],
|
||||
})
|
||||
export class SearchOrgAutocompleteComponent implements OnInit, OnDestroy {
|
||||
public myControl: UntypedFormControl = new UntypedFormControl();
|
||||
public filteredOrgs: Array<Org.AsObject> = [];
|
||||
public isLoading: boolean = false;
|
||||
@ViewChild('auto') public matAutocomplete!: MatAutocomplete;
|
||||
@Output() public selectionChanged: EventEmitter<Org.AsObject> = new EventEmitter();
|
||||
export class SearchOrgAutocompleteComponent {
|
||||
public readonly selectionChanged = output<Org>();
|
||||
|
||||
private unsubscribed$: Subject<void> = new Subject();
|
||||
constructor(
|
||||
public authService: AuthenticationService,
|
||||
private auth: GrpcAuthService,
|
||||
) {
|
||||
this.myControl.valueChanges
|
||||
.pipe(
|
||||
takeUntil(this.unsubscribed$),
|
||||
debounceTime(200),
|
||||
tap(() => (this.isLoading = true)),
|
||||
switchMap((value) => {
|
||||
const stateQuery = new OrgQuery();
|
||||
const orgStateQuery = new OrgStateQuery();
|
||||
orgStateQuery.setState(OrgState.ORG_STATE_ACTIVE);
|
||||
stateQuery.setStateQuery(orgStateQuery);
|
||||
protected readonly searchControl = new FormControl<Org | null>(null, { validators: [requiredValidator] });
|
||||
protected readonly searchSignal = signal('');
|
||||
protected readonly debouncedSearchSignal = toSignal(toObservable(this.searchSignal).pipe(debounceTime(250)), {
|
||||
initialValue: this.searchSignal(),
|
||||
});
|
||||
|
||||
let queries: OrgQuery[] = [stateQuery];
|
||||
private readonly authService = inject(NewAuthService);
|
||||
private readonly userService = inject(UserService);
|
||||
|
||||
if (value) {
|
||||
const nameQuery = new OrgQuery();
|
||||
const orgNameQuery = new OrgNameQuery();
|
||||
orgNameQuery.setName(value);
|
||||
orgNameQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE);
|
||||
nameQuery.setNameQuery(orgNameQuery);
|
||||
queries = [stateQuery, nameQuery];
|
||||
}
|
||||
protected readonly query = injectInfiniteQuery(() => {
|
||||
const search = this.debouncedSearchSignal();
|
||||
|
||||
return from(this.auth.listMyProjectOrgs(undefined, 0, queries)).pipe(
|
||||
map((resp) => {
|
||||
return resp.resultList.sort((left, right) => left.name.localeCompare(right.name));
|
||||
}),
|
||||
);
|
||||
}),
|
||||
)
|
||||
.subscribe((returnValue) => {
|
||||
this.isLoading = false;
|
||||
this.filteredOrgs = returnValue;
|
||||
});
|
||||
}
|
||||
const stateQuery = [
|
||||
{
|
||||
query: {
|
||||
case: 'stateQuery',
|
||||
value: {
|
||||
state: OrgState.ACTIVE,
|
||||
},
|
||||
},
|
||||
},
|
||||
] satisfies MessageInitShape<typeof ListMyProjectOrgsRequestSchema>['queries'];
|
||||
|
||||
public ngOnInit(): void {
|
||||
const query = new OrgQuery();
|
||||
const orgStateQuery = new OrgStateQuery();
|
||||
orgStateQuery.setState(OrgState.ORG_STATE_ACTIVE);
|
||||
query.setStateQuery(orgStateQuery);
|
||||
return {
|
||||
queryKey: [this.userService.userId(), AuthService.name, AuthService.method.listMyProjectOrgs.name, 'infinite', search],
|
||||
placeholderData: keepPreviousData,
|
||||
queryFn: async ({ pageParam, signal }) =>
|
||||
this.authService.listMyProjectOrgs(
|
||||
{
|
||||
query: {
|
||||
limit: 20,
|
||||
offset: BigInt(pageParam.offset),
|
||||
},
|
||||
sortingColumn: OrgFieldName.NAME,
|
||||
queries: search
|
||||
? [
|
||||
...stateQuery,
|
||||
{
|
||||
query: {
|
||||
case: 'nameQuery',
|
||||
value: {
|
||||
name: search,
|
||||
method: TextQueryMethod.CONTAINS_IGNORE_CASE,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
: stateQuery,
|
||||
},
|
||||
signal,
|
||||
),
|
||||
initialPageParam: {
|
||||
offset: 0,
|
||||
},
|
||||
getNextPageParam: (lastPage, allPages, { offset }) => {
|
||||
const nextPageParam = { offset: offset + lastPage.result.length };
|
||||
const loadedCount = allPages.reduce((count, page) => count + page.result.length, 0);
|
||||
|
||||
this.auth.listMyProjectOrgs(undefined, 0, [query]).then((orgs) => {
|
||||
this.filteredOrgs = orgs.resultList;
|
||||
if (loadedCount < lastPage.details!.totalResult) {
|
||||
return nextPageParam;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// used to only open matTooltip if the text gets truncated
|
||||
protected readonly showTooltip = signal(false);
|
||||
|
||||
constructor() {
|
||||
const toastService = inject(ToastService);
|
||||
effect(() => {
|
||||
const error = this.query.error();
|
||||
if (error) {
|
||||
toastService.showError(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnDestroy(): void {
|
||||
this.unsubscribed$.next();
|
||||
protected async onScroll(position: 'bottom' | 'top') {
|
||||
if (this.query.isFetchingNextPage() || !this.query.hasNextPage() || position === 'top') {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.query.fetchNextPage();
|
||||
}
|
||||
|
||||
public displayFn(org?: Org.AsObject): string {
|
||||
return org ? `${org.name}` : '';
|
||||
}
|
||||
|
||||
public selected(event: MatAutocompleteSelectedEvent): void {
|
||||
this.selectionChanged.emit(event.option.value);
|
||||
protected displayOrg(org: Org | null) {
|
||||
return org?.name ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatChipsModule } from '@angular/material/chips';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
|
||||
import { SearchOrgAutocompleteComponent } from './search-org-autocomplete.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [SearchOrgAutocompleteComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatAutocompleteModule,
|
||||
MatChipsModule,
|
||||
MatButtonModule,
|
||||
InputModule,
|
||||
MatIconModule,
|
||||
ReactiveFormsModule,
|
||||
MatProgressSpinnerModule,
|
||||
FormsModule,
|
||||
TranslateModule,
|
||||
MatSelectModule,
|
||||
],
|
||||
exports: [SearchOrgAutocompleteComponent],
|
||||
})
|
||||
export class SearchOrgAutocompleteModule {}
|
||||
+2
-2
@@ -9,8 +9,8 @@
|
||||
$secondary-text: map-get($foreground, secondary-text);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
|
||||
$link-hover-color: if($is-dark-theme, map-get($primary, 200), $primary-color);
|
||||
$link-color: if($is-dark-theme, $lighter-primary-color, $primary-color);
|
||||
$link-hover-color: if(sass($is-dark-theme): map-get($primary, 200) ; else: $primary-color);
|
||||
$link-color: if(sass($is-dark-theme): $lighter-primary-color; else: $primary-color);
|
||||
|
||||
.user-autocomplete-found {
|
||||
margin: 0.5rem 0;
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
$list-background-color: map-get($background, 300);
|
||||
$card-background-color: map-get($background, cards);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if($is-dark-theme, #fff, #000);
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if(sass($is-dark-theme): #fff; else: #000);
|
||||
|
||||
.shortcut-container {
|
||||
width: 100%;
|
||||
|
||||
@@ -32,12 +32,12 @@
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
color: if($is-dark-theme, #ffffff60, #00000060);
|
||||
color: if(sass($is-dark-theme): #ffffff60; else: #00000060);
|
||||
margin-top: 1rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
border-top: 1px solid if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
|
||||
&:nth-child(2) {
|
||||
border-top: none;
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@if ((loading$ | async) === false && !dataSource?.data?.length) {
|
||||
@if ((loading$ | async) === false && !dataSource.data.length) {
|
||||
<div class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'SMTP.LIST.EMPTY' | translate }}</span>
|
||||
@@ -139,7 +139,6 @@
|
||||
}
|
||||
|
||||
<cnsl-paginator
|
||||
#paginator
|
||||
class="paginator"
|
||||
[timestamp]="configsResult?.details?.viewTimestamp"
|
||||
[length]="configsResult?.details?.totalResult || 0"
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
flex-shrink: 0;
|
||||
|
||||
&.dark {
|
||||
display: if($is-dark-theme, block, none);
|
||||
display: if(sass($is-dark-theme): block; else: none);
|
||||
}
|
||||
|
||||
&.light {
|
||||
display: if($is-dark-theme, none, block);
|
||||
display: if(sass($is-dark-theme): none; else: block);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
max-width: 400px;
|
||||
background: if($is-dark-theme, #00000020, map-get($background, cards));
|
||||
background: if(sass($is-dark-theme): #00000020; else: map-get($background, cards));
|
||||
margin-left: -1rem;
|
||||
margin-right: -1rem;
|
||||
padding: 0 1rem 0.5rem 1rem;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
$foreground: map-get($theme, foreground);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$card-background-color: map-get($background, cards);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
|
||||
.cnsl-table-action-wrapper {
|
||||
height: 36px;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
.theme-flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid if($is-dark-theme, #ffffff20, #00000020);
|
||||
border: 1px solid if(sass($is-dark-theme): #ffffff20; else: #00000020);
|
||||
border-radius: 50vw;
|
||||
padding: 0.25rem;
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: if($is-dark-theme, #ffffff10, #00000010) !important;
|
||||
background-color: if(sass($is-dark-theme): #ffffff10; else: #00000010) !important;
|
||||
.moon,
|
||||
.sun {
|
||||
opacity: 1;
|
||||
|
||||
@@ -196,7 +196,7 @@
|
||||
></tr>
|
||||
</table>
|
||||
</div>
|
||||
@if ((dataSource.loading$ | async) === false && !dataSource?.totalResult) {
|
||||
@if ((dataSource.loading$ | async) === false && !dataSource.totalResult) {
|
||||
<div class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'GRANTS.EMPTY' | translate }}</span>
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
$list-background-color: map-get($background, 300);
|
||||
$card-background-color: map-get($background, cards);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if($is-dark-theme, #fff, #000);
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if(sass($is-dark-theme): #fff; else: #000);
|
||||
|
||||
.home-title {
|
||||
font-size: 2rem;
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
<div class="flow-type">
|
||||
<i class="type-icon las la-dot-circle"></i>
|
||||
<span>{{ flow.type?.name?.localizedMessage }}</span>
|
||||
@if (flow.type && (flow.triggerActionsList?.length ?? 0) > 0) {
|
||||
@if (flow.type && flow.triggerActionsList.length > 0) {
|
||||
<button
|
||||
matTooltip="{{ 'ACTIONS.CLEAR' | translate }}"
|
||||
mat-icon-button
|
||||
@@ -67,12 +67,16 @@
|
||||
<mat-icon svgIcon="mdi_arrow_right_bottom" class="icon"></mat-icon>
|
||||
<span>{{ trigger.triggerType?.name?.localizedMessage }}</span>
|
||||
<span class="fill-space"></span>
|
||||
<button color="warn" mat-icon-button (click)="removeTriggerActionsList(i)">
|
||||
<button color="warn" mat-icon-button (click)="removeTriggerActionsList(flow, i)">
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<span class="fill-space"></span>
|
||||
<div class="flow-action-wrapper" cdkDropList (cdkDropListDropped)="drop(i, trigger.actionsList, $event)">
|
||||
<div
|
||||
class="flow-action-wrapper"
|
||||
cdkDropList
|
||||
(cdkDropListDropped)="drop(flow, i, trigger.actionsList, $event)"
|
||||
>
|
||||
@for (action of trigger.actionsList; track action) {
|
||||
<div cdkDrag cdkDragLockAxis="y" cdkDragBoundary=".action-wrapper" class="flow-action">
|
||||
<i class="las la-code"></i>
|
||||
|
||||
@@ -21,7 +21,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
standalone: false,
|
||||
})
|
||||
export class ActionsComponent {
|
||||
protected flow!: Flow.AsObject;
|
||||
protected flow?: Flow.AsObject;
|
||||
|
||||
protected typeControl: UntypedFormControl = new UntypedFormControl();
|
||||
|
||||
@@ -124,23 +124,23 @@ export class ActionsComponent {
|
||||
});
|
||||
}
|
||||
|
||||
drop(triggerActionsListIndex: number, array: any[], event: CdkDragDrop<Action.AsObject[]>) {
|
||||
drop(flow: Flow.AsObject, triggerActionsListIndex: number, array: any[], event: CdkDragDrop<Action.AsObject[]>) {
|
||||
moveItemInArray(array, event.previousIndex, event.currentIndex);
|
||||
this.saveFlow(triggerActionsListIndex);
|
||||
this.saveFlow(flow, triggerActionsListIndex);
|
||||
}
|
||||
|
||||
saveFlow(index: number) {
|
||||
saveFlow(flow: Flow.AsObject, index: number) {
|
||||
if (
|
||||
this.flow.type &&
|
||||
this.flow.triggerActionsList &&
|
||||
this.flow.triggerActionsList[index] &&
|
||||
this.flow.triggerActionsList[index]?.triggerType
|
||||
flow.type &&
|
||||
flow.triggerActionsList &&
|
||||
flow.triggerActionsList[index] &&
|
||||
flow.triggerActionsList[index]?.triggerType
|
||||
) {
|
||||
this.mgmtService
|
||||
.setTriggerActions(
|
||||
this.flow.triggerActionsList[index].actionsList.map((action) => action.id),
|
||||
this.flow.type.id,
|
||||
this.flow.triggerActionsList[index].triggerType?.id ?? '',
|
||||
flow.triggerActionsList[index].actionsList.map((action) => action.id),
|
||||
flow.type.id,
|
||||
flow.triggerActionsList[index].triggerType?.id ?? '',
|
||||
)
|
||||
.then(() => {
|
||||
this.toast.showInfo('FLOWS.TOAST.ACTIONSSET', true);
|
||||
@@ -151,8 +151,8 @@ export class ActionsComponent {
|
||||
}
|
||||
}
|
||||
|
||||
protected removeTriggerActionsList(index: number) {
|
||||
if (this.flow.type && this.flow.triggerActionsList && this.flow.triggerActionsList[index]) {
|
||||
protected removeTriggerActionsList(flow: Flow.AsObject, index: number) {
|
||||
if (flow.type && flow.triggerActionsList && flow.triggerActionsList[index]) {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.CLEAR',
|
||||
@@ -166,10 +166,10 @@ export class ActionsComponent {
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp) {
|
||||
this.mgmtService
|
||||
.setTriggerActions([], this.flow?.type?.id ?? '', this.flow.triggerActionsList[index].triggerType?.id ?? '')
|
||||
.setTriggerActions([], flow?.type?.id ?? '', flow.triggerActionsList[index].triggerType?.id ?? '')
|
||||
.then(() => {
|
||||
this.toast.showInfo('FLOWS.TOAST.ACTIONSSET', true);
|
||||
this.loadFlow(this.flow?.type?.id ?? '');
|
||||
this.loadFlow(flow?.type?.id ?? '');
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
|
||||
@@ -68,12 +68,12 @@
|
||||
</cnsl-info-section>
|
||||
}
|
||||
|
||||
@if (app && app.oidcConfig && app.oidcConfig.complianceProblemsList && app.oidcConfig.complianceProblemsList?.length) {
|
||||
@if (app && app.oidcConfig && app.oidcConfig.complianceProblemsList && app.oidcConfig.complianceProblemsList.length) {
|
||||
<div class="compliance">
|
||||
<h2 class="compliance-title">{{ 'APP.COMPLIANCE' | translate }}</h2>
|
||||
<cnsl-info-section class="problem" [type]="InfoSectionType.ALERT">
|
||||
<ul style="margin: 0">
|
||||
@for (problem of app.oidcConfig?.complianceProblemsList || []; track problem) {
|
||||
@for (problem of app.oidcConfig.complianceProblemsList; track problem) {
|
||||
<li style="margin: 0 0 0.5rem 0">
|
||||
{{ problem.localizedMessage }}
|
||||
</li>
|
||||
@@ -444,7 +444,7 @@
|
||||
@if (currentSetting.id === 'additional-origins') {
|
||||
<cnsl-card title=" {{ 'APP.ADDITIONALORIGINS' | translate }}">
|
||||
<p class="app-desc cnsl-secondary-text">{{ 'APP.ADDITIONALORIGINSDESC' | translate }}</p>
|
||||
@if (additionalOriginsList && appType && appType?.value !== undefined) {
|
||||
@if (additionalOriginsList && appType?.value !== undefined) {
|
||||
<cnsl-additional-origins
|
||||
class="app-input"
|
||||
[canWrite]="canWrite"
|
||||
@@ -507,7 +507,7 @@
|
||||
description="{{ 'USER.MACHINE.KEYSDESC' | translate }}"
|
||||
>
|
||||
<cnsl-client-keys [projectId]="projectId" [appId]="app.id"></cnsl-client-keys>
|
||||
@if (apiForm && app?.apiConfig) {
|
||||
@if (apiForm && app.apiConfig) {
|
||||
<div class="btn-container">
|
||||
<button
|
||||
class="submit-button"
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
.current-auth-method {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
border: 1px solid if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
color: white;
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.5rem 1rem;
|
||||
|
||||
@@ -115,8 +115,8 @@ h1 {
|
||||
|
||||
$list-background-color: map-get($background, 300);
|
||||
$card-background-color: map-get($background, cards);
|
||||
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if($is-dark-theme, #fff, #000);
|
||||
$border-color: if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
$border-selected-color: if(sass($is-dark-theme): #fff; else: #000);
|
||||
|
||||
.integrate-layout-container {
|
||||
background: map-get($background, metadata-section);
|
||||
@@ -172,11 +172,11 @@ h1 {
|
||||
}
|
||||
|
||||
.dark-only {
|
||||
display: if($is-dark-theme, block, none);
|
||||
display: if(sass($is-dark-theme): block; else: none);
|
||||
}
|
||||
|
||||
.light-only {
|
||||
display: if($is-dark-theme, none, block);
|
||||
display: if(sass($is-dark-theme): none; else: block);
|
||||
}
|
||||
|
||||
span {
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
>
|
||||
@if (currentCreateStep === 1) {
|
||||
<h1>{{ 'PROJECT.GRANT.CREATE.SEL_ORG' | translate }}</h1>
|
||||
<cnsl-search-org-autocomplete class="block" (selectionChanged)="selectOrg($event)"> </cnsl-search-org-autocomplete>
|
||||
<cnsl-search-org-autocomplete (selectionChanged)="selectOrg($event)" class="block"> </cnsl-search-org-autocomplete>
|
||||
@if (org) {
|
||||
<span> {{ 'PROJECT.GRANT.CREATE.FOR_ORG' | translate }} {{ org.name }} - {{ org.primaryDomain }} </span>
|
||||
}
|
||||
|
||||
+15
-34
@@ -1,11 +1,11 @@
|
||||
import { Location } from '@angular/common';
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Component, DestroyRef, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { Org } from 'src/app/proto/generated/zitadel/org_pb';
|
||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { Org } from '@zitadel/proto/zitadel/org_pb';
|
||||
import { NewMgmtService } from 'src/app/services/new-mgmt.service';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
|
||||
const ROUTEPARAM = 'projectid';
|
||||
|
||||
@@ -15,8 +15,8 @@ const ROUTEPARAM = 'projectid';
|
||||
styleUrls: ['./project-grant-create.component.scss'],
|
||||
standalone: false,
|
||||
})
|
||||
export class ProjectGrantCreateComponent implements OnInit, OnDestroy {
|
||||
public org?: Org.AsObject;
|
||||
export class ProjectGrantCreateComponent implements OnInit {
|
||||
public org?: Org;
|
||||
public projectId: string = '';
|
||||
public grantId: string = '';
|
||||
public rolesKeyList: string[] = [];
|
||||
@@ -24,17 +24,17 @@ export class ProjectGrantCreateComponent implements OnInit, OnDestroy {
|
||||
public createSteps: number = 2;
|
||||
public currentCreateStep: number = 1;
|
||||
|
||||
private destroy$: Subject<void> = new Subject();
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private toast: ToastService,
|
||||
private mgmtService: ManagementService,
|
||||
private _location: Location,
|
||||
private breadcrumbService: BreadcrumbService,
|
||||
private readonly route: ActivatedRoute,
|
||||
private readonly toast: ToastService,
|
||||
private readonly mgmtService: NewMgmtService,
|
||||
private readonly _location: Location,
|
||||
private readonly breadcrumbService: BreadcrumbService,
|
||||
private readonly destroyRef: DestroyRef,
|
||||
) {}
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.route.params.pipe(takeUntil(this.destroy$)).subscribe((params) => {
|
||||
this.route.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => {
|
||||
this.projectId = params['projectid'];
|
||||
|
||||
const breadcrumbs = [
|
||||
@@ -53,25 +53,6 @@ export class ProjectGrantCreateComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
public searchOrg(domain: string): void {
|
||||
this.mgmtService
|
||||
.getOrgByDomainGlobal(domain)
|
||||
.then((ret) => {
|
||||
if (ret.org) {
|
||||
const tmp = ret.org;
|
||||
this.org = tmp;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
this._location.back();
|
||||
}
|
||||
@@ -79,7 +60,7 @@ export class ProjectGrantCreateComponent implements OnInit, OnDestroy {
|
||||
public addGrant(): void {
|
||||
if (this.org) {
|
||||
this.mgmtService
|
||||
.addProjectGrant(this.org.id, this.projectId, this.rolesKeyList)
|
||||
.addProjectGrant({ grantedOrgId: this.org.id, projectId: this.projectId, roleKeys: this.rolesKeyList })
|
||||
.then(() => {
|
||||
this.close();
|
||||
})
|
||||
@@ -89,7 +70,7 @@ export class ProjectGrantCreateComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
public selectOrg(org: Org.AsObject): void {
|
||||
public selectOrg(org: Org): void {
|
||||
this.org = org;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@ import { CreateLayoutModule } from 'src/app/modules/create-layout/create-layout.
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
import { ProjectRolesTableModule } from 'src/app/modules/project-roles-table/project-roles-table.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { SearchOrgAutocompleteComponent } from 'src/app/modules/search-org-autocomplete/search-org-autocomplete.component';
|
||||
|
||||
import { SearchOrgAutocompleteModule } from 'src/app/modules/search-org-autocomplete/search-org-autocomplete.module';
|
||||
import { ProjectGrantCreateRoutingModule } from './project-grant-create-routing.module';
|
||||
import { ProjectGrantCreateComponent } from './project-grant-create.component';
|
||||
|
||||
@@ -39,7 +39,7 @@ import { ProjectGrantCreateComponent } from './project-grant-create.component';
|
||||
MatProgressSpinnerModule,
|
||||
FormsModule,
|
||||
TranslateModule,
|
||||
SearchOrgAutocompleteModule,
|
||||
SearchOrgAutocompleteComponent,
|
||||
],
|
||||
})
|
||||
export default class ProjectGrantCreateModule {}
|
||||
|
||||
+12
-12
@@ -28,13 +28,13 @@
|
||||
</div>
|
||||
|
||||
<mat-menu #actions="matMenu" xPosition="before">
|
||||
@if (grant?.state === ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE) {
|
||||
<button mat-menu-item (click)="changeState(ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE)">
|
||||
@if (grant && grant.state === ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE) {
|
||||
<button mat-menu-item (click)="changeState(grant, ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE)">
|
||||
{{ 'USER.PAGES.DEACTIVATE' | translate }}
|
||||
</button>
|
||||
}
|
||||
@if (grant?.state === ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE) {
|
||||
<button mat-menu-item (click)="changeState(ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE)">
|
||||
@if (grant && grant.state === ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE) {
|
||||
<button mat-menu-item (click)="changeState(grant, ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE)">
|
||||
{{ 'USER.PAGES.REACTIVATE' | translate }}
|
||||
</button>
|
||||
}
|
||||
@@ -48,8 +48,8 @@
|
||||
<cnsl-project-grant-illustration
|
||||
[grantedProject]="grant"
|
||||
[projectRoleOptions]="projectRoleOptions"
|
||||
(roleRemoved)="removeRole($event)"
|
||||
(editRoleClicked)="editRoles()"
|
||||
(roleRemoved)="removeRole(grant, $event)"
|
||||
(editRoleClicked)="editRoles(grant)"
|
||||
>
|
||||
</cnsl-project-grant-illustration>
|
||||
}
|
||||
@@ -63,15 +63,15 @@
|
||||
[canWrite]="['project.grant.member.write', 'project.grant.member.write:' + grant.grantId] | hasRole | async"
|
||||
[canDelete]="['project.grant.member.delete', 'project.grant.member.delete:' + grant.grantId] | hasRole | async"
|
||||
[memberRoleOptions]="memberRoleOptions"
|
||||
(updateRoles)="updateMemberRoles($event.member, $event.change)"
|
||||
(deleteMember)="removeProjectMember($event)"
|
||||
(updateRoles)="updateMemberRoles(grant, $event.member, $event.change)"
|
||||
(deleteMember)="removeProjectMember(grant, $event)"
|
||||
[factoryLoadFunc]="changePageFactory"
|
||||
(changedSelection)="selection = $event"
|
||||
[refreshTrigger]="changePage"
|
||||
>
|
||||
<button
|
||||
selectactions
|
||||
(click)="removeProjectMemberSelection()"
|
||||
(click)="removeProjectMemberSelection(grant)"
|
||||
[disabled]="
|
||||
(['project.grant.member.delete', 'project.grant.member.delete:' + grant.grantId] | hasRole | async) === false
|
||||
"
|
||||
@@ -82,7 +82,7 @@
|
||||
<div class="cnsl-action-button">
|
||||
<i class="las la-trash"></i>
|
||||
<span>{{ 'ACTIONS.SELECTIONDELETE' | translate }}</span>
|
||||
<cnsl-action-keys [type]="ActionKeysType.DELETE" (actionTriggered)="removeProjectMemberSelection()">
|
||||
<cnsl-action-keys [type]="ActionKeysType.DELETE" (actionTriggered)="removeProjectMemberSelection(grant)">
|
||||
</cnsl-action-keys>
|
||||
</div>
|
||||
</button>
|
||||
@@ -92,13 +92,13 @@
|
||||
[disabled]="
|
||||
(['project.grant.member.write', 'project.grant.member.write:' + grant.grantId] | hasRole | async) === false
|
||||
"
|
||||
(click)="openAddMember()"
|
||||
(click)="openAddMember(grant)"
|
||||
color="primary"
|
||||
mat-raised-button
|
||||
>
|
||||
<div class="cnsl-action-button">
|
||||
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
|
||||
<cnsl-action-keys (actionTriggered)="openAddMember()"> </cnsl-action-keys>
|
||||
<cnsl-action-keys (actionTriggered)="openAddMember(grant)"> </cnsl-action-keys>
|
||||
</div>
|
||||
</button>
|
||||
</cnsl-members-table>
|
||||
|
||||
+31
-62
@@ -27,7 +27,7 @@ import { ProjectGrantMembersDataSource } from './project-grant-members-datasourc
|
||||
export class ProjectGrantDetailComponent {
|
||||
public INITIALPAGESIZE: number = 25;
|
||||
|
||||
public grant!: GrantedProject.AsObject;
|
||||
public grant: GrantedProject.AsObject | undefined;
|
||||
public projectid: string = '';
|
||||
public grantid: string = '';
|
||||
|
||||
@@ -99,13 +99,13 @@ export class ProjectGrantDetailComponent {
|
||||
});
|
||||
}
|
||||
|
||||
public changeState(newState: ProjectGrantState): void {
|
||||
public changeState(grant: GrantedProject.AsObject, newState: ProjectGrantState): void {
|
||||
if (newState === ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE) {
|
||||
this.mgmtService
|
||||
.reactivateProjectGrant(this.grantid, this.projectid)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.REACTIVATED', true);
|
||||
this.grant.state = newState;
|
||||
grant.state = newState;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
@@ -115,7 +115,7 @@ export class ProjectGrantDetailComponent {
|
||||
.deactivateProjectGrant(this.grantid, this.projectid)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.DEACTIVATED', true);
|
||||
this.grant.state = newState;
|
||||
grant.state = newState;
|
||||
setTimeout(() => {
|
||||
this.changePage.emit();
|
||||
}, 1000);
|
||||
@@ -144,56 +144,25 @@ export class ProjectGrantDetailComponent {
|
||||
});
|
||||
}
|
||||
|
||||
updateRoles(selectionChange: string[]): void {
|
||||
this.mgmtService
|
||||
.updateProjectGrant(this.grant.grantId, this.grant.projectId, selectionChange)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.GRANT.TOAST.PROJECTGRANTUPDATED', true);
|
||||
setTimeout(() => {
|
||||
this.changePage.emit();
|
||||
}, 1000);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
this.changePage.emit();
|
||||
});
|
||||
public async removeProjectMemberSelection(grant: GrantedProject.AsObject) {
|
||||
await Promise.all(this.selection.map((member) => this.removeProjectMember(grant, member)));
|
||||
}
|
||||
|
||||
public removeProjectMemberSelection(): void {
|
||||
Promise.all(
|
||||
this.selection.map((member) => {
|
||||
return this.mgmtService
|
||||
.removeProjectGrantMember(this.grant.projectId, this.grant.grantId, member.userId)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.GRANT.TOAST.PROJECTGRANTMEMBERREMOVED', true);
|
||||
setTimeout(() => {
|
||||
this.changePage.emit();
|
||||
}, 1000);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.changePage.emit();
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}),
|
||||
);
|
||||
public async removeProjectMember(grant: GrantedProject.AsObject, member: Member.AsObject) {
|
||||
try {
|
||||
await this.mgmtService.removeProjectGrantMember(grant.projectId, grant.grantId, member.userId);
|
||||
|
||||
this.toast.showInfo('PROJECT.GRANT.TOAST.PROJECTGRANTMEMBERREMOVED', true);
|
||||
|
||||
await new Promise<void>((res) => setTimeout(res, 1000));
|
||||
} catch (error) {
|
||||
this.toast.showError(error);
|
||||
} finally {
|
||||
this.changePage.emit();
|
||||
}
|
||||
}
|
||||
|
||||
public removeProjectMember(member: Member.AsObject): void {
|
||||
this.mgmtService
|
||||
.removeProjectGrantMember(this.grant.projectId, this.grant.grantId, member.userId)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.GRANT.TOAST.PROJECTGRANTMEMBERREMOVED', true);
|
||||
setTimeout(() => {
|
||||
this.changePage.emit();
|
||||
}, 1000);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.changePage.emit();
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
|
||||
public async openAddMember(): Promise<any> {
|
||||
public async openAddMember(grant: GrantedProject.AsObject): Promise<any> {
|
||||
const dialogRef = this.dialog.open(MemberCreateDialogComponent, {
|
||||
data: {
|
||||
creationType: CreationType.PROJECT_GRANTED,
|
||||
@@ -210,7 +179,7 @@ export class ProjectGrantDetailComponent {
|
||||
const userIds = users.map((user) => user.id);
|
||||
Promise.all(
|
||||
userIds.map((userid: string) => {
|
||||
return this.mgmtService.addProjectGrantMember(this.grant.projectId, this.grant.grantId, userid, resp.roles);
|
||||
return this.mgmtService.addProjectGrantMember(grant.projectId, grant.grantId, userid, resp.roles);
|
||||
}),
|
||||
)
|
||||
.then(() => {
|
||||
@@ -228,9 +197,9 @@ export class ProjectGrantDetailComponent {
|
||||
});
|
||||
}
|
||||
|
||||
updateMemberRoles(member: Member.AsObject, selectionChange: string[]): void {
|
||||
updateMemberRoles(grant: GrantedProject.AsObject, member: Member.AsObject, selectionChange: string[]): void {
|
||||
this.mgmtService
|
||||
.updateProjectGrantMember(this.grant.projectId, this.grant.grantId, member.userId, selectionChange)
|
||||
.updateProjectGrantMember(grant.projectId, grant.grantId, member.userId, selectionChange)
|
||||
.then(() => {
|
||||
setTimeout(() => {
|
||||
this.changePage.emit();
|
||||
@@ -243,13 +212,13 @@ export class ProjectGrantDetailComponent {
|
||||
});
|
||||
}
|
||||
|
||||
removeRole(role: string): void {
|
||||
const index = this.grant.grantedRoleKeysList.findIndex((r) => r === role);
|
||||
removeRole(grant: GrantedProject.AsObject, role: string): void {
|
||||
const index = grant.grantedRoleKeysList.findIndex((r) => r === role);
|
||||
if (index > -1) {
|
||||
this.grant.grantedRoleKeysList.splice(index, 1);
|
||||
grant.grantedRoleKeysList.splice(index, 1);
|
||||
|
||||
this.mgmtService
|
||||
.updateProjectGrant(this.grant.grantId, this.grant.projectId, this.grant.grantedRoleKeysList)
|
||||
.updateProjectGrant(grant.grantId, grant.projectId, grant.grantedRoleKeysList)
|
||||
.then(() => {
|
||||
setTimeout(() => {
|
||||
this.changePage.emit();
|
||||
@@ -263,13 +232,13 @@ export class ProjectGrantDetailComponent {
|
||||
}
|
||||
}
|
||||
|
||||
public editRoles(): void {
|
||||
public editRoles(grant: GrantedProject.AsObject): void {
|
||||
const dialogRef = this.dialog.open<UserGrantRoleDialogComponent, UserGrantRoleDialogData, UserGrantRoleDialogResult>(
|
||||
UserGrantRoleDialogComponent,
|
||||
{
|
||||
data: {
|
||||
projectId: this.grant.projectId,
|
||||
selectedRoleKeysList: this.grant.grantedRoleKeysList,
|
||||
projectId: grant.projectId,
|
||||
selectedRoleKeysList: grant.grantedRoleKeysList,
|
||||
i18nTitle: 'PROJECT.GRANT.EDITTITLE',
|
||||
},
|
||||
width: '600px',
|
||||
@@ -281,10 +250,10 @@ export class ProjectGrantDetailComponent {
|
||||
return;
|
||||
}
|
||||
this.mgmtService
|
||||
.updateProjectGrant(this.grant.grantId, this.grant.projectId, resp.roles)
|
||||
.updateProjectGrant(grant.grantId, grant.projectId, resp.roles)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.GRANT.TOAST.PROJECTGRANTUPDATED', true);
|
||||
this.grant.grantedRoleKeysList = resp.roles;
|
||||
grant.grantedRoleKeysList = resp.roles;
|
||||
setTimeout(() => {
|
||||
this.changePage.emit();
|
||||
}, 1000);
|
||||
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
@mixin project-grant-illustration-theme($theme) {
|
||||
$foreground: map-get($theme, foreground);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$overlayColor: if($is-dark-theme, #ffffff10, #00000008);
|
||||
$highlightedOverlayColor: if($is-dark-theme, #68c4cf14, #68c4cf14);
|
||||
$borderColor: if($is-dark-theme, #ffffff20, #00000020);
|
||||
$overlayColor: if(sass($is-dark-theme): #ffffff10; else: #00000008);
|
||||
$highlightedOverlayColor: if(sass($is-dark-theme): #68c4cf14; else: #68c4cf14);
|
||||
$borderColor: if(sass($is-dark-theme): #ffffff20; else: #00000020);
|
||||
|
||||
.pgi {
|
||||
display: flex;
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@
|
||||
<tr class="highlight" mat-row *matRowDef="let grant; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
@if ((dataSource.loading$ | async) === false && !dataSource?.totalResult) {
|
||||
@if ((dataSource.loading$ | async) === false && !dataSource.totalResult) {
|
||||
<div class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'PROJECT.GRANT.EMPTY' | translate }}</span>
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
@if ((loading$ | async) === false && !dataSource?.data?.length) {
|
||||
@if ((loading$ | async) === false && !dataSource.data.length) {
|
||||
<div class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'PROJECT.TABLE.EMPTY' | translate }}</span>
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
@if ((loading$ | async) === false && !dataSource?.data?.length) {
|
||||
@if ((loading$ | async) === false && !dataSource.data.length) {
|
||||
<div class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'USER.PASSWORDLESS.EMPTY' | translate }}</span>
|
||||
|
||||
+1
-1
@@ -93,7 +93,7 @@
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
|
||||
@if ((loading$ | async) === false && !dataSource?.data?.length) {
|
||||
@if ((loading$ | async) === false && !dataSource.data.length) {
|
||||
<div class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'USER.MFA.EMPTY' | translate }}</span>
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@if ((loading$ | async) === false && !dataSource?.data?.length) {
|
||||
@if ((loading$ | async) === false && !dataSource.data.length) {
|
||||
<div class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'USER.EXTERNALIDP.EMPTY' | translate }}</span>
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
@if ((loading$ | async) === false && !dataSource?.data?.length) {
|
||||
@if ((loading$ | async) === false && !dataSource.data.length) {
|
||||
<div class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'USER.PASSWORDLESS.EMPTY' | translate }}</span>
|
||||
|
||||
@@ -233,7 +233,7 @@
|
||||
></tr>
|
||||
</table>
|
||||
</div>
|
||||
@if (!loading() && !dataSource?.data?.length) {
|
||||
@if (!loading() && !dataSource.data.length) {
|
||||
<div class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{ 'USER.TABLE.EMPTY' | translate }}</span>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { GrpcService } from './grpc.service';
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import { create, MessageInitShape } from '@bufbuild/protobuf';
|
||||
import {
|
||||
AddMyAuthFactorOTPSMSResponse,
|
||||
GetMyLoginPolicyResponse,
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
ListMyMetadataResponse,
|
||||
VerifyMyPhoneResponse,
|
||||
ListMyZitadelPermissionsResponse,
|
||||
ListMyProjectOrgsRequestSchema,
|
||||
} from '@zitadel/proto/zitadel/auth_pb';
|
||||
import { injectQuery } from '@tanstack/angular-query-experimental';
|
||||
import { UserService } from './user.service';
|
||||
@@ -82,4 +83,8 @@ export class NewAuthService {
|
||||
queryFn: () => this.listMyZitadelPermissions().then(({ result }) => result),
|
||||
}));
|
||||
}
|
||||
|
||||
public listMyProjectOrgs(req: MessageInitShape<typeof ListMyProjectOrgsRequestSchema>, signal?: AbortSignal) {
|
||||
return this.grpcService.authNew.listMyProjectOrgs(req, { signal });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import { GrpcService } from './grpc.service';
|
||||
import {
|
||||
AddOrgResponse,
|
||||
AddProjectGrantRequestSchema,
|
||||
DeactivateOrgResponse,
|
||||
GenerateMachineSecretRequestSchema,
|
||||
GenerateMachineSecretResponse,
|
||||
@@ -123,4 +124,8 @@ export class NewMgmtService {
|
||||
public addOrg(name: string): Promise<AddOrgResponse> {
|
||||
return this.grpcService.mgmtNew.addOrg({ name });
|
||||
}
|
||||
|
||||
public addProjectGrant(req: MessageInitShape<typeof AddProjectGrantRequestSchema>) {
|
||||
return this.grpcService.mgmtNew.addProjectGrant(req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
$is-dark-theme: map.get($theme, is-dark);
|
||||
|
||||
.cm-s-material.CodeMirror {
|
||||
background-color: if($is-dark-theme, #00000020, #263238);
|
||||
background-color: if(sass($is-dark-theme): #00000020; else: #263238);
|
||||
color: #eff;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid if($is-dark-theme, #403e3e, #00000040);
|
||||
border: 1px solid if(sass($is-dark-theme): #403e3e; else: #00000040);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
transform: all 0.2 linear;
|
||||
font-size: 1rem;
|
||||
border: none;
|
||||
border: 1px solid if($is-dark-theme, #f9f7f775, #1a191954);
|
||||
background-color: if($is-dark-theme, #00000040, #00000004);
|
||||
border: 1px solid if(sass($is-dark-theme): #f9f7f775; else: #1a191954);
|
||||
background-color: if(sass($is-dark-theme): #00000040; else: #00000004);
|
||||
border-radius: 4px;
|
||||
height: 40px;
|
||||
padding: 10px;
|
||||
@@ -34,7 +34,7 @@
|
||||
margin-bottom: 2px;
|
||||
|
||||
&:hover {
|
||||
border-color: if($is-dark-theme, #e0e0e0, #1a1b1b);
|
||||
border-color: if(sass($is-dark-theme): #e0e0e0; else: #1a1b1b);
|
||||
}
|
||||
|
||||
&:active,
|
||||
@@ -49,11 +49,11 @@
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
border-color: if($is-dark-theme, #36373850, #cccdce50);
|
||||
color: if($is-dark-theme, #ffffff80, #00000061);
|
||||
border-color: if(sass($is-dark-theme): #36373850; else: #cccdce50);
|
||||
color: if(sass($is-dark-theme): #ffffff80; else: #00000061);
|
||||
|
||||
&::placeholder {
|
||||
color: if($is-dark-theme, #ffffff80, #00000061);
|
||||
color: if(sass($is-dark-theme): #ffffff80; else: #00000061);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
}
|
||||
|
||||
.no-content-row {
|
||||
background-color: if($is-dark-theme, #ffffff10, #f4f4f470);
|
||||
background-color: if(sass($is-dark-theme): #ffffff10; else: #f4f4f470);
|
||||
border-bottom-left-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
display: flex;
|
||||
@@ -123,41 +123,41 @@
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
background-color: if($is-dark-theme, map.get($background, state), #e4e7e4);
|
||||
background-color: if(sass($is-dark-theme): map.get($background, state) ; else: #e4e7e4);
|
||||
box-shadow: 0 0 3px #0000001a;
|
||||
|
||||
&.active {
|
||||
background-color: if($is-dark-theme, map.get($background, state-active), #cbf4c9);
|
||||
color: if($is-dark-theme, #cbf4c9, #0e6245);
|
||||
background-color: if(sass($is-dark-theme): map.get($background, state-active) ; else: #cbf4c9);
|
||||
color: if(sass($is-dark-theme): #cbf4c9; else: #0e6245);
|
||||
}
|
||||
|
||||
&.inactive {
|
||||
color: if($is-dark-theme, #ffc1c1, #620e0e);
|
||||
background-color: if($is-dark-theme, map.get($background, state-inactive), #ffc1c1);
|
||||
color: if(sass($is-dark-theme): #ffc1c1; else: #620e0e);
|
||||
background-color: if(sass($is-dark-theme): map.get($background, state-inactive) ; else: #ffc1c1);
|
||||
}
|
||||
|
||||
&.neutral {
|
||||
background: if($is-dark-theme, #01489c78, #47a8ff82);
|
||||
color: if($is-dark-theme, #47a8ff, #01489c);
|
||||
background: if(sass($is-dark-theme): #01489c78; else: #47a8ff82);
|
||||
color: if(sass($is-dark-theme): #47a8ff; else: #01489c);
|
||||
}
|
||||
}
|
||||
|
||||
.bg-state {
|
||||
background-color: if($is-dark-theme, map.get($background, state), #e4e7e4) !important;
|
||||
background-color: if(sass($is-dark-theme): map.get($background, state) ; else: #e4e7e4) !important;
|
||||
|
||||
&.active {
|
||||
background-color: if($is-dark-theme, map.get($background, state-active), #cbf4c9) !important;
|
||||
color: if($is-dark-theme, #cbf4c9, #0e6245) !important;
|
||||
background-color: if(sass($is-dark-theme): map.get($background, state-active) ; else: #cbf4c9) !important;
|
||||
color: if(sass($is-dark-theme): #cbf4c9; else: #0e6245) !important;
|
||||
}
|
||||
|
||||
&.inactive {
|
||||
color: if($is-dark-theme, #ffc1c1, #620e0e) !important;
|
||||
background-color: if($is-dark-theme, map.get($background, state-inactive), #ffc1c1) !important;
|
||||
color: if(sass($is-dark-theme): #ffc1c1; else: #620e0e) !important;
|
||||
background-color: if(sass($is-dark-theme): map.get($background, state-inactive) ; else: #ffc1c1) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.color-shadow {
|
||||
border: 1px solid if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
border: 1px solid if(sass($is-dark-theme): rgba(#8795a1, 0.2) ; else: rgba(#8795a1, 0.2));
|
||||
box-shadow: 0 0 3px #0000001a;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/* https://github.com/tailwindlabs/tailwindcss-intellisense/issues/1158#issuecomment-2968949608 */
|
||||
@import 'tailwindcss/utilities' prefix(tw);
|
||||
@import 'tailwindcss/theme' prefix(tw);
|
||||
|
||||
@custom-variant dark (&:where(.dark-theme, .dark-theme *));
|
||||
Reference in New Issue
Block a user