Skip to content

Commit

Permalink
Merge branch 'dh2-beta-release' into dh2-i18n-rc1
Browse files Browse the repository at this point in the history
  • Loading branch information
kennethbruskiewicz committed Dec 18, 2024
2 parents e8895b5 + 7736fe9 commit 43c6a41
Show file tree
Hide file tree
Showing 29 changed files with 227 additions and 152 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module.exports = {
ignorePatterns: [
'.eslintrc.js',
'web/webpack.config.js',
'web/webpack.schemas.js',
'lib/rollup.config.js',
'**/dist/**/*.js',
'.venv',
Expand Down
17 changes: 8 additions & 9 deletions lib/AppContext.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import * as $ from 'jquery';
import i18n from 'i18next';

import { DataHarmonizer } from '@/lib';
import { findLocalesForLangcodes } from '@/lib/utils/i18n';
import { DataHarmonizer } from '.';
import { findLocalesForLangcodes } from './utils/i18n';
import {
Template,
findSlotNamesForClass,
getTemplatePathInScope,
} from '@/lib/utils/templates';
import { wait } from '@/lib/utils/general';
import { invert, removeNumericKeys, consolidate } from '@/lib/utils/objects';
import { createDataHarmonizerContainer, createDataHarmonizerTab } from '@/web';
} from '../lib/utils/templates';
import { wait } from '../lib/utils/general';
import { invert, removeNumericKeys, consolidate } from '../lib/utils/objects';
import { createDataHarmonizerContainer, createDataHarmonizerTab } from '../web';
import { getExportFormats } from 'schemas';

// COMMENTED OUT: WIP FEATURE
// import { buildAppContext, setup1M } from '@/lib/utils/1m';
Expand Down Expand Up @@ -409,9 +410,7 @@ export default class AppContext {
}

async loadExportFormats(schema) {
this.exportFormats = (
await import(`@/web/templates/${schema}/export.js`)
).default;
this.exportFormats = await getExportFormats(schema);
return this.exportFormats;
}

Expand Down
48 changes: 25 additions & 23 deletions lib/DataHarmonizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ import 'jquery-ui/dist/themes/base/jquery-ui.css';

import i18next from 'i18next';
import { utils as XlsxUtils, read as xlsxRead } from 'xlsx/xlsx.js';
import { renderContent, urlToClickableAnchor } from '@/lib/utils/content';
import { readFileAsync, updateSheetRange } from '@/lib/utils/files';
import { findSlotNamesForClass } from '@/lib/utils/templates';
import { renderContent, urlToClickableAnchor } from './utils/content';
import { readFileAsync, updateSheetRange } from '../lib/utils/files';
import { findSlotNamesForClass } from '../lib/utils/templates';
import {
isValidHeaderRow,
rowIsEmpty,
wait,
stripDiv,
isEmptyUnitVal,
pascalToLowerWithSpaces,
} from '@/lib/utils/general';
import { invert, deepMerge, looseMatchInObject } from '@/lib/utils/objects';
} from '../lib/utils/general';
import { invert, deepMerge, looseMatchInObject } from '../lib/utils/objects';

import {
changeCase,
Expand All @@ -31,40 +31,42 @@ import {
MULTIVALUED_DELIMITER,
parseMultivaluedValue,
titleOverText,
} from '@/lib/utils/fields';
} from './utils/fields';

import {
checkProvenance,
itemCompare,
validateValAgainstVocab,
validateValsAgainstVocab,
// validateUniqueValues,
} from '@/lib/utils/validation';
} from './utils/validation';

import 'handsontable/dist/handsontable.full.css';
import '@/lib/data-harmonizer.css';
import './data-harmonizer.css';
import '@selectize/selectize/dist/css/selectize.bootstrap4.css';

