RSS Git Download  Clone
Raw Blame History 5kB 133 lines
import { Component, Inject, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatToolbarModule } from '@angular/material/toolbar';
import { DialogCancelButtonComponent } from '../components/dialog-cancel-button.component';
import { I18nService } from '../services/i18n.service';
import { CommonService } from '../services/common.service';
import { SettingsService } from '../services/settings.service';

const timestring = require('timestring');
const humanizeDuration = require('humanize-duration');

export interface TtlDialogData {
    model: { ttl: number };
}

/**
 * TTL dialog — Angular replacement for p3xrDialogTtl.
 * Edits TTL value with number input and human-readable timestring input.
 */
@Component({
    selector: 'p3xr-ttl-dialog',
    standalone: true,
    imports: [
        CommonModule, FormsModule,
        MatDialogModule, MatFormFieldModule, MatInputModule,
        MatButtonModule, MatIconModule, MatToolbarModule,
        DialogCancelButtonComponent,
    ],
    template: `
        <form (ngSubmit)="submit()" novalidate>
            <mat-toolbar class="p3xr-dialog-toolbar p3xr-mat-layout-strong">
                <span mat-dialog-title class="p3xr-dialog-title">
                    {{ strings().confirm?.ttl?.title || 'TTL' }}
                </span>
                <button mat-icon-button type="button" (click)="cancel()">
                    <mat-icon>close</mat-icon>
                </button>
            </mat-toolbar>

            <mat-dialog-content class="p3xr-dialog-content">
                <div>{{ strings().confirm?.ttl?.textContent }}</div>

                <mat-form-field class="full-width">
                    <mat-label>{{ strings().confirm?.ttl?.placeholder || 'TTL (seconds)' }}</mat-label>
                    <input matInput type="number" name="ttl" [(ngModel)]="model.ttl" min="-1"
                           [placeholder]="strings().confirm?.ttl?.placeholderPlaceholder || '-1'" />
                </mat-form-field>

                <mat-form-field class="full-width">
                    <mat-label>{{ strings().confirm?.ttl?.convertTextToTime || 'Duration' }}</mat-label>
                    <input matInput name="convertTextToTime" [(ngModel)]="convertTextToTime"
                           (ngModelChange)="onTextTimeChange($event)"
                           [placeholder]="strings().confirm?.ttl?.convertTextToTimePlaceholder || '1h 30m'" />
                </mat-form-field>

                <button mat-button class="btn-accent p3xr-timestring-link" type="button" (click)="openTimestringNpm()">
                    https://www.npmjs.com/package/timestring
                </button>
            </mat-dialog-content>

            <mat-dialog-actions class="p3xr-dialog-actions">
                <p3xr-dialog-cancel (cancel)="cancel()"></p3xr-dialog-cancel>
                <button mat-raised-button class="btn-primary" type="submit">
                    <mat-icon>timer</mat-icon>
                    {{ strings().intention?.ttl || 'Set TTL' }}
                </button>
            </mat-dialog-actions>
        </form>
    `,
    styles: [`
        .full-width { width: 100%; }
    `],
})
export class TtlDialogComponent implements OnInit {
    model: { ttl: number } = { ttl: -1 };
    convertTextToTime = '';
    strings;

    constructor(
        @Inject(MatDialogRef) private dialogRef: MatDialogRef<TtlDialogComponent>,
        @Inject(MAT_DIALOG_DATA) private data: TtlDialogData,
        @Inject(I18nService) private i18n: I18nService,
        @Inject(CommonService) private common: CommonService,
        @Inject(SettingsService) private settingsService: SettingsService,
    ) {
        this.strings = this.i18n.strings;
    }

    ngOnInit(): void {
        this.model = { ...this.data.model };
        if (typeof this.model.ttl === 'number' && this.model.ttl > 0) {
            try {
                const hdOpts = this.settingsService.getHumanizeDurationOptions();
                this.convertTextToTime = humanizeDuration(this.model.ttl * 1000, {
                    ...hdOpts,
                    delimiter: ' ',
                });
            } catch (e) {
                this.convertTextToTime = '';
            }
        }
    }

    onTextTimeChange(value: string): void {
        try {
            this.model.ttl = timestring(String(value), 's');
        } catch (e) {
            console.warn('timestring parse error', e);
        }
    }

    openTimestringNpm(): void {
        window.open('https://www.npmjs.com/package/timestring#keywords', '_blank');
    }

    submit(): void {
        if (isNaN(this.model.ttl)) {
            this.model.ttl = Math.round(this.model.ttl);
        }
        this.dialogRef.close({ model: this.model });
    }

    cancel(): void {
        this.dialogRef.close(undefined);
    }
}