mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-31 04:23:40 +00:00
chore: enable strict mode (#1569)
* chore: enable strict mode * refactor: remove sync data access from PatchDbService * launchable even when no LAN url Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<h1>
|
||||
<ion-text color="warning">Warning</ion-text>
|
||||
</h1>
|
||||
<div class="ion-text-left" [innerHTML]="params.message | markdown"></div>
|
||||
<div class="ion-text-left" [innerHTML]="params.message || '' | markdown"></div>
|
||||
|
||||
@@ -7,9 +7,8 @@ import { BaseSlide } from '../wizard-types'
|
||||
styleUrls: ['../app-wizard.component.scss'],
|
||||
})
|
||||
export class AlertComponent implements BaseSlide {
|
||||
@Input() params: {
|
||||
message: string
|
||||
}
|
||||
@Input()
|
||||
params!: { message: string }
|
||||
|
||||
async load() {}
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ SwiperCore.use([IonicSlides])
|
||||
styleUrls: ['./app-wizard.component.scss'],
|
||||
})
|
||||
export class AppWizardComponent {
|
||||
@Input() params: {
|
||||
@Input()
|
||||
params!: {
|
||||
action: WizardAction
|
||||
title: string
|
||||
slides: SlideDefinition[]
|
||||
@@ -31,16 +32,17 @@ export class AppWizardComponent {
|
||||
}
|
||||
|
||||
// content container so we can scroll to top between slide transitions
|
||||
@ViewChild(IonContent) content: IonContent
|
||||
@ViewChild(IonContent)
|
||||
content?: IonContent
|
||||
|
||||
swiper: Swiper
|
||||
swiper?: Swiper
|
||||
|
||||
//a slide component gives us hook into a slide. Allows us to call load when slide comes into view
|
||||
@ViewChildren('components')
|
||||
slideComponentsQL: QueryList<BaseSlide>
|
||||
slideComponentsQL?: QueryList<BaseSlide>
|
||||
|
||||
get slideComponents(): BaseSlide[] {
|
||||
return this.slideComponentsQL.toArray()
|
||||
return this.slideComponentsQL?.toArray() || []
|
||||
}
|
||||
|
||||
get currentSlide(): BaseSlide {
|
||||
@@ -48,7 +50,7 @@ export class AppWizardComponent {
|
||||
}
|
||||
|
||||
get currentIndex(): number {
|
||||
return this.swiper.activeIndex
|
||||
return this.swiper?.activeIndex || NaN
|
||||
}
|
||||
|
||||
initializing = true
|
||||
@@ -58,7 +60,7 @@ export class AppWizardComponent {
|
||||
|
||||
ionViewDidEnter() {
|
||||
this.initializing = false
|
||||
this.swiper.allowTouchMove = false
|
||||
if (this.swiper) this.swiper.allowTouchMove = false
|
||||
this.loadSlide()
|
||||
}
|
||||
|
||||
@@ -71,8 +73,8 @@ export class AppWizardComponent {
|
||||
}
|
||||
|
||||
async next() {
|
||||
await this.content.scrollToTop()
|
||||
this.swiper.slideNext(500)
|
||||
await this.content?.scrollToTop()
|
||||
this.swiper?.slideNext(500)
|
||||
}
|
||||
|
||||
setError(e: any) {
|
||||
|
||||
@@ -8,7 +8,8 @@ import { BaseSlide } from '../wizard-types'
|
||||
styleUrls: ['../app-wizard.component.scss'],
|
||||
})
|
||||
export class CompleteComponent implements BaseSlide {
|
||||
@Input() params: {
|
||||
@Input()
|
||||
params!: {
|
||||
verb: string // loader verb: '*stopping* ...'
|
||||
title: string
|
||||
Fn: () => Promise<any>
|
||||
@@ -17,13 +18,13 @@ export class CompleteComponent implements BaseSlide {
|
||||
@Output() onSuccess: EventEmitter<void> = new EventEmitter()
|
||||
@Output() onError: EventEmitter<string> = new EventEmitter()
|
||||
|
||||
message: string
|
||||
message = ''
|
||||
|
||||
loading = true
|
||||
|
||||
async load() {
|
||||
this.message =
|
||||
capitalizeFirstLetter(this.params.verb) + ' ' + this.params.title
|
||||
capitalizeFirstLetter(this.params.verb || '') + ' ' + this.params.title
|
||||
try {
|
||||
await this.params.Fn()
|
||||
this.onSuccess.emit()
|
||||
|
||||
@@ -10,7 +10,8 @@ import { BaseSlide } from '../wizard-types'
|
||||
styleUrls: ['./dependents.component.scss', '../app-wizard.component.scss'],
|
||||
})
|
||||
export class DependentsComponent implements BaseSlide {
|
||||
@Input() params: {
|
||||
@Input()
|
||||
params!: {
|
||||
title: string
|
||||
verb: string // *Uninstalling* will cause problems...
|
||||
Fn: () => Promise<Breakages>
|
||||
@@ -19,21 +20,21 @@ export class DependentsComponent implements BaseSlide {
|
||||
@Output() onSuccess: EventEmitter<void> = new EventEmitter()
|
||||
@Output() onError: EventEmitter<string> = new EventEmitter()
|
||||
|
||||
breakages: Breakages
|
||||
warningMessage: string | undefined
|
||||
breakages?: Breakages
|
||||
warningMessage = ''
|
||||
|
||||
loading = true
|
||||
|
||||
readonly pkgs$ = this.patch.watch$('package-data')
|
||||
|
||||
constructor(public readonly patch: PatchDbService) {}
|
||||
constructor(private readonly patch: PatchDbService) {}
|
||||
|
||||
async load() {
|
||||
try {
|
||||
this.breakages = await this.params.Fn()
|
||||
if (this.breakages && !isEmptyObject(this.breakages)) {
|
||||
this.warningMessage =
|
||||
capitalizeFirstLetter(this.params.verb) +
|
||||
capitalizeFirstLetter(this.params.verb || '') +
|
||||
' ' +
|
||||
this.params.title +
|
||||
' will prohibit the following services from functioning properly.'
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
type === 'create' ? 'Create Backup' : 'Restore From Backup'
|
||||
}}</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<ion-button [disabled]="backupService.loading" (click)="refresh()">
|
||||
<ion-button [disabled]="loading" (click)="refresh()">
|
||||
Refresh
|
||||
<ion-icon slot="end" name="refresh"></ion-icon>
|
||||
</ion-button>
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
<ion-content class="ion-padding">
|
||||
<!-- loading -->
|
||||
<text-spinner
|
||||
*ngIf="backupService.loading; else loaded"
|
||||
*ngIf="loading; else loaded"
|
||||
[text]="loadingText"
|
||||
></text-spinner>
|
||||
|
||||
<!-- loaded -->
|
||||
<ng-template #loaded>
|
||||
<!-- error -->
|
||||
<ion-item *ngIf="backupService.loadingError; else noError">
|
||||
<ion-item *ngIf="loadingError; else noError">
|
||||
<ion-label>
|
||||
<ion-text color="danger">
|
||||
{{ backupService.loadingError }}
|
||||
{{ loadingError }}
|
||||
</ion-text>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
@@ -49,7 +49,7 @@
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<!-- cifs list -->
|
||||
<ng-container *ngFor="let target of backupService.cifs; let i = index">
|
||||
<ng-container *ngFor="let target of cifs; let i = index">
|
||||
<ion-item
|
||||
button
|
||||
*ngIf="target.entry as cifs"
|
||||
@@ -91,7 +91,7 @@
|
||||
<ion-item-divider>Physical Drives</ion-item-divider>
|
||||
<!-- no drives -->
|
||||
<ion-item
|
||||
*ngIf="!backupService.drives.length; else hasDrives"
|
||||
*ngIf="!drives.length; else hasDrives"
|
||||
class="ion-padding-bottom"
|
||||
>
|
||||
<ion-label>
|
||||
@@ -119,7 +119,7 @@
|
||||
<ng-template #hasDrives>
|
||||
<ion-item
|
||||
button
|
||||
*ngFor="let target of backupService.drives"
|
||||
*ngFor="let target of drives"
|
||||
(click)="select(target)"
|
||||
>
|
||||
<ion-icon slot="start" name="save-outline" size="large"></ion-icon>
|
||||
|
||||
@@ -25,11 +25,11 @@ type BackupType = 'create' | 'restore'
|
||||
styleUrls: ['./backup-drives.component.scss'],
|
||||
})
|
||||
export class BackupDrivesComponent {
|
||||
@Input() type: BackupType
|
||||
@Input() type!: BackupType
|
||||
@Output() onSelect: EventEmitter<
|
||||
MappedBackupTarget<CifsBackupTarget | DiskBackupTarget>
|
||||
> = new EventEmitter()
|
||||
loadingText: string
|
||||
loadingText = ''
|
||||
|
||||
constructor(
|
||||
private readonly loadingCtrl: LoadingController,
|
||||
@@ -38,9 +38,25 @@ export class BackupDrivesComponent {
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly embassyApi: ApiService,
|
||||
private readonly errToast: ErrorToastService,
|
||||
public readonly backupService: BackupService,
|
||||
private readonly backupService: BackupService,
|
||||
) {}
|
||||
|
||||
get loading() {
|
||||
return this.backupService.loading
|
||||
}
|
||||
|
||||
get loadingError() {
|
||||
return this.backupService.loadingError
|
||||
}
|
||||
|
||||
get drives() {
|
||||
return this.backupService.drives
|
||||
}
|
||||
|
||||
get cifs() {
|
||||
return this.backupService.cifs
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.loadingText =
|
||||
this.type === 'create'
|
||||
@@ -234,10 +250,14 @@ export class BackupDrivesComponent {
|
||||
styleUrls: ['./backup-drives.component.scss'],
|
||||
})
|
||||
export class BackupDrivesHeaderComponent {
|
||||
@Input() type: BackupType
|
||||
@Input() type!: BackupType
|
||||
@Output() onClose: EventEmitter<void> = new EventEmitter()
|
||||
|
||||
constructor(public readonly backupService: BackupService) {}
|
||||
constructor(private readonly backupService: BackupService) {}
|
||||
|
||||
get loading() {
|
||||
return this.backupService.loading
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.backupService.getBackupTargets()
|
||||
@@ -250,8 +270,8 @@ export class BackupDrivesHeaderComponent {
|
||||
styleUrls: ['./backup-drives.component.scss'],
|
||||
})
|
||||
export class BackupDrivesStatusComponent {
|
||||
@Input() type: string
|
||||
@Input() hasValidBackup: boolean
|
||||
@Input() type!: BackupType
|
||||
@Input() hasValidBackup!: boolean
|
||||
}
|
||||
|
||||
const CifsSpec: ConfigSpec = {
|
||||
|
||||
@@ -13,10 +13,10 @@ import { getErrorMessage, Emver } from '@start9labs/shared'
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class BackupService {
|
||||
cifs: MappedBackupTarget<CifsBackupTarget>[]
|
||||
drives: MappedBackupTarget<DiskBackupTarget>[]
|
||||
cifs: MappedBackupTarget<CifsBackupTarget>[] = []
|
||||
drives: MappedBackupTarget<DiskBackupTarget>[] = []
|
||||
loading = true
|
||||
loadingError: string | IonicSafeString
|
||||
loadingError: string | IonicSafeString = ''
|
||||
|
||||
constructor(
|
||||
private readonly embassyApi: ApiService,
|
||||
|
||||
@@ -8,32 +8,30 @@ import { combineLatest, Subscription } from 'rxjs'
|
||||
templateUrl: './badge-menu.component.html',
|
||||
styleUrls: ['./badge-menu.component.scss'],
|
||||
})
|
||||
|
||||
export class BadgeMenuComponent {
|
||||
unreadCount: number
|
||||
sidebarOpen: boolean
|
||||
unreadCount = 0
|
||||
sidebarOpen = false
|
||||
|
||||
subs: Subscription[] = []
|
||||
|
||||
constructor (
|
||||
constructor(
|
||||
private readonly splitPane: SplitPaneTracker,
|
||||
private readonly patch: PatchDbService,
|
||||
) { }
|
||||
) {}
|
||||
|
||||
ngOnInit () {
|
||||
ngOnInit() {
|
||||
this.subs = [
|
||||
combineLatest([
|
||||
this.patch.watch$('server-info', 'unread-notification-count'),
|
||||
this.splitPane.sidebarOpen$,
|
||||
])
|
||||
.subscribe(([unread, menu]) => {
|
||||
]).subscribe(([unread, menu]) => {
|
||||
this.unreadCount = unread
|
||||
this.sidebarOpen = menu
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
ngOnDestroy() {
|
||||
this.subs.forEach(sub => sub.unsubscribe())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
(['string', 'number'] | includes: data.spec.type) &&
|
||||
!$any(data.spec).nullable
|
||||
"
|
||||
> *</span
|
||||
>
|
||||
*
|
||||
</span>
|
||||
|
||||
<span *ngIf="data.spec.type === 'list' && Range.from(data.spec.range).min"
|
||||
> *</span
|
||||
|
||||
@@ -35,8 +35,8 @@ interface Config {
|
||||
styleUrls: ['./form-object.component.scss'],
|
||||
})
|
||||
export class FormObjectComponent {
|
||||
@Input() objectSpec: ConfigSpec
|
||||
@Input() formGroup: FormGroup
|
||||
@Input() objectSpec!: ConfigSpec
|
||||
@Input() formGroup!: FormGroup
|
||||
@Input() unionSpec?: ValueSpecUnion
|
||||
@Input() current?: Config
|
||||
@Input() original?: Config
|
||||
@@ -396,7 +396,7 @@ interface HeaderData {
|
||||
})
|
||||
export class FormLabelComponent {
|
||||
Range = Range
|
||||
@Input() data: HeaderData
|
||||
@Input() data!: HeaderData
|
||||
|
||||
constructor(private readonly alertCtrl: AlertController) {}
|
||||
|
||||
@@ -424,6 +424,6 @@ export class FormLabelComponent {
|
||||
styleUrls: ['./form-object.component.scss'],
|
||||
})
|
||||
export class FormErrorComponent {
|
||||
@Input() control: AbstractFormGroupDirective
|
||||
@Input() spec: ValueSpec
|
||||
@Input() control!: AbstractFormGroupDirective
|
||||
@Input() spec!: ValueSpec
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*ngIf="!loading && needInfinite"
|
||||
position="top"
|
||||
threshold="0"
|
||||
(ionInfinite)="loadData($event)"
|
||||
(ionInfinite)="doInfinite($event)"
|
||||
>
|
||||
<ion-infinite-scroll-content
|
||||
loadingSpinner="lines"
|
||||
@@ -25,11 +25,11 @@
|
||||
></div>
|
||||
</div>
|
||||
<div id="button-div" *ngIf="!loading" style="width: 100%; text-align: center">
|
||||
<ion-button *ngIf="!loadingMore" (click)="loadMore()" strong color="dark">
|
||||
<ion-button *ngIf="!loadingNext" (click)="getNext()" strong color="dark">
|
||||
Load More
|
||||
<ion-icon slot="end" name="refresh"></ion-icon>
|
||||
</ion-button>
|
||||
<ion-spinner *ngIf="loadingMore" name="lines" color="warning"></ion-spinner>
|
||||
<ion-spinner *ngIf="loadingNext" name="lines" color="warning"></ion-spinner>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
||||
@@ -17,29 +17,91 @@ var convert = new Convert({
|
||||
styleUrls: ['./logs.page.scss'],
|
||||
})
|
||||
export class LogsPage {
|
||||
@ViewChild(IonContent) private content: IonContent
|
||||
@Input() fetchLogs: (params: {
|
||||
@ViewChild(IonContent)
|
||||
private content?: IonContent
|
||||
|
||||
@Input()
|
||||
fetchLogs!: (params: {
|
||||
before_flag?: boolean
|
||||
limit?: number
|
||||
cursor?: string
|
||||
}) => Promise<RR.LogsRes>
|
||||
|
||||
loading = true
|
||||
loadingMore = false
|
||||
logs: string
|
||||
loadingNext = false
|
||||
needInfinite = true
|
||||
startCursor: string
|
||||
endCursor: string
|
||||
limit = 200
|
||||
scrollToBottomButton = false
|
||||
startCursor?: string
|
||||
endCursor?: string
|
||||
limit = 400
|
||||
isOnBottom = true
|
||||
|
||||
constructor(private readonly errToast: ErrorToastService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.getLogs()
|
||||
async ngOnInit() {
|
||||
await this.getPrior()
|
||||
this.loading = false
|
||||
}
|
||||
|
||||
async fetch(isBefore: boolean = true) {
|
||||
async getNext() {
|
||||
this.loadingNext = true
|
||||
const logs = await this.fetch(false)
|
||||
if (!logs?.length) return (this.loadingNext = false)
|
||||
|
||||
const container = document.getElementById('container')
|
||||
const newLogs = document.getElementById('template')?.cloneNode(true)
|
||||
|
||||
if (!(newLogs instanceof HTMLElement)) return
|
||||
|
||||
newLogs.innerHTML =
|
||||
logs.map(l => `${l.timestamp} ${convert.toHtml(l.message)}`).join('\n') +
|
||||
(logs.length ? '\n' : '')
|
||||
container?.append(newLogs)
|
||||
this.loadingNext = false
|
||||
this.scrollEvent()
|
||||
}
|
||||
|
||||
async doInfinite(e: any): Promise<void> {
|
||||
await this.getPrior()
|
||||
e.target.complete()
|
||||
}
|
||||
|
||||
scrollEvent() {
|
||||
const buttonDiv = document.getElementById('button-div')
|
||||
this.isOnBottom =
|
||||
!!buttonDiv && buttonDiv.getBoundingClientRect().top < window.innerHeight
|
||||
}
|
||||
|
||||
scrollToBottom() {
|
||||
this.content?.scrollToBottom(500)
|
||||
}
|
||||
|
||||
private async getPrior() {
|
||||
// get logs
|
||||
const logs = await this.fetch()
|
||||
if (!logs?.length) return
|
||||
|
||||
const container = document.getElementById('container')
|
||||
const beforeContainerHeight = container?.scrollHeight || 0
|
||||
const newLogs = document.getElementById('template')?.cloneNode(true)
|
||||
|
||||
if (!(newLogs instanceof HTMLElement)) return
|
||||
|
||||
newLogs.innerHTML =
|
||||
logs.map(l => `${l.timestamp} ${convert.toHtml(l.message)}`).join('\n') +
|
||||
(logs.length ? '\n' : '')
|
||||
container?.prepend(newLogs)
|
||||
const afterContainerHeight = container?.scrollHeight || 0
|
||||
|
||||
// scroll down
|
||||
scrollBy(0, afterContainerHeight - beforeContainerHeight)
|
||||
this.content?.scrollToPoint(0, afterContainerHeight - beforeContainerHeight)
|
||||
|
||||
if (logs.length < this.limit) {
|
||||
this.needInfinite = false
|
||||
}
|
||||
}
|
||||
|
||||
private async fetch(isBefore: boolean = true) {
|
||||
try {
|
||||
const cursor = isBefore ? this.startCursor : this.endCursor
|
||||
const logsRes = await this.fetchLogs({
|
||||
@@ -55,79 +117,10 @@ export class LogsPage {
|
||||
if ((!isBefore || !this.endCursor) && logsRes['end-cursor']) {
|
||||
this.endCursor = logsRes['end-cursor']
|
||||
}
|
||||
this.loading = false
|
||||
|
||||
return logsRes.entries
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
}
|
||||
}
|
||||
|
||||
async getLogs() {
|
||||
try {
|
||||
// get logs
|
||||
const logs = await this.fetch()
|
||||
if (!logs?.length) return
|
||||
|
||||
const container = document.getElementById('container')
|
||||
const beforeContainerHeight = container?.scrollHeight || 0
|
||||
const newLogs = document.getElementById('template')?.cloneNode(true)
|
||||
|
||||
if (!(newLogs instanceof HTMLElement)) return
|
||||
|
||||
newLogs.innerHTML =
|
||||
logs
|
||||
.map(l => `${l.timestamp} ${convert.toHtml(l.message)}`)
|
||||
.join('\n') + (logs.length ? '\n' : '')
|
||||
container?.prepend(newLogs)
|
||||
const afterContainerHeight = container?.scrollHeight || 0
|
||||
|
||||
// scroll down
|
||||
scrollBy(0, afterContainerHeight - beforeContainerHeight)
|
||||
this.content.scrollToPoint(
|
||||
0,
|
||||
afterContainerHeight - beforeContainerHeight,
|
||||
)
|
||||
|
||||
if (logs.length < this.limit) {
|
||||
this.needInfinite = false
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
async loadMore() {
|
||||
try {
|
||||
this.loadingMore = true
|
||||
const logs = await this.fetch(false)
|
||||
if (!logs?.length) return (this.loadingMore = false)
|
||||
|
||||
const container = document.getElementById('container')
|
||||
const newLogs = document.getElementById('template')?.cloneNode(true)
|
||||
|
||||
if (!(newLogs instanceof HTMLElement)) return
|
||||
|
||||
newLogs.innerHTML =
|
||||
logs
|
||||
.map(l => `${l.timestamp} ${convert.toHtml(l.message)}`)
|
||||
.join('\n') + (logs.length ? '\n' : '')
|
||||
container?.append(newLogs)
|
||||
this.loadingMore = false
|
||||
this.scrollEvent()
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
scrollEvent() {
|
||||
const buttonDiv = document.getElementById('button-div')
|
||||
this.isOnBottom =
|
||||
!!buttonDiv && buttonDiv.getBoundingClientRect().top < window.innerHeight
|
||||
}
|
||||
|
||||
scrollToBottom() {
|
||||
this.content.scrollToBottom(500)
|
||||
}
|
||||
|
||||
async loadData(e: any): Promise<void> {
|
||||
await this.getLogs()
|
||||
e.target.complete()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,5 +6,5 @@ import { Component, Input } from '@angular/core'
|
||||
styleUrls: ['./qr.component.scss'],
|
||||
})
|
||||
export class QRComponent {
|
||||
@Input() text: string
|
||||
@Input() text!: string
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
import { Component, Input } from '@angular/core'
|
||||
import { Component, Input, OnChanges } from '@angular/core'
|
||||
|
||||
@Component({
|
||||
selector: 'skeleton-list',
|
||||
templateUrl: './skeleton-list.component.html',
|
||||
styleUrls: ['./skeleton-list.component.scss'],
|
||||
})
|
||||
export class SkeletonListComponent {
|
||||
@Input() groups: string
|
||||
@Input() rows: string = '3'
|
||||
export class SkeletonListComponent implements OnChanges {
|
||||
@Input() groups = 0
|
||||
@Input() rows = 3
|
||||
groupsArr: number[] = []
|
||||
rowsArr: number[] = []
|
||||
|
||||
ngOnInit () {
|
||||
if (this.groups) {
|
||||
this.groupsArr = Array(Number(this.groups)).fill(0).map((_, i) => i)
|
||||
}
|
||||
this.rowsArr = Array(Number(this.rows)).fill(0).map((_, i) => i)
|
||||
ngOnChanges() {
|
||||
this.groupsArr = Array(this.groups).fill(0)
|
||||
this.rowsArr = Array(this.rows).fill(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export class StatusComponent {
|
||||
PS = PrimaryStatus
|
||||
PR = PrimaryRendering
|
||||
|
||||
@Input() rendering: StatusRendering
|
||||
@Input() rendering!: StatusRendering
|
||||
@Input() size?: string
|
||||
@Input() style?: string = 'regular'
|
||||
@Input() weight?: string = 'normal'
|
||||
|
||||
Reference in New Issue
Block a user