import specifyHeadersModal from '@/lib/specifyHeadersModal.html';
import unmappedHeadersModal from '@/lib/unmappedHeadersModal.html';
import fieldDescriptionsModal from '@/lib/fieldDescriptionsModal.html';
import specifyHeadersModal from './specifyHeadersModal.html';
import unmappedHeadersModal from './unmappedHeadersModal.html';
import fieldDescriptionsModal from './fieldDescriptionsModal.html';

import HelpSidebar from '@/lib/HelpSidebar';
import HelpSidebar from './HelpSidebar';

// NOTE: this is odd! package.json is a developer file. why should a UI component care about it?
import pkg from '@/package.json';
import Validator from '@/lib/Validator';
import pkg from '../package.json';
import Validator from './Validator';

const VERSION = pkg.version;
const VERSION_TEXT = 'DataHarmonizer v' + VERSION;

import { DateEditor, DatetimeEditor, TimeEditor } from '@/lib/editors';
import {
DateEditor,
DatetimeEditor,
TimeEditor,
KeyValueListEditor,
keyValueListValidator,
keyValueListRenderer,
multiKeyValueListRenderer,
} from '@/lib/editors';
} from './editors';

Handsontable.cellTypes.registerCellType('key-value-list', {
editor: KeyValueListEditor,
Expand Down Expand Up @@ -2236,7 +2238,7 @@ class DataHarmonizer {
// if sources exist, fetch transformed Value
if (field.sources) {
if (field.multivalued === true) {
//Map list of semicolon-delimited choices
// Map list of semicolon-delimited choices
// ISSUE: relying on semicolon delimiter in input
for (let cellVal of mappedCellVal.split(';')) {
mappedCell.push(
Expand Down Expand Up @@ -2655,7 +2657,6 @@ class DataHarmonizer {
if (number >= 0) {
// Here we have the 3 field call, with units sandwitched in the middle
if (binOffset === 2) {

const unit = matrix[row][hotRowNextCol];
// Host age unit is interpreted by default to be year.
// If user selects month, value is converted into years for binning.
Expand Down Expand Up @@ -2693,7 +2694,7 @@ class DataHarmonizer {
const bin_values = fields[hotRowBinCol].flatVocabulary;
if (value in bin_values && (!bin_value || bin_value === '')) {
selection = value;
console.log("no bin value", value);
console.log('no bin value', value);
}
// If a unit field exists, then set that to metadata too.
if (binOffset == 2) {
Expand Down Expand Up @@ -2742,7 +2743,7 @@ class DataHarmonizer {
doPreValidationRepairs(data) {
return new Promise((resolve) => {
const cellChanges = [];
const whitespace_minimized_re = new RegExp(/\s+/,'g');
const whitespace_minimized_re = new RegExp(/\s+/, 'g');
let fullVersion =
VERSION_TEXT +
', ' +
Expand All @@ -2762,15 +2763,16 @@ class DataHarmonizer {
const datatype = field.datatype;

if (cellVal && datatype === 'xsd:token') {

const minimized = cellVal.replace(whitespace_minimized_re, ' ').trim();
const minimized = cellVal
.replace(whitespace_minimized_re, ' ')
.trim();
// Update cellVal in advance of validateVal(s) below
if (minimized !== cellVal) {
cellVal = minimized;
data[row][col] = cellVal;
cellChanges.push([row, col, minimized, 'thisChange']);
}
};
}

if (datatype === 'Provenance') {
checkProvenance(cellChanges, fullVersion, cellVal, row, col);
Expand Down
4 changes: 2 additions & 2 deletions lib/HelpSidebar.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import $ from 'jquery';
import { renderContent } from '@/lib/utils/content';
import '@/lib/HelpSidebar.css';
import { renderContent } from './utils/content';
import './HelpSidebar.css';

const DEFAULT_OPTIONS = {
width: 300,
Expand Down
21 changes: 9 additions & 12 deletions lib/Toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,24 @@ import {
exportWorkbook,
importJsonFile,
prependToSheet,
} from '@/lib/utils/files';
import { nullValuesToString, isEmptyUnitVal } from '@/lib/utils/general';
import { MULTIVALUED_DELIMITER, titleOverText } from '@/lib/utils/fields';
import { takeKeys, invert } from '@/lib/utils/objects';
} from '../lib/utils/files';
import { nullValuesToString, isEmptyUnitVal } from '../lib/utils/general';
import { MULTIVALUED_DELIMITER, titleOverText } from '../lib/utils/fields';
import { takeKeys, invert } from '../lib/utils/objects';
import {
findBestLocaleMatch,
templatePathForSchemaURI,
rangeToContainerClass,
LocaleNotSupportedError,
} from '@/lib/utils/templates';
} from '../lib/utils/templates';

import {
findLocalesForLangcodes,
interface_translation,
} from '@/lib/utils/i18n';
import { findLocalesForLangcodes, interface_translation } from './utils/i18n';
import i18next from 'i18next';

import template from '@/lib/toolbar.html';
import '@/lib//toolbar.css';
import template from './toolbar.html';
import './/toolbar.css';

import menu from '@/web/templates/menu.json';
import { menu } from 'schemas';
import pkg from '../package.json';

const VERSION = pkg.version;
Expand Down
46 changes: 25 additions & 21 deletions lib/Validator.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Datatypes } from '@/lib/utils/datatypes';
import { validateUniqueValues } from '@/lib/utils/validation';
import { rowIsEmpty } from '@/lib/utils/general';
import { Datatypes } from './utils/datatypes';
import { validateUniqueValues } from './utils/validation';
import { rowIsEmpty } from './utils/general';

class Validator {
#schema;
Expand Down Expand Up @@ -58,7 +58,7 @@ class Validator {
return;
}
// todos is an array of strings.
const slotType = this.getSlotType(slotDefinition);// LinkML schema.type object
const slotType = this.getSlotType(slotDefinition); // LinkML schema.type object

// Slot type could be:
// a number, string, date ...
Expand All @@ -74,11 +74,15 @@ class Validator {
}
}

// Cycle through each slotDefinition any_of etc. object entries and get
// Cycle through each slotDefinition any_of etc. object entries and get
// the datatype of its .range (or recurse) and in LinkML fashion attach
// minimum_value and maximum_value to the slotDefinition OR its any_of
// etc array BASED ON top level todos. E.g. inheriting min/max criteria.
for (const def of slotDefinition.any_of ?? slotDefinition.all_of ?? slotDefinition.exactly_one_of ?? slotDefinition.none_of ?? []) {
for (const def of slotDefinition.any_of ??
slotDefinition.all_of ??
slotDefinition.exactly_one_of ??
slotDefinition.none_of ??
[]) {
processTodos(def, todos);
}
};
Expand Down Expand Up @@ -248,8 +252,7 @@ class Validator {

const validate = (value) => {
if (!value) {
if (slotDefinition.required)
return 'This field is required';
if (slotDefinition.required) return 'This field is required';
// value_presence is subject to dynamic rules?
if (slotDefinition.value_presence === 'PRESENT')
return 'Value is not present';
Expand Down Expand Up @@ -283,7 +286,8 @@ class Validator {
// Message needs
for (const value of splitValues) {
let parse_error = false;
if (slotType) {// Doesn't pertain to slots which are ONLY enumerations.
if (slotType) {
// Doesn't pertain to slots which are ONLY enumerations.
const parsed = this.#parser.parse(value, slotType.uri);

// Issue: parse can fail on decimal but menu has "Missing"
Expand All @@ -297,15 +301,14 @@ class Validator {
// All these cases have encountered an item which matches basic data
// datatype and so sudden death is ok.
else {

if (slotMinimumValue !== undefined && parsed < slotMinimumValue) {
return 'Value is less than minimum value';
}

if (slotMaximumValue !== undefined && parsed > slotMaximumValue) {
return 'Value is greater than maximum value';
}

if (
(slotDefinition.equals_string !== undefined &&
parsed !== slotDefinition.equals_string) ||
Expand All @@ -322,14 +325,12 @@ class Validator {
return 'Value does not match pattern';
}

// Here slotType value tested and is ok!
// Here slotType value tested and is ok!
continue;
}

// Here value didn't parse to slotType

}
else {
} else {
// No basic slot type here so only enumeration handling.
}

Expand Down Expand Up @@ -378,17 +379,20 @@ class Validator {
}
}

if (anyOfValidators.length || allOfValidators.length || exactlyOneOfValidators.length || noneOfValidators.length) {
if (
anyOfValidators.length ||
allOfValidators.length ||
exactlyOneOfValidators.length ||
noneOfValidators.length
) {
// We passed validation here which means a parse error can be overriden
}
else if (parse_error.length) {
//There were no other ranges besides basic slotType so
} else if (parse_error.length) {
//There were no other ranges besides basic slotType so
return parse_error;
}
}
};


return validate;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/editors/DateEditor.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import FlatpickrEditor from '@/lib/editors/FlatpickrEditor';
import FlatpickrEditor from './FlatpickrEditor';

class DateEditor extends FlatpickrEditor {
getFlatpickrConfig() {
Expand Down
2 changes: 1 addition & 1 deletion lib/editors/DatetimeEditor.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import FlatpickrEditor from '@/lib/editors/FlatpickrEditor';
import FlatpickrEditor from './FlatpickrEditor';

class DatetimeEditor extends FlatpickrEditor {
getFlatpickrConfig() {
Expand Down
4 changes: 2 additions & 2 deletions lib/editors/KeyValueEditor.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Handsontable from 'handsontable';
import { MULTIVALUED_DELIMITER, titleOverText } from '@/lib/utils/fields';
import { isEmptyUnitVal } from '@/lib/utils/general';
import { MULTIVALUED_DELIMITER, titleOverText } from '../utils/fields';
import { isEmptyUnitVal } from '../utils/general';

// Derived from: https://jsfiddle.net/handsoncode/f0b41jug/

Expand Down
2 changes: 1 addition & 1 deletion lib/editors/TimeEditor.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import FlatpickrEditor from '@/lib/editors/FlatpickrEditor';
import FlatpickrEditor from './FlatpickrEditor';

class TimeEditor extends FlatpickrEditor {
getFlatpickrConfig() {
Expand Down
10 changes: 5 additions & 5 deletions lib/editors/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
export { default as DateEditor } from '@/lib/editors/DateEditor';
export { default as DatetimeEditor } from '@/lib/editors/DatetimeEditor';
export { default as TimeEditor } from '@/lib/editors/TimeEditor';
export { default as FlatpickrEditor } from '@/lib/editors/FlatpickrEditor';
export { default as DateEditor } from './DateEditor.js';
export { default as DatetimeEditor } from './DatetimeEditor.js';
export { default as TimeEditor } from './TimeEditor.js';
export { default as FlatpickrEditor } from './FlatpickrEditor.js';
export {
default as KeyValueListEditor,
keyValueListRenderer,
keyValueListValidator,
multiKeyValueListRenderer,
} from '@/lib/editors/KeyValueEditor';
} from './KeyValueEditor.js';
14 changes: 5 additions & 9 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
export { default as Footer } from '@/lib/Footer';
export { default as Toolbar } from '@/lib/Toolbar';
export { default as DataHarmonizer } from '@/lib/DataHarmonizer';
export { default as AppContext } from '@/lib/AppContext';
export {
DATE_OBJECT,
JSON_SCHEMA_FORMAT,
INPUT_FORMAT,
} from '@/lib/utils/fields';
export { default as Footer } from './Footer';
export { default as Toolbar } from './Toolbar';
export { default as DataHarmonizer } from './DataHarmonizer';
export { default as AppContext } from './AppContext';
export { DATE_OBJECT, JSON_SCHEMA_FORMAT, INPUT_FORMAT } from './utils/fields';
Loading

0 comments on commit 43c6a41

Please sign in to comment.