Merge branch 'master' into 4-mongodb_api
This commit is contained in:
commit
400d03492b
@ -3,6 +3,8 @@ import {RestService} from '../../services/rest.service';
|
||||
import {NGXLogger} from 'ngx-logger';
|
||||
import {MatSnackBar} from '@angular/material/snack-bar';
|
||||
import {ImageMetadata} from '../../interfaces/interface';
|
||||
// @ts-ignore
|
||||
import metaFile from '../../../../../iotclient/metadata_full.json';
|
||||
|
||||
@Component({
|
||||
selector: 'app-file-uploader',
|
||||
@ -40,34 +42,36 @@ export class FileUploaderComponent implements OnInit {
|
||||
|
||||
if (this.filename) {
|
||||
this.id = this.filename;
|
||||
metaDict['filename'] = this.filename;
|
||||
} else {
|
||||
this.id = this.currentFileName;
|
||||
metaDict['filename'] = this.currentFileName;
|
||||
}
|
||||
|
||||
metaDict['filename'] = this.currentFileName;
|
||||
|
||||
if (this.mode === 'post') {
|
||||
if (this.longitude && this.latitude) {
|
||||
metaDict['longitude'] = Number.parseFloat(this.longitude);
|
||||
metaDict['latitude'] = Number.parseFloat(this.latitude);
|
||||
} else if (this.meta && this.meta.longitude && this.meta.latitude) {
|
||||
if (this.meta && this.meta.longitude && this.meta.latitude) {
|
||||
metaDict['longitude'] = this.meta.longitude;
|
||||
metaDict['latitude'] = this.meta.latitude;
|
||||
} else if (this.longitude && this.latitude) {
|
||||
metaDict['longitude'] = Number.parseFloat(this.longitude);
|
||||
metaDict['latitude'] = Number.parseFloat(this.latitude);
|
||||
} else {
|
||||
throw new Error('Long/Lat necessary if new file!');
|
||||
}
|
||||
}
|
||||
|
||||
if (this.name) {
|
||||
metaDict['name'] = this.name;
|
||||
} else if (this.meta && this.meta.name) {
|
||||
if (this.meta && this.meta.name) {
|
||||
metaDict['name'] = this.meta.name;
|
||||
} else if (this.name) {
|
||||
metaDict['name'] = this.name;
|
||||
} else {
|
||||
if (this.mode === 'post') {
|
||||
throw new Error('Name necessary if new file');
|
||||
}
|
||||
}
|
||||
|
||||
// metaDict['name'] = this.currentFileName;
|
||||
|
||||
if (this.tag) {
|
||||
metaDict['tag'] = this.tag;
|
||||
} else if (this.meta && this.meta.tag) {
|
||||
@ -95,6 +99,7 @@ export class FileUploaderComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.logger.debug('meta', metaFile);
|
||||
}
|
||||
|
||||
onFileSelected(fileEvent: Event) {
|
||||
@ -109,6 +114,12 @@ export class FileUploaderComponent implements OnInit {
|
||||
this.file = e.target.result;
|
||||
this.currentFileName = file.name;
|
||||
this.logger.debug('Selected file', this.currentFileName, this.file);
|
||||
const metaData = this.loadMetaForFile();
|
||||
if (metaData) {
|
||||
this.name = metaData.name;
|
||||
this.longitude = metaData.longitude + '';
|
||||
this.latitude = metaData.latitude + '';
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsArrayBuffer(file);
|
||||
@ -150,4 +161,14 @@ export class FileUploaderComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
private loadMetaForFile() {
|
||||
const metaData = (metaFile as {
|
||||
filename: string,
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
name: string;
|
||||
}[]).find(m => m.filename === this.currentFileName);
|
||||
this.logger.debug('Found corresponding meta', this.currentFileName, metaData);
|
||||
return metaData;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,21 +3,27 @@
|
||||
<div style="font-weight: bolder; font-size: 20px">
|
||||
<span style="width: 22.5em; display: inline-block; margin-left: 1.15em">Name</span>
|
||||
<span style="width: 22.5em; display: inline-block">Date</span>
|
||||
<span style="width: 22.5em; display: inline-block">File valid</span>
|
||||
<span style="width: 22.5em; display: inline-block">File available | valid</span>
|
||||
</div>
|
||||
|
||||
<mat-expansion-panel
|
||||
*ngFor="let image of filterOnlyNewestImageVersion() | slice:paginationGetStart():paginationGetEnd()"
|
||||
(opened)="loadImage(getImageIndex(image), image.filename.split('.')[0])"
|
||||
*ngFor="let image of filterOnlyNewestImageVersion() | slice:paginationGetStart():paginationGetEnd(); let i = index"
|
||||
(opened)="openImageExpansion[i][0] = true; loadImage(getImageIndex(image), image.identifier)"
|
||||
(closed)="openImageExpansion[i][0] = false;"
|
||||
[expanded]="openImageExpansion[i][0]"
|
||||
>
|
||||
<!-- (opened)="loadImage(getImageIndex(image), image.filename.split('.')[0])"-->
|
||||
<mat-expansion-panel-header (click)="$event.stopPropagation()">
|
||||
<h4 style="width: 25em"
|
||||
>{{image.name}}</h4>
|
||||
<h4 style="width: 25em"
|
||||
>{{image.datetime}}</h4>
|
||||
<h4 style="width: 25em; color: red">
|
||||
✓ | X (TO BE DONE)
|
||||
<h4 style="width: 25em; margin-left: 6em;" *ngIf="image.available !== undefined || image.valid !== undefined;
|
||||
else loadingValidity">
|
||||
{{image.available ? '✓' : 'X' }} | {{image.valid ? '✓' : 'X' }}
|
||||
</h4>
|
||||
<ng-template #loadingValidity>
|
||||
<h4 style="width: 25em; margin-left: 7em;">...</h4>
|
||||
</ng-template>
|
||||
<span style="float: right; margin-left: auto; margin-right: 1em;">
|
||||
<button mat-raised-button color="warn"
|
||||
(click)="deleteImage(image); $event.stopPropagation()">
|
||||
@ -43,17 +49,16 @@
|
||||
<ng-template #loadingImage>
|
||||
<mat-spinner style="margin: auto;"></mat-spinner>
|
||||
</ng-template>
|
||||
|
||||
</div>
|
||||
</mat-grid-tile>
|
||||
|
||||
<mat-grid-tile colspan="3">
|
||||
<div style="display: block; width: 100%">
|
||||
<h3>Metadata:</h3>
|
||||
<p *ngIf="image.version">version: {{image.version}}</p>
|
||||
<p *ngIf="image.filename">filename: {{image.filename}}</p>
|
||||
<p *ngIf="image.latitude">latitude: {{image.latitude}}</p>
|
||||
<p *ngIf="image.longitude">longitude: {{image.longitude}}</p>
|
||||
<p *ngIf="image.version">version: {{image.version}}</p>
|
||||
</div>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
@ -61,21 +66,57 @@
|
||||
<app-file-uploader [mode]="'put'"
|
||||
[filename]="image.filename.split('.')[0]"
|
||||
[meta]=image
|
||||
(reload)="this.reload.emit()"
|
||||
(reload)="reload.emit(); checkValidity()"
|
||||
></app-file-uploader>
|
||||
<!-- (reload)="image.image_b64 = undefined; this.loadImage(getImageIndex(image), image.identifier)"-->
|
||||
|
||||
<ng-container *ngIf="getRelatedImageMeta(image); let relatedImageMetadata">
|
||||
<mat-expansion-panel *ngIf="relatedImageMetadata.length > 0">
|
||||
<ng-container *ngIf="getRelatedImageMeta(image); let relatedImages">
|
||||
<mat-expansion-panel *ngIf="relatedImages.length > 0" [expanded]="openImageExpansion[i][1]">
|
||||
<mat-expansion-panel-header>
|
||||
Previous version meta
|
||||
Previous versions
|
||||
</mat-expansion-panel-header>
|
||||
<ng-template matExpansionPanelContent>
|
||||
<div *ngFor="let imageMeta of relatedImageMetadata">
|
||||
<p *ngIf="imageMeta.filename">filename: {{imageMeta.filename}}</p>
|
||||
<p *ngIf="imageMeta.latitude">latitude: {{imageMeta.latitude}}</p>
|
||||
<p *ngIf="imageMeta.longitude">longitude: {{imageMeta.longitude}}</p>
|
||||
<p *ngIf="imageMeta.version">version: {{imageMeta.version}}</p>
|
||||
</div>
|
||||
|
||||
<mat-expansion-panel *ngFor="let relImage of relatedImages.slice().reverse(); let j = index"
|
||||
(opened)="loadImage(-1, relImage.identifier, relImage);
|
||||
openImageExpansion[i][2+j]=true"
|
||||
(closed)="openImageExpansion[i][2+j] = false"
|
||||
[expanded]="openImageExpansion[i][2+j]"
|
||||
>
|
||||
<!-- <mat-divider></mat-divider>-->
|
||||
<!-- <p *ngIf="imageMeta.version">version: {{imageMeta.version}}</p>-->
|
||||
<!-- <p *ngIf="imageMeta.name">name: {{imageMeta.name}}</p>-->
|
||||
<!-- <p *ngIf="imageMeta.tag">tag: {{imageMeta.tag}}</p>-->
|
||||
<!-- <p *ngIf="imageMeta.filename">filename: {{imageMeta.filename}}</p>-->
|
||||
<!-- <p *ngIf="imageMeta.latitude">latitude: {{imageMeta.latitude}}</p>-->
|
||||
<!-- <p *ngIf="imageMeta.longitude">longitude: {{imageMeta.longitude}}</p>-->
|
||||
<mat-expansion-panel-header>
|
||||
<p>version: {{relImage.version ? relImage.version : 0}}</p>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<mat-grid-list cols="4" rowHeight="22em" style="width: 100%; margin: auto">
|
||||
|
||||
<mat-grid-tile style="justify-content: left!important;" colspan="1">
|
||||
<div style="width: 20em; height: 20em; border: solid; margin-bottom: 1em; display: flex">
|
||||
<img *ngIf="relImage.image_b64, let subB64; else loadingSubImage"
|
||||
[src]="subB64"
|
||||
style="width: 100%; margin: auto" [alt]="image.filename"/>
|
||||
<ng-template #loadingSubImage>
|
||||
<mat-spinner style="margin: auto;"></mat-spinner>
|
||||
</ng-template>
|
||||
</div>
|
||||
</mat-grid-tile>
|
||||
|
||||
<mat-grid-tile colspan="3">
|
||||
<div style="display: block; width: 100%">
|
||||
<p *ngIf="relImage.filename">filename: {{relImage.filename}}</p>
|
||||
<p *ngIf="relImage.latitude">latitude: {{relImage.latitude}}</p>
|
||||
<p *ngIf="relImage.longitude">longitude: {{relImage.longitude}}</p>
|
||||
</div>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
</mat-expansion-panel>
|
||||
|
||||
</ng-template>
|
||||
</mat-expansion-panel>
|
||||
</ng-container>
|
||||
@ -87,11 +128,12 @@
|
||||
[length]="filterOnlyNewestImageVersion().length"
|
||||
[pageSize]="pageSizeOptions[0]"
|
||||
[pageSizeOptions]="pageSizeOptions"
|
||||
(page)="lastPageEvent = $event"
|
||||
(page)="lastPageEvent = $event; openImageExpansion = ALL_CLOSED_DEFAULT; checkValidity()"
|
||||
showFirstLastButtons
|
||||
hidePageSize
|
||||
></mat-paginator>
|
||||
|
||||
<mat-divider style="margin-top: 2em"></mat-divider>
|
||||
<h3>Upload New Image</h3>
|
||||
<app-file-uploader [mode]="'post'" (reload)="reload.emit()"></app-file-uploader>
|
||||
<app-file-uploader [mode]="'post'" (reload)="reload.emit(); checkValidity()"></app-file-uploader>
|
||||
<mat-divider style="margin-top: 2em"></mat-divider>
|
||||
|
||||
@ -20,6 +20,9 @@ export class ImagesComponent implements OnInit, AfterViewInit {
|
||||
pageSizeOptions: number[] = [5, 10, 25, 100];
|
||||
lastPageEvent: PageEvent;
|
||||
|
||||
ALL_CLOSED_DEFAULT = [...Array(5)].map(() => this.getDefaultBoolDict(false));
|
||||
openImageExpansion = this.ALL_CLOSED_DEFAULT;
|
||||
|
||||
constructor(
|
||||
public restService: RestService,
|
||||
private logger: NGXLogger,
|
||||
@ -27,8 +30,15 @@ export class ImagesComponent implements OnInit, AfterViewInit {
|
||||
) {
|
||||
}
|
||||
|
||||
private getDefaultBoolDict(value: boolean) {
|
||||
return new Proxy({}, {
|
||||
get: (target, name) => name in target ? target[name] : value
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.lastPageEvent = {pageIndex: 0, pageSize: this.pageSizeOptions[0], length: this.images.length};
|
||||
this.checkValidity();
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
@ -50,29 +60,58 @@ export class ImagesComponent implements OnInit, AfterViewInit {
|
||||
}).catch(err => this.logger.error(err));
|
||||
}
|
||||
|
||||
loadImage(i: number, id: string): void {
|
||||
this.restService.getImage(id).toPromise().then(image => {
|
||||
this.images[i].image_b64 = 'data:image/jpg;base64,' + image.image_data;
|
||||
this.logger.debug('image_b64', i, id, this.images[i].image_b64);
|
||||
}).catch(err => {
|
||||
this.logger.error('loadImage', i, id, err);
|
||||
});
|
||||
loadImage(i: number, id: string, relImage?: ImageMetadata): void {
|
||||
if (!relImage) {
|
||||
this.restService.getImage(id).toPromise().then(image => {
|
||||
this.images[i].image_b64 = 'data:image/jpg;base64,' + image.image_data;
|
||||
this.logger.debug('image_b64', i, id, this.images[i].image_b64);
|
||||
}).catch(err => {
|
||||
this.logger.error('loadImage', i, id, err);
|
||||
});
|
||||
} else {
|
||||
this.restService.getImage(id).toPromise().then(image => {
|
||||
relImage.image_b64 = 'data:image/jpg;base64,' + image.image_data;
|
||||
this.logger.debug('image_b64', i, id, relImage.image_b64);
|
||||
}).catch(err => {
|
||||
this.logger.error('loadImage', i, id, err);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
filterOnlyNewestImageVersion() {
|
||||
return this.images.filter(image => !image.previous);
|
||||
return this.images.filter(image => !image.identifier.includes('_'));
|
||||
}
|
||||
|
||||
getImageIndex(image: ImageMetadata) {
|
||||
return this.images.findIndex(img => image === img);
|
||||
}
|
||||
|
||||
getRelatedImageMeta(image: ImageMetadata, images: ImageMetadata[] = []) {
|
||||
const found = this.images.find(im => im.previous === image.identifier);
|
||||
if (found) {
|
||||
return this.getRelatedImageMeta(found, images.concat(found));
|
||||
} else {
|
||||
return images;
|
||||
}
|
||||
getRelatedImageMeta(image: ImageMetadata) {
|
||||
return this.images.filter(im => im.identifier.includes(image.identifier) && im.identifier !== image.identifier);
|
||||
}
|
||||
|
||||
checkValidity() {
|
||||
setTimeout(() => {
|
||||
const start = this.paginationGetStart();
|
||||
const end = this.paginationGetEnd();
|
||||
const filteredImages = this.filterOnlyNewestImageVersion();
|
||||
this.logger.debug('check validity', start, end, filteredImages);
|
||||
|
||||
for (let i = start; i < end; i++) {
|
||||
try {
|
||||
filteredImages[i].valid = undefined;
|
||||
filteredImages[i].available = undefined;
|
||||
this.restService.checkImageValid(filteredImages[i].identifier).toPromise().then(
|
||||
res => {
|
||||
filteredImages[i].valid = res.valid;
|
||||
filteredImages[i].available = res.available;
|
||||
}
|
||||
);
|
||||
} catch {
|
||||
this.logger.debug('skip non-existing index', i);
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,19 @@ export class LandingComponent implements OnInit {
|
||||
}
|
||||
|
||||
loadImages(): void {
|
||||
this.restService.getAllImages().toPromise().then(images => this.images = images).catch(err => this.logger.error(err));
|
||||
this.restService.getAllImages().toPromise().then(images =>
|
||||
this.images = images.sort((im1, im2) => {
|
||||
if (im1.name > im2.name) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (im1.name < im2.name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
})
|
||||
).catch(err => this.logger.error(err));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -5,15 +5,33 @@
|
||||
[longitude]="longitude"
|
||||
[zoom]="2">
|
||||
<agm-marker
|
||||
*ngFor="let image of images"
|
||||
*ngFor="let image of getImagesForMap()"
|
||||
[latitude]="image.latitude"
|
||||
[longitude]="image.longitude"
|
||||
[opacity]="1"
|
||||
[markerDraggable]="true"
|
||||
(markerClick)="selectMarker($event)"
|
||||
[markerDraggable]="false"
|
||||
(markerClick)="loadImage(selectMarker($event))"
|
||||
></agm-marker>
|
||||
</agm-map>
|
||||
|
||||
<p *ngIf="selectedImage">
|
||||
<div *ngIf="selectedImage">
|
||||
Latitude: {{ selectedImage.latitude }} Longitude: {{ selectedImage.longitude }} Name: {{selectedImage.name}}
|
||||
</p>
|
||||
|
||||
<mat-divider style="margin-bottom: 1em;"></mat-divider>
|
||||
|
||||
<div style="width: 20em; height: 20em; border: solid; margin-bottom: 1em; display: flex">
|
||||
<img *ngIf="selectedImage.image_b64, let b64; else loadingImage"
|
||||
[src]="b64"
|
||||
style="width: 100%; margin: auto" [alt]="selectedImage.filename"/>
|
||||
<ng-template #loadingImage>
|
||||
<mat-spinner style="margin: auto;"></mat-spinner>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<p *ngIf="selectedImage.filename">filename: {{selectedImage.filename}}</p>
|
||||
<!-- <p *ngIf="selectedImage.latitude">latitude: {{selectedImage.latitude}}</p>-->
|
||||
<!-- <p *ngIf="selectedImage.longitude">longitude: {{selectedImage.longitude}}</p>-->
|
||||
<p *ngIf="selectedImage.version">version: {{selectedImage.version}}</p>
|
||||
<p *ngIf="selectedImage.tag">tag: {{selectedImage.tag}}</p>
|
||||
<!-- <p *ngIf="selectedImage.name">name: {{selectedImage.name}}</p>-->
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {ImageMetadata} from '../../interfaces/interface';
|
||||
import {RestService} from '../../services/rest.service';
|
||||
|
||||
// @ts-ignore
|
||||
@Component({
|
||||
@ -16,7 +17,7 @@ export class MapComponent implements OnInit {
|
||||
latitude = 43.879078;
|
||||
longitude = -103.4615581;
|
||||
|
||||
constructor() {
|
||||
constructor(private restService: RestService) {
|
||||
|
||||
}
|
||||
|
||||
@ -25,6 +26,25 @@ export class MapComponent implements OnInit {
|
||||
}
|
||||
|
||||
selectMarker(event) {
|
||||
this.selectedImage = this.images.find(image => image.latitude === event.latitude && image.longitude === event.longitude);
|
||||
console.log(event, this.images);
|
||||
this.selectedImage = this.images.find(image =>
|
||||
image.latitude === event.latitude && image.longitude === event.longitude && !image.identifier.includes('_')
|
||||
);
|
||||
return this.selectedImage;
|
||||
}
|
||||
|
||||
getImagesForMap() {
|
||||
return this.images.filter(im => !im.identifier.includes('_'));
|
||||
}
|
||||
|
||||
loadImage(image: ImageMetadata): void {
|
||||
image.image_b64 = '';
|
||||
this.restService.getImage(image.identifier).toPromise().then(im => {
|
||||
image.image_b64 = 'data:image/jpg;base64,' + im.image_data;
|
||||
}).catch(err => {
|
||||
console.error('loadImage', image, err);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -3,6 +3,8 @@ export interface StorageHealth {
|
||||
}
|
||||
|
||||
export interface ImageMetadata {
|
||||
available?: boolean;
|
||||
valid?: boolean;
|
||||
id: string;
|
||||
datetime: string;
|
||||
device_id: string;
|
||||
@ -34,3 +36,8 @@ export interface ImagePostResponse {
|
||||
id: string;
|
||||
filename: string;
|
||||
}
|
||||
|
||||
export interface Validity {
|
||||
available: boolean;
|
||||
valid: boolean;
|
||||
}
|
||||
|
||||
@ -4,12 +4,11 @@ import {NGXLogger} from 'ngx-logger';
|
||||
import {environment} from '../../environments/environment';
|
||||
import {Observable} from 'rxjs';
|
||||
import {tap} from 'rxjs/operators';
|
||||
import {GetImageResponse, ImagePostResponse, StorageHealth} from '../interfaces/interface';
|
||||
import {GetImageResponse, ImagePostResponse, StorageHealth, Validity} from '../interfaces/interface';
|
||||
|
||||
@Injectable()
|
||||
export class RestService {
|
||||
|
||||
constructor(
|
||||
constructor(
|
||||
private logger: NGXLogger,
|
||||
private http: HttpClient
|
||||
) {
|
||||
@ -21,6 +20,7 @@ export class RestService {
|
||||
private deleteImageUrl = this.imageUrl + '/delete';
|
||||
private postImageUrl = this.imageUrl + '/post';
|
||||
private updateImageUrl = this.imageUrl + '/update';
|
||||
private getValidityOfImageUrl = this.imageUrl + '/status';
|
||||
private healthCheckUrl = this.currentLocation + '/check';
|
||||
|
||||
public getAllImages(): Observable<any> {
|
||||
@ -78,4 +78,10 @@ export class RestService {
|
||||
tap(next => this.logger.debug('healthCheck', next))
|
||||
);
|
||||
}
|
||||
|
||||
public checkImageValid(id: string): Observable<Validity> {
|
||||
return this.http.get<Validity>(this.getValidityOfImageUrl + '/' + id).pipe(
|
||||
tap(next => this.logger.debug('checkValid', id, next))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,9 @@
|
||||
"es2017",
|
||||
"dom"
|
||||
],
|
||||
"allowJs": true
|
||||
"allowJs": true,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import requests
|
||||
import json
|
||||
import time
|
||||
from datetime import datetime
|
||||
import sys, getopt
|
||||
import sys, getopt, random
|
||||
|
||||
def build_post_payload(identifier, metadata_payload, file_payload):
|
||||
return {
|
||||
@ -233,16 +233,75 @@ def print_cursor():
|
||||
print('Cursor on ' + str(index) + " out of " + str(len(metadata)) + " - " + metadata[index]['filename'])
|
||||
|
||||
|
||||
testCommands=[]
|
||||
testscriptData=[]
|
||||
|
||||
def test_script(argv):
|
||||
try:
|
||||
testscriptData.append(False)
|
||||
testscriptData.append(0)
|
||||
opts, args=getopt.getopt(argv,"t")
|
||||
except getopt.GetoptError:
|
||||
print("Error by starting test script")
|
||||
sys.exit(2)
|
||||
for opt, arg in opts:
|
||||
if opt == '-t':
|
||||
testscriptData.clear()
|
||||
testscriptData.append(True)
|
||||
testCommands.append("deleteall")
|
||||
for i in range(2):
|
||||
testCommands.append("trigger")
|
||||
testCommands.append("fetchall")
|
||||
testCommands.append("delete")
|
||||
testCommands.append("fetchall")
|
||||
for i in range(3):
|
||||
testCommands.append("trigger")
|
||||
testCommands.append("update")
|
||||
testCommands.append("fetchall")
|
||||
for i in range(2):
|
||||
testCommands.append("trigger")
|
||||
testCommands.append("update")
|
||||
testCommands.append("trigger")
|
||||
testCommands.append("delete")
|
||||
testCommands.append("fetchall")
|
||||
for i in range(3):
|
||||
testCommands.append("trigger")
|
||||
testCommands.append("update")
|
||||
testCommands.append("fetchall")
|
||||
for i in range(2):
|
||||
testCommands.append("trigger")
|
||||
testCommands.append("fetchall")
|
||||
testCommands.append("delete")
|
||||
testCommands.append("fetchall")
|
||||
for i in range(5):
|
||||
testCommands.append("trigger")
|
||||
testCommands.append("fetchall")
|
||||
testCommands.append("exit")
|
||||
testscriptData.append(len(testCommands))
|
||||
else:
|
||||
testscriptData.append(False)
|
||||
testscriptData.append(0)
|
||||
|
||||
|
||||
# main input loop
|
||||
command = "dummy"
|
||||
|
||||
|
||||
test_script(sys.argv[1:])
|
||||
i = 0
|
||||
while (command.lower() not in ["exit", "quit", "end"]):
|
||||
|
||||
try:
|
||||
command = input("Please enter command: ")
|
||||
except:
|
||||
print()
|
||||
if testscriptData[0] and i < testscriptData[1]:
|
||||
command = testCommands[i]
|
||||
if i > 0:
|
||||
time.sleep(random.randrange(5, 60))
|
||||
print(datetime.now())
|
||||
if command == "delete" or command == "update":
|
||||
index -= 1
|
||||
i+=1
|
||||
else:
|
||||
command = input("Please enter command: ")
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
print("Error while reading keyboard input")
|
||||
break
|
||||
command_split = command.split(" ")
|
||||
|
||||
@ -70,7 +70,7 @@ class DropboxService(StorageServiceInterface):
|
||||
return file_bytes
|
||||
|
||||
@staticmethod
|
||||
def move_file(identifier_from: str, identifier_to: str, file: bytes) -> bool:
|
||||
def move_file(identifier_from: str, identifier_to: str) -> bool:
|
||||
"""Move/Rename a file on the dropbox storage.
|
||||
|
||||
:param identifier_from: Location of the file to be moved
|
||||
|
||||
@ -66,7 +66,7 @@ class MinioService(StorageServiceInterface):
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def move_file(identifier_from: str, identifier_to: str, file: bytes) -> bool:
|
||||
def move_file(identifier_from: str, identifier_to: str) -> bool:
|
||||
"""Move/Rename a file on the S3 storage.
|
||||
|
||||
Consists of a PUT method (copying the object) and a delete method.
|
||||
@ -79,6 +79,8 @@ class MinioService(StorageServiceInterface):
|
||||
filename_from = identifier_from + '.jpg'
|
||||
filename_to = identifier_to
|
||||
|
||||
file = MinioService.read_file(filename_from)
|
||||
|
||||
if not MinioService.delete_file(filename_from):
|
||||
print("MinioService: Updating (delete) file {} failed".format(filename_from))
|
||||
return False
|
||||
|
||||
@ -74,20 +74,22 @@ class MongoDBService:
|
||||
|
||||
old = {"identifier": identifier} # Query for old version
|
||||
|
||||
metadata_orig = MongoDBService.getSingle(identifier)
|
||||
metadata_new = metadata_orig
|
||||
metadata_new['previous'] = identifier + '_' + str(metadata_orig['version'])
|
||||
identifier_changed = identifier + '_' + str(metadata_orig['version']) # Set identifier to include version
|
||||
metadata_new['version'] = str(int(metadata_new['version']) + 1) # Increment version by one
|
||||
existing_meta_data_copy = MongoDBService.getSingle(identifier)
|
||||
id_for_previous = identifier + '_' + str(meta['version'])
|
||||
existing_meta_data_copy['previous'] = id_for_previous
|
||||
identifier_changed = id_for_previous # Set identifier to include version
|
||||
|
||||
metadata_new.update(meta)
|
||||
del meta['filename']
|
||||
existing_meta_data_copy.update(meta)
|
||||
|
||||
existing_meta_data_copy['version'] = meta['version'] + 1 # Increment version by one
|
||||
|
||||
print("MongoDBService: identifier_changed: ", identifier_changed)
|
||||
col.update_one(old, {"$set": {"identifier": identifier_changed, "filename": identifier_changed + '.jpg'}})
|
||||
|
||||
print("MongoDBService: Old object is ", col.find_one({"identifier": identifier_changed}))
|
||||
|
||||
MongoDBService.createSingle(metadata_new, identifier, decoded_image)
|
||||
MongoDBService.createSingle(existing_meta_data_copy, identifier, decoded_image)
|
||||
print("MongoDBService: New object is ", col.find_one({"identifier": identifier}))
|
||||
|
||||
return True
|
||||
|
||||
@ -24,6 +24,7 @@ urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
url(r'^image/get/all$', ImageEndpoint.image_api_get_all),
|
||||
url(r'^image/get/(?P<identifier>[\w-]+)$', ImageEndpoint.image_api_get_single),
|
||||
url(r'^image/status/(?P<identifier>[\w-]+)$', ImageEndpoint.image_api_get_status),
|
||||
url(r'^image/get/(?P<identifier>[\w-]+)/version/(?P<version>[\w-]+)$', ImageEndpoint.image_api_get_single_version),
|
||||
url(r'^image/delete/all$', ImageEndpoint.image_api_delete_all),
|
||||
url(r'^image/delete/(?P<identifier>[\w-]+)$', ImageEndpoint.image_api_delete),
|
||||
|
||||
@ -48,6 +48,31 @@ class ImageEndpoint:
|
||||
logger.debug('Image GET single call: {}'.format(request))
|
||||
return ImageEndpoint.get_image(identifier)
|
||||
|
||||
@staticmethod
|
||||
@api_view(['GET'])
|
||||
def image_api_get_status(request, identifier):
|
||||
# get metadata from MongoDB
|
||||
metadata = MongoDBService.getSingle(identifier)
|
||||
if not metadata:
|
||||
return JsonResponse({'valid': False, 'available': False})
|
||||
|
||||
# get stored SHA512 hash
|
||||
stored_hash = metadata.get('sha512', '')
|
||||
no_image = True
|
||||
|
||||
for service in ImageEndpoint.storageServiceList:
|
||||
service_image_bytes = service.read_file(metadata['filename'])
|
||||
if service_image_bytes is not None:
|
||||
no_image = False
|
||||
actual_service_hash = create_sha512(service_image_bytes)
|
||||
if stored_hash != actual_service_hash:
|
||||
return JsonResponse({'valid': False, 'available': True})
|
||||
|
||||
if no_image:
|
||||
JsonResponse({'valid': False, 'available': False})
|
||||
|
||||
return JsonResponse({'valid': True, 'available': True})
|
||||
|
||||
@staticmethod
|
||||
def get_image(identifier):
|
||||
|
||||
@ -210,7 +235,6 @@ class ImageEndpoint:
|
||||
def image_api_update(request, identifier):
|
||||
logger.debug('Image UPDATE single call: {}'.format(request))
|
||||
|
||||
|
||||
try:
|
||||
payload = json.loads(request.body)
|
||||
except json.decoder.JSONDecodeError:
|
||||
@ -222,7 +246,7 @@ class ImageEndpoint:
|
||||
'Error': str(e)}, status=500, safe=False)
|
||||
|
||||
b64encoded_image = payload['image_data']
|
||||
identifier = payload['id']
|
||||
# identifier = identifier
|
||||
metadata = payload['metadata']
|
||||
filename = payload['metadata']['filename']
|
||||
|
||||
@ -233,6 +257,7 @@ class ImageEndpoint:
|
||||
'id': identifier}, status=404, safe=False)
|
||||
|
||||
metadata['version'] = mongodb_metadata['version']
|
||||
filename = mongodb_metadata['filename']
|
||||
|
||||
decoded_image = WrapperService.unwrap_file(b64encoded_image)
|
||||
|
||||
@ -240,7 +265,7 @@ class ImageEndpoint:
|
||||
|
||||
for service in ImageEndpoint.storageServiceList:
|
||||
orig_new_name = identifier + '_' + str(metadata['version']) + '.jpg'
|
||||
if not service.move_file(identifier, orig_new_name, decoded_image):
|
||||
if not service.move_file(identifier, orig_new_name):
|
||||
print("Could not move file from {} to {}".format(identifier, orig_new_name))
|
||||
if not service.create_file(filename, decoded_image):
|
||||
print("Could not save updated image to " + service.name)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user