Initial commit for gisaf/fastapi
This commit is contained in:
commit
adce44722f
1361 changed files with 42521 additions and 0 deletions
|
@ -0,0 +1,6 @@
|
|||
.item {
|
||||
border: 1px solid grey;
|
||||
margin: 0 3px;
|
||||
padding: 0 2px;
|
||||
border-radius: 3px;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<div class='item'>
|
||||
<div class='path'>
|
||||
{{ file.path }}
|
||||
</div>
|
||||
<div class='url'>
|
||||
{{ file.url }}
|
||||
</div>
|
||||
<div class='status'>
|
||||
{{ file.status }}
|
||||
</div>
|
||||
<div class='store'>
|
||||
{{ file.store }}
|
||||
</div>
|
||||
<div class='time'>
|
||||
{{ file.time }}
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,25 @@
|
|||
import { Component, OnInit, Input,
|
||||
ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core'
|
||||
import { ActivatedRoute } from '@angular/router'
|
||||
|
||||
import { AdminDataService } from '../../admin-data.service'
|
||||
import { AdminBasketFile } from '../data.service'
|
||||
|
||||
@Component({
|
||||
selector: 'gisaf-admin-basket-item',
|
||||
templateUrl: './basket-item.component.html',
|
||||
styleUrls: ['./basket-item.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AdminBasketItemComponent implements OnInit {
|
||||
constructor(
|
||||
public adminDataService: AdminDataService,
|
||||
private route: ActivatedRoute,
|
||||
private cdr: ChangeDetectorRef,
|
||||
) {}
|
||||
|
||||
@Input() file: AdminBasketFile
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
}
|
19
src/app/admin/admin-basket/admin-basket-resolver.service.ts
Normal file
19
src/app/admin/admin-basket/admin-basket-resolver.service.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { Injectable } from '@angular/core'
|
||||
import { Router, Resolve, RouterStateSnapshot, ActivatedRouteSnapshot } from '@angular/router'
|
||||
import { Observable, forkJoin } from 'rxjs'
|
||||
import { map } from 'rxjs/operators'
|
||||
|
||||
import { AdminBasket, AdminBasketDataService } from './data.service'
|
||||
|
||||
@Injectable()
|
||||
export class BasketResolver implements Resolve<object> {
|
||||
constructor(
|
||||
private router: Router,
|
||||
private basketDataService: AdminBasketDataService,
|
||||
) {}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<AdminBasket> {
|
||||
var name = route.paramMap.get('name')
|
||||
return this.basketDataService.getBasket(name)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
.container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.container mat-form-field {
|
||||
flex: 1 1 0;
|
||||
}
|
||||
|
||||
.container form {
|
||||
border: 1px solid grey;
|
||||
padding: 2px 1em;
|
||||
border-radius: 0.6em;
|
||||
margin-bottom: 3px;
|
||||
background-color: #424242;
|
||||
}
|
||||
|
||||
.importButtonGroup {
|
||||
flex: 5 1 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
mat-form-field.store {
|
||||
width: 18em;
|
||||
}
|
||||
|
||||
mat-form-field.status {
|
||||
width: 4em;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<div class='container'>
|
||||
<form [formGroup]="formGroup">
|
||||
<mat-form-field [hidden]="is_upload_field_hidden('project')">
|
||||
<mat-label>Project</mat-label>
|
||||
<mat-select formControlName="project">
|
||||
<mat-option
|
||||
*ngFor="let item of basket.projects || adminDataService.surveyMeta.projects"
|
||||
[value]="item.name">
|
||||
{{ item.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field [hidden]="is_upload_field_hidden('surveyor')">
|
||||
<mat-label>Surveyor</mat-label>
|
||||
<mat-select formControlName="surveyor">
|
||||
<mat-option
|
||||
*ngFor="let item of adminDataService.surveyMeta.surveyors"
|
||||
[value]="item.name">
|
||||
{{ item.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field [hidden]="is_upload_field_hidden('equipment')">
|
||||
<mat-label>Equipment</mat-label>
|
||||
<mat-select formControlName="equipment">
|
||||
<mat-option
|
||||
*ngFor="let item of adminDataService.surveyMeta.equipments"
|
||||
[value]="item.name">
|
||||
{{ item.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class='store' [hidden]="is_upload_field_hidden('store_line_work')">
|
||||
<mat-label>Store</mat-label>
|
||||
<mat-select formControlName="store_line_work">
|
||||
<mat-option
|
||||
*ngFor="let item of adminDataService.surveyMeta.stores_line_work"
|
||||
[value]="item.name">
|
||||
{{ item.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class='store' [hidden]="is_upload_field_hidden('store_misc')">
|
||||
<mat-label>Store</mat-label>
|
||||
<mat-select formControlName="store_misc">
|
||||
<mat-option
|
||||
*ngFor="let item of adminDataService.surveyMeta.stores_misc"
|
||||
[value]="item.name">
|
||||
{{ item.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class='status' [hidden]="is_upload_field_hidden('status')">
|
||||
<mat-label>Status</mat-label>
|
||||
<mat-select formControlName="status">
|
||||
<mat-option
|
||||
*ngFor="let item of adminDataService.surveyMeta.statuses"
|
||||
[value]="item">
|
||||
{{ item }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<div class='importButtonGroup'>
|
||||
<button mat-button (click)="fileInput.click()" [disabled]="!formGroup.valid">
|
||||
<mat-icon>file_upload</mat-icon>
|
||||
Add file
|
||||
</button>
|
||||
<mat-checkbox formControlName='autoImport'
|
||||
matTooltip='Automatically import the content of the file in the database when its added to the basket'>
|
||||
Auto import
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<input hidden (change)="onFileUpload()" #fileInput type="file" id="file">
|
||||
</form>
|
||||
</div>
|
|
@ -0,0 +1,115 @@
|
|||
import { Component, OnInit, Input, ViewChild, ElementRef,
|
||||
ChangeDetectorRef, ChangeDetectionStrategy, SimpleChanges, OnChanges } from '@angular/core'
|
||||
import { HttpClient } from '@angular/common/http'
|
||||
import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms'
|
||||
|
||||
import { MatTableDataSource } from '@angular/material/table'
|
||||
|
||||
import { AdminDataService } from '../../admin-data.service'
|
||||
import { AdminBasketFile, AdminBasket } from '../data.service'
|
||||
import { MatSnackBar } from '@angular/material/snack-bar'
|
||||
import { HtmlSnackbarComponent } from '../../../custom-snackbar/custom-snackbar.component'
|
||||
|
||||
@Component({
|
||||
selector: 'gisaf-admin-basket-upload',
|
||||
templateUrl: './basket-upload.component.html',
|
||||
styleUrls: ['./basket-upload.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AdminBasketUploadComponent implements OnInit, OnChanges {
|
||||
constructor(
|
||||
public adminDataService: AdminDataService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
private http: HttpClient,
|
||||
private snackBar: MatSnackBar,
|
||||
) {}
|
||||
|
||||
@ViewChild('fileInput') fileInput: ElementRef
|
||||
@Input() basket: AdminBasket
|
||||
@Input() dataSource: MatTableDataSource<object>
|
||||
|
||||
//upload_fields = ['store', 'status', 'project', 'surveyor', 'equipment']
|
||||
|
||||
formGroup: UntypedFormGroup = new UntypedFormGroup({})
|
||||
|
||||
ngOnInit() {
|
||||
let defaults = this.adminDataService.surveyMeta.defaults
|
||||
this.formGroup = new UntypedFormGroup({
|
||||
'store_misc': new UntypedFormControl(defaults['store_misc'], [Validators.required]),
|
||||
'store_line_work': new UntypedFormControl(defaults['store_line_work'], [Validators.required]),
|
||||
'status': new UntypedFormControl(defaults['status'], [Validators.required]),
|
||||
'project': new UntypedFormControl(defaults['project'], [Validators.required]),
|
||||
'surveyor': new UntypedFormControl(defaults['surveyor'], [Validators.required]),
|
||||
'equipment': new UntypedFormControl(defaults['equipment'], [Validators.required]),
|
||||
'autoImport': new UntypedFormControl(true),
|
||||
})
|
||||
this.setupRequired()
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
this.setupRequired()
|
||||
}
|
||||
|
||||
setupRequired() {
|
||||
for (let field in this.formGroup.controls) {
|
||||
if (this.basket.uploadFields.includes(field)) {
|
||||
this.formGroup.controls[field].setValidators(Validators.required)
|
||||
}
|
||||
else {
|
||||
this.formGroup.controls[field].clearValidators()
|
||||
}
|
||||
this.formGroup.controls[field].updateValueAndValidity({onlySelf: true})
|
||||
}
|
||||
this.formGroup.updateValueAndValidity({onlySelf: true})
|
||||
}
|
||||
|
||||
onFileUpload() {
|
||||
const formData = new FormData()
|
||||
formData.append('file', <File>this.fileInput.nativeElement.files[0])
|
||||
let fg = this.formGroup.getRawValue()
|
||||
for (let field in fg) {
|
||||
if (this.basket.uploadFields.indexOf(field) != -1) {
|
||||
formData.append(field, fg[field])
|
||||
}
|
||||
}
|
||||
formData.append('autoImport', this.formGroup.get('autoImport').value)
|
||||
this.http.post('upload/basket/' + this.basket.name, formData).subscribe(
|
||||
resp => {
|
||||
let importResult = resp['import_result']
|
||||
const importTime = resp['time'] || (importResult && importResult['time'])
|
||||
const fileImport = new AdminBasketFile(
|
||||
resp['id'],
|
||||
resp['dir'],
|
||||
resp['name'],
|
||||
resp['url'],
|
||||
resp['md5'],
|
||||
importTime && new Date(importTime),
|
||||
resp['comment'],
|
||||
resp['status'],
|
||||
resp['store'],
|
||||
resp['project'],
|
||||
resp['surveyor'],
|
||||
resp['equipment'],
|
||||
)
|
||||
this.dataSource.data.push(fileImport)
|
||||
this.dataSource.data = this.dataSource.data
|
||||
let msg = 'File ' + fileImport.name + ' added to basket'
|
||||
if (importResult) {
|
||||
this.snackBar.openFromComponent(HtmlSnackbarComponent, {
|
||||
data: importResult
|
||||
//duration: 3000
|
||||
})
|
||||
|
||||
}
|
||||
else {
|
||||
this.snackBar.open(msg, 'Close')
|
||||
}
|
||||
this.cdr.markForCheck()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
is_upload_field_hidden(fname: string) {
|
||||
return this.basket.uploadFields.indexOf(fname)==-1
|
||||
}
|
||||
}
|
66
src/app/admin/admin-basket/basket.component.css
Normal file
66
src/app/admin/admin-basket/basket.component.css
Normal file
|
@ -0,0 +1,66 @@
|
|||
h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
gisaf-admin-basket-upload {
|
||||
flex: 1 1 0;
|
||||
}
|
||||
|
||||
.filter button {
|
||||
min-width: 1em!important;
|
||||
}
|
||||
|
||||
.cdk-column-delete, .cdk-column-import {
|
||||
max-width: 4em;
|
||||
width: 3em;
|
||||
}
|
||||
|
||||
.cdk-column-name>span {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.even {
|
||||
background-color: #f5f5f512;
|
||||
}
|
||||
|
||||
.tools {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tools .filter {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
.tools .upload {
|
||||
flex: 1 1 0;
|
||||
}
|
||||
|
||||
:host ::ng-deep th.mat-mdc-header-cell, :host ::ng-deep td.mat-mdc-cell, :host ::ng-deep td.mat-mdc-footer-cell {
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
|
||||
:host ::ng-deep td.mat-mdc-cell {
|
||||
border-bottom-style: inherit;
|
||||
}
|
||||
|
||||
table.content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mat-column-delete, .mat-column-import {
|
||||
width: 3em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
th.mat-mdc-header-cell:first-of-type, td.mat-mdc-cell:first-of-type, td.mat-mdc-footer-cell:first-of-type {
|
||||
padding-left: inherit;
|
||||
}
|
||||
|
||||
th.mat-mdc-header-cell:last-of-type, td.mat-mdc-cell:last-of-type, td.mat-mdc-footer-cell:last-of-type {
|
||||
padding-right: inherit;
|
||||
}
|
||||
|
||||
td .mat-mdc-button {
|
||||
min-width: inherit ! important;
|
||||
}
|
107
src/app/admin/admin-basket/basket.component.html
Normal file
107
src/app/admin/admin-basket/basket.component.html
Normal file
|
@ -0,0 +1,107 @@
|
|||
<div fxFlexFill fxLayout='column'>
|
||||
<h1>Basket: {{ basket.name }}</h1>
|
||||
<div class='tools'>
|
||||
<mat-form-field class='filter'>
|
||||
<mat-label>Filter table</mat-label>
|
||||
<input matInput
|
||||
(input)="applyFilter()"
|
||||
matTooltip="Filter the items of the basket from the table"
|
||||
[(ngModel)]="filterText"/>
|
||||
<button mat-button matSuffix mat-icon-button
|
||||
*ngIf="filterText"
|
||||
aria-label="Clear"
|
||||
(click)="filterText='';applyFilter()"
|
||||
>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
<gisaf-admin-basket-upload [basket]='basket' [dataSource]='dataSource'>
|
||||
</gisaf-admin-basket-upload>
|
||||
</div>
|
||||
<table mat-table matSort [dataSource]="dataSource" class='content'>
|
||||
<ng-container matColumnDef="delete">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<form [formGroup]="unlockDeleteFormGroup">
|
||||
<mat-checkbox formControlName='canDelete' matTooltip='Unlock delete buttons'>
|
||||
</mat-checkbox>
|
||||
</form>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let item">
|
||||
<button mat-button (click)="deleteItem(item)" matTooltip="Delete"
|
||||
[disabled]="!unlockDeleteFormGroup.controls['canDelete'].value">
|
||||
<mat-icon aria-label="delete">delete</mat-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="import">
|
||||
<th mat-header-cell *matHeaderCellDef>Import</th>
|
||||
<td mat-cell *matCellDef="let item">
|
||||
<button mat-button (click)="importItem(item, $event.ctrlKey)"
|
||||
matTooltip="Import to the database. Press 'Control' key for a dry run (no actual change will happen)"
|
||||
>
|
||||
<mat-icon aria-label="import">input</mat-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
|
||||
<td mat-cell *matCellDef="let item">
|
||||
<span (click)="download(item)" [title]="item.dir">{{ item.name }}</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="store">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Store</th>
|
||||
<td mat-cell *matCellDef="let item">{{ item.store }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="time">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Import time</th>
|
||||
<td mat-cell *matCellDef="let item">{{ isDate(item.time) ? (item.time | date:'dd/MM/yyyy, HH:mm:ss') : 'never' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="url">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>URL</th>
|
||||
<td mat-cell *matCellDef="let item">{{ item.url }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Status</th>
|
||||
<td mat-cell *matCellDef="let item">{{ item.status }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="project">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Project</th>
|
||||
<td mat-cell *matCellDef="let item">{{ item.project }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="surveyor">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Surveyor</th>
|
||||
<td mat-cell *matCellDef="let item">{{ item.surveyor }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="equipment">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Equipment</th>
|
||||
<td mat-cell *matCellDef="let item">{{ item.equipment }}</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="getColumns();sticky:true"></tr>
|
||||
<tr mat-row [ngClass]="{even: even}"
|
||||
*matRowDef="let row; let even = even; columns:getColumns()"
|
||||
></tr>
|
||||
</table>
|
||||
<!--
|
||||
<gisaf-admin-basket-item [file]='file' *ngFor='let file of basket.file'>
|
||||
</gisaf-admin-basket-item>
|
||||
-->
|
||||
<mat-paginator
|
||||
class="paginator"
|
||||
[pageSizeOptions]="[10, 20, 50, 100]"
|
||||
[pageIndex]='0'
|
||||
[pageSize]='10'
|
||||
showFirstLastButtons
|
||||
>
|
||||
</mat-paginator>
|
||||
</div>
|
107
src/app/admin/admin-basket/basket.component.ts
Normal file
107
src/app/admin/admin-basket/basket.component.ts
Normal file
|
@ -0,0 +1,107 @@
|
|||
import { Component, OnInit, Input, ViewChild, ElementRef,
|
||||
ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core'
|
||||
import { ActivatedRoute } from '@angular/router'
|
||||
import { UntypedFormGroup, UntypedFormControl } from '@angular/forms'
|
||||
|
||||
import { SelectionModel } from '@angular/cdk/collections'
|
||||
import { MatPaginator } from '@angular/material/paginator'
|
||||
import { MatSnackBar } from '@angular/material/snack-bar'
|
||||
import { MatSort } from '@angular/material/sort'
|
||||
import { MatTableDataSource } from '@angular/material/table'
|
||||
|
||||
import { AdminDataService } from '../admin-data.service'
|
||||
import { AdminBasketDataService, AdminBasket, AdminBasketFile } from './data.service'
|
||||
import { HtmlSnackbarComponent } from '../../custom-snackbar/custom-snackbar.component'
|
||||
|
||||
@Component({
|
||||
selector: 'gisaf-admin-basket',
|
||||
templateUrl: './basket.component.html',
|
||||
styleUrls: ['./basket.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AdminBasketComponent implements OnInit {
|
||||
constructor(
|
||||
public adminDataService: AdminDataService,
|
||||
public adminBasketDataService: AdminBasketDataService,
|
||||
private route: ActivatedRoute,
|
||||
private snackBar: MatSnackBar,
|
||||
private cdr: ChangeDetectorRef,
|
||||
) {}
|
||||
|
||||
basket: AdminBasket
|
||||
dataSource: MatTableDataSource<object>
|
||||
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator
|
||||
@ViewChild(MatSort, {static: true}) sort: MatSort
|
||||
selection = new SelectionModel(true, [])
|
||||
unlockDeleteFormGroup: UntypedFormGroup = new UntypedFormGroup({})
|
||||
columns: string[] = [
|
||||
'name',
|
||||
'status',
|
||||
'time',
|
||||
'store',
|
||||
'project',
|
||||
'surveyor',
|
||||
'equipment',
|
||||
'import',
|
||||
'delete',
|
||||
]
|
||||
filterText: string
|
||||
|
||||
ngOnInit() {
|
||||
this.route.data.subscribe(
|
||||
(basket: object) => {
|
||||
this.basket = basket['basket']
|
||||
this.dataSource = new MatTableDataSource(this.basket.files)
|
||||
this.dataSource.sort = this.sort
|
||||
this.dataSource.paginator = this.paginator
|
||||
this.cdr.markForCheck()
|
||||
}
|
||||
)
|
||||
this.unlockDeleteFormGroup = new UntypedFormGroup({
|
||||
'canDelete': new UntypedFormControl(),
|
||||
})
|
||||
}
|
||||
|
||||
getColumns() {
|
||||
return this.columns.filter(
|
||||
col => this.basket.columns.indexOf(col) != -1
|
||||
)
|
||||
}
|
||||
|
||||
applyFilter() {
|
||||
this.dataSource.filter = this.filterText.trim().toLowerCase()
|
||||
}
|
||||
|
||||
download(item: AdminBasketFile) {
|
||||
window.open('/download/basket/' + this.basket.name + '/' + item.id + '/' + item.name)
|
||||
}
|
||||
|
||||
importItem(item: AdminBasketFile, dryRun: boolean) {
|
||||
this.adminBasketDataService.importItem(this.basket.name, item.id, dryRun).subscribe(
|
||||
resp => {
|
||||
this.basket.files.find(row => row.id == item.id).time = new Date(resp.time)
|
||||
this.snackBar.openFromComponent(HtmlSnackbarComponent, {
|
||||
data: resp,
|
||||
//duration: 3000
|
||||
})
|
||||
this.cdr.markForCheck()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
deleteItem(item: AdminBasketFile) {
|
||||
this.adminBasketDataService.deleteItem(this.basket.name, item.id).subscribe(
|
||||
id => {
|
||||
let dsi = this.dataSource.data.findIndex(fi => fi['id'] == id)
|
||||
this.dataSource.data.splice(dsi, 1)
|
||||
// Force Angular change detection (??)
|
||||
this.dataSource.data = this.dataSource.data
|
||||
this.cdr.markForCheck()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
isDate(val: any) {
|
||||
return val instanceof Date && isFinite(<any>val)
|
||||
}
|
||||
}
|
223
src/app/admin/admin-basket/data.service.ts
Normal file
223
src/app/admin/admin-basket/data.service.ts
Normal file
|
@ -0,0 +1,223 @@
|
|||
import { Injectable } from '@angular/core'
|
||||
|
||||
import { Observable } from 'rxjs'
|
||||
import { map } from 'rxjs/operators'
|
||||
|
||||
import { Apollo, gql } from 'apollo-angular'
|
||||
|
||||
import { Project } from '../admin-data.service'
|
||||
|
||||
export class AdminBasketFile {
|
||||
constructor(
|
||||
public id: number,
|
||||
public dir: string,
|
||||
public name: string,
|
||||
public url: string,
|
||||
public md5: string,
|
||||
public time: Date,
|
||||
public comment: string,
|
||||
public status: string,
|
||||
public store: string,
|
||||
public project: string,
|
||||
public surveyor: string,
|
||||
public equipment: string,
|
||||
public import_result?: string,
|
||||
) {}
|
||||
}
|
||||
|
||||
export class AdminBasket {
|
||||
constructor(
|
||||
public name: string,
|
||||
public files?: AdminBasketFile[],
|
||||
public columns?: string[],
|
||||
public uploadFields?: string[],
|
||||
public projects?: Project[],
|
||||
) {}
|
||||
}
|
||||
|
||||
export class BasketImportResult {
|
||||
constructor(
|
||||
public time: Date,
|
||||
public message: string,
|
||||
public details?: string,
|
||||
) {}
|
||||
}
|
||||
|
||||
export class AdminBasketUploadFieldData {
|
||||
constructor(
|
||||
public stores: string[],
|
||||
public statuses: string[],
|
||||
public projects: string[],
|
||||
public surveyors: string[],
|
||||
public equipments: string[],
|
||||
) {}
|
||||
}
|
||||
|
||||
const getAdminBasketsQuery = gql`
|
||||
query admin_baskets {
|
||||
admin_baskets {
|
||||
name
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const getAdminBasketUploadFieldDataQuery = gql`
|
||||
query admin_basket_upload_field_data {
|
||||
admin_basket_upload_field_data {
|
||||
store
|
||||
status
|
||||
project
|
||||
surveyor
|
||||
equipment
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const getAdminBasketQuery = gql`
|
||||
query admin_basket ($name: String!) {
|
||||
admin_basket (name: $name) {
|
||||
name
|
||||
files {
|
||||
id
|
||||
name
|
||||
dir
|
||||
url
|
||||
md5
|
||||
time
|
||||
comment
|
||||
status
|
||||
store
|
||||
project
|
||||
surveyor
|
||||
equipment
|
||||
}
|
||||
columns
|
||||
uploadFields
|
||||
projects
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const deleteAdminBasketItemMutation = gql`
|
||||
mutation deleteBasketItem ($basket: String!, $id: Int!) {
|
||||
deleteBasketItem (basket: $basket, id: $id) {
|
||||
result
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const importAdminBasketItemMutation = gql`
|
||||
mutation importBasketItem ($basket: String!, $id: Int!, $dryRun: Boolean) {
|
||||
importBasketItem (basket: $basket, id: $id, dryRun: $dryRun) {
|
||||
result {
|
||||
message
|
||||
time
|
||||
details
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@Injectable()
|
||||
export class AdminBasketDataService {
|
||||
constructor(
|
||||
private apollo: Apollo,
|
||||
) {}
|
||||
|
||||
getBaskets(): Observable<AdminBasket[]> {
|
||||
// Get the list a basket names
|
||||
return this.apollo.query({
|
||||
query: getAdminBasketsQuery,
|
||||
}).pipe(map(
|
||||
res => res['data']['admin_baskets'].map(
|
||||
(data: object) => new AdminBasket(
|
||||
data['name'],
|
||||
)
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
getBasketUploadFieldData(): Observable<AdminBasketUploadFieldData> {
|
||||
// Get the list a basket names
|
||||
return this.apollo.query({
|
||||
query: getAdminBasketUploadFieldDataQuery,
|
||||
}).pipe(map(
|
||||
res => res['data']['admin_basket_upload_field_data'].map(
|
||||
(data: object) => new AdminBasketUploadFieldData(
|
||||
data['store'],
|
||||
data['status'],
|
||||
data['project'],
|
||||
data['surveyor'],
|
||||
data['equipment'],
|
||||
)
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
getBasket(name: string): Observable<AdminBasket> {
|
||||
// Get all info and content of a basket
|
||||
return this.apollo.query({
|
||||
query: getAdminBasketQuery,
|
||||
variables: {
|
||||
name: name
|
||||
}
|
||||
}).pipe(map(
|
||||
res => {
|
||||
let data = res['data']['admin_basket']
|
||||
return new AdminBasket(
|
||||
data['name'],
|
||||
data['files'].map(file => new AdminBasketFile(
|
||||
file['id'],
|
||||
file['dir'],
|
||||
file['name'],
|
||||
file['url'],
|
||||
file['md5'],
|
||||
new Date(file['time']),
|
||||
file['comment'],
|
||||
file['status'],
|
||||
file['store'],
|
||||
file['project'],
|
||||
file['surveyor'],
|
||||
file['equipment'],
|
||||
)),
|
||||
data['columns'],
|
||||
data['uploadFields'],
|
||||
// XXX: the proejct id isn't actually used in the UI,
|
||||
// but required in class definition
|
||||
data['projects'] && data['projects'].map(
|
||||
(projectName: string) => new Project(undefined, projectName)
|
||||
),
|
||||
)
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
importItem(basket: string, id: number, dryRun: boolean=false): Observable<BasketImportResult> {
|
||||
return this.apollo.mutate({
|
||||
mutation: importAdminBasketItemMutation,
|
||||
variables: {
|
||||
basket: basket,
|
||||
id: id,
|
||||
dryRun: dryRun
|
||||
}
|
||||
}).pipe(map(
|
||||
resp => new BasketImportResult(
|
||||
resp['data']['importBasketItem']['result']['time'],
|
||||
resp['data']['importBasketItem']['result']['message'],
|
||||
JSON.parse(resp['data']['importBasketItem']['result']['details']),
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
deleteItem(basket: string, id: number) {
|
||||
return this.apollo.mutate({
|
||||
mutation: deleteAdminBasketItemMutation,
|
||||
variables: {
|
||||
basket: basket,
|
||||
id: id,
|
||||
}
|
||||
}).pipe(map(
|
||||
resp => resp['data']['deleteBasketItem']['result']
|
||||
))
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue