Skip to content

Commit

Permalink
feat: enhanced scientific metadata unit field validation using math-j… (
Browse files Browse the repository at this point in the history
#1353)

* feat: enhanced scientific metadata unit field validation using math-js and improved unit field UI

* feat: added e2e test for unit validation

* build(deps): bump actions/upload-artifact from 3 to 4

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>

* build(deps-dev): bump the eslint group with 4 updates

Bumps the eslint group with 4 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin), [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser), [eslint](https://github.com/eslint/eslint) and [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier).

Updates `@typescript-eslint/eslint-plugin` from 6.14.0 to 6.16.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.16.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.14.0 to 6.16.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.16.0/packages/parser)

Updates `eslint` from 8.55.0 to 8.56.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](eslint/eslint@v8.55.0...v8.56.0)

Updates `eslint-plugin-prettier` from 5.0.1 to 5.1.2
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md)
- [Commits](prettier/eslint-plugin-prettier@v5.0.1...v5.1.2)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: eslint-plugin-prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <[email protected]>

* build(deps-dev): bump the angular group with 3 updates

Bumps the angular group with 3 updates: [@angular-devkit/build-angular](https://github.com/angular/angular-cli), [@angular-devkit/core](https://github.com/angular/angular-cli) and [@angular/cli](https://github.com/angular/angular-cli).


Updates `@angular-devkit/build-angular` from 16.2.10 to 16.2.11
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](angular/angular-cli@16.2.10...16.2.11)

Updates `@angular-devkit/core` from 16.2.10 to 16.2.11
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](angular/angular-cli@16.2.10...16.2.11)

Updates `@angular/cli` from 16.2.10 to 16.2.11
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](angular/angular-cli@16.2.10...16.2.11)

---
updated-dependencies:
- dependency-name: "@angular-devkit/build-angular"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular-devkit/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/cli"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
...

Signed-off-by: dependabot[bot] <[email protected]>

