add tab groups and tenent detail components aswell as active tab directive
This commit is contained in:
parent
2645de2e9f
commit
ec1773909b
9767
src/angular/frontend/package-lock.json
generated
Normal file
9767
src/angular/frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,8 @@
|
|||||||
|
import { ActiveTabDirective } from './active-tab.directive';
|
||||||
|
|
||||||
|
describe('ActiveTabDirective', () => {
|
||||||
|
it('should create an instance', () => {
|
||||||
|
const directive = new ActiveTabDirective();
|
||||||
|
expect(directive).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
import {Directive, input, TemplateRef} from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: 'ng-template[tabId]'
|
||||||
|
})
|
||||||
|
export class ActiveTabDirective {
|
||||||
|
|
||||||
|
public tabId = input.required<string>()
|
||||||
|
|
||||||
|
constructor(public template: TemplateRef<any>) {}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
<div class="tabs">
|
||||||
|
@for (tab of tabs(); track tab.id) {
|
||||||
|
<button
|
||||||
|
class="tab secondary"
|
||||||
|
[ngClass]="{'active': tab.id == activeTabId()}"
|
||||||
|
(click)="changeTab($event, tab.id)"
|
||||||
|
>
|
||||||
|
{{tab.name}}
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="tab-content">
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
:host {
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
|
||||||
|
--_tabGroup_bgColor : var(--neutral-80);
|
||||||
|
--_tab_bgColor: var(--secondary-30);
|
||||||
|
--_tab_hoverColor: var(--secondary-30);
|
||||||
|
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 1ch;
|
||||||
|
background-color: var(--_tabGroup_bgColor);
|
||||||
|
border-radius: 1000px;
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
border-radius: 1000px;
|
||||||
|
background-color: unset;
|
||||||
|
color: var(--neutral-10);
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: var(--neutral-90);
|
||||||
|
background-color: var(--_tab_bgColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 0 0 1px var(--_tab_hoverColor) inset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TabGroupComponent } from './tab-group.component';
|
||||||
|
|
||||||
|
describe('TabGroupComponent', () => {
|
||||||
|
let component: TabGroupComponent;
|
||||||
|
let fixture: ComponentFixture<TabGroupComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [TabGroupComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(TabGroupComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
import {
|
||||||
|
AfterViewInit,
|
||||||
|
Component,
|
||||||
|
ContentChildren,
|
||||||
|
input,
|
||||||
|
model,
|
||||||
|
OnInit,
|
||||||
|
QueryList,
|
||||||
|
ViewContainerRef
|
||||||
|
} from '@angular/core';
|
||||||
|
import {NgClass} from '@angular/common';
|
||||||
|
import {ActiveTabDirective} from './active-tab.directive';
|
||||||
|
import {takeUntilDestroyed, toObservable} from '@angular/core/rxjs-interop';
|
||||||
|
|
||||||
|
export interface TabGroup {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-tab-group',
|
||||||
|
imports: [
|
||||||
|
NgClass
|
||||||
|
],
|
||||||
|
templateUrl: './tab-group.component.html',
|
||||||
|
styleUrl: './tab-group.component.scss',
|
||||||
|
standalone: true
|
||||||
|
})
|
||||||
|
export class TabGroupComponent implements OnInit, AfterViewInit {
|
||||||
|
|
||||||
|
public tabs = input.required<TabGroup[]>();
|
||||||
|
public activeTabId = model<string | null>();
|
||||||
|
|
||||||
|
@ContentChildren(ActiveTabDirective) tabTemplates!: QueryList<ActiveTabDirective>;
|
||||||
|
|
||||||
|
constructor(private vcr: ViewContainerRef) {
|
||||||
|
|
||||||
|
toObservable(this.activeTabId)
|
||||||
|
.pipe(takeUntilDestroyed())
|
||||||
|
.subscribe(id => {
|
||||||
|
if (id)
|
||||||
|
this.renderTab(id);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
if (!this.activeTabId() && this.tabs().length > 0) {
|
||||||
|
this.activeTabId.set(this.tabs()[0]!.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
const activeTabId = this.activeTabId();
|
||||||
|
if (activeTabId)
|
||||||
|
this.renderTab(activeTabId);
|
||||||
|
}
|
||||||
|
|
||||||
|
changeTab($event: PointerEvent, id: string) {
|
||||||
|
$event.preventDefault();
|
||||||
|
if (id == this.activeTabId()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.activeTabId.update(() => id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderTab(id: string) {
|
||||||
|
|
||||||
|
if (!this.tabTemplates) return;
|
||||||
|
|
||||||
|
this.vcr.clear();
|
||||||
|
|
||||||
|
const tab = this.tabTemplates.find(t => t.tabId() === this.activeTabId());
|
||||||
|
|
||||||
|
if (tab) {
|
||||||
|
const tabOption = this.tabs().find(x => x.id == id);
|
||||||
|
this.vcr.createEmbeddedView(tab.template, {$implicit: tabOption});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
<app-tab-group [tabs]="tabs">
|
||||||
|
|
||||||
|
<ng-template tabId="subjects" let-tab>
|
||||||
|
{{tab.name}} - content
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template tabId="apps" let-tab>
|
||||||
|
{{tab.name}} - content
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template tabId="groups" let-tab>
|
||||||
|
{{tab.name}} - content
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template tabId="roles" let-tab>
|
||||||
|
{{tab.name}} - content
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template tabId="authorities" let-tab>
|
||||||
|
{{tab.name}} - content
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
</app-tab-group>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TenantDetailComponent } from './tenant-detail.component';
|
||||||
|
|
||||||
|
describe('TenantDetailComponent', () => {
|
||||||
|
let component: TenantDetailComponent;
|
||||||
|
let fixture: ComponentFixture<TenantDetailComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [TenantDetailComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(TenantDetailComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {TabGroup, TabGroupComponent} from '../../tab-group/tab-group.component';
|
||||||
|
import {ActiveTabDirective} from '../../tab-group/active-tab.directive';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-tenant-detail',
|
||||||
|
imports: [
|
||||||
|
TabGroupComponent,
|
||||||
|
ActiveTabDirective
|
||||||
|
],
|
||||||
|
templateUrl: './tenant-detail.component.html',
|
||||||
|
styleUrl: './tenant-detail.component.scss',
|
||||||
|
})
|
||||||
|
export class TenantDetailComponent {
|
||||||
|
|
||||||
|
protected tabs = [
|
||||||
|
{
|
||||||
|
id: "subjects",
|
||||||
|
name: "Users"
|
||||||
|
} satisfies TabGroup,
|
||||||
|
{
|
||||||
|
id: "apps",
|
||||||
|
name: "Apps"
|
||||||
|
} satisfies TabGroup,
|
||||||
|
{
|
||||||
|
id: "groups",
|
||||||
|
name: "Groups"
|
||||||
|
} satisfies TabGroup,
|
||||||
|
{
|
||||||
|
id: "roles",
|
||||||
|
name: "Roles"
|
||||||
|
} satisfies TabGroup,
|
||||||
|
{
|
||||||
|
id: "authorities",
|
||||||
|
name: "Authorities"
|
||||||
|
} satisfies TabGroup
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user