Add file uploader support
This commit is contained in:
parent
f4c86a06e2
commit
813f4b094b
@ -10,8 +10,10 @@
|
|||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-list-header>
|
<ion-list-header>
|
||||||
Navigate
|
<ion-buttons class="ion-padding-start">
|
||||||
<ion-buttons class="ion-padding-end">
|
<ion-button fill="outline" [color]="refreshingMenu ? 'success' : 'light'" (click)="onMenuRefresh()">
|
||||||
|
<ion-icon color="tertiary" name="refresh"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
<ion-button fill="outline" color="light" (click)="onTopLevelCreate()">
|
<ion-button fill="outline" color="light" (click)="onTopLevelCreate()">
|
||||||
<ion-icon color="primary" name="add-circle"></ion-icon>
|
<ion-icon color="primary" name="add-circle"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
@ -50,4 +52,4 @@
|
|||||||
</ion-content>
|
</ion-content>
|
||||||
</div>
|
</div>
|
||||||
</ion-split-pane>
|
</ion-split-pane>
|
||||||
</ion-app>
|
</ion-app>
|
||||||
|
@ -16,18 +16,17 @@ import { Observable } from 'rxjs';
|
|||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
public addChildTarget: any = false;
|
public addChildTarget: any = false;
|
||||||
public deleteTarget: any = false;
|
public deleteTarget: any = false;
|
||||||
|
public refreshingMenu = false;
|
||||||
public lastClickEvent: Array<any> = [];
|
public lastClickEvent: Array<any> = [];
|
||||||
public nodes = [];
|
public nodes = [];
|
||||||
public options = {
|
public options = {
|
||||||
actionMapping: {
|
actionMapping: {
|
||||||
mouse: {
|
mouse: {
|
||||||
dblClick: (tree, node, $event) => {
|
dblClick: (tree, node, $event) => {
|
||||||
console.log({ tree, node, $event });
|
|
||||||
const id = node.data.id;
|
const id = node.data.id;
|
||||||
this.router.navigate(['/editor', { id }]);
|
this.router.navigate(['/editor', { id }]);
|
||||||
},
|
},
|
||||||
click: (tree, node, $event) => {
|
click: (tree, node, $event) => {
|
||||||
console.log('click', { tree, node, $event });
|
|
||||||
TREE_ACTIONS.FOCUS(tree, node, $event);
|
TREE_ACTIONS.FOCUS(tree, node, $event);
|
||||||
this.addChildTarget = node;
|
this.addChildTarget = node;
|
||||||
this.deleteTarget = node;
|
this.deleteTarget = node;
|
||||||
@ -158,6 +157,14 @@ export class AppComponent implements OnInit {
|
|||||||
await alert.present();
|
await alert.present();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMenuRefresh() {
|
||||||
|
this.refreshingMenu = true;
|
||||||
|
this.reloadMenuItems().subscribe();
|
||||||
|
setTimeout(() => {
|
||||||
|
this.refreshingMenu = false;
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
reloadMenuItems() {
|
reloadMenuItems() {
|
||||||
return new Observable(sub => {
|
return new Observable(sub => {
|
||||||
this.api.get('/menu/items').subscribe(result => {
|
this.api.get('/menu/items').subscribe(result => {
|
||||||
@ -178,7 +185,6 @@ export class AppComponent implements OnInit {
|
|||||||
toggleDark() {
|
toggleDark() {
|
||||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
this.darkMode = !this.darkMode;
|
this.darkMode = !this.darkMode;
|
||||||
console.log('toggel Dark mode');
|
|
||||||
document.body.classList.toggle('dark', this.darkMode);
|
document.body.classList.toggle('dark', this.darkMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,12 @@ import {ColumnsComponent} from './editor/database/columns/columns.component';
|
|||||||
import {FormsModule} from '@angular/forms';
|
import {FormsModule} from '@angular/forms';
|
||||||
import {CodeComponent} from './editor/code/code.component';
|
import {CodeComponent} from './editor/code/code.component';
|
||||||
import {MonacoEditorModule} from 'ngx-monaco-editor';
|
import {MonacoEditorModule} from 'ngx-monaco-editor';
|
||||||
|
import {FilesComponent} from './editor/files/files.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [HostComponent, NodePickerComponent, DatabaseComponent, ColumnsComponent, CodeComponent],
|
declarations: [HostComponent, NodePickerComponent, DatabaseComponent, ColumnsComponent, CodeComponent, FilesComponent],
|
||||||
imports: [CommonModule, IonicModule, AgGridModule, FormsModule, MonacoEditorModule],
|
imports: [CommonModule, IonicModule, AgGridModule, FormsModule, MonacoEditorModule],
|
||||||
entryComponents: [HostComponent, NodePickerComponent, DatabaseComponent, ColumnsComponent, CodeComponent],
|
entryComponents: [HostComponent, NodePickerComponent, DatabaseComponent, ColumnsComponent, CodeComponent, FilesComponent],
|
||||||
exports: [HostComponent, NodePickerComponent, DatabaseComponent, ColumnsComponent, CodeComponent]
|
exports: [HostComponent, NodePickerComponent, DatabaseComponent, ColumnsComponent, CodeComponent, FilesComponent]
|
||||||
})
|
})
|
||||||
export class ComponentsModule {}
|
export class ComponentsModule {}
|
||||||
|
@ -35,17 +35,19 @@ export class DatabaseComponent implements OnInit {
|
|||||||
rowData = [];
|
rowData = [];
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.loader.create({message: 'Loading database...'}).then(loader => {
|
// this.loader.create({message: 'Loading database...'}).then(loader => {
|
||||||
loader.present().then(() => {
|
// setTimeout(() => {
|
||||||
|
// loader.present().then(() => {
|
||||||
this.getInitObservable().subscribe(() => {
|
this.getInitObservable().subscribe(() => {
|
||||||
this.getColumnLoadObservable().subscribe(() => {
|
this.getColumnLoadObservable().subscribe(() => {
|
||||||
this.getDataLoadObservable().subscribe(() => {
|
this.getDataLoadObservable().subscribe(() => {
|
||||||
loader.dismiss();
|
// loader.dismiss();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
// });
|
||||||
});
|
// }, 100);
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
onCellValueChanged() {
|
onCellValueChanged() {
|
||||||
@ -80,7 +82,7 @@ export class DatabaseComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
const endpoint = `/db/${this.hostRecord.PageId}/${this.hostRecord.UUID}/set/${this.hostRecord.Value.Value}/columns`
|
const endpoint = `/db/${this.hostRecord.PageId}/${this.hostRecord.UUID}/set/${this.hostRecord.Value.Value}/columns`
|
||||||
this.api.post(endpoint, {columns: this.columnDefs}).subscribe(res => {
|
this.api.post(endpoint, {columns: this.columnDefs}).subscribe(res => {
|
||||||
this.columnDefs = res.data;
|
// this.columnDefs = res.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -202,7 +204,7 @@ export class DatabaseComponent implements OnInit {
|
|||||||
|
|
||||||
getInitObservable(): Observable<any> {
|
getInitObservable(): Observable<any> {
|
||||||
return new Observable<any>(sub => {
|
return new Observable<any>(sub => {
|
||||||
if ( this.hostRecord && this.pendingSetup ) {
|
if ( this.hostRecord.UUID && this.pendingSetup ) {
|
||||||
if ( !this.hostRecord.Value ) {
|
if ( !this.hostRecord.Value ) {
|
||||||
this.hostRecord.Value = {};
|
this.hostRecord.Value = {};
|
||||||
}
|
}
|
||||||
|
23
src/app/components/editor/files/files.component.html
Normal file
23
src/app/components/editor/files/files.component.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<div class="files-wrapper">
|
||||||
|
<div class="new-uploads" style="margin: 20px;">
|
||||||
|
<form #uploadForm [action]="getApiSubmit()" enctype="multipart/form-data" method="post">
|
||||||
|
<input style="margin-top: 10px;" type="file" id="file" name="uploaded_file">
|
||||||
|
<ion-button (click)="onSubmitClick()" type="submit" fill="outline" class="ion-margin-start">Upload</ion-button>
|
||||||
|
<ion-button (click)="onDestroyClick()" type="submit" fill="outline" class="ion-margin-start" color="danger">Drop Files</ion-button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="existing-uploads">
|
||||||
|
<ion-grid>
|
||||||
|
<ion-row>
|
||||||
|
<ion-col *ngFor="let upload of fileRecords; let i = index" size-xl="4" size-lg="6" size-md="12">
|
||||||
|
<ion-card>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>{{ fileRecords[i].original_name }}</ion-label>
|
||||||
|
<ion-button (click)="downloadFile(fileRecords[i])" fill="outline" color="lighter" slot="end"><ion-icon color="primary" name="arrow-down"></ion-icon></ion-button>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
</ion-col>
|
||||||
|
</ion-row>
|
||||||
|
</ion-grid>
|
||||||
|
</div>
|
||||||
|
</div>
|
4
src/app/components/editor/files/files.component.scss
Normal file
4
src/app/components/editor/files/files.component.scss
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
div.files-wrapper {
|
||||||
|
border: 2px solid #8c8c8c;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
104
src/app/components/editor/files/files.component.ts
Normal file
104
src/app/components/editor/files/files.component.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import {Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
|
||||||
|
import HostRecord from '../../../structures/HostRecord';
|
||||||
|
import {ApiService} from '../../../service/api.service';
|
||||||
|
import {AlertController} from '@ionic/angular';
|
||||||
|
import {Observable} from 'rxjs';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'editor-files',
|
||||||
|
templateUrl: './files.component.html',
|
||||||
|
styleUrls: ['./files.component.scss'],
|
||||||
|
})
|
||||||
|
export class FilesComponent implements OnInit {
|
||||||
|
@Input() hostRecord: HostRecord;
|
||||||
|
@Output() hostRecordChange = new EventEmitter<HostRecord>();
|
||||||
|
@Output() requestParentSave = new EventEmitter<FilesComponent>();
|
||||||
|
@Output() requestParentDelete = new EventEmitter<FilesComponent>();
|
||||||
|
@ViewChild('uploadForm', {static: false}) uploadForm: ElementRef;
|
||||||
|
|
||||||
|
public fileRecords: Array<any> = [];
|
||||||
|
public pendingSetup = true;
|
||||||
|
public dbRecord: any = {};
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected api: ApiService,
|
||||||
|
protected alerts: AlertController,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.getInitObservable().subscribe(() => {
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getApiSubmit() {
|
||||||
|
return this.api._build_url(`file/upload/${this.hostRecord.PageId}/${this.hostRecord.UUID}/${this.hostRecord.Value.Value}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmitClick() {
|
||||||
|
this.uploadForm.nativeElement.submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadFile(fileRecord) {
|
||||||
|
// tslint:disable-next-line:max-line-length
|
||||||
|
window.open(this.api._build_url(`files/${this.hostRecord.PageId}/${this.hostRecord.UUID}/get/${this.hostRecord.Value.Value}/${fileRecord._id}`), '_blank');
|
||||||
|
}
|
||||||
|
|
||||||
|
async onDestroyClick() {
|
||||||
|
const alert = await this.alerts.create({
|
||||||
|
header: 'Are you sure?',
|
||||||
|
message: 'You are about to delete these files. This action cannot be undone.',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: 'Keep Them',
|
||||||
|
role: 'cancel',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Delete Them',
|
||||||
|
handler: async () => {
|
||||||
|
this.api.post(`/files/${this.hostRecord.PageId}/${this.hostRecord.UUID}/delete/${this.hostRecord.Value.Value}`)
|
||||||
|
.subscribe(res => {
|
||||||
|
this.requestParentDelete.emit(this);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
await alert.present();
|
||||||
|
}
|
||||||
|
|
||||||
|
getInitObservable(): Observable<any> {
|
||||||
|
return new Observable<any>(sub => {
|
||||||
|
if ( this.hostRecord && this.pendingSetup ) {
|
||||||
|
if ( !this.hostRecord.Value ) {
|
||||||
|
this.hostRecord.Value = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !this.hostRecord.Value.Value ) {
|
||||||
|
this.api.post(`/files/${this.hostRecord.PageId}/${this.hostRecord.UUID}/create`).subscribe(res => {
|
||||||
|
this.dbRecord = res.data;
|
||||||
|
this.fileRecords = res.data.files;
|
||||||
|
this.hostRecord.Value.Mode = 'files';
|
||||||
|
this.hostRecord.Value.Value = res.data.UUID;
|
||||||
|
this.hostRecord.value = res.data.UUID;
|
||||||
|
this.hostRecordChange.emit(this.hostRecord);
|
||||||
|
this.pendingSetup = false;
|
||||||
|
sub.next(true);
|
||||||
|
sub.complete();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.api.get(`/files/${this.hostRecord.PageId}/${this.hostRecord.UUID}/get/${this.hostRecord.Value.Value}`).subscribe(res => {
|
||||||
|
this.fileRecords = res.data.files;
|
||||||
|
this.pendingSetup = false;
|
||||||
|
sub.next(true);
|
||||||
|
sub.complete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.pendingSetup = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -42,4 +42,12 @@
|
|||||||
(requestParentDelete)="onRequestDelete($event)"
|
(requestParentDelete)="onRequestDelete($event)"
|
||||||
></editor-code>
|
></editor-code>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="files-wrapper" *ngIf="record.type === 'file_ref'">
|
||||||
|
<editor-files
|
||||||
|
[hostRecord]="record"
|
||||||
|
(hostRecordChange)="onRecordChange($event)"
|
||||||
|
(requestParentSave)="onRequestParentSave($event)"
|
||||||
|
(requestParentDelete)="onRequestDelete($event)"
|
||||||
|
></editor-files>
|
||||||
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -70,7 +70,6 @@ export class HostComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onLIKeyUp($event, i) {
|
onLIKeyUp($event, i) {
|
||||||
console.log({$event});
|
|
||||||
if ( $event.code === 'Enter' ) {
|
if ( $event.code === 'Enter' ) {
|
||||||
/*const newListLines = [];
|
/*const newListLines = [];
|
||||||
this.liItems.forEach((li, index) => {
|
this.liItems.forEach((li, index) => {
|
||||||
|
@ -35,4 +35,8 @@
|
|||||||
<ion-icon slot="start" name="code"></ion-icon>
|
<ion-icon slot="start" name="code"></ion-icon>
|
||||||
<ion-label>Code Editor</ion-label>
|
<ion-label>Code Editor</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
<ion-item button (click)="onSelect('file_ref')">
|
||||||
|
<ion-icon slot="start" name="document"></ion-icon>
|
||||||
|
<ion-label>Upload Files</ion-label>
|
||||||
|
</ion-item>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
@ -29,8 +29,6 @@ export class EditorPage implements OnInit {
|
|||||||
this.route.params.subscribe(params => {
|
this.route.params.subscribe(params => {
|
||||||
this.pageId = params.id;
|
this.pageId = params.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('editor page', this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {}
|
ngOnInit() {}
|
||||||
@ -41,6 +39,7 @@ export class EditorPage implements OnInit {
|
|||||||
this.pageRecord = pageRecord;
|
this.pageRecord = pageRecord;
|
||||||
this.pages.get_nodes(pageRecord).subscribe((hosts: Array<HostRecord>) => {
|
this.pages.get_nodes(pageRecord).subscribe((hosts: Array<HostRecord>) => {
|
||||||
this.hostRecords = hosts;
|
this.hostRecords = hosts;
|
||||||
|
this.onSaveClick();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -59,10 +58,8 @@ export class EditorPage implements OnInit {
|
|||||||
});
|
});
|
||||||
|
|
||||||
popover.onDidDismiss().then(arg => {
|
popover.onDidDismiss().then(arg => {
|
||||||
console.log({arg});
|
|
||||||
const defValue = this.getDefaultValue(arg.data);
|
const defValue = this.getDefaultValue(arg.data);
|
||||||
const hostRec = new HostRecord(defValue);
|
const hostRec = new HostRecord(defValue);
|
||||||
console.log({hostRec});
|
|
||||||
hostRec.type = arg.data;
|
hostRec.type = arg.data;
|
||||||
hostRec.PageId = this.pageRecord.UUID;
|
hostRec.PageId = this.pageRecord.UUID;
|
||||||
this.hostRecords.push(hostRec);
|
this.hostRecords.push(hostRec);
|
||||||
|
@ -48,7 +48,7 @@ export class ApiService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _build_url(endpoint) {
|
public _build_url(endpoint) {
|
||||||
if ( !endpoint.startsWith('/') ) {
|
if ( !endpoint.startsWith('/') ) {
|
||||||
endpoint = `/${endpoint}`;
|
endpoint = `/${endpoint}`;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,6 @@ export class PageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
save_nodes(page: PageRecord, nodes: Array<HostRecord>): Observable<Array<HostRecord>> {
|
save_nodes(page: PageRecord, nodes: Array<HostRecord>): Observable<Array<HostRecord>> {
|
||||||
console.log('save nodes', {nodes})
|
|
||||||
return new Observable<Array<HostRecord>>(sub => {
|
return new Observable<Array<HostRecord>>(sub => {
|
||||||
nodes = nodes.map(x => {
|
nodes = nodes.map(x => {
|
||||||
x.PageId = page.UUID;
|
x.PageId = page.UUID;
|
||||||
|
Loading…
Reference in New Issue
Block a user