mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
drives page
This commit is contained in:
committed by
Aiden McClelland
parent
31318687bf
commit
0cd2a32b24
@@ -33,6 +33,11 @@ const routes: Routes = [
|
||||
canActivateChild: [AuthGuard],
|
||||
loadChildren: () => import('./pages/apps-routes/apps-routing.module').then(m => m.AppsRoutingModule),
|
||||
},
|
||||
{
|
||||
path: 'drives',
|
||||
canActivate: [AuthGuard],
|
||||
loadChildren: () => import('./pages/server-routes/external-drives/external-drives.module').then( m => m.ExternalDrivesPageModule),
|
||||
},
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
|
||||
@@ -47,6 +47,11 @@ export class AppComponent {
|
||||
url: '/notifications',
|
||||
icon: 'notifications-outline',
|
||||
},
|
||||
{
|
||||
title: 'External Drives',
|
||||
url: '/drives',
|
||||
icon: 'albums-outline',
|
||||
},
|
||||
]
|
||||
|
||||
constructor (
|
||||
|
||||
@@ -161,7 +161,7 @@ export interface DiskInfo {
|
||||
|
||||
export interface DiskPartition {
|
||||
logicalname: string,
|
||||
isMounted: boolean, // Do not let them back up to this if true
|
||||
isMounted: boolean, // We do not allow backups to mounted partitions
|
||||
size: string | null,
|
||||
label: string | null,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { ExternalDrivesPage } from './external-drives.page'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
|
||||
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
|
||||
import { ObjectConfigComponentModule } from 'src/app/components/object-config/object-config.component.module'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ExternalDrivesPage,
|
||||
},
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
SharingModule,
|
||||
ObjectConfigComponentModule,
|
||||
RouterModule.forChild(routes),
|
||||
PwaBackComponentModule,
|
||||
BadgeMenuComponentModule,
|
||||
],
|
||||
declarations: [ExternalDrivesPage],
|
||||
})
|
||||
export class ExternalDrivesPageModule { }
|
||||
@@ -0,0 +1,38 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<pwa-back-button></pwa-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>External Drives</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<badge-menu-button></badge-menu-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content *ngIf="!($loading$ | async)" class="ion-padding-top">
|
||||
<ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
|
||||
<ion-refresher-content pullingIcon="lines" refreshingSpinner="lines"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<ion-item-divider>
|
||||
Storage
|
||||
</ion-item-divider>
|
||||
|
||||
<ion-item-group>
|
||||
<!-- <ion-list> -->
|
||||
<ion-item *ngFor="let d of disks; let i = index">
|
||||
<ion-icon slot="start" name="save-outline"></ion-icon>
|
||||
<ion-label>{{d.logicalname}}</ion-label>
|
||||
<ion-button *ngIf="!(d.$ejecting$ | async)" slot="end" fill="clear" color="medium" (click)="ejectDisk(i)">
|
||||
<ion-icon color="primary" class="icon" src="/assets/icon/eject.svg"></ion-icon>
|
||||
</ion-button>
|
||||
<ion-spinner *ngIf="d.$ejecting$ | async" name="lines" color="medium"></ion-spinner>
|
||||
</ion-item>
|
||||
<!-- </ion-list> -->
|
||||
</ion-item-group>
|
||||
</ion-content>
|
||||
|
||||
<ion-content *ngIf="$loading$ | async" class="ion-padding-top">
|
||||
<ion-spinner class="center" name="lines" color="warning"></ion-spinner>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,61 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { pauseFor } from 'src/app/util/misc.util'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
import { DiskInfo } from 'src/app/models/server-model'
|
||||
import { markAsLoadingDuring$, markAsLoadingDuringAsync, markAsLoadingDuringP } from 'src/app/services/loader.service'
|
||||
import { BehaviorSubject } from 'rxjs'
|
||||
import { AlertController } from '@ionic/angular'
|
||||
|
||||
type Ejectable<T> = T & { $ejecting$: BehaviorSubject<boolean> }
|
||||
|
||||
@Component({
|
||||
selector: 'external-drives',
|
||||
templateUrl: './external-drives.page.html',
|
||||
styleUrls: ['./external-drives.page.scss'],
|
||||
})
|
||||
export class ExternalDrivesPage {
|
||||
disks: Ejectable<DiskInfo>[] = []
|
||||
$loading$ = new BehaviorSubject(false)
|
||||
|
||||
constructor (
|
||||
private readonly apiService: ApiService,
|
||||
private readonly alertCtrl: AlertController,
|
||||
) { }
|
||||
|
||||
ngOnInit () {
|
||||
markAsLoadingDuringP(this.$loading$, this.fetchDisks())
|
||||
}
|
||||
|
||||
async doRefresh (event: any) {
|
||||
await Promise.all([
|
||||
this.fetchDisks(),
|
||||
pauseFor(600),
|
||||
])
|
||||
event.target.complete()
|
||||
}
|
||||
|
||||
async fetchDisks () {
|
||||
return this.apiService.getExternalDisks().then(ds => {
|
||||
this.disks = ds.map(d => ({ ...d, $ejecting$: new BehaviorSubject(false)})).sort( (a, b) => a.logicalname < b.logicalname ? -1 : 1 )
|
||||
})
|
||||
}
|
||||
|
||||
async ejectDisk (diskIndex: number) {
|
||||
const d = this.disks[diskIndex]
|
||||
markAsLoadingDuringP(d.$ejecting$, this.apiService.ejectExternalDisk(d.logicalname))
|
||||
.then(() => this.disks.splice(diskIndex, 1))
|
||||
.catch((e: Error) => {
|
||||
this.alertError(`Could not eject ${d.logicalname}: ${e.message}`)
|
||||
})
|
||||
}
|
||||
|
||||
async alertError (desc: string) {
|
||||
const alert = await this.alertCtrl.create({
|
||||
backdropDismiss: true,
|
||||
message: desc,
|
||||
cssClass: 'alert-error-message',
|
||||
})
|
||||
await alert.present()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ const routes: Routes = [
|
||||
path: 'developer',
|
||||
canActivate: [AuthGuard],
|
||||
loadChildren: () => import('./developer-routes/developer-routing.module').then( m => m.DeveloperRoutingModule),
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
|
||||
@@ -57,6 +57,7 @@ export abstract class ApiService {
|
||||
abstract deleteWifi (ssid: string): Promise<Unit>
|
||||
abstract restartServer (): Promise<Unit>
|
||||
abstract shutdownServer (): Promise<Unit>
|
||||
abstract ejectExternalDisk (logicalName: string): Promise<Unit>
|
||||
}
|
||||
|
||||
export module ReqRes {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { HttpErrorResponse } from '@angular/common/http'
|
||||
import { isUnauthorized } from 'src/app/util/web.util'
|
||||
import { Replace } from 'src/app/util/types.util'
|
||||
import { AppMetrics, parseMetricsPermissive } from 'src/app/util/metrics.util'
|
||||
import { modulateTime } from 'src/app/util/misc.util'
|
||||
// import { modulateTime } from 'src/app/util/misc.util'
|
||||
|
||||
@Injectable()
|
||||
export class LiveApiService extends ApiService {
|
||||
@@ -61,6 +61,10 @@ export class LiveApiService extends ApiService {
|
||||
return this.authRequest<ReqRes.GetExternalDisksRes>({ method: Method.GET, url: `/disks` })
|
||||
}
|
||||
|
||||
async ejectExternalDisk (logicalName: string): Promise<Unit> {
|
||||
return this.authRequest({ method: Method.DELETE, url: `/disks/${logicalName}` })
|
||||
}
|
||||
|
||||
async updateAgent (version: string): Promise<Unit> {
|
||||
const data: ReqRes.PostUpdateAgentReq = {
|
||||
version: `=${version}`,
|
||||
|
||||
@@ -29,13 +29,17 @@ export class MockApiService extends ApiService {
|
||||
async postConfigureDependency (dependencyId: string, dependentId: string, dryRun?: boolean): Promise<{ config: object, breakages: DependentBreakage[] }> {
|
||||
await pauseFor(2000)
|
||||
throw new Error ('some misc backend error ohh we forgot to make this endpoint or something')
|
||||
// return { config: mockCupsDependentConfig, breakages: [ ] }
|
||||
}
|
||||
|
||||
async getServer (): Promise<ApiServer> {
|
||||
return mockGetServer()
|
||||
}
|
||||
|
||||
async ejectExternalDisk (): Promise<Unit> {
|
||||
await pauseFor(2000)
|
||||
return { }
|
||||
}
|
||||
|
||||
async getCheckAuth (): Promise<ReqRes.GetCheckAuthRes> {
|
||||
return { }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user