Skip to content
Permalink
Browse files
feat(value): refactor boolean value (DEV-98) (#554)
* fix(value): display boolean value even it doesn't exist

* style(boolean value): display checkbox instead of true or false

* refactor(boolean-value): format code

* chore(advanced search): compare boolean value in useful way

* style(search): refactor advanced search

* style(search): refactor advanced search

* style(search): resolve style issue in date picker

* test(search): fix tests

* test(search): fix test in advanced search

* style(value): fixing styling issue in boolean value
  • Loading branch information
kilchenmann committed Oct 20, 2021
1 parent 436c270 commit 7affa5e7c94b35929d795e29380fb31b9906c520
Show file tree
Hide file tree
Showing 30 changed files with 178 additions and 92 deletions.
@@ -137,7 +137,11 @@ <h3 class="label mat-title">
</div>
<!-- Add button -->
<div *ngIf="addValueIsAllowed(prop) && project?.status">
<button mat-icon-button type="button" class="value-action create"
<!-- boolen value will always be displayed even if value is not defined (value = false) -->
<span *ngIf="prop.propDef.objectType === booleanValueTypeIri">
<app-boolean-value [mode]="'read'" class="boolean-value"></app-boolean-value>
</span>
<button *ngIf="prop.propDef.objectType !== booleanValueTypeIri" mat-icon-button type="button" class="value-action create"
(click)="showAddValueForm(prop, $event)"
title="Add a new value">
<mat-icon>add_box</mat-icon>
@@ -402,7 +402,11 @@ describe('PropertiesComponent', () => {
// so the amount of add buttons on the page should increase by 1
// standoff links value and has incoming link value are system props and cannot be added: -2
addButtons = propertyViewComponentDe.queryAll(By.css('button.create'));
expect(addButtons.length).toEqual(18);
expect(addButtons.length).toEqual(17);

// in case of boolean value, we do not display the add button, but the boolean value itself
const booleanValue = propertyViewComponentDe.queryAll(By.css('.boolean-value'));
expect(booleanValue.length).toEqual(1);

});

@@ -122,6 +122,8 @@ export class PropertiesComponent implements OnInit, OnChanges, OnDestroy {

representationConstants = RepresentationConstants;

booleanValueTypeIri = Constants.BooleanValue;

hasIncomingLinkIri = Constants.KnoraApiV2 + Constants.HashDelimiter + 'hasIncomingLinkValue';

project: ReadProject;
@@ -2,7 +2,7 @@
<app-text-value-as-string #createVal *ngSwitchCase="'ReadTextValueAsString'" [mode]="mode" [valueRequiredValidator]="isRequiredProp" [parentForm]="parentForm" [formName]="formName" [textArea]="textArea"></app-text-value-as-string>
<app-text-value-as-xml #createVal *ngSwitchCase="'ReadTextValueAsXml'" [mode]="mode" [valueRequiredValidator]="isRequiredProp" [parentForm]="parentForm" [formName]="formName"></app-text-value-as-xml>
<app-int-value #createVal *ngSwitchCase="constants.IntValue" [mode]="mode" [valueRequiredValidator]="isRequiredProp" [parentForm]="parentForm" [formName]="formName"></app-int-value>
<app-boolean-value #createVal *ngSwitchCase="constants.BooleanValue" [mode]="mode" [valueRequiredValidator]="isRequiredProp" [parentForm]="parentForm" [formName]="formName"></app-boolean-value>
<app-boolean-value #createVal *ngSwitchCase="constants.BooleanValue" [mode]="mode" [valueRequiredValidator]="isRequiredProp" [parentForm]="parentForm" [formName]="formName" [moreSpace]="true"></app-boolean-value>
<app-uri-value #createVal *ngSwitchCase="constants.UriValue" [mode]="mode" [valueRequiredValidator]="isRequiredProp" [parentForm]="parentForm" [formName]="formName"></app-uri-value>
<app-decimal-value #createVal *ngSwitchCase="constants.DecimalValue" [mode]="mode" [valueRequiredValidator]="isRequiredProp" [parentForm]="parentForm" [formName]="formName"></app-decimal-value>
<app-color-value #createVal *ngSwitchCase="constants.ColorValue" [mode]="mode" [valueRequiredValidator]="isRequiredProp" [parentForm]="parentForm" [formName]="formName"></app-color-value>
@@ -1,11 +1,13 @@
<span *ngIf="mode === 'read'; else showForm" class="read-mode-view">
<span class="rm-value">{{valueFormControl.value | formattedBoolean:preferredDisplayType}}</span>
<span class="rm-value">
<mat-icon>{{valueFormControl.value ? 'check_box' : 'check_box_outline_blank'}}</mat-icon>
</span>
<span class="rm-comment" *ngIf="shouldShowComment">{{commentFormControl.value}}</span>
</span>
<ng-template #showForm>
<span [formGroup]="form" (ngSubmit)="onSubmit()">
<mat-checkbox [formControlName]="'value'" class="value boolValue child-value-component">
{{valueFormControl.value | formattedBoolean:preferredDisplayType}}

<mat-checkbox [formControlName]="'value'" class="value boolValue child-value-component" [class.more-space]="moreSpace">
</mat-checkbox>
<mat-error *ngIf="valueFormControl.hasError('valueNotChanged') && valueFormControl.dirty">
<span class="custom-error-message">New value must be different than the current value.</span>
@@ -1 +1,13 @@
@import "../../../../../assets/style/viewer";

.read-mode-view .mat-icon,
.boolValue {
margin-top: 4px;
margin-left: 4px;
display: block;

&.more-space {
margin-top: 16px;
}
}

@@ -114,7 +114,7 @@ describe('BooleanValueComponent', () => {

expect(testHostComponent.booleanValueComponent.mode).toEqual('read');

expect(valueReadModeNativeElement.innerText).toEqual('true');
expect(valueReadModeNativeElement.innerText).toEqual('check_box');
});

it('should make an existing value editable', () => {
@@ -127,7 +127,6 @@ describe('BooleanValueComponent', () => {
valueBooleanNativeElement = valueBooleanDebugElement.nativeElement;

checkboxEl = valueBooleanDebugElement.query(By.css('input[type="checkbox"]')).nativeElement;
checkboxLabel = valueBooleanDebugElement.query(By.css('span[class="mat-checkbox-label"]')).nativeElement;

expect(testHostComponent.booleanValueComponent.mode).toEqual('update');

@@ -137,8 +136,6 @@ describe('BooleanValueComponent', () => {

expect(checkboxEl.checked).toBe(true);

expect(checkboxLabel.innerText).toEqual('true');

checkboxEl.click();

testHostFixture.detectChanges();
@@ -155,7 +152,6 @@ describe('BooleanValueComponent', () => {

expect(checkboxEl.disabled).toBe(false);

expect(checkboxLabel.innerText).toEqual('false');
});

it('should validate an existing value with an added comment', () => {
@@ -168,7 +164,6 @@ describe('BooleanValueComponent', () => {
valueBooleanNativeElement = valueBooleanDebugElement.nativeElement;

checkboxEl = valueBooleanDebugElement.query(By.css('input[type="checkbox"]')).nativeElement;
checkboxLabel = valueBooleanDebugElement.query(By.css('span[class="mat-checkbox-label"]')).nativeElement;

commentBooleanDebugElement = valueComponentDe.query(By.css('textarea.comment'));
commentBooleanNativeElement = commentBooleanDebugElement.nativeElement;
@@ -181,8 +176,6 @@ describe('BooleanValueComponent', () => {

expect(checkboxEl.checked).toBe(true);

expect(checkboxLabel.innerText).toEqual('true');

commentBooleanNativeElement.value = 'this is a comment';

commentBooleanNativeElement.dispatchEvent(new Event('input'));
@@ -208,7 +201,6 @@ describe('BooleanValueComponent', () => {
valueBooleanNativeElement = valueBooleanDebugElement.nativeElement;

checkboxEl = valueBooleanDebugElement.query(By.css('input[type="checkbox"]')).nativeElement;
checkboxLabel = valueBooleanDebugElement.query(By.css('span[class="mat-checkbox-label"]')).nativeElement;

expect(testHostComponent.booleanValueComponent.mode).toEqual('update');

@@ -218,16 +210,12 @@ describe('BooleanValueComponent', () => {

expect(checkboxEl.checked).toBe(true);

expect(checkboxLabel.innerText).toEqual('true');

checkboxEl.click();

testHostFixture.detectChanges();

expect(checkboxEl.checked).toBe(false);

expect(checkboxLabel.innerText).toEqual('false');

testHostComponent.booleanValueComponent.resetFormControl();

testHostFixture.detectChanges();
@@ -236,7 +224,6 @@ describe('BooleanValueComponent', () => {

expect(checkboxEl.checked).toBe(true);

expect(checkboxLabel.innerText).toEqual('true');
});

it('should set a new display value', () => {
@@ -250,7 +237,7 @@ describe('BooleanValueComponent', () => {

testHostFixture.detectChanges();

expect(valueReadModeNativeElement.innerText).toEqual('false');
expect(valueReadModeNativeElement.innerText).toEqual('check_box_outline_blank');

expect(testHostComponent.booleanValueComponent.form.valid).toBeTruthy();
});
@@ -273,7 +260,6 @@ describe('BooleanValueComponent', () => {
let valueBooleanDebugElement: DebugElement;
let valueBooleanNativeElement;
let checkboxEl;
let checkboxLabel;
let commentBooleanDebugElement: DebugElement;
let commentBooleanNativeElement;

@@ -292,7 +278,6 @@ describe('BooleanValueComponent', () => {
valueBooleanDebugElement = valueComponentDe.query(By.css('mat-checkbox'));
valueBooleanNativeElement = valueBooleanDebugElement.nativeElement;
checkboxEl = valueBooleanDebugElement.query(By.css('input[type="checkbox"]')).nativeElement;
checkboxLabel = valueBooleanDebugElement.query(By.css('span[class="mat-checkbox-label"]')).nativeElement;

commentBooleanDebugElement = valueComponentDe.query(By.css('textarea.comment'));
commentBooleanNativeElement = commentBooleanDebugElement.nativeElement;
@@ -301,7 +286,6 @@ describe('BooleanValueComponent', () => {
expect(testHostComponent.booleanValueComponent.form.valid).toBeTruthy();
expect(checkboxEl.disabled).toBe(false);
expect(checkboxEl.checked).toBe(false);
expect(checkboxLabel.innerText).toEqual('false');
expect(commentBooleanNativeElement.value).toEqual('');
});

@@ -16,6 +16,8 @@ export class BooleanValueComponent extends BaseValueDirective implements OnInit,

@Input() displayValue?: ReadBooleanValue;

@Input() moreSpace?: boolean;

valueFormControl: FormControl;
commentFormControl: FormControl;

@@ -1,4 +1,4 @@
<form *ngIf="!errorMessage" [formGroup]="form" (ngSubmit)="submit()" class="dsp-form-content">
<form *ngIf="!errorMessage" [formGroup]="form" (ngSubmit)="submit()" class="app-form-content">

<div *ngIf="ontologiesMetadata?.ontologies.length > 0">
<app-search-select-ontology [formGroup]="form" [ontologiesMetadata]="ontologiesMetadata"
@@ -8,7 +8,7 @@
<app-resource-and-property-selection *ngIf="activeOntology !== undefined" #resAndPropSel [formGroup]="form" [activeOntology]="activeOntology" [topLevel]="true">
</app-resource-and-property-selection>

<div class="dsp-form-action">
<div class="app-form-action">
<button class="reset" mat-button type="button" (click)="resourceAndPropertySelection?.resetForm()" [disabled]="this.activeOntology === undefined">
Reset
</button>
@@ -10,7 +10,7 @@ import {
ViewChild
} from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { ApiResponseError, Constants, KnoraApiConnection, OntologiesMetadata } from '@dasch-swiss/dsp-js';
import { ApiResponseError, Constants, KnoraApiConnection, OntologiesMetadata, OntologyMetadata } from '@dasch-swiss/dsp-js';
import { Subscription } from 'rxjs';
import { DspApiConnectionToken } from 'src/app/main/declarations/dsp-api-tokens';
import { NotificationService } from 'src/app/main/services/notification.service';
@@ -100,6 +100,9 @@ export class AdvancedSearchComponent implements OnInit, OnDestroy, AfterViewChec
response.ontologies = response.ontologies.filter(onto => onto.attachedToProject !== Constants.SystemProjectIRI);

this.ontologiesMetadata = response;

this.preSelectFirstOntology(this.ontologiesMetadata.ontologies);

},
(error: ApiResponseError) => {
this._notification.openSnackBar(error);
@@ -112,18 +115,28 @@ export class AdvancedSearchComponent implements OnInit, OnDestroy, AfterViewChec
response.ontologies = response.ontologies.filter(onto => onto.attachedToProject !== Constants.SystemProjectIRI);

this.ontologiesMetadata = response;

this.preSelectFirstOntology(this.ontologiesMetadata.ontologies);

},
(error: ApiResponseError) => {
this._notification.openSnackBar(error);
this.errorMessage = error;
});
}

}

setActiveOntology(ontologyIri: string) {
this.activeOntology = ontologyIri;
}

preSelectFirstOntology(ontologies: OntologyMetadata[]) {
if (ontologies.length === 1) {
this.activeOntology = ontologies[0].id;
}
}

submit() {

if (!this.formValid) {
@@ -1,31 +1,35 @@
<div [formGroup]="form">
<div class="form" [formGroup]="form">

<div class="select-resource-class">
<app-search-select-resource-class *ngIf="resourceClasses?.length > 0"
#resourceClass
[formGroup]="form"
[resourceClassDefinitions]="resourceClasses"
(resourceClassSelected)="getPropertiesForResourceClass($event)">
</app-search-select-resource-class>
</div>
<app-search-select-resource-class *ngIf="resourceClasses?.length > 0"
#resourceClass
class="select-resource-class"
[formGroup]="form"
[resourceClassDefinitions]="resourceClasses"
(resourceClassSelected)="getPropertiesForResourceClass($event)">
</app-search-select-resource-class>

<div class="select-property" *ngIf="properties !== undefined">
<div *ngFor="let prop of activeProperties; let i = index">
<div class="select-property" [class.res-pointer-level]="!topLevel" *ngIf="properties !== undefined">

<app-search-select-property #property [activeResourceClass]="activeResourceClass" [formGroup]="form" [index]="i"
[properties]="properties" [topLevel]="topLevel"></app-search-select-property>
<!-- select property -->
<app-search-select-property *ngFor="let prop of activeProperties; let i = index"
#property
[activeResourceClass]="activeResourceClass"
[formGroup]="form"
[index]="i"
[properties]="properties"
[topLevel]="topLevel">
</app-search-select-property>

</div>
</div>

<div class="select-property buttons">
<div class="select-property buttons" [class.res-pointer-level]="!topLevel">
<button mat-mini-fab class="property-button add-property-button" color="primary" type="button"
(click)="addProperty()" [disabled]="activeProperties.length >= 4">
(click)="addProperty()" [disabled]="activeProperties.length >= 4">
<mat-icon aria-label="add a property">add</mat-icon>
</button>

<button mat-mini-fab class="property-button remove-property-button" color="primary" type="button"
(click)="removeProperty()" [disabled]="activeProperties.length == 0">
<button mat-mini-fab class="property-button remove-property-button" color="warn" type="button"
(click)="removeProperty()" [disabled]="!activeProperties.length">
<mat-icon aria-label="remove property">remove</mat-icon>
</button>
</div>
@@ -1,7 +1,15 @@
.form {
display: inherit;
}

.select-property {
margin-left: 16px;

.property-button {
margin: 0 12px 64px 0;
}
}

.res-pointer-level {
margin-left: -160px;
}
@@ -1,12 +1,31 @@
<span *ngIf="properties.length > 0" [formGroup]="form" >
<!-- property header -->
<div *ngIf="index === 0 && topLevel" class="search-property-header">
<span class="fill-remaining-space"></span>
<span class="mat-caption">Sort criterion</span>
</div>

<div *ngIf="properties.length > 0" class="search-property-line" [formGroup]="form">

<!-- select property -->
<mat-form-field class="search-property-field medium-field">
<mat-select placeholder="Select Properties" [formControlName]="'property'" class="select-property">
<mat-option *ngFor="let prop of properties" [value]="prop">{{ prop.label }}</mat-option>
</mat-select>
</mat-form-field>

<!-- comparison operator and property value field -->
<app-specify-property-value #specifyPropertyValue [formGroup]="form" *ngIf="propertySelected !== undefined"
[property]="propertySelected" [topLevel]="topLevel"></app-specify-property-value>
[property]="propertySelected" [topLevel]="topLevel"></app-specify-property-value>

<span class="fill-remaining-space"></span>
<span>
<mat-slide-toggle *ngIf="propertySelected !== undefined && sortCriterion()"
[formControlName]="'isSortCriterion'"
[color]="'primary'"
class="sort-criterion-toggle"
matTooltip="Sort search results by value of this property"
matTooltipPosition="above">
</mat-slide-toggle>
</span>

<mat-checkbox *ngIf="propertySelected !== undefined && sortCriterion()" [formControlName]="'isSortCriterion'" matTooltip="Sort criterion"></mat-checkbox>
</span>
</div>
@@ -1,3 +1,21 @@
.search-property-field {
margin-right: 8px;
:host {
width: 100%;

.search-property-header {
width: 100%;
display: inline-flex;
}

.search-property-line {
display: inline-flex;
width: 100%;

.search-property-field {
margin-right: 8px;
}

.sort-criterion-toggle {
margin: 16px 16px 0 0;
}
}
}

0 comments on commit 7affa5e

Please sign in to comment.