mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-02 05:23:14 +00:00
fix: fix discussed issues (#2467)
* fix: fix discussed issues * chore: fix issues * fix package lock --------- Co-authored-by: Matt Hill <mattnine@protonmail.com>
This commit is contained in:
@@ -24,6 +24,7 @@ import { ThemeSwitcherService } from './services/theme-switcher.service'
|
||||
import { DateTransformerService } from './services/date-transformer.service'
|
||||
import { DatetimeTransformerService } from './services/datetime-transformer.service'
|
||||
import { MarketplaceService } from './services/marketplace.service'
|
||||
import { RoutingStrategyService } from './apps/portal/services/routing-strategy.service'
|
||||
|
||||
const {
|
||||
useMocks,
|
||||
@@ -79,6 +80,10 @@ export const APP_PROVIDERS: Provider[] = [
|
||||
provide: AbstractMarketplaceService,
|
||||
useClass: MarketplaceService,
|
||||
},
|
||||
{
|
||||
provide: RouteReuseStrategy,
|
||||
useExisting: RoutingStrategyService,
|
||||
},
|
||||
]
|
||||
|
||||
export function appInitializer(
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<span class="link">
|
||||
<tui-badged-content [style.--tui-radius.rem]="1.5">
|
||||
<tui-badge-alert *ngIf="badge" size="m" tuiSlot="top">
|
||||
<tui-badge-notification *ngIf="badge" size="m" tuiSlot="top">
|
||||
{{ badge }}
|
||||
</tui-badge-alert>
|
||||
</tui-badge-notification>
|
||||
<tui-svg
|
||||
*ngIf="icon.startsWith('tuiIcon'); else url"
|
||||
class="icon"
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
Input,
|
||||
} from '@angular/core'
|
||||
import {
|
||||
TuiBadgeAlertModule,
|
||||
TuiBadgedContentModule,
|
||||
TuiBadgeNotificationModule,
|
||||
} from '@taiga-ui/experimental'
|
||||
import { RouterLink } from '@angular/router'
|
||||
import { TickerModule } from '@start9labs/shared'
|
||||
@@ -37,7 +37,7 @@ import { toRouterLink } from '../../utils/to-router-link'
|
||||
TuiSvgModule,
|
||||
TickerModule,
|
||||
TuiBadgedContentModule,
|
||||
TuiBadgeAlertModule,
|
||||
TuiBadgeNotificationModule,
|
||||
ActionsComponent,
|
||||
],
|
||||
})
|
||||
|
||||
@@ -1,18 +1,28 @@
|
||||
@import '@taiga-ui/core/styles/taiga-ui-local';
|
||||
|
||||
:host {
|
||||
@include scrollbar-hidden;
|
||||
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
// TODO: Theme
|
||||
background: rgb(97 95 95 / 84%);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tab {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 7.5rem;
|
||||
|
||||
&_active {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
// TODO: Theme
|
||||
background: #373a3f;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CommonModule, Location } from '@angular/common'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { RouterModule } from '@angular/router'
|
||||
import { Router, RouterModule } from '@angular/router'
|
||||
import { TuiButtonModule, TuiSvgModule } from '@taiga-ui/core'
|
||||
import { NavigationService } from '../../services/navigation.service'
|
||||
import { NavigationItem } from '../../types/navigation-item'
|
||||
@@ -14,7 +14,7 @@ import { NavigationItem } from '../../types/navigation-item'
|
||||
imports: [CommonModule, RouterModule, TuiButtonModule, TuiSvgModule],
|
||||
})
|
||||
export class NavigationComponent {
|
||||
private readonly location = inject(Location)
|
||||
private readonly router = inject(Router)
|
||||
private readonly navigation = inject(NavigationService)
|
||||
|
||||
readonly tabs$ = this.navigation.getTabs()
|
||||
@@ -22,6 +22,6 @@ export class NavigationComponent {
|
||||
removeTab(tab: NavigationItem, active: boolean) {
|
||||
this.navigation.removeTab(tab)
|
||||
|
||||
if (active) this.location.back()
|
||||
if (active) this.router.navigate(['./portal/desktop'])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { TuiDialogService, TuiSvgModule } from '@taiga-ui/core'
|
||||
import { TuiFadeModule } from '@taiga-ui/experimental'
|
||||
import { BackupsCreateService } from './services/create.service'
|
||||
import { BackupsRestoreService } from './services/restore.service'
|
||||
import { BackupsUpcomingComponent } from './components/upcoming.component'
|
||||
@@ -24,15 +25,20 @@ import { JOBS } from './modals/jobs.component'
|
||||
</div>
|
||||
</button>
|
||||
</section>
|
||||
<section>
|
||||
<h3 class="g-title">Upcoming Jobs</h3>
|
||||
<h3 class="g-title">Upcoming Jobs</h3>
|
||||
<div tuiFade class="g-hidden-scrollbar">
|
||||
<table backupsUpcoming class="g-table"></table>
|
||||
</section>
|
||||
</div>
|
||||
`,
|
||||
host: { class: 'g-page' },
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [CommonModule, TuiSvgModule, BackupsUpcomingComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
TuiSvgModule,
|
||||
TuiFadeModule,
|
||||
BackupsUpcomingComponent,
|
||||
],
|
||||
})
|
||||
export class BackupsComponent {
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
@@ -64,7 +70,9 @@ export class BackupsComponent {
|
||||
icon: 'tuiIconDatabaseLarge',
|
||||
description: 'Manage backup targets',
|
||||
action: () =>
|
||||
this.dialogs.open(TARGETS, { label: 'Backup Targets' }).subscribe(),
|
||||
this.dialogs
|
||||
.open(TARGETS, { label: 'Backup Targets', size: 'l' })
|
||||
.subscribe(),
|
||||
},
|
||||
{
|
||||
name: 'History',
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
TuiLinkModule,
|
||||
TuiSvgModule,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiFadeModule } from '@taiga-ui/experimental'
|
||||
import { TuiCheckboxModule } from '@taiga-ui/kit'
|
||||
import { BehaviorSubject } from 'rxjs'
|
||||
import { BackupRun } from 'src/app/services/api/api.types'
|
||||
@@ -38,68 +39,70 @@ import { REPORT } from './report.component'
|
||||
Delete Selected
|
||||
</button>
|
||||
</h3>
|
||||
<table class="g-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<tui-checkbox
|
||||
[disabled]="!selected.length"
|
||||
[ngModel]="all"
|
||||
(ngModelChange)="toggle()"
|
||||
></tui-checkbox>
|
||||
</th>
|
||||
<th>Started At</th>
|
||||
<th>Duration</th>
|
||||
<th>Result</th>
|
||||
<th>Job</th>
|
||||
<th>Target</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
*ngFor="
|
||||
let run of runs;
|
||||
let index = index;
|
||||
else: loading;
|
||||
empty: blank
|
||||
"
|
||||
[style.background]="selected[index] ? 'var(--tui-clear)' : ''"
|
||||
>
|
||||
<td><tui-checkbox [(ngModel)]="selected[index]"></tui-checkbox></td>
|
||||
<td>{{ run['started-at'] | date : 'medium' }}</td>
|
||||
<td>
|
||||
{{ run['started-at'] | duration : run['completed-at'] }} Minutes
|
||||
</td>
|
||||
<td>
|
||||
<tui-svg
|
||||
*ngIf="run.report | hasError; else noError"
|
||||
src="tuiIconClose"
|
||||
[style.color]="'var(--tui-negative)'"
|
||||
></tui-svg>
|
||||
<ng-template #noError>
|
||||
<tui-svg
|
||||
src="tuiIconCheck"
|
||||
[style.color]="'var(--tui-positive)'"
|
||||
></tui-svg>
|
||||
</ng-template>
|
||||
<button tuiLink (click)="showReport(run)">Report</button>
|
||||
</td>
|
||||
<td>{{ run.job.name || 'No job' }}</td>
|
||||
<td>
|
||||
<tui-svg [src]="run.job.target.type | getBackupIcon"></tui-svg>
|
||||
{{ run.job.target.name }}
|
||||
</td>
|
||||
</tr>
|
||||
<ng-template #loading>
|
||||
<tr *ngFor="let row of ['', '', '']">
|
||||
<td colspan="6"><div class="tui-skeleton">Loading</div></td>
|
||||
<div tuiFade class="g-hidden-scrollbar">
|
||||
<table class="g-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<tui-checkbox
|
||||
[disabled]="!selected.length"
|
||||
[ngModel]="all"
|
||||
(ngModelChange)="toggle()"
|
||||
></tui-checkbox>
|
||||
</th>
|
||||
<th>Started At</th>
|
||||
<th>Duration</th>
|
||||
<th>Result</th>
|
||||
<th>Job</th>
|
||||
<th>Target</th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template #blank>
|
||||
<tr><td colspan="6">No backups have been run yet.</td></tr>
|
||||
</ng-template>
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
*ngFor="
|
||||
let run of runs;
|
||||
let index = index;
|
||||
else: loading;
|
||||
empty: blank
|
||||
"
|
||||
[style.background]="selected[index] ? 'var(--tui-clear)' : ''"
|
||||
>
|
||||
<td><tui-checkbox [(ngModel)]="selected[index]"></tui-checkbox></td>
|
||||
<td>{{ run['started-at'] | date : 'medium' }}</td>
|
||||
<td>
|
||||
{{ run['started-at'] | duration : run['completed-at'] }} Minutes
|
||||
</td>
|
||||
<td>
|
||||
<tui-svg
|
||||
*ngIf="run.report | hasError; else noError"
|
||||
src="tuiIconClose"
|
||||
[style.color]="'var(--tui-negative)'"
|
||||
></tui-svg>
|
||||
<ng-template #noError>
|
||||
<tui-svg
|
||||
src="tuiIconCheck"
|
||||
[style.color]="'var(--tui-positive)'"
|
||||
></tui-svg>
|
||||
</ng-template>
|
||||
<button tuiLink (click)="showReport(run)">Report</button>
|
||||
</td>
|
||||
<td>{{ run.job.name || 'No job' }}</td>
|
||||
<td>
|
||||
<tui-svg [src]="run.job.target.type | getBackupIcon"></tui-svg>
|
||||
{{ run.job.target.name }}
|
||||
</td>
|
||||
</tr>
|
||||
<ng-template #loading>
|
||||
<tr *ngFor="let row of ['', '', '']">
|
||||
<td colspan="6"><div class="tui-skeleton">Loading</div></td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template #blank>
|
||||
<tr><td colspan="6">No backups have been run yet.</td></tr>
|
||||
</ng-template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
@@ -111,6 +114,7 @@ import { REPORT } from './report.component'
|
||||
TuiCheckboxModule,
|
||||
TuiSvgModule,
|
||||
TuiLinkModule,
|
||||
TuiFadeModule,
|
||||
DurationPipe,
|
||||
HasErrorPipe,
|
||||
GetBackupIconPipe,
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
TuiNotificationModule,
|
||||
TuiSvgModule,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiFadeModule } from '@taiga-ui/experimental'
|
||||
import { TUI_PROMPT, TuiPromptData } from '@taiga-ui/kit'
|
||||
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
|
||||
import { BehaviorSubject, filter } from 'rxjs'
|
||||
@@ -39,52 +40,54 @@ import { EDIT } from './edit.component'
|
||||
Create New Job
|
||||
</button>
|
||||
</h3>
|
||||
<table class="g-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Target</th>
|
||||
<th>Packages</th>
|
||||
<th>Schedule</th>
|
||||
<th [style.width.rem]="3.5"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let job of jobs || null; else: loading; empty: blank">
|
||||
<td>{{ job.name }}</td>
|
||||
<td>
|
||||
<tui-svg [src]="job.target.type | getBackupIcon"></tui-svg>
|
||||
{{ job.target.name }}
|
||||
</td>
|
||||
<td>Packages: {{ job['package-ids'].length }}</td>
|
||||
<td>{{ (job.cron | toHumanCron).message }}</td>
|
||||
<td>
|
||||
<button
|
||||
tuiIconButton
|
||||
appearance="icon"
|
||||
size="xs"
|
||||
icon="tuiIconEdit2"
|
||||
(click)="update(job)"
|
||||
></button>
|
||||
<button
|
||||
tuiIconButton
|
||||
appearance="icon"
|
||||
size="xs"
|
||||
icon="tuiIconTrash2"
|
||||
(click)="delete(job.id)"
|
||||
></button>
|
||||
</td>
|
||||
</tr>
|
||||
<ng-template #loading>
|
||||
<tr *ngFor="let i of ['', '']">
|
||||
<td colspan="5"><div class="tui-skeleton">Loading</div></td>
|
||||
<div class="g-hidden-scrollbar" tuiFade>
|
||||
<table class="g-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Target</th>
|
||||
<th>Packages</th>
|
||||
<th>Schedule</th>
|
||||
<th [style.width.rem]="3.5"></th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template #blank>
|
||||
<tr><td colspan="5">No jobs found.</td></tr>
|
||||
</ng-template>
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let job of jobs || null; else: loading; empty: blank">
|
||||
<td>{{ job.name }}</td>
|
||||
<td>
|
||||
<tui-svg [src]="job.target.type | getBackupIcon"></tui-svg>
|
||||
{{ job.target.name }}
|
||||
</td>
|
||||
<td>Packages: {{ job['package-ids'].length }}</td>
|
||||
<td>{{ (job.cron | toHumanCron).message }}</td>
|
||||
<td>
|
||||
<button
|
||||
tuiIconButton
|
||||
appearance="icon"
|
||||
size="xs"
|
||||
icon="tuiIconEdit2"
|
||||
(click)="update(job)"
|
||||
></button>
|
||||
<button
|
||||
tuiIconButton
|
||||
appearance="icon"
|
||||
size="xs"
|
||||
icon="tuiIconTrash2"
|
||||
(click)="delete(job.id)"
|
||||
></button>
|
||||
</td>
|
||||
</tr>
|
||||
<ng-template #loading>
|
||||
<tr *ngFor="let i of ['', '']">
|
||||
<td colspan="5"><div class="tui-skeleton">Loading</div></td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template #blank>
|
||||
<tr><td colspan="5">No jobs found.</td></tr>
|
||||
</ng-template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [
|
||||
@@ -93,6 +96,7 @@ import { EDIT } from './edit.component'
|
||||
TuiNotificationModule,
|
||||
TuiButtonModule,
|
||||
TuiSvgModule,
|
||||
TuiFadeModule,
|
||||
ToHumanCronPipe,
|
||||
GetBackupIconPipe,
|
||||
],
|
||||
|
||||
@@ -107,8 +107,10 @@ export class BackupsTargetModal {
|
||||
}
|
||||
|
||||
goToTargets() {
|
||||
this.dialogs.open(TARGETS, { label: 'Backup Targets' }).subscribe()
|
||||
this.context.$implicit.complete()
|
||||
this.dialogs
|
||||
.open(TARGETS, { label: 'Backup Targets', size: 'l' })
|
||||
.subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { BackupConfig } from '../types/backup-config'
|
||||
import { BackupsPhysicalComponent } from '../components/physical.component'
|
||||
import { BackupsTargetsComponent } from '../components/targets.component'
|
||||
import { TuiFadeModule } from '@taiga-ui/experimental'
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
@@ -60,23 +61,27 @@ import { BackupsTargetsComponent } from '../components/targets.component'
|
||||
Refresh
|
||||
</button>
|
||||
</h3>
|
||||
<table
|
||||
class="g-table"
|
||||
[backupsPhysical]="targets?.['unknown-disks'] || null"
|
||||
(add)="addPhysical($event)"
|
||||
></table>
|
||||
<div class="g-hidden-scrollbar" tuiFade>
|
||||
<table
|
||||
class="g-table"
|
||||
[backupsPhysical]="targets?.['unknown-disks'] || null"
|
||||
(add)="addPhysical($event)"
|
||||
></table>
|
||||
</div>
|
||||
<h3 class="g-title">
|
||||
Saved Targets
|
||||
<button tuiButton size="s" icon="tuiIconPlus" (click)="addRemote()">
|
||||
Add Target
|
||||
</button>
|
||||
</h3>
|
||||
<table
|
||||
class="g-table"
|
||||
[backupsTargets]="targets?.saved || null"
|
||||
(delete)="onDelete($event)"
|
||||
(update)="onUpdate($event)"
|
||||
></table>
|
||||
<div class="g-hidden-scrollbar" tuiFade>
|
||||
<table
|
||||
class="g-table"
|
||||
[backupsTargets]="targets?.saved || null"
|
||||
(delete)="onDelete($event)"
|
||||
(update)="onUpdate($event)"
|
||||
></table>
|
||||
</div>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [
|
||||
@@ -85,6 +90,7 @@ import { BackupsTargetsComponent } from '../components/targets.component'
|
||||
TuiButtonModule,
|
||||
BackupsPhysicalComponent,
|
||||
BackupsTargetsComponent,
|
||||
TuiFadeModule,
|
||||
],
|
||||
})
|
||||
export class BackupsTargetsModal implements OnInit {
|
||||
@@ -103,6 +109,7 @@ export class BackupsTargetsModal implements OnInit {
|
||||
|
||||
async refresh() {
|
||||
this.loading$.next(true)
|
||||
this.targets = undefined
|
||||
|
||||
try {
|
||||
this.targets = await this.api.getBackupTargets({})
|
||||
|
||||
@@ -46,7 +46,7 @@ import { InstallProgressPipe } from '../pipes/install-progress.pipe'
|
||||
<tui-accordion-item borders="top-bottom">
|
||||
<div class="g-action">
|
||||
<tui-avatar size="s" [src]="pkg | mimeType | trustUrl" />
|
||||
<div [style.flex]="1">
|
||||
<div [style.flex]="1" [style.overflow]="'hidden'">
|
||||
<strong>{{ pkg.manifest.title }}</strong>
|
||||
<div>
|
||||
<!-- @TODO left side should be local['old-manifest'] (or whatever), not manifest. -->
|
||||
|
||||
@@ -6,7 +6,7 @@ import { NavigationItem } from '../types/navigation-item'
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class NavigationService {
|
||||
readonly tabs = new BehaviorSubject<readonly NavigationItem[]>([])
|
||||
private readonly tabs = new BehaviorSubject<readonly NavigationItem[]>([])
|
||||
|
||||
getTabs(): Observable<readonly NavigationItem[]> {
|
||||
return this.tabs
|
||||
@@ -21,4 +21,8 @@ export class NavigationService {
|
||||
this.tabs.next([...this.tabs.value, tab])
|
||||
}
|
||||
}
|
||||
|
||||
hasTab(path: string): boolean {
|
||||
return this.tabs.value.some(t => t.routerLink === path)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import { inject, Injectable } from '@angular/core'
|
||||
import {
|
||||
ActivatedRouteSnapshot,
|
||||
BaseRouteReuseStrategy,
|
||||
createUrlTreeFromSnapshot,
|
||||
DetachedRouteHandle,
|
||||
UrlSerializer,
|
||||
} from '@angular/router'
|
||||
import { NavigationService } from './navigation.service'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class RoutingStrategyService extends BaseRouteReuseStrategy {
|
||||
private readonly url = inject(UrlSerializer)
|
||||
private readonly navigation = inject(NavigationService)
|
||||
private readonly handlers = new Map<string, DetachedRouteHandle>()
|
||||
|
||||
override shouldDetach(route: ActivatedRouteSnapshot): boolean {
|
||||
const path = this.getPath(route)
|
||||
const store = this.navigation.hasTab(path)
|
||||
|
||||
if (!store) this.handlers.delete(path)
|
||||
|
||||
return store
|
||||
}
|
||||
|
||||
override store(
|
||||
route: ActivatedRouteSnapshot,
|
||||
handle: DetachedRouteHandle,
|
||||
): void {
|
||||
this.handlers.set(this.getPath(route), handle)
|
||||
}
|
||||
|
||||
override shouldAttach(route: ActivatedRouteSnapshot): boolean {
|
||||
return !!this.handlers.get(this.getPath(route))
|
||||
}
|
||||
|
||||
override retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null {
|
||||
return this.handlers.get(this.getPath(route)) || null
|
||||
}
|
||||
|
||||
override shouldReuseRoute(
|
||||
future: ActivatedRouteSnapshot,
|
||||
curr: ActivatedRouteSnapshot,
|
||||
): boolean {
|
||||
// return future.routeConfig === curr.routeConfig
|
||||
// TODO: Copied from ionic for backwards compatibility, remove later
|
||||
if (future.routeConfig !== curr.routeConfig) {
|
||||
return false
|
||||
}
|
||||
|
||||
// checking router params
|
||||
const futureParams = future.params
|
||||
const currentParams = curr.params
|
||||
const keysA = Object.keys(futureParams)
|
||||
const keysB = Object.keys(currentParams)
|
||||
if (keysA.length !== keysB.length) {
|
||||
return false
|
||||
}
|
||||
// Test for A's keys different from B.
|
||||
for (const key of keysA) {
|
||||
if (currentParams[key] !== futureParams[key]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private getPath(route: ActivatedRouteSnapshot): string {
|
||||
return this.url.serialize(createUrlTreeFromSnapshot(route, ['.']))
|
||||
}
|
||||
}
|
||||
@@ -382,6 +382,7 @@ ul {
|
||||
|
||||
.g-table {
|
||||
width: 100%;
|
||||
min-width: 40rem;
|
||||
|
||||
td,
|
||||
th {
|
||||
@@ -467,3 +468,8 @@ button.g-action {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.g-hidden-scrollbar {
|
||||
@include scrollbar-hidden;
|
||||
overflow: auto !important;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user