Skip to content

Commit

Permalink
✨ custom mount option
Browse files Browse the repository at this point in the history
  • Loading branch information
yuudi committed Oct 24, 2024
1 parent 249ae89 commit 0c2525f
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 21 deletions.
2 changes: 1 addition & 1 deletion docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Run backend: `rclone rcd --rc-user="<your username>" --rc-pass="<your password>"

Run frontend: `ng serve`

Api calling will be proxied to backed [config](./src/proxy.conf.mjs)
Api calling will be proxied to backed [config](../src/proxy.conf.mjs)

## Translation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,24 @@ export class NewBackendComponent implements OnInit {
}

// warn user
const enum action {
back,
continue,
}
this.dialog
.open(SimpleDialogComponent, {
data: {
title: $localize`Warning`,
message: $localize`This provider requires authentication. Because you are using a remote backend, automatic authentication (OAuth) is not possible for you. You may need to authorize on local rclone instance and copy the token to the backend.`,
actions: ['Go back', 'Continue Anyway'],
actions: [
{ label: $localize`Go back`, value: action.back },
{ label: $localize`Continue Anyway`, value: action.continue },
],
},
})
.afterClosed()
.subscribe((result) => {
if (result !== 'Continue Anyway') {
if (result !== action.continue) {
this.providerSelected = undefined;
this.stepperSelectedIndex = 0;
}
Expand Down
12 changes: 10 additions & 2 deletions src/app/features/functions/mount/mount.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export class MountComponent implements OnInit {
noModTime?: boolean;
vfsCacheMode?: string;
vfsCacheMaxAge?: string;
customMountOpt?: string;
customVfsOpt?: string;
}
> = this.dialog.open(NewMountDialogComponent, {
data: {
Expand Down Expand Up @@ -83,8 +85,8 @@ export class MountComponent implements OnInit {
return;
}
}
const mountOpt: { [key: string]: string | boolean | number } = {};
const vfsOpt: { [key: string]: string | boolean | number } = {};
let mountOpt: { [key: string]: string | boolean | number } = {};
let vfsOpt: { [key: string]: string | boolean | number } = {};
if (dialogResult.readonly !== undefined) {
mountOpt['readonly'] = dialogResult.readonly;
}
Expand All @@ -106,6 +108,12 @@ export class MountComponent implements OnInit {
if (dialogResult.vfsCacheMaxAge !== undefined) {
vfsOpt['vfsCacheMaxAge'] = dialogResult.vfsCacheMaxAge;
}
if (dialogResult.customMountOpt !== undefined) {
mountOpt = { ...mountOpt, ...JSON.parse(dialogResult.customMountOpt) };
}
if (dialogResult.customVfsOpt !== undefined) {
vfsOpt = { ...vfsOpt, ...JSON.parse(dialogResult.customVfsOpt) };
}

const id = await this.mountService.createSetting({
Fs: dialogResult.Fs,
Expand Down
2 changes: 2 additions & 0 deletions src/app/features/functions/mount/mount.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { MatMenuModule } from '@angular/material/menu';
import { MatSelectModule } from '@angular/material/select';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatTooltipModule } from '@angular/material/tooltip';

import { MountRoutingModule } from './mount-routing.module';
import { MountComponent } from './mount.component';
Expand All @@ -26,6 +27,7 @@ import { NewMountDialogComponent } from './new-mount-dialog/new-mount-dialog.com
CommonModule,
ReactiveFormsModule,
MountRoutingModule,
MatTooltipModule,
MatListModule,
MatButtonModule,
MatIconModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ <h3 mat-dialog-title i18n>Create MountPoint</h3>
</mat-option>
</mat-select>
</mat-form-field>
<mat-checkbox *ngIf="hasCron" formControlName="autoMount" i18n>
<mat-slide-toggle *ngIf="hasCron" formControlName="autoMount" i18n>
Auto Mount on Startup
</mat-checkbox>
<mat-checkbox
</mat-slide-toggle>
<mat-slide-toggle
*ngIf="data.osType === 'windows'"
formControlName="AutoMountPoint"
i18n
>
Automatic MountPoint
</mat-checkbox>
</mat-slide-toggle>
<mat-form-field *ngIf="mountForm.value.AutoMountPoint === false">
<mat-label i18n>MountPoint</mat-label>
<input matInput formControlName="MountPoint" />
Expand All @@ -35,16 +35,16 @@ <h3 mat-dialog-title i18n>Create MountPoint</h3>
</button>
</div>
<ng-container *ngIf="showAdvancedOptions">
<mat-checkbox formControlName="readonly" i18n>
<mat-slide-toggle formControlName="readonly" i18n>
Mount as Readonly Drive
</mat-checkbox>
<mat-checkbox
</mat-slide-toggle>
<mat-slide-toggle
*ngIf="data.osType === 'windows'"
formControlName="windowsNetworkMode"
i18n
>
Mount as Windows Network Drive
</mat-checkbox>
</mat-slide-toggle>
<mat-form-field>
<mat-label i18n>Cache Mode</mat-label>
<mat-select formControlName="vfsCacheMode">
Expand All @@ -58,6 +58,10 @@ <h3 mat-dialog-title i18n>Create MountPoint</h3>
<mat-option value="full" i18n> Full </mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-label i18n>Cache Max Age</mat-label>
<input matInput formControlName="vfsCacheMaxAge" />
</mat-form-field>
<mat-form-field *ngIf="data.osType !== 'windows'">
<mat-label i18n>File Permissions</mat-label>
<input matInput formControlName="filePerms" />
Expand All @@ -66,9 +70,35 @@ <h3 mat-dialog-title i18n>Create MountPoint</h3>
<mat-label i18n>Directory Permissions</mat-label>
<input matInput formControlName="dirPerms" />
</mat-form-field>
<mat-checkbox formControlName="noModTime" i18n>
<mat-slide-toggle formControlName="noModTime" i18n>
Skip modification time (can speed things up)
</mat-checkbox>
</mat-slide-toggle>
<mat-form-field>
<mat-label i18n>Custom Mount Option (Json)</mat-label>
<textarea matInput formControlName="customMountOpt"></textarea>
<button
mat-icon-button
i18n-matTooltip
matTooltip="Help"
matSuffix
(click)="getMountOptHelp()"
>
<mat-icon fontIcon="help"></mat-icon>
</button>
</mat-form-field>
<mat-form-field>
<mat-label i18n>Custom Vfs Option (Json)</mat-label>
<textarea matInput formControlName="customVfsOpt"></textarea>
<button
mat-icon-button
i18n-matTooltip
matTooltip="Help"
matSuffix
(click)="getVfsOptHelp()"
>
<mat-icon fontIcon="help"></mat-icon>
</button>
</mat-form-field>
</ng-container>
</form>
<div mat-dialog-actions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@
display: flex;
justify-content: center;
}

mat-slide-toggle {
margin: 1em;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Component, Inject } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';

import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog';

import { jsonStringValidator } from 'src/app/shared/json-string-validator.directive';
import { SimpleDialogComponent } from 'src/app/shared/simple-dialog/simple-dialog.component';
import { environment } from 'src/environments/environment';

@Component({
Expand Down Expand Up @@ -32,11 +35,14 @@ export class NewMountDialogComponent {
'1h',
[Validators.required, Validators.pattern(/^\d+[smhd]$/)],
],
customMountOpt: ['{\n}', jsonStringValidator()],
customVfsOpt: ['{\n}', jsonStringValidator()],
});
showAdvancedOptions = false;
hasCron = environment.electron;

constructor(
private dialog: MatDialog,
private fb: FormBuilder,
@Inject(MAT_DIALOG_DATA)
public data: {
Expand All @@ -51,4 +57,23 @@ export class NewMountDialogComponent {
this.mountForm.controls.MountPoint.setValue('/mnt/rclone');
}
}

getMountOptHelp() {
this.dialog.open(SimpleDialogComponent, {
data: {
title: $localize`Information`,
message: $localize`This is options for advanced user only!\nPlease input options in JSON format, keys are in PascalCase.\nAvailable options: please refer to https://github.com/rclone/rclone/blob/master/cmd/mountlib/mount.go\nfind "type Options struct" part`,
actions: [{ label: $localize`Close`, value: 0 }],
},
});
}
getVfsOptHelp() {
this.dialog.open(SimpleDialogComponent, {
data: {
title: $localize`Information`,
message: $localize`This is options for advanced user only!\nPlease input options in JSON format, keys are in PascalCase.\nAvailable options: please refer to https://github.com/rclone/rclone/blob/master/vfs/vfscommon/options.go\nfind "type Options struct" part`,
actions: [{ label: $localize`Close`, value: 0 }],
},
});
}
}
12 changes: 12 additions & 0 deletions src/app/shared/json-string-validator.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';

