RED-6713: add select domain menu

This commit is contained in:
Dan Percic 2023-05-21 20:13:03 +03:00
parent 8cda38a673
commit 04adad3a75
13 changed files with 150 additions and 66 deletions

View File

@ -67,6 +67,9 @@ import { RedRoleGuard } from '@users/red-role.guard';
import { SkeletonTopBarComponent } from '@components/skeleton/skeleton-top-bar/skeleton-top-bar.component';
import { DossierSkeletonComponent } from '@components/skeleton/dossier-skeleton/dossier-skeleton.component';
import { SkeletonStatsComponent } from '@components/skeleton/skeleton-stats/skeleton-stats.component';
import { UserMenuComponent } from '@components/user-menu/user-menu.component';
import { TenantsMenuComponent } from '@components/tenants-menu/tenants-menu.component';
import { MatDividerModule } from '@angular/material/divider';
export const appModuleFactory = (config: AppConfig) => {
@NgModule({
@ -81,6 +84,8 @@ export const appModuleFactory = (config: AppConfig) => {
SkeletonTopBarComponent,
SkeletonStatsComponent,
BaseScreenComponent,
UserMenuComponent,
TenantsMenuComponent,
DownloadsListScreenComponent,
],
imports: [
@ -163,6 +168,7 @@ export const appModuleFactory = (config: AppConfig) => {
IqserListingModule,
IconButtonComponent,
TenantPipe,
MatDividerModule,
],
providers: [
{

View File

@ -21,8 +21,8 @@
<redaction-spotlight-search
*allow="roles.search; if: (isSearchScreen$ | async) === false && (currentUser.isUser || currentUser.isManager)"
[actions]="searchActions"
[placeholder]="'search.placeholder' | translate"
[attr.help-mode-key]="'search_in_entire_application'"
[placeholder]="'search.placeholder' | translate"
></redaction-spotlight-search>
<iqser-help-button *deny="roles.getRss" [attr.help-mode-key]="'help_mode'" id="help-mode-button"></iqser-help-button>
@ -36,18 +36,7 @@
<iqser-user-button [attr.help-mode-key]="'open_usermenu'" [matMenuTriggerFor]="userMenu" id="userMenu"></iqser-user-button>
<mat-menu #userMenu="matMenu" xPosition="before">
<div id="user-menu-items">
<ng-container *ngFor="let item of userMenuItems; trackBy: trackByName">
<a (click)="item.action?.()" *ngIf="item.show" [id]="item.id" [routerLink]="item.routerLink | tenant" mat-menu-item>
{{ item.name | translate }}
</a>
</ng-container>
<button (click)="userService.logout()" id="logout" mat-menu-item>
<mat-icon svgIcon="iqser:logout"></mat-icon>
<span translate="top-bar.navigation-items.my-account.children.logout"> </span>
</button>
</div>
<app-user-menu></app-user-menu>
</mat-menu>
</div>
</div>

View File

@ -5,7 +5,6 @@ import { NavigationStart, Router } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { SpotlightSearchAction } from '@components/spotlight-search/spotlight-search-action';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { filter, map, startWith } from 'rxjs/operators';
import { BASE_HREF, IqserPermissionsService, List, shareDistinctLast, TenantsService } from '@iqser/common-ui';
import { BreadcrumbsService } from '@services/breadcrumbs.service';
@ -14,15 +13,6 @@ import { ARCHIVE_ROUTE, DOSSIERS_ARCHIVE, DOSSIERS_ROUTE } from '@red/domain';
import { ROLES } from '@users/roles';
import { REDDocumentViewer } from '../../modules/pdf-viewer/services/document-viewer.service';
interface MenuItem {
readonly id: string;
readonly name: string;
readonly routerLink?: string;
readonly show: boolean;
readonly action?: () => void;
readonly showDot?: () => boolean;
}
const isNavigationStart = event => event instanceof NavigationStart;
const isSearchScreen: (url: string) => boolean = url => url.includes('/search');
@ -34,38 +24,6 @@ export class BaseScreenComponent {
readonly roles = ROLES;
readonly documentViewer = inject(REDDocumentViewer);
readonly currentUser = this.userService.currentUser;
readonly userMenuItems: readonly MenuItem[] = [
{
id: 'account',
name: _('top-bar.navigation-items.my-account.children.account'),
routerLink: '/main/account',
show: true,
},
{
id: 'admin',
name: _('top-bar.navigation-items.my-account.children.admin'),
routerLink: '/main/admin',
show: (this.currentUser.isManager || this.currentUser.isUserAdmin) && this.permissionsService.has([ROLES.templates.read]),
},
{
id: 'downloads',
name: _('top-bar.navigation-items.my-account.children.downloads'),
routerLink: '/main/downloads',
show: this.currentUser.isUser && this.permissionsService.has(ROLES.readDownloadStatus),
},
{
id: 'trash',
name: _('top-bar.navigation-items.my-account.children.trash'),
routerLink: '/main/trash',
show: this.currentUser.isUser && this.permissionsService.has([ROLES.dossiers.read, ROLES.files.readStatus]),
},
{
id: 'select-tenant',
name: _('top-bar.navigation-items.my-account.children.select-tenant'),
action: () => this.selectTenant(),
show: this._tenantsService.hasMultiple(),
},
];
readonly searchActions: List<SpotlightSearchAction> = [
{
text: this._translateService.instant('search.this-dossier'),
@ -98,7 +56,7 @@ export class BaseScreenComponent {
private readonly _router: Router,
private readonly _translateService: TranslateService,
private readonly _featuresService: FeaturesService,
private readonly _tenantsService: TenantsService,
protected readonly _tenantsService: TenantsService,
readonly permissionsService: IqserPermissionsService,
readonly userService: UserService,
readonly userPreferenceService: UserPreferenceService,
@ -116,14 +74,6 @@ export class BaseScreenComponent {
return !isDossierOverview;
}
trackByName(_index: number, item: MenuItem) {
return item.name;
}
selectTenant() {
window.open(window.location.origin + this.#baseHref, '_blank');
}
#search(query: string, dossierIds: string[], onlyActive = false) {
const queryParams = { query, dossierIds: dossierIds.join(','), onlyActive };
this._router.navigate([`/${this._tenantsService.activeTenantId}/main/search`], { queryParams }).then();

View File

@ -0,0 +1,14 @@
<div id="tenants-menu-items">
<ng-container *ngFor="let item of storedTenants(); trackBy: trackBy">
<div class="label">{{ item.tenant.displayName }}</div>
<a (click)="selectTenant(item.tenant.tenantId)" [id]="item.tenant.tenantId" mat-menu-item>
{{ item.email }}
</a>
<mat-divider class="pb-3 pt-3"></mat-divider>
</ng-container>
<a (click)="selectTenant()" mat-menu-item>
<span translate="top-bar.navigation-items.my-account.children.join-another-tenant"> </span>
</a>
</div>

View File

@ -0,0 +1,13 @@
:host {
display: contents;
}
.label {
font-family: var(--iqser-font-family);
font-size: var(--iqser-font-size);
background-color: var(--iqser-background);
color: var(--iqser-disabled);
padding-left: 17px;
padding-top: 5px;
padding-bottom: 5px;
}

View File

@ -0,0 +1,29 @@
import { Component, computed, inject } from '@angular/core';
import { BASE_HREF, IStoredTenant, TenantsService } from '@iqser/common-ui';
@Component({
selector: 'app-tenants-menu',
templateUrl: './tenants-menu.component.html',
styleUrls: ['./tenants-menu.component.scss'],
})
export class TenantsMenuComponent {
readonly tenantsService = inject(TenantsService);
readonly storedTenants = computed(() => this.#getStoredTenants(this.tenantsService.activeTenant().tenantId));
readonly #baseHref = inject(BASE_HREF);
trackBy(_index: number, item: IStoredTenant) {
return item.tenant.tenantId;
}
selectTenant(tenantId?: string) {
const tenant = tenantId ? '/' + tenantId : '/';
window.open(window.location.origin + this.#baseHref + tenant, '_blank');
}
#getStoredTenants(activeTenantId: string) {
const storedTenants = this.tenantsService.getStoredTenants();
return storedTenants.filter(t => t.tenant.tenantId !== activeTenantId);
}
}

View File

@ -0,0 +1,20 @@
<div id="user-menu-items">
<ng-container *ngFor="let item of userMenuItems; trackBy: trackBy">
<a (click)="item.action?.()" *ngIf="item.show" [id]="item.id" [routerLink]="item.routerLink | tenant" mat-menu-item>
{{ item.name | translate }}
</a>
</ng-container>
<a *ngIf="tenantsService.hasMultiple()" [id]="'switch-accounts'" [matMenuTriggerFor]="tenantsMenu" mat-menu-item>
{{ 'top-bar.navigation-items.my-account.children.select-tenant' | translate }}
</a>
<button (click)="userService.logout()" id="logout" mat-menu-item>
<mat-icon svgIcon="iqser:logout"></mat-icon>
<span translate="top-bar.navigation-items.my-account.children.logout"> </span>
</button>
</div>
<mat-menu #tenantsMenu="matMenu" xPosition="before">
<app-tenants-menu></app-tenants-menu>
</mat-menu>

View File

@ -0,0 +1,3 @@
:host {
display: contents;
}

View File

@ -0,0 +1,56 @@
import { Component, inject } from '@angular/core';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { ROLES } from '@users/roles';
import { getCurrentUser, IqserPermissionsService, List, TenantsService } from '@iqser/common-ui';
import { User } from '@red/domain';
import { UserService } from '@users/user.service';
interface MenuItem {
readonly id: string;
readonly name: string;
readonly routerLink?: string;
readonly show: boolean;
readonly action?: () => void;
readonly showDot?: () => boolean;
}
@Component({
selector: 'app-user-menu',
templateUrl: './user-menu.component.html',
styleUrls: ['./user-menu.component.scss'],
})
export class UserMenuComponent {
readonly currentUser = getCurrentUser<User>();
readonly tenantsService = inject(TenantsService);
readonly userService = inject(UserService);
readonly #permissionsService = inject(IqserPermissionsService);
readonly userMenuItems: List<MenuItem> = [
{
id: 'account',
name: _('top-bar.navigation-items.my-account.children.account'),
routerLink: '/main/account',
show: true,
},
{
id: 'admin',
name: _('top-bar.navigation-items.my-account.children.admin'),
routerLink: '/main/admin',
show: (this.currentUser.isManager || this.currentUser.isUserAdmin) && this.#permissionsService.has([ROLES.templates.read]),
},
{
id: 'downloads',
name: _('top-bar.navigation-items.my-account.children.downloads'),
routerLink: '/main/downloads',
show: this.currentUser.isUser && this.#permissionsService.has(ROLES.readDownloadStatus),
},
{
id: 'trash',
name: _('top-bar.navigation-items.my-account.children.trash'),
routerLink: '/main/trash',
show: this.currentUser.isUser && this.#permissionsService.has([ROLES.dossiers.read, ROLES.files.readStatus]),
},
];
trackBy(_index: number, item: MenuItem) {
return item.id;
}
}

View File

@ -2094,6 +2094,7 @@
"account": "Konto",
"admin": "Einstellungen",
"downloads": "Meine Downloads",
"join-another-tenant": "",
"language": {
"de": "Deutsch",
"en": "Englisch",

View File

@ -2094,13 +2094,14 @@
"account": "Account",
"admin": "Settings",
"downloads": "My Downloads",
"join-another-tenant": "Join another domain",
"language": {
"de": "German",
"en": "English",
"label": "Language"
},
"logout": "Logout",
"select-tenant": "Select Tenant",
"select-tenant": "Switch accounts",
"trash": "Trash"
}
}

View File

@ -2094,6 +2094,7 @@
"account": "Konto",
"admin": "Einstellungen",
"downloads": "Meine Downloads",
"join-another-tenant": "",
"language": {
"de": "Deutsch",
"en": "Englisch",

View File

@ -2094,13 +2094,14 @@
"account": "Account",
"admin": "Settings",
"downloads": "My Downloads",
"join-another-tenant": "Join another domain",
"language": {
"de": "German",
"en": "English",
"label": "Language"
},
"logout": "Logout",
"select-tenant": "Select Tenant",
"select-tenant": "Switch accounts",
"trash": "Trash"
}
}