From 05a118b069dea14eecaa67915db1ea593d069ae8 Mon Sep 17 00:00:00 2001 From: VLE2FE Date: Fri, 7 Aug 2020 10:49:18 +0200 Subject: [PATCH] changed status, added restoring samples and changed password guidelines --- src/app/app.component.html | 10 ++++---- src/app/app.component.ts | 4 ++-- src/app/models/sample.model.ts | 1 + src/app/samples/samples.component.html | 33 ++++++++++++++++++++------ src/app/samples/samples.component.scss | 2 +- src/app/samples/samples.component.ts | 33 ++++++++++++++++++-------- src/app/services/validation.service.ts | 21 ++-------------- 7 files changed, 60 insertions(+), 44 deletions(-) diff --git a/src/app/app.component.html b/src/app/app.component.html index 6244c7f..6899d22 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,18 +1,18 @@ - +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index b2a3a5b..4ea85c2 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -21,7 +21,7 @@ export class AppComponent { bugReport = {do: '', work: ''}; constructor( - public loginService: LoginService, + public login: LoginService, private router: Router ) { } @@ -31,7 +31,7 @@ export class AppComponent { } logout() { - this.loginService.logout(); + this.login.logout(); this.router.navigate(['/']); } diff --git a/src/app/models/sample.model.ts b/src/app/models/sample.model.ts index fd5f741..9172d3a 100644 --- a/src/app/models/sample.model.ts +++ b/src/app/models/sample.model.ts @@ -23,6 +23,7 @@ export class SampleModel extends BaseModel { sample_references: {sample_id: IdModel, relation: string}[], custom_fields: {[prop: string]: string} } = {comment: '', sample_references: [], custom_fields: {}}; + status = ''; added: Date = null; deserialize(input: any): this { diff --git a/src/app/samples/samples.component.html b/src/app/samples/samples.component.html index 022b8a9..3666bf9 100644 --- a/src/app/samples/samples.component.html +++ b/src/app/samples/samples.component.html @@ -6,9 +6,9 @@ - - Validate + {{validation ? 'Validate' : 'Validation'}}
@@ -19,13 +19,20 @@
+ [disabled]="!filters.status.new && !filters.status.deleted" + (ngModelChange)="loadSamples({firstPage: true})"> validated - new + + deleted +
@@ -135,7 +142,8 @@ - + {{sample.number}} @@ -151,12 +159,16 @@ {{sample.batch}} {{sample.notes | object: ['_id', 'sample_references']}} {{sample[key[1]] | exists: key[2]}} + {{sample.status}} {{sample.added | date:'dd/MM/yy'}} - + *ngIf="sample.status !== 'deleted' && + (login.isLevel.dev || (login.isLevel.write && sample.user_id === login.userId))"> + + @@ -208,6 +220,13 @@ {{measurement.value}} User{{sampleDetailsSample.user}} + Status{{sampleDetailsSample.status}}
+ + + + Do you really want to restore this sample? + + diff --git a/src/app/samples/samples.component.scss b/src/app/samples/samples.component.scss index 9684546..decf552 100644 --- a/src/app/samples/samples.component.scss +++ b/src/app/samples/samples.component.scss @@ -17,7 +17,7 @@ rb-table { width: 100%; } -.rb-ic.rb-ic-edit { + td .clickable.rb-ic { font-size: 1.1rem; color: $color-gray-silver-sand; cursor: pointer; diff --git a/src/app/samples/samples.component.ts b/src/app/samples/samples.component.ts index 45a7ee6..4425339 100644 --- a/src/app/samples/samples.component.ts +++ b/src/app/samples/samples.component.ts @@ -39,13 +39,12 @@ export class SamplesComponent implements OnInit { totalSamples = 0; // total number of samples csvUrl = ''; // store url separate so it only has to be generated when clicking the download button filters = { - status: {new: true, validated: true}, + status: {new: true, validated: true, deleted: false}, pageSize: 25, toPage: 0, sort: 'added-asc', filters: [ {field: 'number', label: 'Number', active: false, autocomplete: [], mode: 'eq', values: ['']}, - {field: 'material.number', label: 'Material number', active: false, autocomplete: [], mode: 'eq', values: ['']}, {field: 'material.name', label: 'Material name', active: false, autocomplete: [], mode: 'eq', values: ['']}, {field: 'material.supplier', label: 'Supplier', active: false, autocomplete: [], mode: 'eq', values: ['']}, {field: 'material.group', label: 'Material', active: false, autocomplete: [], mode: 'eq', values: ['']}, @@ -72,7 +71,8 @@ export class SamplesComponent implements OnInit { {id: 'color', label: 'Color', active: true, sortable: true}, {id: 'batch', label: 'Batch', active: true, sortable: true}, {id: 'notes', label: 'Notes', active: false, sortable: false}, - {id: 'added', label: 'Added', active: true, sortable: true}, + {id: 'status', label: 'Status', active: true, sortable: true}, + {id: 'added', label: 'Added', active: true, sortable: true} ]; isActiveKey: {[key: string]: boolean} = {}; activeKeys: KeyInterface[] = []; @@ -97,18 +97,16 @@ export class SamplesComponent implements OnInit { this.filters.filters.find(e => e.field === 'color').autocomplete = [...new Set(this.d.arr.materials.reduce((s, e) => {s.push(...e.numbers.map(el => el.color)); return s; }, []))]; this.loadSamples(); - console.log(this.d.id.materials); }); this.d.load('materialSuppliers', () => { this.filters.filters.find(e => e.field === 'material.supplier').autocomplete = this.d.arr.materialSuppliers; }); this.d.load('materialGroups', () => { - console.log(this.d.arr.materialGroups); this.filters.filters.find(e => e.field === 'material.group').autocomplete = this.d.arr.materialGroups; }); this.d.load('userKey'); this.loadTemplateKeys('material', 'type'); - this.loadTemplateKeys('measurement', 'added'); + this.loadTemplateKeys('measurement', 'status'); } loadTemplateKeys(collection, insertBefore) { @@ -185,9 +183,7 @@ export class SamplesComponent implements OnInit { }) { // return url to fetch samples const additionalTableKeys = ['material_id', '_id', 'user_id']; // keys which should always be added if export = false const query: string[] = []; - query.push( - 'status=' + (this.filters.status.new && this.filters.status.validated ? 'all' : (this.filters.status.new ? 'new' : 'validated')) - ); + query.push(...Object.keys(this.filters.status).filter(e => this.filters.status[e]).map(e => 'status[]=' + e)); if (options.paging) { if (this.samples[0]) { // do not include from-id when page size was changed if (!options.pagingOptions.firstPage) { @@ -326,6 +322,7 @@ export class SamplesComponent implements OnInit { this.api.put('/sample/validate/' + sample._id); } }); + this.loadSamples(); this.validation = false; } else { @@ -333,9 +330,25 @@ export class SamplesComponent implements OnInit { } } + restoreSample(id, modal, event) { + this.stopPropagation(event); + this.modalService.open(modal).then(res => { + if (res) { + this.api.put('/sample/restore/' + id, {}, ignore => { + this.samples.find(e => e._id === id).status = 'new'; + }); + } + }); + } + selectAll(event) { this.samples.forEach(sample => { - sample.validate = event.target.checked; + if (sample.status !== 'deleted') { + sample.validate = event.target.checked; + } + else { + sample.validate = false; + } }); } diff --git a/src/app/services/validation.service.ts b/src/app/services/validation.service.ts index a58ec72..070e3a5 100644 --- a/src/app/services/validation.service.ts +++ b/src/app/services/validation.service.ts @@ -14,7 +14,7 @@ export class ValidationService { .max(128); private vPassword = Joi.string() - .pattern(/^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!"#%&'()*+,-.\/:;<=>?@[\]^_`{|}~])(?=\S+$)[a-zA-Z0-9!"#%&'()*+,\-.\/:;<=>?@[\]^_`{|}~]{8,}$/) + .min(8) .max(128); constructor() { } @@ -44,24 +44,7 @@ export class ValidationService { password(data) { const {ignore, error} = this.vPassword.validate(data); if (error) { - if (Joi.string().min(8).validate(data).error) { - return {ok: false, error: 'password must have at least 8 characters'}; - } - else if (Joi.string().pattern(/[a-z]+/).validate(data).error) { - return {ok: false, error: 'password must have at least one lowercase character'}; - } - else if (Joi.string().pattern(/[A-Z]+/).validate(data).error) { - return {ok: false, error: 'password must have at least one uppercase character'}; - } - else if (Joi.string().pattern(/[0-9]+/).validate(data).error) { - return {ok: false, error: 'password must have at least one number'}; - } - else if (Joi.string().pattern(/[!"#%&'()*+,-.\/:;<=>?@[\]^_`{|}~]+/).validate(data).error) { - return {ok: false, error: 'password must have at least one of the following characters !"#%&\'()*+,-.\\/:;<=>?@[]^_`{|}~'}; - } - else { - return {ok: false, error: 'password must only contain a-zA-Z0-9!"#%&\'()*+,-./:;<=>?@[]^_`{|}~'}; - } + return {ok: false, error: 'password must have at least 8 characters'}; } return {ok: true, error: ''}; }