Skip to content

Commit

Permalink
feat(browser-setting): set some value associated with browser or Rclo…
Browse files Browse the repository at this point in the history
…neNg rather server
  • Loading branch information
ElonH committed Jul 4, 2020
1 parent 3f0ef49 commit cded9c5
Show file tree
Hide file tree
Showing 12 changed files with 304 additions and 7 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
"lint": "ng lint",
"deploy:dry": "ng deploy --dry-run",
"deploy": "ng deploy",
"build:schemas": "ts-json-schema-generator --path ./src/app/@dataflow/rclone/options-get-flow.ts --type IRcloneOptions --expose none -o ./src/app/@dataflow/extra/server-setting-schema.json",
"build:schemas": "npm run build:schemas:server && npm run build:schemas:browser",
"build:schemas:server": "ts-json-schema-generator --path ./src/app/@dataflow/rclone/options-get-flow.ts --type IRcloneOptions --expose none -o ./src/app/@dataflow/extra/server-setting-schema.json",
"build:schemas:browser": "ts-json-schema-generator --path ./src/app/@dataflow/extra/browser-setting-flow.ts --type IBrowserSetting --expose none -o ./src/app/@dataflow/extra/browser-setting-schema.json",
"tslint-check": "tslint-config-prettier-check ./tslint.json"
},
"private": true,
Expand Down
62 changes: 62 additions & 0 deletions src/app/@dataflow/extra/browser-setting-flow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* if modify any thing in `IBrowserSetting`, include name, type, or common description,
* please run `npm run build:schemas:browser` to update schema.json file
*/

import { Observable, of } from 'rxjs';
import { BareFlow, CombErr } from '../core';

/**
* @description
*/
export interface IBrowserSetting {
/**
* 请求间隔, 需要定时从rclone服务器中获取数据的时间间隔.
*
* 单位: 毫秒(ms)
*
* 影响范围:
* - 响应时间的刷新频率(位于主侧栏左上角)
* - Dashboard 和 Job Manager 的更新间隔
*
* 建议:
* - 如果与 rclone 服务器响应时间小于 100ms(通常在局域网下), 可以适当调低数值
*/
'rng.request-interval': number;
}

export const brwoserSettingDefault: IBrowserSetting = {
'rng.request-interval': 3000,
};

export type NestedPartial<T> = {
[K in keyof T]?: T[K] extends Array<infer R> ? Array<NestedPartial<R>> : NestedPartial<T[K]>;
};