export function jsonStringValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
try {
JSON.parse(control.value);
return null;
} catch {
return { invalidJsonString: true };
}
};
}
6 changes: 3 additions & 3 deletions src/app/shared/simple-dialog/simple-dialog.component.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<h3 mat-dialog-title>{{ data.title }}</h3>
<div mat-dialog-content>{{ data.message }}</div>
<div mat-dialog-content class="message">{{ data.message }}</div>
<div mat-dialog-actions>
<button
*ngFor="let action of data.actions"
mat-button
[mat-dialog-close]="action"
[mat-dialog-close]="action.value"
>
{{ action }}
{{ action.label }}
</button>
</div>
3 changes: 3 additions & 0 deletions src/app/shared/simple-dialog/simple-dialog.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.message {
white-space: pre-wrap;
}
7 changes: 5 additions & 2 deletions src/app/shared/simple-dialog/simple-dialog.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ import { MatButtonModule } from '@angular/material/button';
templateUrl: './simple-dialog.component.html',
styleUrls: ['./simple-dialog.component.scss'],
})
export class SimpleDialogComponent {
export class SimpleDialogComponent<T> {
constructor(
@Inject(MAT_DIALOG_DATA)
public data: {
title: string;
message: string;
actions: string[];
actions: {
value: T;
label: string;
}[];
},
) {}
}

0 comments on commit 0c2525f

Please sign in to comment.