diff --git a/dbrepo-metadata-db/setup-schema.sql b/dbrepo-metadata-db/setup-schema.sql index a24971600a29e3ab0371454f759b16ad99807adf..e207d09e4452cd2c5451550f93daedf5f2e48f5d 100644 --- a/dbrepo-metadata-db/setup-schema.sql +++ b/dbrepo-metadata-db/setup-schema.sql @@ -304,7 +304,7 @@ CREATE TABLE IF NOT EXISTS `mdb_columns_concepts` id bigint NOT NULL, cID bigint NOT NULL, created timestamp NOT NULL DEFAULT NOW(), - PRIMARY KEY (id), + PRIMARY KEY (id, cid), FOREIGN KEY (cID) REFERENCES mdb_columns (ID) ) WITH SYSTEM VERSIONING; @@ -313,7 +313,7 @@ CREATE TABLE IF NOT EXISTS `mdb_columns_units` id bigint NOT NULL, cID bigint NOT NULL, created timestamp NOT NULL DEFAULT NOW(), - PRIMARY KEY (id), + PRIMARY KEY (id, cID), FOREIGN KEY (cID) REFERENCES mdb_columns (ID) ) WITH SYSTEM VERSIONING; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java index 6a0ecd6de983cf09722372e7ba2d369c35edfeea..8c4dd227c1dbfd5643eb07cdb08468bcbe56fbb5 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java @@ -88,13 +88,13 @@ public class TableColumn implements Comparable<TableColumn> { @CreatedDate private Instant created; - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) + @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) @JoinTable(name = "mdb_columns_concepts", joinColumns = @JoinColumn(name = "cid", referencedColumnName = "id", nullable = false), inverseJoinColumns = @JoinColumn(name = "id", referencedColumnName = "id")) private TableColumnConcept concept; - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) + @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) @JoinTable(name = "mdb_columns_units", joinColumns = @JoinColumn(name = "cid", referencedColumnName = "id", nullable = false), inverseJoinColumns = @JoinColumn(name = "id", referencedColumnName = "id")) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java index ca9853256d9b36dd772a23b8e38288df5da369ff..5d6edc84d85f2d5ebda0b370a73ad6345ac27029 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java @@ -47,7 +47,7 @@ public class TableColumnConcept { private Instant created; @ToString.Exclude - @OneToMany(fetch = FetchType.LAZY) + @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @org.springframework.data.annotation.Transient @JoinTable(name = "mdb_columns_concepts", inverseJoinColumns = { diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java index 8f115bdf13fe12f7aff76e6eb1d6a09658d5eccf..01cb3a0faac85b1b7e0eb899f52bd62fd90cc863 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java @@ -47,9 +47,9 @@ public class TableColumnUnit { private Instant created; @ToString.Exclude - @OneToMany(fetch = FetchType.LAZY) + @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @org.springframework.data.annotation.Transient - @JoinTable(name = "mdb_columns_concepts", + @JoinTable(name = "mdb_columns_units", inverseJoinColumns = { @JoinColumn(name = "cid", referencedColumnName = "id", insertable = false, updatable = false) }, diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java index ebe9b7375d672f0d57fcae8e6927f5bdb74a23da..4b515952b62b2193d9ffbcf22fb4fe95dce72f56 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java @@ -87,7 +87,7 @@ public class TableColumnEndpoint { throws TableNotFoundException, TableMalformedException, DatabaseNotFoundException, ContainerNotFoundException, NotAllowedException, SemanticEntityPersistException, SemanticEntityNotFoundException, QueryMalformedException, AccessDeniedException { - log.debug("endpoint update table, id={}, tableId={}, {}", id, tableId, PrincipalUtil.formatForDebug(principal)); + log.debug("endpoint update table, id={}, tableId={}, columnId={}, {}", id, tableId, columnId, PrincipalUtil.formatForDebug(principal)); if (principal != null && !UserUtil.hasRole(principal, "modify-foreign-table-column-semantics")) { endpointValidator.validateOnlyAccess(id, principal, true); endpointValidator.validateOnlyOwnerOrWriteAll(id, tableId, principal); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/SemanticServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/SemanticServiceImpl.java index 3841509198c3d4aa4590d635a0bf7281d8d8e238..4e0887db8edc163a559da3e846c32a5add965035 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/SemanticServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/SemanticServiceImpl.java @@ -125,13 +125,13 @@ public class SemanticServiceImpl implements SemanticService { .build(); } /* save in metadata database */ - final TableColumnConcept concept = tableMapper.entityDtoToTableColumnConcept( - entityService.findOneByUri(ontology, uri)); - log.info("Saved concept with uri {} in metadata database", concept.getUri()); + final TableColumnConcept concept = tableMapper.entityDtoToTableColumnConcept(entityService.findOneByUri(ontology, uri)); + final TableColumnConcept entity = tableColumnConceptRepository.save(concept); + log.info("Saved concept with uri {} in metadata database", entity.getUri()); /* save in open search database */ - conceptIdxRepository.save(tableMapper.tableColumnConceptToConceptDto(concept)); - log.info("Saved concept with uri {} in open search database", concept.getUri()); - return concept; + conceptIdxRepository.save(tableMapper.tableColumnConceptToConceptDto(entity)); + log.info("Saved concept with uri {} in open search database", entity.getUri()); + return entity; } @Override @@ -144,11 +144,12 @@ public class SemanticServiceImpl implements SemanticService { } /* save in metadata database */ final TableColumnUnit unit = tableMapper.entityDtoToTableColumnUnit(entityService.findOneByUri(ontology, uri)); - log.info("Saved unit with uri {} in metadata database", unit.getUri()); + final TableColumnUnit entity = tableColumnUnitRepository.save(unit); + log.info("Saved unit with uri {} in metadata database", entity.getUri()); /* save in open search database */ - unitIdxRepository.save(tableMapper.tableColumnUnitToUnitDto(unit)); - log.info("Saved unit with uri {} in open search database", unit.getUri()); - return unit; + unitIdxRepository.save(tableMapper.tableColumnUnitToUnitDto(entity)); + log.info("Saved unit with uri {} in open search database", entity.getUri()); + return entity; } private Ontology getCompatibleOntology(String uri) { diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java index fa5e9d60f43bd61e3cbd915e097d7dcad7d5bb35..8330501cb2db3edc236527e3f2117bba05537fb0 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java @@ -246,24 +246,26 @@ public class TableServiceImpl extends HibernateConnector implements TableService if (updateDto.getUnitUri() != null) { try { column.setUnit(semanticService.findUnit(updateDto.getUnitUri())); + log.debug("Found unit with uri {} in metadata database", updateDto.getUnitUri()); } catch (UnitNotFoundException e) { - log.warn("Unit with uri {} not found in metadata database", updateDto.getUnitUri()); column.setUnit(semanticService.saveUnit(updateDto.getUnitUri())); + log.info("Unit with uri {} was created in metadata database", updateDto.getUnitUri()); } } else { column.setUnit(null); - log.debug("remove unit of column, column={}", column); + log.debug("remove unit of column with id={}", columnId); } if (updateDto.getConceptUri() != null) { try { column.setConcept(semanticService.findConcept(updateDto.getConceptUri())); + log.debug("Found concept with uri {} in metadata database", updateDto.getConceptUri()); } catch (ConceptNotFoundException e) { - log.warn("Concept with uri {} not found in metadata database", updateDto.getConceptUri()); column.setConcept(semanticService.saveConcept(updateDto.getConceptUri())); + log.info("Concept with uri {} was created in metadata database", updateDto.getConceptUri()); } } else { column.setConcept(null); - log.debug("remove ColumnConcept of column, column={}", column); + log.debug("remove ColumnConcept of column with id={}", columnId); } /* update in metadata database */ final TableColumn out = tableColumnRepository.save(column); diff --git a/dbrepo-search-service/app/api/routes.py b/dbrepo-search-service/app/api/routes.py index be2812da9d0cb71fef278433c88635005611418b..b6d45b3091867b94f40f6118cf7a048b909a695d 100644 --- a/dbrepo-search-service/app/api/routes.py +++ b/dbrepo-search-service/app/api/routes.py @@ -154,8 +154,6 @@ def search(): search_term = req_body.get("search_term") t1 = req_body.get("t1") t2 = req_body.get("t2") - field = req_body.get("field") - value = req_body.get("value") fieldValuePairs = req_body.get("field_value_pairs") response = general_search(search_term, t1, t2, fieldValuePairs) return response, 200 diff --git a/dbrepo-search-service/app/opensearch_client.py b/dbrepo-search-service/app/opensearch_client.py index 2dcc1e0f7c4b8beae08a799c8e9dc1dd7f83e64e..0b454b05d0b26a8d44c61253f607aa3a68ecbf7b 100644 --- a/dbrepo-search-service/app/opensearch_client.py +++ b/dbrepo-search-service/app/opensearch_client.py @@ -173,8 +173,19 @@ def general_search(search_term=None, t1=None, t2=None, fieldValuePairs=None): ) response["status"] = 200 return response - if t1 and t2 is not None: - logging.debug('query has time range present') + if t1 is not None: + logging.debug(f"query has start value {t1} present") + time_range_query = { + "range": { + "created": { + "gte": t1, + "lte": t2, + } + } + } + queries.append(time_range_query) + if t1 is not None and t2 is not None: + logging.debug(f"query has start value {t1} and end value {t2} present") time_range_query = { "range": { "created": { diff --git a/dbrepo-ui/api/database.service.js b/dbrepo-ui/api/database.service.js index 7eb8f36f074b8d2197172665bd92df323f9dfe2c..fa020ef185a8f1e18a5d814ff8af9157240e0834 100644 --- a/dbrepo-ui/api/database.service.js +++ b/dbrepo-ui/api/database.service.js @@ -1,5 +1,4 @@ -import Vue from 'vue' -import api from '@/api' +import api, { displayError } from '@/api' class DatabaseService { findAll () { @@ -11,9 +10,7 @@ class DatabaseService { resolve(databases) }) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to load databases', error) - Vue.$toast.error(`[${code}] Failed to load databases: ${message}`) + displayError(error, 'Failed to load databases') reject(error) }) }) @@ -28,9 +25,7 @@ class DatabaseService { resolve(databases) }) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to load my databases', error) - Vue.$toast.error(`[${code}] Failed to load my databases: ${message}`) + displayError(error, 'Failed to load my databases') reject(error) }) }) @@ -45,9 +40,7 @@ class DatabaseService { resolve(count) }) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to count databases', error) - Vue.$toast.error(`[${code}] Failed to count databases: ${message}`) + displayError(error, 'Failed to count databases') reject(error) }) }) @@ -61,9 +54,7 @@ class DatabaseService { console.debug('response database', database) resolve(database) }).catch((error) => { - const { code, message } = error.response.data - console.error('Failed to load database', error) - Vue.$toast.error(`[${code}] Failed to load database: ${message}`) + displayError(error, 'Failed to load database') reject(error) }) }) @@ -77,9 +68,7 @@ class DatabaseService { console.debug('response database', database) resolve(database) }).catch((error) => { - const { code, message } = error.response.data - console.error('Failed to create database', error) - Vue.$toast.error(`[${code}] Failed to create database: ${message}`) + displayError(error, 'Failed to create database') reject(error) }) }) @@ -90,9 +79,7 @@ class DatabaseService { api.delete(`/api/database/${databaseId}`, { headers: { Accept: 'application/json' } }) .then(() => resolve()) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to delete database', error) - Vue.$toast.error(`[${code}] Failed to delete database: ${message}`) + displayError(error, 'Failed to delete database') reject(error) }) }) @@ -106,9 +93,7 @@ class DatabaseService { console.debug('response database', database) resolve(database) }).catch((error) => { - const { code, message } = error.response.data - console.error('Failed to modify database visibility', error) - Vue.$toast.error(`[${code}] Failed to modify database visibility: ${message}`) + displayError(error, 'Failed to modify database visibility') reject(error) }) }) @@ -122,9 +107,7 @@ class DatabaseService { console.debug('response database', database) resolve(database) }).catch((error) => { - const { code, message } = error.response.data - console.error('Failed to modify database owner', error) - Vue.$toast.error(`[${code}] Failed to modify database owner: ${message}`) + displayError(error, 'Failed to modify database owner') reject(error) }) }) @@ -140,10 +123,8 @@ class DatabaseService { }) .catch((error) => { const { status } = error - const { code, message } = error.response.data if (status !== 401 && status !== 403 && status !== 405) { /* ignore no access errors */ - console.error('Failed to check database access', error) - Vue.$toast.error(`[${code}] Failed to check database access: ${message}`) + displayError(error, 'Failed to check database access') reject(error) } }) @@ -159,9 +140,7 @@ class DatabaseService { resolve(database) }) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to modify database access', error) - Vue.$toast.error(`[${code}] Failed to modify database access: ${message}`) + displayError(error, 'Failed to modify database access') reject(error) }) }) @@ -172,9 +151,7 @@ class DatabaseService { api.delete(`/api/database/${databaseId}/access/${userId}`, { headers: { Accept: 'application/json' } }) .then(() => resolve()) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to revoke database access', error) - Vue.$toast.error(`[${code}] Failed to revoke database access: ${message}`) + displayError(error, 'Failed to revoke database access') reject(error) }) }) @@ -185,9 +162,7 @@ class DatabaseService { api.post(`/api/database/${databaseId}/access/${userId}`, { type }, { headers: { Accept: 'application/json' } }) .then(() => resolve()) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to give database access', error) - Vue.$toast.error(`[${code}] Failed to give database access: ${message}`) + displayError(error, 'Failed to give database access') reject(error) }) }) @@ -202,9 +177,7 @@ class DatabaseService { resolve(licenses) }) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to load licenses', error) - Vue.$toast.error(`[${code}] Failed to load licenses: ${message}`) + displayError(error, 'Failed to load licenses') reject(error) }) }) @@ -219,9 +192,7 @@ class DatabaseService { resolve(view) }) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to find view', error) - Vue.$toast.error(`[${code}] Failed to find view: ${message}`) + displayError(error, 'Failed to find view') reject(error) }) }) @@ -236,9 +207,7 @@ class DatabaseService { resolve(view) }) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to delete view', error) - Vue.$toast.error(`[${code}] Failed to delete view: ${message}`) + displayError(error, 'Failed to create view') reject(error) }) }) @@ -249,9 +218,7 @@ class DatabaseService { api.delete(`/api/database/${databaseId}/view/${viewId}`, { headers: { Accept: 'application/json' } }) .then(() => resolve()) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to delete view', error) - Vue.$toast.error(`[${code}] Failed to delete view: ${message}`) + displayError(error, 'Failed to delete view') reject(error) }) }) diff --git a/dbrepo-ui/api/index.js b/dbrepo-ui/api/index.js index ed74b41a8085364ff600214cba82c5ff62bc8efb..c56e45b3ddd33a95128133fb6966ec9dbd6ca6e6 100644 --- a/dbrepo-ui/api/index.js +++ b/dbrepo-ui/api/index.js @@ -13,8 +13,13 @@ const instance = axios.create({ function displayError (error, warning) { const { code, message } = error.response.data + if (code && message) { + console.error(warning, error) + Vue.$toast.error(`[${code}] ${warning}: ${message}`) + return + } console.error(warning, error) - Vue.$toast.error(`[${code}] ${warning}: ${message}`) + Vue.$toast.error(`[${error.code}] ${warning}: ${error.message}`) } export default instance diff --git a/dbrepo-ui/api/search.service.js b/dbrepo-ui/api/search.service.js index 2dac62689fa3fe5cc329af3ddeeb1942fbfa5068..faca4dd92a5576350c8d88e692d3e3a8c2b92202 100644 --- a/dbrepo-ui/api/search.service.js +++ b/dbrepo-ui/api/search.service.js @@ -23,8 +23,12 @@ class SearchService { // transform values to what the search API expects const searchTerm = searchData.search_term delete searchData.search_term + const t1 = searchData.t1 + const t2 = searchData.t2 searchData = Object.fromEntries(Object.entries(searchData).filter(([_, v]) => v != null && v !== '')) // https://stackoverflow.com/questions/286141/remove-blank-attributes-from-an-object-in-javascript const payload = { + t1, + t2, search_term: searchTerm, field_value_pairs: { ...searchData } } diff --git a/dbrepo-ui/api/semantic.mapper.js b/dbrepo-ui/api/semantic.mapper.js new file mode 100644 index 0000000000000000000000000000000000000000..79f71083bd4d4807c2f983bba2a85da9c6f07567 --- /dev/null +++ b/dbrepo-ui/api/semantic.mapper.js @@ -0,0 +1,17 @@ +class SemanticMapper { + mapConcepts (concepts) { + return concepts.map((concept) => { + concept.name = concept.name ? concept.name : concept.uri + return concept + }) + } + + mapUnits (units) { + return units.map((unit) => { + unit.name = unit.name ? unit.name : unit.uri + return unit + }) + } +} + +export default new SemanticMapper() diff --git a/dbrepo-ui/api/user.service.js b/dbrepo-ui/api/user.service.js index 0eacd13861c1c9ef74b10cb74c4a91ba554b2aaf..fd4cc2ba8b8112a16d50cc1934af2adebf1c4c3d 100644 --- a/dbrepo-ui/api/user.service.js +++ b/dbrepo-ui/api/user.service.js @@ -1,5 +1,4 @@ -import Vue from 'vue' -import api from '@/api' +import api, { displayError } from '@/api' import UserMapper from '@/api/user.mapper' class UserService { @@ -12,9 +11,7 @@ class UserService { resolve(users) }) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to load users', error) - Vue.$toast.error(`[${code}] Failed to load users: ${message}`) + displayError(error, 'Failed to load users') reject(error) }) }) @@ -28,9 +25,7 @@ class UserService { console.debug('response user', response.data, 'mapped user', user) resolve(user) }).catch((error) => { - const { code, message } = error.response.data - console.error('Failed to load user', error) - Vue.$toast.error(`[${code}] Failed to load user: ${message}`) + displayError(error, 'Failed to load user') reject(error) }) }) @@ -44,9 +39,7 @@ class UserService { console.debug('response user', response.data, 'mapped user', user) resolve(user) }).catch((error) => { - const { code, message } = error.response.data - console.error('Failed to update user information', error) - Vue.$toast.error(`[${code}] Failed to update user information: ${message}`) + displayError(error, 'Failed to update user information') reject(error) }) }) @@ -61,17 +54,15 @@ class UserService { resolve(user) }).catch((error) => { const { status } = error - const { code, message } = error.response.data if (status === 417) { - Vue.$toast.error('This e-mail address is already taken') + displayError(error, 'This e-mail address is already taken') } else if (status === 409) { - Vue.$toast.error('This username is already taken') + displayError(error, 'This username is already taken') } else if (status === 428) { - Vue.$toast.warning(`[${code}] Account was created: ${message}`) + displayError(error, 'Account was created') } else { - Vue.$toast.error(`[${code}] Failed to create user: ${message}`) + displayError(error, 'Failed to create user') } - console.error('Failed to create user', error) this.loading = false reject(error) }) @@ -83,9 +74,7 @@ class UserService { api.put(`/api/user/${id}/password`, { password }, { headers: { Accept: 'application/json' } }) .then(() => resolve()) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to update user password', error) - Vue.$toast.error(`[${code}] Failed to update user password: ${message}`) + displayError(error, 'Failed to update password') reject(error) }) }) @@ -96,9 +85,7 @@ class UserService { api.put(`/api/user/${id}/theme`, { theme_dark: themeDark }, { headers: { Accept: 'application/json' } }) .then(() => resolve()) .catch((error) => { - const { code, message } = error.response.data - console.error('Failed to update user theme', error) - Vue.$toast.error(`[${code}] Failed to update user theme: ${message}`) + displayError(error, 'Failed to update theme') reject(error) }) }) diff --git a/dbrepo-ui/components/search/AdvancedSearch.vue b/dbrepo-ui/components/search/AdvancedSearch.vue index ff71d33cd36e25837d2cd5bc286039d4e52ec478..3ed3e3cddcd8b48a9548a22f423d735c1661e13e 100644 --- a/dbrepo-ui/components/search/AdvancedSearch.vue +++ b/dbrepo-ui/components/search/AdvancedSearch.vue @@ -13,6 +13,7 @@ label="Type" /> </v-col> </v-row> + <p>The following fields are <code>AND</code> connected and depend on the type above.</p> <v-row dense> <v-col cols="3"> <v-text-field @@ -69,6 +70,44 @@ clearable /> </v-col> </v-row> + <p v-if="isColumnFilter" class="mt-4"> + If you select a <code>concept</code> and <code>unit</code>, you can search across columns regardless of their + unit of measurement. + </p> + <v-row v-if="isColumnFilter" dense> + <v-col cols="3"> + <v-select + v-model="advancedSearchData['concept.uri']" + clearable + :items="concepts" + item-text="name" + item-value="uri" + label="Concept" /> + </v-col> + <v-col cols="3"> + <v-select + v-model="advancedSearchData['unit.uri']" + clearable + :items="units" + item-text="name" + item-value="uri" + label="Unit" /> + </v-col> + <v-col cols="3"> + <v-text-field + v-model="advancedSearchData['t1']" + clearable + type="number" + label="Start Value" /> + </v-col> + <v-col cols="3"> + <v-text-field + v-model="advancedSearchData['t2']" + clearable + type="number" + label="End Value" /> + </v-col> + </v-row> <v-row dense> <v-btn class="mr-2" color="primary" :loading="loading" small @click="advancedSearch"> Search @@ -81,6 +120,8 @@ <script> import SearchService from '@/api/search.service' import QueryMapper from '@/api/query.mapper' +import SemanticService from '@/api/semantic.service' +import SemanticMapper from '@/api/semantic.mapper' export default { data () { @@ -88,6 +129,8 @@ export default { loading: false, loadingFields: false, showAdvancedSearch: false, + concepts: [], + units: [], columnTypes: QueryMapper.mySql8DataTypes().map((datatype) => { datatype.value = datatype.value.toUpperCase() return datatype @@ -123,6 +166,9 @@ export default { hideNameField: selectedOption === 'identifier', hideInternalNameField: ['identifier', 'user', 'concept', 'unit'].includes(selectedOption) } + }, + isColumnFilter () { + return this.advancedSearchData.type === 'column' } }, watch: { @@ -131,7 +177,6 @@ export default { if (!newType) { return } - console.debug('switched advanced search type to', newType) this.resetAdvancedSearchFields() this.loadingFields = true SearchService.getFields(newType) @@ -149,6 +194,14 @@ export default { }, mounted () { this.advancedSearch() + SemanticService.findAllConcepts() + .then((response) => { + this.concepts = SemanticMapper.mapConcepts(response) + }) + SemanticService.findAllUnits() + .then((response) => { + this.units = SemanticMapper.mapUnits(response) + }) }, methods: { /* Removes all advanced search fields when switching the type */ @@ -164,6 +217,12 @@ export default { } else { delete this.advancedSearchData.search_term } + if ('t1' in this.advancedSearchData && this.advancedSearchData.t1) { + this.advancedSearchData.t1 = Number(this.advancedSearchData.t1) + } + if ('t2' in this.advancedSearchData && this.advancedSearchData.t2) { + this.advancedSearchData.t2 = Number(this.advancedSearchData.t2) + } this.loading = true SearchService.search(this.advancedSearchData) .then((response) => {