/**
* @description override partical browser config from input port,
* and output full browser configuration
*/
export abstract class BrowserSettingFlow extends BareFlow<
NestedPartial<IBrowserSetting>,
IBrowserSetting
> {
public abstract prerequest$: Observable<CombErr<NestedPartial<IBrowserSetting>>>;
protected data: IBrowserSetting;
constructor() {
super();
let strg = localStorage.getItem('browserConfig');
if (!strg) {
strg = JSON.stringify(brwoserSettingDefault);
localStorage.setItem('browserConfig', strg);
}
this.data = JSON.parse(strg);
}
protected request(
pre: CombErr<NestedPartial<IBrowserSetting>>
): Observable<CombErr<IBrowserSetting>> {
this.data = { ...this.data, ...pre[0] };
localStorage.setItem('browserConfig', JSON.stringify(this.data));
return of([this.data, []]);
}
}
17 changes: 17 additions & 0 deletions src/app/@dataflow/extra/browser-setting-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$ref": "#/definitions/IBrowserSetting",
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"IBrowserSetting": {
"additionalProperties": false,
"properties": {
"rng.request-interval": {
"description": "请求间隔, 需要定时从rclone服务器中获取数据的时间间隔.\n\n单位: 毫秒(ms)\n\n影响范围:\n - 响应时间的刷新频率(位于主侧栏左上角)\n - Dashboard 和 Job Manager 的更新间隔\n\n建议:\n - 如果与 rclone 服务器响应时间小于 100ms(通常在局域网下), 可以适当调低数值",
"type": "number"
}
},
"required": ["rng.request-interval"],
"type": "object"
}
}
}
1 change: 1 addition & 0 deletions src/app/@dataflow/extra/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './navigation-flow';
export * from './current-user-flow';
export * from './clipboard-flow';
export * from './operations-list-extends-flow';
export * from './browser-setting-flow';
13 changes: 10 additions & 3 deletions src/app/pages/connection.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { combineLatest, interval, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { map, switchMap } from 'rxjs/operators';
import { CombErr } from '../@dataflow/core';
import {
ConnectionFlow,
Expand All @@ -9,17 +9,24 @@ import {
NoopAuthFlowSupNode,
} from '../@dataflow/rclone';
import { CurrentUserService } from './current-user.service';
import { BrowserSettingService } from './settings/browser-setting/browser-setting.service';

@Injectable({
providedIn: 'root',
})
export class ConnectionService {
private timer = interval(3000);
private timer: Observable<number>;
public rst$: NoopAuthFlow;
public connection$: ConnectionFlow;
public listCmd$: ListCmdFlow;

constructor(currentUserService: CurrentUserService) {
constructor(
currentUserService: CurrentUserService,
private browserSettingService: BrowserSettingService
) {
this.timer = browserSettingService
.partialBrowserSetting$('rng.request-interval')
.pipe(switchMap(([int, err]) => interval(int)));
const outer = this;
this.rst$ = new (class extends NoopAuthFlow {
public prerequest$ = combineLatest([
Expand Down
5 changes: 3 additions & 2 deletions src/app/pages/pages-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ export const MENU_ITEMS: NbMenuItem[] = [
link: 'settings/server',
},
{
title: 'Appearance Setting',
icon: 'browser-outline', // todo: ng g module pages/settings/rng --module app --route settings/rng
title: 'Browser Setting',
icon: 'browser-outline',
link: 'settings/browser',
},
{ title: 'Other', group: true },
{ title: 'About', icon: 'npm-outline', link: 'about' },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { BrowserSettingComponent } from './browser-setting.component';

describe('BrowserSettingComponent', () => {
let component: BrowserSettingComponent;
let fixture: ComponentFixture<BrowserSettingComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [BrowserSettingComponent],
}).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(BrowserSettingComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
125 changes: 125 additions & 0 deletions src/app/pages/settings/browser-setting/browser-setting.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { EditorComponent as MonacoEditorComponent, NgxEditorModel } from 'ngx-monaco-editor';
import { ResponsiveSizeInfoRx } from 'ngx-responsive';
import { Subject, Subscription } from 'rxjs';
import { IBrowserSetting } from '../../../@dataflow/extra';
import * as browserSettingSchema from '../../../@dataflow/extra/browser-setting-schema.json';
import { BrowserSettingService } from './browser-setting.service';

@Component({
template: `
<nb-card>
<nb-card-header>
Browser Conf
<button class="push-to-right" nbButton size="small" status="success" (click)="save()">
Save
</button>
<button nbButton size="small" status="danger" (click)="recover()">Recover</button>
</nb-card-header>
<nb-card-body>
<!-- <div class="row">
<div class="col"> -->
<ngx-monaco-editor
[options]="editorOptions"
[model]="editorModel"
(onInit)="editorOnInit($event)"
></ngx-monaco-editor>
<!-- </div>
</div> -->
</nb-card-body>
</nb-card>
`,
styles: [
`
nb-card {
margin: 0;
}
nb-card-header {
display: flex;
}
button {
margin: 0 0.5rem;
}
.push-to-right {
margin-left: auto;
}
nb-card-body {
padding: 0;
overflow-y: hidden;
}
:host ngx-monaco-editor {
height: calc(100vh - 4.75rem - 4.25rem - 0.15rem);
}
:host ngx-monaco-editor ::ng-deep .editor-container {
height: 100%;
}
`,
],
})
export class BrowserSettingComponent implements OnInit {
constructor(private service: BrowserSettingService, private rsp: ResponsiveSizeInfoRx) {}
editorOptions: monaco.editor.IStandaloneEditorConstructionOptions = {
theme: 'vs',
language: 'json',
wordWrap: 'on',
// Set this to false to not auto word wrap minified files
wordWrapMinified: true,
// try "same", "indent" or "none"
wrappingIndent: 'indent',
};
editorModel: NgxEditorModel = {
value: '',
language: 'json',
// uri: monaco.Uri.parse('server-setting.json'),
};

private connector: Subscription[] = [];

private saveTrigger = new Subject<number>();
private recoverTrigger = new Subject<number>();
private originOptions: IBrowserSetting;

@ViewChild(MonacoEditorComponent, { static: true }) editorComponent: MonacoEditorComponent;
save() {
this.saveTrigger.next(1);
}
recover() {
this.recoverTrigger.next(1);
}

editorOnInit(editor: monaco.editor.IStandaloneCodeEditor) {
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
validate: true,
schemas: [
{
uri: 'browser-setting-schema.json',
fileMatch: [''],
schema: { ...browserSettingSchema.definitions.IBrowserSetting },
},
],
});
function updateValue(v: IBrowserSetting) {
editor.setValue(JSON.stringify(v, null, 4));
editor.trigger('', 'editor.action.formatDocument', {});
}
this.connector.forEach(x => x.unsubscribe());
this.connector = [];
this.connector.push(
this.service.browserSetting$.getOutput().subscribe(x => {
if (x[1].length !== 0) return;
this.originOptions = x[0];
updateValue(x[0]);
}),
this.rsp.getResponsiveSize.subscribe(x => {
editor.updateOptions({ minimap: { enabled: x !== 'xs' } });
}),
this.saveTrigger.subscribe(() => {
this.service.update(JSON.parse(editor.getValue()));
}),
this.recoverTrigger.subscribe(() => {
updateValue(this.originOptions);
})
);
}
ngOnInit() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* tslint:disable:no-unused-variable */

import { async, inject, TestBed } from '@angular/core/testing';
import { BrowserSettingService } from './browser-setting.service';

describe('Service: BrowserSetting', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [BrowserSettingService],
});
});

it('should ...', inject([BrowserSettingService], (service: BrowserSettingService) => {
expect(service).toBeTruthy();
}));
});
39 changes: 39 additions & 0 deletions src/app/pages/settings/browser-setting/browser-setting.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { map } from 'rxjs/operators';
import { CombErr } from '../../../@dataflow/core';
import { BrowserSettingFlow, IBrowserSetting, NestedPartial } from '../../../@dataflow/extra';
import { NestedGet } from '../../../@dataflow/rclone';

@Injectable({
providedIn: 'root',
})
export class BrowserSettingService {
browserSetting$: BrowserSettingFlow;

private trigger = new Subject<NestedPartial<IBrowserSetting>>();
constructor() {
const outer = this;
this.browserSetting$ = new (class extends BrowserSettingFlow {
public prerequest$: Observable<CombErr<NestedPartial<IBrowserSetting>>> = outer.trigger.pipe(
map(x => [x, []])
);
})();
this.browserSetting$.deploy();
this.browserSetting$.getOutput().subscribe();
this.trigger.next({});
}
public partialBrowserSetting$(...path: (number | string)[]) {
return this.browserSetting$.getOutput().pipe(
map(
(x): CombErr<any> => {
if (x[1].length !== 0) return x;
return [NestedGet(x[0], ...path), []];
}
)
);
}
public update(data: NestedPartial<IBrowserSetting>) {
this.trigger.next(data);
}
}
2 changes: 2 additions & 0 deletions src/app/pages/settings/settings-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { BrowserSettingComponent } from './browser-setting/browser-setting.component';
import { SettingsComponent } from './settings.component';
import { SeverSettingComponent } from './sever-setting/sever-setting.component';

Expand All @@ -10,6 +11,7 @@ const routes: Routes = [
component: SettingsComponent,
children: [
{ path: 'server', component: SeverSettingComponent },
{ path: 'browser', component: BrowserSettingComponent },
{ path: '', redirectTo: 'server', pathMatch: 'full' },
],
},
Expand Down
3 changes: 2 additions & 1 deletion src/app/pages/settings/settings.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { NgModule } from '@angular/core';

import { NbButtonModule, NbCardModule, NbLayoutModule } from '@nebular/theme';
import { MonacoEditorModule } from 'ngx-monaco-editor';
import { BrowserSettingComponent } from './browser-setting/browser-setting.component';
import { SettingsRoutingModule } from './settings-routing.module';
import { SettingsComponent } from './settings.component';
import { SeverSettingComponent } from './sever-setting/sever-setting.component';

@NgModule({
declarations: [SettingsComponent, SeverSettingComponent],
declarations: [SettingsComponent, SeverSettingComponent, BrowserSettingComponent],
imports: [
CommonModule,
SettingsRoutingModule,
Expand Down

0 comments on commit cded9c5

Please sign in to comment.