* fix: update package-lock.json

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • Loading branch information
Junjiequan and dependabot[bot] authored Jan 9, 2024
1 parent ffe9f40 commit 3a6492a
Show file tree
Hide file tree
Showing 10 changed files with 256 additions and 27 deletions.
93 changes: 92 additions & 1 deletion cypress/e2e/datasets/datasets-metadata.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
describe("Datasets", () => {
const metadataName = "some name";
const metadataValue = "some value";
const metadataQuantityValue = 1128;
const metadataValidUnitValue = "m";
const metadataInvalidUnitValue = "invalidUnit";

beforeEach(() => {
cy.login(Cypress.config("username"), Cypress.config("password"));
Expand Down Expand Up @@ -80,7 +83,7 @@ describe("Datasets", () => {
});
});

it("should not be able to create a dataset with duplicate name", () => {
it("should not be able to create a metadata with duplicate name", () => {
cy.createDataset("raw");

cy.visit("/datasets");
Expand Down Expand Up @@ -146,6 +149,94 @@ describe("Datasets", () => {
cy.get("mat-error").contains("Name is already taken");
cy.get("button[data-cy=save-changes-button]").should("be.disabled");
});

it("should show warning icon in the edit and view table if the metadata unit is invalid or cannot be converted", () => {
cy.createDataset("raw");

cy.visit("/datasets");

cy.get(".dataset-table mat-table mat-header-row").should("exist");

cy.finishedLoading();

cy.get('[data-cy="text-search"] input[type="search"]')
.clear()
.type("Cypress");

cy.isLoading();

cy.get("mat-row").contains("Cypress Dataset").first().click();

cy.wait("@fetch");

cy.finishedLoading();

cy.scrollTo("bottom");

cy.get('[role="tab"]').contains("Edit").click();

cy.get('[data-cy="add-new-row"]').click();

cy.get("mat-select[data-cy=field-type-input]").last().click();
cy.get("mat-option")
.contains("quantity")
.then((option) => {
option[0].click();
});

cy.get("[data-cy=metadata-name-input]")
.last()
.type(`${metadataName}{enter}`);

cy.get("[data-cy=metadata-value-input]")
.last()
.type(`${metadataQuantityValue}{enter}`);

cy.get("[data-cy=metadata-unit-input]")
.last()
.type(`${metadataValidUnitValue}{enter}`);

cy.get('[aria-label="warning invalid unit"]').should("not.exist");

cy.get('[data-cy="add-new-row"]').click();

cy.get("mat-select[data-cy=field-type-input]").last().click();
cy.get("mat-option")
.contains("quantity")
.then((option) => {
option[0].click();
});

cy.get("[data-cy=metadata-name-input]")
.last()
.type(`${metadataName}-2{enter}`);

cy.get("[data-cy=metadata-value-input]")
.last()
.type(`${metadataQuantityValue}{enter}`);

cy.get("[data-cy=metadata-unit-input]")
.last()
.type(`${metadataInvalidUnitValue}{enter}`);

cy.wait(1000);

cy.get('[aria-label="warning invalid unit"]').should("exist");

cy.get('[role="tab"]').contains("View").click();

cy.get(".unit-input")
.contains(`${metadataValidUnitValue}`)
.within(() => {
cy.get(".unit-input--warning").should("not.exist");
});

cy.get(".unit-input")
.contains(`${metadataInvalidUnitValue}`)
.within(() => {
cy.get(".unit-input--warning").should("exist");
});
});
});

describe("Remove metadata item", () => {
Expand Down
94 changes: 92 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"filesize": "^10.0.7",
"lodash-es": "^4.17.21",
"luxon": "^3.3.0",
"mathjs": "^12.2.1",
"ngx-json-viewer": "^3",
"ngx-linky": "^4.0.0",
"ngx-material-luxon": "^1.1.1",
Expand Down Expand Up @@ -76,8 +77,8 @@
"coveralls": "^3.0.7",
"cypress": "^13.1.0",
"eslint": "^8.2.0",
"eslint-plugin-ngrx": "^2.0.3",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-ngrx": "^2.0.3",
"eslint-plugin-prettier": "^5.0.0",
"jasmine": "^5.0.0",
"jasmine-core": "^5.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,19 @@
formControlName="fieldUnit"
[matAutocomplete]="metadataUnits"
(focus)="getUnits(i)"
data-cy="metadata-unit-input"
/>
<div
class="unit-warning"
*ngIf="invalidUnitWarning[i]"
mat-icon-button
matSuffix
(click)="$event.stopPropagation()"
[attr.aria-label]="'warning invalid unit'"
[matTooltip]="invalidUnitWarning[i]"
>
<mat-icon>{{ "error_outline" }}</mat-icon>
</div>
<mat-autocomplete #metadataUnits="matAutocomplete">
<mat-option
*ngFor="let unit of filteredUnits$ | async"
Expand All @@ -90,10 +102,6 @@
<mat-error *ngIf="fieldHasError(i, 'fieldUnit')">
A unit is required for quantities
</mat-error>

<mat-hint *ngIf="invalidUnitWarning[i]">
{{ invalidUnitWarning[i] }}
</mat-hint>
</mat-form-field>
</div>
<div class="formColumn" fxFlexAlign="center">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
}
}

.unit-warning {
cursor: pointer;
margin-bottom: -0.5em;
color: rgba(105, 85, 6, 0.8);
}

::ng-deep mat-hint {
white-space: nowrap;
color: rgb(179, 0, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ export class MetadataEditComponent implements OnInit, OnChanges {
Validators.required,
Validators.minLength(1),
]),
fieldUnit: new FormControl("", [Validators.required]),
fieldUnit: new FormControl("", [
Validators.required,
this.whiteSpaceValidator(),
]),
});

this.items.push(field);
Expand All @@ -71,7 +74,7 @@ export class MetadataEditComponent implements OnInit, OnChanges {
this.items
.at(index)
.get("fieldUnit")
?.setValidators([Validators.required]);
?.setValidators([Validators.required, this.whiteSpaceValidator()]);
this.items.at(index).get("fieldUnit")?.updateValueAndValidity();
} else {
this.items.at(index).get("fieldUnit")?.clearValidators();
Expand All @@ -91,6 +94,14 @@ export class MetadataEditComponent implements OnInit, OnChanges {
: null;
};
}
whiteSpaceValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (control.value.length > 0 && !control.value.trim()) {
return { whitespace: true };
}
return null;
};
}

doSave() {
this.metadata = this.createMetadataObject();
Expand Down Expand Up @@ -220,15 +231,18 @@ export class MetadataEditComponent implements OnInit, OnChanges {
this.items.controls.forEach((control, index) => {
control
.get("fieldUnit")
.valueChanges.pipe(debounceTime(300), distinctUntilChanged())
.valueChanges.pipe(debounceTime(600), distinctUntilChanged())
.subscribe((value) => {
this.invalidUnitWarning[index] = this.getCustomUnitWarning(value);
});
});
}

getCustomUnitWarning(value: string): string {
return !value || this.unitsService.getUnits().includes(value)
if (value.length > 0 && !value.trim()) {
return "A unit is required for quantities";
}
return this.unitsService.unitValidation(value)
? ""
: "Unrecognized unit, conversion disabled";
}
Expand Down
Loading

0 comments on commit 3a6492a

Please sign in to comment.