mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-31 04:23:40 +00:00
display bottom item in backup list and refactor for cleanliness (#1609)
* display bottom item in backup list and refactor for cleanliness * fix spelling mistake * display initial toggle to deselect all, as all are selected by default * add select/deselect all to backup restore and handle backup case when no services intalled Co-authored-by: Lucy Cifferello <12953208+elvece@users.noreply.github.com>
This commit is contained in:
@@ -3,7 +3,9 @@
|
|||||||
<ion-buttons slot="start">
|
<ion-buttons slot="start">
|
||||||
<ion-back-button defaultHref="embassy"></ion-back-button>
|
<ion-back-button defaultHref="embassy"></ion-back-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>{{ title }}</ion-title>
|
<ion-title>{{
|
||||||
|
type === 'create' ? 'Create Backup' : 'Restore From Backup'
|
||||||
|
}}</ion-title>
|
||||||
<ion-buttons slot="end">
|
<ion-buttons slot="end">
|
||||||
<ion-button [disabled]="backupService.loading" (click)="refresh()">
|
<ion-button [disabled]="backupService.loading" (click)="refresh()">
|
||||||
Refresh
|
Refresh
|
||||||
@@ -11,4 +13,4 @@
|
|||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|||||||
@@ -1,137 +1,145 @@
|
|||||||
<!-- loading -->
|
<backup-drives-header [type]="type"></backup-drives-header>
|
||||||
<text-spinner
|
|
||||||
*ngIf="backupService.loading; else loaded"
|
|
||||||
[text]="loadingText"
|
|
||||||
></text-spinner>
|
|
||||||
|
|
||||||
<!-- loaded -->
|
<ion-content class="ion-padding">
|
||||||
<ng-template #loaded>
|
<!-- loading -->
|
||||||
<!-- error -->
|
<text-spinner
|
||||||
<ion-item *ngIf="backupService.loadingError; else noError">
|
*ngIf="backupService.loading; else loaded"
|
||||||
<ion-label>
|
[text]="loadingText"
|
||||||
<ion-text color="danger">
|
></text-spinner>
|
||||||
{{ backupService.loadingError }}
|
|
||||||
</ion-text>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ng-template #noError>
|
<!-- loaded -->
|
||||||
<ion-item-group>
|
<ng-template #loaded>
|
||||||
<!-- ** cifs ** -->
|
<!-- error -->
|
||||||
<ion-item-divider>LAN Shared Folders</ion-item-divider>
|
<ion-item *ngIf="backupService.loadingError; else noError">
|
||||||
<ion-item>
|
<ion-label>
|
||||||
<ion-label>
|
<ion-text color="danger">
|
||||||
<h2>
|
{{ backupService.loadingError }}
|
||||||
LAN Shared Folders are the recommended way to create Embassy
|
</ion-text>
|
||||||
backups. View the
|
</ion-label>
|
||||||
<a
|
</ion-item>
|
||||||
href="https://start9.com/latest/user-manual/backups/cifs-setup"
|
|
||||||
target="_blank"
|
<ng-template #noError>
|
||||||
noreferrer
|
<ion-item-group>
|
||||||
>Instructions</a
|
<!-- ** cifs ** -->
|
||||||
>
|
<ion-item-divider>LAN Shared Folders</ion-item-divider>
|
||||||
</h2>
|
<ion-item>
|
||||||
</ion-label>
|
<ion-label>
|
||||||
</ion-item>
|
<h2>
|
||||||
<!-- add new cifs -->
|
LAN Shared Folders are the recommended way to create Embassy
|
||||||
<ion-item button detail="false" (click)="presentModalAddCifs()">
|
backups. View the
|
||||||
<ion-icon
|
<a
|
||||||
slot="start"
|
href="https://start9.com/latest/user-manual/backups/cifs-setup"
|
||||||
name="folder-open-outline"
|
target="_blank"
|
||||||
size="large"
|
noreferrer
|
||||||
color="dark"
|
>Instructions</a
|
||||||
></ion-icon>
|
>
|
||||||
<ion-label>
|
</h2>
|
||||||
<b>Open New</b>
|
</ion-label>
|
||||||
</ion-label>
|
</ion-item>
|
||||||
</ion-item>
|
<!-- add new cifs -->
|
||||||
<!-- cifs list -->
|
<ion-item button detail="false" (click)="presentModalAddCifs()">
|
||||||
<ng-container *ngFor="let target of backupService.cifs; let i = index">
|
|
||||||
<ion-item button *ngIf="target.entry as cifs" (click)="select(target)">
|
|
||||||
<ion-icon
|
<ion-icon
|
||||||
slot="start"
|
slot="start"
|
||||||
name="folder-open-outline"
|
name="folder-open-outline"
|
||||||
size="large"
|
size="large"
|
||||||
|
color="dark"
|
||||||
></ion-icon>
|
></ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h1>{{ cifs.path.split('/').pop() }}</h1>
|
<b>Open New</b>
|
||||||
<ng-container *ngIf="cifs.mountable">
|
|
||||||
<backup-drives-status
|
|
||||||
[type]="type"
|
|
||||||
[hasValidBackup]="target.hasValidBackup"
|
|
||||||
></backup-drives-status>
|
|
||||||
</ng-container>
|
|
||||||
<h2 *ngIf="!cifs.mountable" class="inline">
|
|
||||||
<ion-icon name="cellular-outline" color="danger"></ion-icon>
|
|
||||||
Unable to connect
|
|
||||||
</h2>
|
|
||||||
<p>Hostname: {{ cifs.hostname }}</p>
|
|
||||||
<p>Path: {{ cifs.path }}</p>
|
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-note
|
</ion-item>
|
||||||
slot="end"
|
<!-- cifs list -->
|
||||||
class="click-area"
|
<ng-container *ngFor="let target of backupService.cifs; let i = index">
|
||||||
(click)="presentActionCifs($event, target, i)"
|
<ion-item
|
||||||
|
button
|
||||||
|
*ngIf="target.entry as cifs"
|
||||||
|
(click)="select(target)"
|
||||||
>
|
>
|
||||||
<ion-icon name="ellipsis-horizontal"></ion-icon>
|
<ion-icon
|
||||||
</ion-note>
|
slot="start"
|
||||||
</ion-item>
|
name="folder-open-outline"
|
||||||
</ng-container>
|
size="large"
|
||||||
|
></ion-icon>
|
||||||
<br />
|
|
||||||
|
|
||||||
<!-- ** drives ** -->
|
|
||||||
<ion-item-divider>Physical Drives</ion-item-divider>
|
|
||||||
<!-- no drives -->
|
|
||||||
<ion-item
|
|
||||||
*ngIf="!backupService.drives.length; else hasDrives"
|
|
||||||
class="ion-padding-bottom"
|
|
||||||
>
|
|
||||||
<ion-label>
|
|
||||||
<h2>
|
|
||||||
<ion-text color="warning">
|
|
||||||
Warning! Plugging a 2nd physical drive directly into your Embassy
|
|
||||||
can lead to data corruption.
|
|
||||||
</ion-text>
|
|
||||||
To safely create a backup to a physical drive, view the
|
|
||||||
<a
|
|
||||||
href="https://start9.com/latest/user-manual/backups/backups-create/#backup-using-a-physical-drive"
|
|
||||||
target="_blank"
|
|
||||||
noreferrer
|
|
||||||
>instructions</a
|
|
||||||
>.
|
|
||||||
</h2>
|
|
||||||
<br />
|
|
||||||
<h2>
|
|
||||||
If your drive is plugged in and does not appear, try
|
|
||||||
<a (click)="refresh()" style="cursor: pointer">refreshing</a>.
|
|
||||||
</h2>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
<!-- drives detected -->
|
|
||||||
<ng-template #hasDrives>
|
|
||||||
<ion-item
|
|
||||||
button
|
|
||||||
*ngFor="let target of backupService.drives"
|
|
||||||
(click)="select(target)"
|
|
||||||
>
|
|
||||||
<ion-icon slot="start" name="save-outline" size="large"></ion-icon>
|
|
||||||
<ng-container *ngIf="target.entry as drive">
|
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h1>{{ drive.label || drive.logicalname }}</h1>
|
<h1>{{ cifs.path.split('/').pop() }}</h1>
|
||||||
<backup-drives-status
|
<ng-container *ngIf="cifs.mountable">
|
||||||
[type]="type"
|
<backup-drives-status
|
||||||
[hasValidBackup]="target.hasValidBackup"
|
[type]="type"
|
||||||
></backup-drives-status>
|
[hasValidBackup]="target.hasValidBackup"
|
||||||
<p>
|
></backup-drives-status>
|
||||||
{{ drive.vendor || 'Unknown Vendor' }} -
|
</ng-container>
|
||||||
{{ drive.model || 'Unknown Model' }}
|
<h2 *ngIf="!cifs.mountable" class="inline">
|
||||||
</p>
|
<ion-icon name="cellular-outline" color="danger"></ion-icon>
|
||||||
<p>Capacity: {{ drive.capacity | convertBytes }}</p>
|
Unable to connect
|
||||||
|
</h2>
|
||||||
|
<p>Hostname: {{ cifs.hostname }}</p>
|
||||||
|
<p>Path: {{ cifs.path }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ng-container>
|
<ion-note
|
||||||
|
slot="end"
|
||||||
|
class="click-area"
|
||||||
|
(click)="presentActionCifs($event, target, i)"
|
||||||
|
>
|
||||||
|
<ion-icon name="ellipsis-horizontal"></ion-icon>
|
||||||
|
</ion-note>
|
||||||
|
</ion-item>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<!-- ** drives ** -->
|
||||||
|
<ion-item-divider>Physical Drives</ion-item-divider>
|
||||||
|
<!-- no drives -->
|
||||||
|
<ion-item
|
||||||
|
*ngIf="!backupService.drives.length; else hasDrives"
|
||||||
|
class="ion-padding-bottom"
|
||||||
|
>
|
||||||
|
<ion-label>
|
||||||
|
<h2>
|
||||||
|
<ion-text color="warning">
|
||||||
|
Warning! Plugging a 2nd physical drive directly into your
|
||||||
|
Embassy can lead to data corruption.
|
||||||
|
</ion-text>
|
||||||
|
To safely create a backup to a physical drive, view the
|
||||||
|
<a
|
||||||
|
href="https://start9.com/latest/user-manual/backups/backups-create/#backup-using-a-physical-drive"
|
||||||
|
target="_blank"
|
||||||
|
noreferrer
|
||||||
|
>instructions</a
|
||||||
|
>.
|
||||||
|
</h2>
|
||||||
|
<br />
|
||||||
|
<h2>
|
||||||
|
If your drive is plugged in and does not appear, try
|
||||||
|
<a (click)="refresh()" style="cursor: pointer">refreshing</a>.
|
||||||
|
</h2>
|
||||||
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ng-template>
|
<!-- drives detected -->
|
||||||
</ion-item-group>
|
<ng-template #hasDrives>
|
||||||
|
<ion-item
|
||||||
|
button
|
||||||
|
*ngFor="let target of backupService.drives"
|
||||||
|
(click)="select(target)"
|
||||||
|
>
|
||||||
|
<ion-icon slot="start" name="save-outline" size="large"></ion-icon>
|
||||||
|
<ng-container *ngIf="target.entry as drive">
|
||||||
|
<ion-label>
|
||||||
|
<h1>{{ drive.label || drive.logicalname }}</h1>
|
||||||
|
<backup-drives-status
|
||||||
|
[type]="type"
|
||||||
|
[hasValidBackup]="target.hasValidBackup"
|
||||||
|
></backup-drives-status>
|
||||||
|
<p>
|
||||||
|
{{ drive.vendor || 'Unknown Vendor' }} -
|
||||||
|
{{ drive.model || 'Unknown Model' }}
|
||||||
|
</p>
|
||||||
|
<p>Capacity: {{ drive.capacity | convertBytes }}</p>
|
||||||
|
</ion-label>
|
||||||
|
</ng-container>
|
||||||
|
</ion-item>
|
||||||
|
</ng-template>
|
||||||
|
</ion-item-group>
|
||||||
|
</ng-template>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-template>
|
</ion-content>
|
||||||
|
|||||||
@@ -17,13 +17,15 @@ import { ApiService } from 'src/app/services/api/embassy-api.service'
|
|||||||
import { ErrorToastService } from '@start9labs/shared'
|
import { ErrorToastService } from '@start9labs/shared'
|
||||||
import { MappedBackupTarget } from 'src/app/types/mapped-backup-target'
|
import { MappedBackupTarget } from 'src/app/types/mapped-backup-target'
|
||||||
|
|
||||||
|
type BackupType = 'create' | 'restore'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'backup-drives',
|
selector: 'backup-drives',
|
||||||
templateUrl: './backup-drives.component.html',
|
templateUrl: './backup-drives.component.html',
|
||||||
styleUrls: ['./backup-drives.component.scss'],
|
styleUrls: ['./backup-drives.component.scss'],
|
||||||
})
|
})
|
||||||
export class BackupDrivesComponent {
|
export class BackupDrivesComponent {
|
||||||
@Input() type: 'create' | 'restore'
|
@Input() type: BackupType
|
||||||
@Output() onSelect: EventEmitter<
|
@Output() onSelect: EventEmitter<
|
||||||
MappedBackupTarget<CifsBackupTarget | DiskBackupTarget>
|
MappedBackupTarget<CifsBackupTarget | DiskBackupTarget>
|
||||||
> = new EventEmitter()
|
> = new EventEmitter()
|
||||||
@@ -232,7 +234,7 @@ export class BackupDrivesComponent {
|
|||||||
styleUrls: ['./backup-drives.component.scss'],
|
styleUrls: ['./backup-drives.component.scss'],
|
||||||
})
|
})
|
||||||
export class BackupDrivesHeaderComponent {
|
export class BackupDrivesHeaderComponent {
|
||||||
@Input() title: string
|
@Input() type: BackupType
|
||||||
@Output() onClose: EventEmitter<void> = new EventEmitter()
|
@Output() onClose: EventEmitter<void> = new EventEmitter()
|
||||||
|
|
||||||
constructor(public readonly backupService: BackupService) {}
|
constructor(public readonly backupService: BackupService) {}
|
||||||
|
|||||||
@@ -11,6 +11,13 @@
|
|||||||
|
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-item-group>
|
<ion-item-group>
|
||||||
|
<ion-item-divider>
|
||||||
|
<ion-buttons slot="end" style="padding-bottom: 6px">
|
||||||
|
<ion-button fill="clear" (click)="toggleSelectAll()">
|
||||||
|
<b>{{ selectAll ? 'Select All' : 'Deselect All' }}</b>
|
||||||
|
</ion-button>
|
||||||
|
</ion-buttons>
|
||||||
|
</ion-item-divider>
|
||||||
<ion-item *ngFor="let option of options">
|
<ion-item *ngFor="let option of options">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ option.title }}</h2>
|
<h2>{{ option.title }}</h2>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export class AppRecoverSelectPage {
|
|||||||
'newer-eos': boolean
|
'newer-eos': boolean
|
||||||
})[]
|
})[]
|
||||||
hasSelection = false
|
hasSelection = false
|
||||||
|
selectAll = true
|
||||||
error: string | IonicSafeString
|
error: string | IonicSafeString
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -62,6 +63,11 @@ export class AppRecoverSelectPage {
|
|||||||
this.hasSelection = this.options.some(o => o.checked)
|
this.hasSelection = this.options.some(o => o.checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleSelectAll() {
|
||||||
|
this.options.forEach(pkg => (pkg.checked = this.selectAll))
|
||||||
|
this.selectAll = !this.selectAll
|
||||||
|
}
|
||||||
|
|
||||||
async restore(): Promise<void> {
|
async restore(): Promise<void> {
|
||||||
const ids = this.options
|
const ids = this.options
|
||||||
.filter(option => !!option.checked)
|
.filter(option => !!option.checked)
|
||||||
|
|||||||
@@ -9,44 +9,50 @@
|
|||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content>
|
<div *ngIf="pkgs.length; else noServices">
|
||||||
<ion-item-group>
|
<ion-content>
|
||||||
<ion-item-divider>
|
<ion-item-group>
|
||||||
<ion-buttons slot="end" style="padding-bottom: 6px">
|
<ion-item-divider>
|
||||||
<ion-button fill="clear" (click)="toggleSelectAll()">
|
<ion-buttons slot="end" style="padding-bottom: 6px">
|
||||||
<b>{{ selectAll ? 'Select All' : 'Deselect All' }}</b>
|
<ion-button fill="clear" (click)="toggleSelectAll()">
|
||||||
|
<b>{{ selectAll ? 'Select All' : 'Deselect All' }}</b>
|
||||||
|
</ion-button>
|
||||||
|
</ion-buttons>
|
||||||
|
</ion-item-divider>
|
||||||
|
<ion-item *ngFor="let pkg of pkgs">
|
||||||
|
<ion-avatar slot="start">
|
||||||
|
<img alt="" [src]="pkg.icon" />
|
||||||
|
</ion-avatar>
|
||||||
|
<ion-label>
|
||||||
|
<h2>{{ pkg.title }}</h2>
|
||||||
|
</ion-label>
|
||||||
|
<ion-checkbox
|
||||||
|
slot="end"
|
||||||
|
[(ngModel)]="pkg.checked"
|
||||||
|
(ionChange)="handleChange()"
|
||||||
|
[disabled]="pkg.disabled"
|
||||||
|
></ion-checkbox>
|
||||||
|
</ion-item>
|
||||||
|
</ion-item-group>
|
||||||
|
</ion-content>
|
||||||
|
|
||||||
|
<ion-footer>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-buttons slot="end" class="ion-padding-end">
|
||||||
|
<ion-button
|
||||||
|
[disabled]="!hasSelection"
|
||||||
|
fill="solid"
|
||||||
|
color="primary"
|
||||||
|
(click)="dismiss(true)"
|
||||||
|
class="enter-click btn-128"
|
||||||
|
>
|
||||||
|
Back Up Selected
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
</ion-item-divider>
|
</ion-toolbar>
|
||||||
<ion-item *ngFor="let pkg of pkgs">
|
</ion-footer>
|
||||||
<ion-avatar slot="start">
|
</div>
|
||||||
<img alt="" [src]="pkg.icon" />
|
|
||||||
</ion-avatar>
|
|
||||||
<ion-label>
|
|
||||||
<h2>{{ pkg.title }}</h2>
|
|
||||||
</ion-label>
|
|
||||||
<ion-checkbox
|
|
||||||
slot="end"
|
|
||||||
[(ngModel)]="pkg.checked"
|
|
||||||
(ionChange)="handleChange()"
|
|
||||||
[disabled]="pkg.disabled"
|
|
||||||
></ion-checkbox>
|
|
||||||
</ion-item>
|
|
||||||
</ion-item-group>
|
|
||||||
</ion-content>
|
|
||||||
|
|
||||||
<ion-footer>
|
<ng-template #noServices>
|
||||||
<ion-toolbar>
|
<ion-content><h2 class="center">No services installed!</h2></ion-content>
|
||||||
<ion-buttons slot="end" class="ion-padding-end">
|
</ng-template>
|
||||||
<ion-button
|
|
||||||
[disabled]="!hasSelection"
|
|
||||||
fill="solid"
|
|
||||||
color="primary"
|
|
||||||
(click)="dismiss(true)"
|
|
||||||
class="enter-click btn-128"
|
|
||||||
>
|
|
||||||
Back Up Selected
|
|
||||||
</ion-button>
|
|
||||||
</ion-buttons>
|
|
||||||
</ion-toolbar>
|
|
||||||
</ion-footer>
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
|||||||
})
|
})
|
||||||
export class BackupSelectPage {
|
export class BackupSelectPage {
|
||||||
hasSelection = false
|
hasSelection = false
|
||||||
selectAll = true
|
selectAll = false
|
||||||
pkgs: {
|
pkgs: {
|
||||||
id: string
|
id: string
|
||||||
title: string
|
title: string
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<backup-drives-header title="Restore From Backup"></backup-drives-header>
|
<backup-drives
|
||||||
|
type="restore"
|
||||||
<ion-content class="ion-padding">
|
class="ion-page"
|
||||||
<backup-drives type="restore" (onSelect)="presentModalPassword($event)"></backup-drives>
|
(onSelect)="presentModalPassword($event)"
|
||||||
</ion-content>
|
></backup-drives>
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
<!-- currently backing up -->
|
<!-- currently backing up -->
|
||||||
<backing-up
|
<backing-up
|
||||||
*ngIf="backingUp$ | async; else notBackingUp"
|
*ngIf="backingUp$ | async; else notBackingUp"
|
||||||
style="height: 100%"
|
class="ion-page"
|
||||||
></backing-up>
|
></backing-up>
|
||||||
|
|
||||||
<!-- not backing up -->
|
<!-- not backing up -->
|
||||||
<ng-template #notBackingUp>
|
<ng-template #notBackingUp>
|
||||||
<backup-drives-header title="Create Backup"></backup-drives-header>
|
<backup-drives
|
||||||
<ion-content class="ion-padding">
|
type="create"
|
||||||
<backup-drives
|
class="ion-page"
|
||||||
type="create"
|
(onSelect)="presentModalSelect($event)"
|
||||||
(onSelect)="presentModalSelect($event)"
|
></backup-drives>
|
||||||
></backup-drives>
|
|
||||||
</ion-content>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export abstract class ApiService implements Source<DataModel>, Http<DataModel> {
|
|||||||
async updateServerWrapper(params: RR.UpdateServerReq) {
|
async updateServerWrapper(params: RR.UpdateServerReq) {
|
||||||
const res = await this.updateServerRaw(params)
|
const res = await this.updateServerRaw(params)
|
||||||
if (res.response === 'no-updates') {
|
if (res.response === 'no-updates') {
|
||||||
throw new Error('Could ont find a newer version of EmbassyOS')
|
throw new Error('Could not find a newer version of EmbassyOS')
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
@@ -271,7 +271,7 @@ export abstract class ApiService implements Source<DataModel>, Http<DataModel> {
|
|||||||
private syncResponse<
|
private syncResponse<
|
||||||
T,
|
T,
|
||||||
F extends (...args: any[]) => Promise<{ response: T; revision?: Revision }>,
|
F extends (...args: any[]) => Promise<{ response: T; revision?: Revision }>,
|
||||||
>(f: F, temp?: Operation<unknown>): (...args: Parameters<F>) => Promise<T> {
|
>(f: F, temp?: Operation<unknown>): (...args: Parameters<F>) => Promise<T> {
|
||||||
return (...a) => {
|
return (...a) => {
|
||||||
// let expireId = undefined
|
// let expireId = undefined
|
||||||
// if (temp) {
|
// if (temp) {
|
||||||
|
|||||||
Reference in New Issue
Block a user