diff --git a/.jupyter/load_test.py b/.jupyter/load_test.py index 0a60af96b754a22996968b1194ddb25822608f4f..688fa6dd8be8212d70db479e8d06f19144f5d81c 100644 --- a/.jupyter/load_test.py +++ b/.jupyter/load_test.py @@ -4,7 +4,6 @@ import time import os import shutil import uuid -import sys import api_query.rest from api_authentication.api.authentication_endpoint_api import AuthenticationEndpointApi @@ -214,6 +213,12 @@ def create_identifier(container_id, database_id, query_id, visibility="everyone" return response +def delete_tuple(container_id, database_id, table_id, keys): + response = data.delete(keys, container_id, database_id, table_id) + print("deleted tuples for table with id %d" % table_id) + return response + + if __name__ == '__main__': # # create 1 user and 3 containers (public, private, public) @@ -245,7 +250,19 @@ if __name__ == '__main__': create_identifier(cid, dbid, qid, visibility="self") qid = create_query(cid, dbid, "select `id` from `" + tname + "`").id create_identifier(cid, dbid, qid) - # container 3 with 3 tables + for i in range(5, 10): + delete_tuple(cid, dbid, tid, { + "keys": { + "id": i + } + }) + time.sleep(1) + delete_tuple(cid, dbid, tid, { + "keys": { + "location": "Schimmelstrasse" + } + }) + # container 3 with 4 tables cid = create_container().id start_container(cid) dbid = create_database(cid).id @@ -258,13 +275,13 @@ if __name__ == '__main__': "primary_key": True, "null_allowed": False, }]) - create_table(cid, dbid, columns=[{ + tid = create_table(cid, dbid, columns=[{ "name": "primary", "type": "number", "unique": True, "primary_key": True, "null_allowed": False, - }]) + }]).id create_table(cid, dbid, columns=[{ "name": "primary", "type": "date", @@ -289,7 +306,7 @@ if __name__ == '__main__': create_query(cid, dbid, "select `date` from `" + tname + "`") qid = create_query(cid, dbid, "select `date`, `location`, `status` from `" + tname + "`").id create_identifier(cid, dbid, qid) - # container 1 + # container 1 (foreign container query) tname = find_table(1, 1, 1).internal_name qid = create_query(1, 1, "select `id` from `" + tname + "`").id create_identifier(1, 1, qid) diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index be516fe2243249fb671a686bd997e4ffb2fd0ddd..879406c364e962bdd04e6d95084dd110056530c1 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -50,7 +50,6 @@ services: fda-public: environment: SPRING_PROFILES_ACTIVE: docker - TZ: Europe/Vienna ports: - "9090:9090" logging: @@ -66,7 +65,6 @@ services: fda-public: environment: SPRING_PROFILES_ACTIVE: docker - TZ: Europe/Vienna ports: - "9095:9095" depends_on: @@ -88,7 +86,6 @@ services: GATEWAY_ENDPOINT: http://fda-gateway-service:9095 SEARCH_ENDPOINT: fda-search-service:9200 SPRING_PROFILES_ACTIVE: docker - TZ: Europe/Vienna ports: - "9092:9092" volumes: @@ -114,7 +111,6 @@ services: environment: GATEWAY_ENDPOINT: http://fda-gateway-service:9095 SPRING_PROFILES_ACTIVE: docker - TZ: Europe/Vienna ports: - "9091:9091" volumes: @@ -146,7 +142,6 @@ services: SMTP_PORT: ${MAIL_PORT} SMTP_USERNAME: ${MAIL_USERNAME} SMTP_PASSWORD: ${MAIL_PASSWORD} - TZ: Europe/Vienna ports: - "9097:9097" depends_on: @@ -171,7 +166,6 @@ services: environment: SPRING_PROFILES_ACTIVE: docker GATEWAY_ENDPOINT: http://fda-gateway-service:9095 - TZ: Europe/Vienna ports: - "9093:9093" volumes: @@ -198,7 +192,6 @@ services: SEARCH_ENDPOINT: fda-search-service:9200 SPRING_PROFILES_ACTIVE: docker multipart.location: /tmp - TZ: Europe/Vienna ports: - "9094:9094" volumes: @@ -225,7 +218,6 @@ services: environment: GATEWAY_ENDPOINT: http://fda-gateway-service:9095 SPRING_PROFILES_ACTIVE: docker - TZ: Europe/Vienna ports: - "9096:9096" depends_on: @@ -269,7 +261,6 @@ services: fda-public: environment: EUREKA_SERVER: http://fda-discovery-service:9090/eureka/ - TZ: Europe/Vienna ports: - "5010:5010" volumes: @@ -290,7 +281,6 @@ services: environment: SPRING_PROFILES_ACTIVE: docker GATEWAY_ENDPOINT: http://fda-gateway-service:9095 - TZ: Europe/Vienna networks: fda-public: ports: diff --git a/docker-compose.yml b/docker-compose.yml index edaeca5bcb33e2c57367bec30a84b7f24d52e365..23fd6d99087aa630594cd5d011b9105307fd4eaa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -50,7 +50,6 @@ services: fda-public: environment: SPRING_PROFILES_ACTIVE: docker - TZ: Europe/Vienna ports: - "9090:9090" logging: @@ -66,7 +65,6 @@ services: fda-public: environment: SPRING_PROFILES_ACTIVE: docker - TZ: Europe/Vienna ports: - "9095:9095" depends_on: @@ -88,7 +86,6 @@ services: GATEWAY_ENDPOINT: http://fda-gateway-service:9095 SEARCH_ENDPOINT: fda-search-service:9200 SPRING_PROFILES_ACTIVE: docker - TZ: Europe/Vienna ports: - "9092:9092" volumes: @@ -114,7 +111,6 @@ services: environment: GATEWAY_ENDPOINT: http://fda-gateway-service:9095 SPRING_PROFILES_ACTIVE: docker - TZ: Europe/Vienna ports: - "9091:9091" volumes: @@ -146,7 +142,6 @@ services: SMTP_PORT: "" SMTP_USERNAME: "" SMTP_PASSWORD: "" - TZ: Europe/Vienna ports: - "9097:9097" depends_on: @@ -171,7 +166,6 @@ services: environment: SPRING_PROFILES_ACTIVE: docker GATEWAY_ENDPOINT: http://fda-gateway-service:9095 - TZ: Europe/Vienna ports: - "9093:9093" volumes: @@ -198,7 +192,6 @@ services: SEARCH_ENDPOINT: fda-search-service:9200 SPRING_PROFILES_ACTIVE: docker multipart.location: /tmp - TZ: Europe/Vienna ports: - "9094:9094" volumes: @@ -225,7 +218,6 @@ services: environment: GATEWAY_ENDPOINT: http://fda-gateway-service:9095 SPRING_PROFILES_ACTIVE: docker - TZ: Europe/Vienna ports: - "9096:9096" depends_on: @@ -269,7 +261,6 @@ services: fda-public: environment: EUREKA_SERVER: http://fda-discovery-service:9090/eureka/ - TZ: Europe/Vienna ports: - "5010:5010" volumes: @@ -290,7 +281,6 @@ services: environment: SPRING_PROFILES_ACTIVE: docker GATEWAY_ENDPOINT: http://fda-gateway-service:9095 - TZ: Europe/Vienna networks: fda-public: ports: diff --git a/fda-authentication-service/rest-service/src/main/resources/application-docker.yml b/fda-authentication-service/rest-service/src/main/resources/application-docker.yml index 78f3bd5c161dd3c9f6eab2dce483d1d2ea3ec2f0..471a1f64f74a45dae58a475116c13614f1f674df 100644 --- a/fda-authentication-service/rest-service/src/main/resources/application-docker.yml +++ b/fda-authentication-service/rest-service/src/main/resources/application-docker.yml @@ -15,7 +15,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-authentication-service cloud: diff --git a/fda-authentication-service/rest-service/src/main/resources/application.yml b/fda-authentication-service/rest-service/src/main/resources/application.yml index bdb5b07e6d3b79ab38dfee0d0a177ab606178311..e10bf37b2614106459391f32fa9081118db13c55 100644 --- a/fda-authentication-service/rest-service/src/main/resources/application.yml +++ b/fda-authentication-service/rest-service/src/main/resources/application.yml @@ -15,7 +15,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-authentication-service cloud: diff --git a/fda-authentication-service/services/src/main/java/at/tuwien/config/JacksonConfig.java b/fda-authentication-service/services/src/main/java/at/tuwien/config/JacksonConfig.java index b8ddbdd0483923017b30023964466be97c6db01c..fba7f99cf2bf1cbb12ac51cd6fd5b80751ff43c1 100644 --- a/fda-authentication-service/services/src/main/java/at/tuwien/config/JacksonConfig.java +++ b/fda-authentication-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -23,7 +23,7 @@ public class JacksonConfig { objectMapper.registerModule(new Jdk8Module()); objectMapper.registerModule(new JavaTimeModule()); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - objectMapper.setTimeZone(TimeZone.getTimeZone("Europe/Vienna")); + objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); log.debug("current time is {}", objectMapper.writeValueAsString(new Date())); return objectMapper; } diff --git a/fda-broker-service/rest-service/src/main/java/at/tuwien/config/JacksonConfig.java b/fda-broker-service/rest-service/src/main/java/at/tuwien/config/JacksonConfig.java index b8ddbdd0483923017b30023964466be97c6db01c..fba7f99cf2bf1cbb12ac51cd6fd5b80751ff43c1 100644 --- a/fda-broker-service/rest-service/src/main/java/at/tuwien/config/JacksonConfig.java +++ b/fda-broker-service/rest-service/src/main/java/at/tuwien/config/JacksonConfig.java @@ -23,7 +23,7 @@ public class JacksonConfig { objectMapper.registerModule(new Jdk8Module()); objectMapper.registerModule(new JavaTimeModule()); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - objectMapper.setTimeZone(TimeZone.getTimeZone("Europe/Vienna")); + objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); log.debug("current time is {}", objectMapper.writeValueAsString(new Date())); return objectMapper; } diff --git a/fda-broker-service/rest-service/src/main/resources/application-docker.yml b/fda-broker-service/rest-service/src/main/resources/application-docker.yml index 1018ed214c1a6f4b4f22db97b6860ac464106678..4a87740a47aaf88121cda5b95384bbb51f5c6a0a 100644 --- a/fda-broker-service/rest-service/src/main/resources/application-docker.yml +++ b/fda-broker-service/rest-service/src/main/resources/application-docker.yml @@ -11,7 +11,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-broker-service rabbitmq: diff --git a/fda-broker-service/rest-service/src/main/resources/application.yml b/fda-broker-service/rest-service/src/main/resources/application.yml index a1f0b02397549f4c2235e56a5f69e0afbe6719c6..aab8e1efeef63ffb7d3213a0e8ce105bd9d9ec57 100644 --- a/fda-broker-service/rest-service/src/main/resources/application.yml +++ b/fda-broker-service/rest-service/src/main/resources/application.yml @@ -11,7 +11,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-broker-service rabbitmq: diff --git a/fda-container-service/rest-service/src/main/resources/application-docker.yml b/fda-container-service/rest-service/src/main/resources/application-docker.yml index 72082793b27a78f11a2ced00e7a11d36cb967c75..c9acde992f56ddcd735387f647d8c12915f49a06 100644 --- a/fda-container-service/rest-service/src/main/resources/application-docker.yml +++ b/fda-container-service/rest-service/src/main/resources/application-docker.yml @@ -15,7 +15,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-container-service cloud: diff --git a/fda-container-service/rest-service/src/main/resources/application.yml b/fda-container-service/rest-service/src/main/resources/application.yml index 6ab8c0b831000fe49fcc7bec6a94ed33764e8583..27519b3585ab9621dbda2b81f8d48babdd85ef5d 100644 --- a/fda-container-service/rest-service/src/main/resources/application.yml +++ b/fda-container-service/rest-service/src/main/resources/application.yml @@ -15,7 +15,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-container-service cloud: diff --git a/fda-container-service/services/src/main/java/at/tuwien/config/JacksonConfig.java b/fda-container-service/services/src/main/java/at/tuwien/config/JacksonConfig.java index b8ddbdd0483923017b30023964466be97c6db01c..fba7f99cf2bf1cbb12ac51cd6fd5b80751ff43c1 100644 --- a/fda-container-service/services/src/main/java/at/tuwien/config/JacksonConfig.java +++ b/fda-container-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -23,7 +23,7 @@ public class JacksonConfig { objectMapper.registerModule(new Jdk8Module()); objectMapper.registerModule(new JavaTimeModule()); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - objectMapper.setTimeZone(TimeZone.getTimeZone("Europe/Vienna")); + objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); log.debug("current time is {}", objectMapper.writeValueAsString(new Date())); return objectMapper; } diff --git a/fda-database-service/rest-service/src/main/resources/application-docker.yml b/fda-database-service/rest-service/src/main/resources/application-docker.yml index 3993836fe9939dc5d9de08c272c600a6be76bbfb..2f2ac885fd078aea4ac4406688b26d8d9bd110f5 100644 --- a/fda-database-service/rest-service/src/main/resources/application-docker.yml +++ b/fda-database-service/rest-service/src/main/resources/application-docker.yml @@ -15,7 +15,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-database-service cloud: diff --git a/fda-database-service/rest-service/src/main/resources/application.yml b/fda-database-service/rest-service/src/main/resources/application.yml index f505a7d7dc74350dbd4e79a93c0e719b2582bc5f..382e1ded41a2c721f3ccf2b216602e51d4e7eefa 100644 --- a/fda-database-service/rest-service/src/main/resources/application.yml +++ b/fda-database-service/rest-service/src/main/resources/application.yml @@ -15,7 +15,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-database-service cloud: diff --git a/fda-database-service/services/src/main/java/at/tuwien/config/JacksonConfig.java b/fda-database-service/services/src/main/java/at/tuwien/config/JacksonConfig.java index b8ddbdd0483923017b30023964466be97c6db01c..fba7f99cf2bf1cbb12ac51cd6fd5b80751ff43c1 100644 --- a/fda-database-service/services/src/main/java/at/tuwien/config/JacksonConfig.java +++ b/fda-database-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -23,7 +23,7 @@ public class JacksonConfig { objectMapper.registerModule(new Jdk8Module()); objectMapper.registerModule(new JavaTimeModule()); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - objectMapper.setTimeZone(TimeZone.getTimeZone("Europe/Vienna")); + objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); log.debug("current time is {}", objectMapper.writeValueAsString(new Date())); return objectMapper; } diff --git a/fda-discovery-service/discovery/src/main/java/at/tuwien/config/JacksonConfig.java b/fda-discovery-service/discovery/src/main/java/at/tuwien/config/JacksonConfig.java index b8ddbdd0483923017b30023964466be97c6db01c..fba7f99cf2bf1cbb12ac51cd6fd5b80751ff43c1 100644 --- a/fda-discovery-service/discovery/src/main/java/at/tuwien/config/JacksonConfig.java +++ b/fda-discovery-service/discovery/src/main/java/at/tuwien/config/JacksonConfig.java @@ -23,7 +23,7 @@ public class JacksonConfig { objectMapper.registerModule(new Jdk8Module()); objectMapper.registerModule(new JavaTimeModule()); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - objectMapper.setTimeZone(TimeZone.getTimeZone("Europe/Vienna")); + objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); log.debug("current time is {}", objectMapper.writeValueAsString(new Date())); return objectMapper; } diff --git a/fda-discovery-service/discovery/src/main/resources/application-docker.yml b/fda-discovery-service/discovery/src/main/resources/application-docker.yml index f2185a9e68605dbf395412b2fd0c5bb51ae863e0..6a28ba573fc366ea4842fbc5c92181de5fbbe4d9 100644 --- a/fda-discovery-service/discovery/src/main/resources/application-docker.yml +++ b/fda-discovery-service/discovery/src/main/resources/application-docker.yml @@ -14,7 +14,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-discovery-service server.port: 9090 diff --git a/fda-discovery-service/discovery/src/main/resources/application.yml b/fda-discovery-service/discovery/src/main/resources/application.yml index da051e6dec12f4d7e2d11932b8defe294f9aa128..662ba464f46b421840efe50f5e1af6227c068d62 100644 --- a/fda-discovery-service/discovery/src/main/resources/application.yml +++ b/fda-discovery-service/discovery/src/main/resources/application.yml @@ -14,7 +14,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-discovery-service server.port: 9090 diff --git a/fda-gateway-service/gateway/src/main/java/at/tuwien/config/JacksonConfig.java b/fda-gateway-service/gateway/src/main/java/at/tuwien/config/JacksonConfig.java index b8ddbdd0483923017b30023964466be97c6db01c..fba7f99cf2bf1cbb12ac51cd6fd5b80751ff43c1 100644 --- a/fda-gateway-service/gateway/src/main/java/at/tuwien/config/JacksonConfig.java +++ b/fda-gateway-service/gateway/src/main/java/at/tuwien/config/JacksonConfig.java @@ -23,7 +23,7 @@ public class JacksonConfig { objectMapper.registerModule(new Jdk8Module()); objectMapper.registerModule(new JavaTimeModule()); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - objectMapper.setTimeZone(TimeZone.getTimeZone("Europe/Vienna")); + objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); log.debug("current time is {}", objectMapper.writeValueAsString(new Date())); return objectMapper; } diff --git a/fda-gateway-service/gateway/src/main/java/at/tuwien/config/ReadyConfig.java b/fda-gateway-service/gateway/src/main/java/at/tuwien/config/ReadyConfig.java index 649c3732bde1c1e8255a1136089a8897f942adf4..f4eae349a40b40c119e4c2d6545390c035b66c1a 100644 --- a/fda-gateway-service/gateway/src/main/java/at/tuwien/config/ReadyConfig.java +++ b/fda-gateway-service/gateway/src/main/java/at/tuwien/config/ReadyConfig.java @@ -20,7 +20,7 @@ public class ReadyConfig { @EventListener(ApplicationReadyEvent.class) public void init() throws IOException, InterruptedException { log.info("Wait more for gateway start"); - Thread.sleep(10 * 1000L); + Thread.sleep(20 * 1000L); Files.touch(new File(readyPath)); } diff --git a/fda-gateway-service/gateway/src/main/resources/application-docker.yml b/fda-gateway-service/gateway/src/main/resources/application-docker.yml index 7a14a409ca6af1dc3d336830aeec2768549733e4..0121560d7579510ef7a6338d8299bc871a9957cf 100644 --- a/fda-gateway-service/gateway/src/main/resources/application-docker.yml +++ b/fda-gateway-service/gateway/src/main/resources/application-docker.yml @@ -14,7 +14,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-gateway-service springdoc.swagger-ui.enabled: false diff --git a/fda-gateway-service/gateway/src/main/resources/application.yml b/fda-gateway-service/gateway/src/main/resources/application.yml index 2eb2c95da2fecb1d3d04d622b9dca79d15d39531..a51a2e8634ecd2c50399300191eaecb761c24f56 100644 --- a/fda-gateway-service/gateway/src/main/resources/application.yml +++ b/fda-gateway-service/gateway/src/main/resources/application.yml @@ -14,7 +14,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: EUTC application: name: fda-gateway-service springdoc.swagger-ui.enabled: false diff --git a/fda-identifier-service/rest-service/src/main/resources/application-docker.yml b/fda-identifier-service/rest-service/src/main/resources/application-docker.yml index 5a8c30e511ec490d43eb664fdf8566ce825cd4b0..acf0f166c0760fecedbc849c9040595d29bb1a4c 100644 --- a/fda-identifier-service/rest-service/src/main/resources/application-docker.yml +++ b/fda-identifier-service/rest-service/src/main/resources/application-docker.yml @@ -15,7 +15,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-identifier-service cloud: diff --git a/fda-identifier-service/rest-service/src/main/resources/application.yml b/fda-identifier-service/rest-service/src/main/resources/application.yml index 36e709f6d4e18cfc49b1806973095a257bec5715..fe5747482347377f7121457269d38fe7d7b2caf2 100644 --- a/fda-identifier-service/rest-service/src/main/resources/application.yml +++ b/fda-identifier-service/rest-service/src/main/resources/application.yml @@ -15,7 +15,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-identifier-service cloud: diff --git a/fda-identifier-service/services/src/main/java/at/tuwien/config/JacksonConfig.java b/fda-identifier-service/services/src/main/java/at/tuwien/config/JacksonConfig.java index b8ddbdd0483923017b30023964466be97c6db01c..fba7f99cf2bf1cbb12ac51cd6fd5b80751ff43c1 100644 --- a/fda-identifier-service/services/src/main/java/at/tuwien/config/JacksonConfig.java +++ b/fda-identifier-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -23,7 +23,7 @@ public class JacksonConfig { objectMapper.registerModule(new Jdk8Module()); objectMapper.registerModule(new JavaTimeModule()); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - objectMapper.setTimeZone(TimeZone.getTimeZone("Europe/Vienna")); + objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); log.debug("current time is {}", objectMapper.writeValueAsString(new Date())); return objectMapper; } diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableDataEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableDataEndpoint.java index 65460e3db1d9057948f0b3ddad8f0bd237fbad0c..36e9d24c4f2019b07eeb1626d371cf559894d85d 100644 --- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableDataEndpoint.java +++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableDataEndpoint.java @@ -4,6 +4,7 @@ import at.tuwien.api.database.query.ImportDto; import at.tuwien.api.database.query.QueryResultDto; import at.tuwien.api.database.table.TableCsvDeleteDto; import at.tuwien.api.database.table.TableCsvDto; +import at.tuwien.api.database.table.TableCsvUpdateDto; import at.tuwien.exception.*; import at.tuwien.service.*; import io.swagger.v3.oas.annotations.Operation; @@ -54,6 +55,25 @@ public class TableDataEndpoint extends AbstractEndpoint { .build(); } + @PutMapping + @Transactional + @Operation(summary = "Update data", security = @SecurityRequirement(name = "bearerAuth")) + public ResponseEntity<Void> update(@NotNull @PathVariable("id") Long containerId, + @NotNull @PathVariable("databaseId") Long databaseId, + @NotNull @PathVariable("tableId") Long tableId, + @NotNull @Valid @RequestBody TableCsvUpdateDto data, + @NotNull Principal principal) + throws TableNotFoundException, DatabaseNotFoundException, TableMalformedException, + ImageNotSupportedException, NotAllowedException, DatabaseConnectionException, QueryMalformedException { + if (!hasDatabasePermission(containerId, databaseId, "DATA_UPDATE", principal)) { + log.error("Missing data update permission"); + throw new NotAllowedException("Missing data update permission"); + } + queryService.update(containerId, databaseId, tableId, data); + return ResponseEntity.accepted() + .build(); + } + @DeleteMapping @Transactional @Operation(summary = "Delete data", security = @SecurityRequirement(name = "bearerAuth")) diff --git a/fda-query-service/rest-service/src/main/resources/application-docker.yml b/fda-query-service/rest-service/src/main/resources/application-docker.yml index 1f8171d23806dde9b5ff6f1e649bb3f8fe358f1a..955a46143cacbf54298714e9e6f4854f3d29ebef 100644 --- a/fda-query-service/rest-service/src/main/resources/application-docker.yml +++ b/fda-query-service/rest-service/src/main/resources/application-docker.yml @@ -15,7 +15,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-query-service rabbitmq: diff --git a/fda-query-service/rest-service/src/main/resources/application.yml b/fda-query-service/rest-service/src/main/resources/application.yml index 030d622c37f65f471942aa4e96dcfc21d82af5cf..afd58b269ac48e38a81f955407c7a3c584fa8cd9 100644 --- a/fda-query-service/rest-service/src/main/resources/application.yml +++ b/fda-query-service/rest-service/src/main/resources/application.yml @@ -15,7 +15,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-query-service rabbitmq: @@ -28,7 +28,7 @@ server.port: 9093 logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: - root: debug + root: warn at.tuwien.: trace at.tuwien.mapper.: trace at.tuwien.service.: trace diff --git a/fda-query-service/services/src/main/java/at/tuwien/config/JacksonConfig.java b/fda-query-service/services/src/main/java/at/tuwien/config/JacksonConfig.java index b8ddbdd0483923017b30023964466be97c6db01c..fba7f99cf2bf1cbb12ac51cd6fd5b80751ff43c1 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/config/JacksonConfig.java +++ b/fda-query-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -23,7 +23,7 @@ public class JacksonConfig { objectMapper.registerModule(new Jdk8Module()); objectMapper.registerModule(new JavaTimeModule()); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - objectMapper.setTimeZone(TimeZone.getTimeZone("Europe/Vienna")); + objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); log.debug("current time is {}", objectMapper.writeValueAsString(new Date())); return objectMapper; } diff --git a/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java b/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java index cbe4f641e367a2f57ccd9bdef54e381f488ba0cf..fab90ea031913a3c81414114341ad9a0534f2fb8 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java +++ b/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java @@ -21,10 +21,12 @@ import org.mapstruct.Mapping; import org.mapstruct.Mappings; import org.mapstruct.Named; import org.mariadb.jdbc.MariaDbBlob; +import org.mariadb.jdbc.internal.ColumnType; import org.springframework.transaction.annotation.Transactional; import java.math.BigInteger; import java.sql.*; +import java.sql.Date; import java.text.Normalizer; import java.time.*; import java.time.format.DateTimeFormatter; @@ -81,7 +83,7 @@ public interface QueryMapper { for (int i = 0; i < columns.size(); i++) { map.put(columns.get(i).getInternalName(), dataColumnToObject(result.getObject(idx[0]++), columns.get(i))); } - resultList.add(map); + resultList.add(map); } return QueryResultDto.builder() .result(resultList) @@ -380,7 +382,7 @@ public interface QueryMapper { .filter(column -> !column.getAutoGenerated()) .map(column -> "`" + column.getInternalName() + "`") .collect(Collectors.joining(","))) - .append(") VALUES (?1);"); + .append(") VALUES (?);"); /* map all columns that are non-auto generated */ final int[] idx = new int[]{0}; try { @@ -414,6 +416,7 @@ public interface QueryMapper { default PreparedStatement tableCsvDtoToRawDeleteQuery(Connection connection, Table table, TableCsvDeleteDto data) throws TableMalformedException, ImageNotSupportedException, QueryMalformedException { + int i = 1; if (table.getColumns().size() == 0) { log.error("Column size is zero"); throw new TableMalformedException("Columns are not known"); @@ -429,15 +432,28 @@ public interface QueryMapper { .append("` WHERE "); final int[] idx = new int[]{0}; data.getKeys() - .forEach((key, value) -> statement.append(idx[0] == 0 ? "" : ", ") + .forEach((key, value) -> statement.append(idx[0]++ == 0 ? "" : ", ") .append("`") .append(key) - .append("` = ?") - .append(idx[0]++)); + .append("` = ?")); /* debug */ log.trace("raw delete query: [{}] with data {}", statement, data.getKeys().values()); + /* prepare */ try { - return connection.prepareStatement(statement.toString()); + final PreparedStatement ps = connection.prepareStatement(statement.toString()); + for (Map.Entry<String, Object> entry : data.getKeys().entrySet()) { + final Optional<TableColumn> optional = table.getColumns() + .stream() + .filter(c -> c.getInternalName().equals(entry.getKey())) + .findFirst(); + if (optional.isEmpty()) { + log.error("Failed to find column"); + log.debug("failed to find column with internal name {} in table {}", entry.getKey(), table); + throw new QueryMalformedException("Failed to find column"); + } + prepareStatementWithColumnTypeObject(ps, optional.get().getColumnType(), i++, entry.getValue()); + } + return ps; } catch (SQLException e) { log.error("Failed to prepare statement"); log.debug("failed to prepare statement {} reason: {}", statement, e.getMessage()); @@ -445,8 +461,9 @@ public interface QueryMapper { } } - default InsertTableRawQuery tableCsvDtoToRawUpdateQuery(Table table, TableCsvUpdateDto data) - throws TableMalformedException, ImageNotSupportedException { + default PreparedStatement tableCsvDtoToRawUpdateQuery(Connection connection, Table table, TableCsvUpdateDto data) + throws TableMalformedException, ImageNotSupportedException, QueryMalformedException { + int i = 1; if (table.getColumns().size() == 0) { log.error("Column size is zero"); throw new TableMalformedException("Columns are not known"); @@ -457,24 +474,22 @@ public interface QueryMapper { throw new ImageNotSupportedException("Image not supported."); } /* parameterized query for prepared statement */ - final StringBuilder query = new StringBuilder("UPDATE `") + final StringBuilder statement = new StringBuilder("UPDATE `") .append(table.getInternalName()) .append("` SET "); final int[] idx = new int[]{0}; data.getData() .forEach((key, value) -> { - query.append(idx[0] == 0 ? "" : ", ") + statement.append(idx[0]++ == 0 ? "" : ", ") .append("`") .append(key) - .append("` = ?") - .append(idx[0]); - idx[0]++; + .append("` = ?"); }); - query.append(" WHERE "); + statement.append(" WHERE "); final int[] jdx = new int[]{0}; data.getKeys() .forEach((key, value) -> { - query.append(jdx[0] == 0 ? "" : ", ") + statement.append(jdx[0] == 0 ? "" : ", ") .append("`") .append(key) .append("` = '") @@ -482,13 +497,20 @@ public interface QueryMapper { .append("'"); jdx[0]++; }); - query.append(";"); + statement.append(";"); /* debug */ - log.trace("raw update query: [{}] with data {}", query, data.getData().values()); - return InsertTableRawQuery.builder() - .query(query.toString()) - .data(data.getData().values()) - .build(); + log.trace("raw update query: [{}] with data {}", statement, data.getData().values()); + try { + final PreparedStatement ps = connection.prepareStatement(statement.toString()); + for (Map.Entry<String, Object> entry : data.getData().entrySet()) { + ps.setString(i++, String.valueOf(entry.getValue())); + } + return ps; + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason: {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } default PreparedStatement tableToRawCountAllQuery(Connection connection, Table table, Instant timestamp) throws ImageNotSupportedException, QueryMalformedException { @@ -537,7 +559,7 @@ public interface QueryMapper { /* put timestamp after "join" and each "on" (but before alias) */ } else { original.append("FOR SYSTEM_TIME AS OF TIMESTAMP '"); - original.append(LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna"))); + original.append(LocalDateTime.ofInstant(timestamp, ZoneId.of("UTC"))); original.append("' "); } if (query.contains("where")) { @@ -549,10 +571,10 @@ public interface QueryMapper { String statement = original.toString(); if (query.contains("join")) { statement = statement.replaceFirst("from ([`a-z0-9_]+) ", "from $1 FOR SYSTEM_TIME AS OF TIMESTAMP '" - + LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna")) + + LocalDateTime.ofInstant(timestamp, ZoneId.of("UTC")) + "' "); statement = statement.replaceAll("join ([`a-z0-9_]+) ", "join $1 FOR SYSTEM_TIME AS OF TIMESTAMP '" - + LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna")) + + LocalDateTime.ofInstant(timestamp, ZoneId.of("UTC")) + "' "); } log.debug("mapped raw view-only query [{}]", statement); @@ -600,7 +622,7 @@ public interface QueryMapper { /* put timestamp after "join" and each "on" (but before alias) */ } else { sb.append(" FOR SYSTEM_TIME AS OF TIMESTAMP '"); - sb.append(LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna"))); + sb.append(LocalDateTime.ofInstant(timestamp, ZoneId.of("UTC"))); sb.append("' "); } if (query.contains("where")) { @@ -615,10 +637,10 @@ public interface QueryMapper { String statement = sb.toString(); if (query.contains("join")) { statement = statement.replaceFirst("from ([`a-z0-9_]+) ", "from $1 FOR SYSTEM_TIME AS OF TIMESTAMP '" - + LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna")) + + LocalDateTime.ofInstant(timestamp, ZoneId.of("UTC")) + "' "); statement = statement.replaceAll("join ([`a-z0-9_]+) ", "join $1 FOR SYSTEM_TIME AS OF TIMESTAMP '" - + LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna")) + + LocalDateTime.ofInstant(timestamp, ZoneId.of("UTC")) + "' "); } log.debug("mapped raw view-only query [{}]", statement); @@ -664,7 +686,7 @@ public interface QueryMapper { statement.append(" FROM `") .append(nameToInternalName(table.getName())) .append("` FOR SYSTEM_TIME AS OF TIMESTAMP '") - .append(LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna"))) + .append(LocalDateTime.ofInstant(timestamp, ZoneId.of("UTC"))) .append("'"); if (size != null && page != null) { log.trace("pagination size/limit of {}", size); @@ -862,27 +884,31 @@ public interface QueryMapper { } } - default Instant objectToInstant(Object data) { - if (data == null) { - return null; + default void prepareStatementWithColumnTypeObject(PreparedStatement ps, TableColumnType columnType, int idx, Object value) throws SQLException { + switch (columnType) { + case TEXT: + case STRING: + ps.setString(idx, String.valueOf(value)); + break; + case DATE: + ps.setDate(idx, Date.valueOf(String.valueOf(value))); + break; + case NUMBER: + ps.setLong(idx, Long.parseLong(String.valueOf(value))); + break; + case DECIMAL: + ps.setDouble(idx, Double.parseDouble(String.valueOf(value))); + break; + case BOOLEAN: + ps.setBoolean(idx, Boolean.parseBoolean(String.valueOf(value))); + break; + case TIMESTAMP: + ps.setTimestamp(idx, Timestamp.valueOf(String.valueOf(value))); + default: + log.error("Failed to map column type {}", columnType); + log.debug("failed to map column type {} at index {} for value {}", columnType, idx, value); + throw new IllegalArgumentException("Failed to map column type"); } - final String str = String.valueOf(data); - log.trace("mapping string {} to instant", str); - final Instant out; - if (str.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z")) { - /* e.g. 2022-07-04T11:31:46Z */ - log.trace("format ISO 8601 matches, e.g. 2022-07-04T11:31:46Z, want to parse '{}'", str); - out = Instant.parse(str); - } else { - /* e.g. 2022-06-20 09:08:13.416567, 2022-06-20 09:08:13.41656 */ - final String timestamp = str.substring(0, 19); - log.trace("want to parse '{}'", timestamp); - out = LocalDateTime.parse(timestamp, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH)) - .atZone(ZoneId.of("UTC")) - .toInstant(); - } - log.trace("instant is {}", out); - return out; } } diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java b/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java index 5c23fcdba8ec7131975ee4f875988b7642ba63ee..8288910dd81270c752d4b3dafde193addfe50a30 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java @@ -10,6 +10,7 @@ import at.tuwien.api.database.table.TableCsvUpdateDto; import at.tuwien.exception.*; import at.tuwien.querystore.Query; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.math.BigInteger; import java.security.Principal; @@ -146,6 +147,10 @@ public interface QueryService { throws ContainerNotFoundException, DatabaseNotFoundException, TableNotFoundException, TableMalformedException, ImageNotSupportedException, DatabaseConnectionException, QueryMalformedException, QueryStoreException; + void update(Long containerId, Long databaseId, Long tableId, TableCsvUpdateDto data) + throws ImageNotSupportedException, TableMalformedException, DatabaseNotFoundException, + TableNotFoundException, DatabaseConnectionException, QueryMalformedException; + /** * Insert data from AMQP client into a table of a table-database id tuple, we need the "root" role for this as the * default "mariadb" user is configured to only be allowed to execute "SELECT" statements. diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java index 159549e16c45ac5ab2a31558014db12060945de5..0ff0e3fc64e7123c1acb80cfb2aa9a2314b28339 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java @@ -1,11 +1,13 @@ package at.tuwien.service.impl; import at.tuwien.ExportResource; +import at.tuwien.InsertTableRawQuery; import at.tuwien.api.database.query.ExecuteStatementDto; import at.tuwien.api.database.query.ImportDto; import at.tuwien.api.database.query.QueryResultDto; import at.tuwien.api.database.table.TableCsvDeleteDto; import at.tuwien.api.database.table.TableCsvDto; +import at.tuwien.api.database.table.TableCsvUpdateDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.table.Table; import at.tuwien.entities.database.table.columns.TableColumn; @@ -21,6 +23,8 @@ import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.select.*; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.RandomStringUtils; +import org.hibernate.Session; +import org.hibernate.query.NativeQuery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.InputStreamResource; import org.springframework.stereotype.Service; @@ -39,7 +43,6 @@ import java.time.DateTimeException; import java.time.Instant; import java.time.format.DateTimeParseException; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; @Log4j2 @@ -229,6 +232,29 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService } } + @Override + @Transactional + public void update(Long containerId, Long databaseId, Long tableId, TableCsvUpdateDto data) + throws ImageNotSupportedException, TableMalformedException, DatabaseNotFoundException, + TableNotFoundException, DatabaseConnectionException, QueryMalformedException { + /* find */ + final Database database = databaseService.find(containerId, databaseId); + final Table table = tableService.find(containerId, databaseId, tableId); + /* run query */ + if (data.getData().size() == 0 || data.getKeys().size() == 0) return; + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); + try { + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = queryMapper.tableCsvDtoToRawUpdateQuery(connection, table, data); + preparedStatement.executeUpdate(); + } catch (SQLException e) { + log.error("Failed to count tuples"); + throw new TableMalformedException("Failed to count tuples", e); + } finally { + dataSource.close(); + } + } + @Override @Transactional public void insert(Long containerId, Long databaseId, Long tableId, TableCsvDto data) @@ -268,17 +294,14 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService if (data.getKeys().size() == 0) return; final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); /* prepare the statement */ - final List<Object> values = new LinkedList<>(data.getKeys() - .values()); try { final Connection connection = dataSource.getConnection(); final PreparedStatement preparedStatement = queryMapper.tableCsvDtoToRawDeleteQuery(connection, table, data); - for (int i = 0; i < data.getKeys().size(); i++) { - preparedStatement.setObject(i, values.get(i)); - } + preparedStatement.executeUpdate(); } catch (SQLException e) { log.error("Failed to delete tuples"); - throw new TableMalformedException("Failed to delete tuples"); + log.debug("failed to delete tuples, reason: {}", e.getMessage()); + throw new TableMalformedException("Failed to delete tuples", e); } finally { dataSource.close(); } diff --git a/fda-table-service/rest-service/src/main/resources/application-docker.yml b/fda-table-service/rest-service/src/main/resources/application-docker.yml index 0ea2cec678a00c17d12ddf87745be5c4f5c1b6a6..6505cdc429eb6b9dda70e42143f1a98adaa42c99 100644 --- a/fda-table-service/rest-service/src/main/resources/application-docker.yml +++ b/fda-table-service/rest-service/src/main/resources/application-docker.yml @@ -15,7 +15,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-table-service rabbitmq: diff --git a/fda-table-service/rest-service/src/main/resources/application.yml b/fda-table-service/rest-service/src/main/resources/application.yml index f932be011f81d9d6dc65149c10d3820c347f2b89..f6d93311ad2176540ceb09c78f5498291c1cc4ce 100644 --- a/fda-table-service/rest-service/src/main/resources/application.yml +++ b/fda-table-service/rest-service/src/main/resources/application.yml @@ -15,7 +15,7 @@ spring: properties: hibernate: jdbc: - time_zone: Europe/Vienna + time_zone: UTC application: name: fda-table-service rabbitmq: diff --git a/fda-table-service/services/src/main/java/at/tuwien/config/JacksonConfig.java b/fda-table-service/services/src/main/java/at/tuwien/config/JacksonConfig.java index b8ddbdd0483923017b30023964466be97c6db01c..fba7f99cf2bf1cbb12ac51cd6fd5b80751ff43c1 100644 --- a/fda-table-service/services/src/main/java/at/tuwien/config/JacksonConfig.java +++ b/fda-table-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -23,7 +23,7 @@ public class JacksonConfig { objectMapper.registerModule(new Jdk8Module()); objectMapper.registerModule(new JavaTimeModule()); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - objectMapper.setTimeZone(TimeZone.getTimeZone("Europe/Vienna")); + objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); log.debug("current time is {}", objectMapper.writeValueAsString(new Date())); return objectMapper; } diff --git a/fda-ui/components/TableList.vue b/fda-ui/components/TableList.vue index 1b8906c9128a6095f3b768a48d24f7d30b5e2105..e7168b8a15b84f18cb6450a4b608e49a21001b80 100644 --- a/fda-ui/components/TableList.vue +++ b/fda-ui/components/TableList.vue @@ -116,14 +116,26 @@ <span v-if="item.auto_generated">●</span> {{ item.auto_generated }} </template> <template v-slot:item.column_concept="{ item }"> - <DialogsColumnUnit :column="item" :table-id="tableDetails.id" @save="details" /> + <v-btn v-if="!item.column_concept" small @click="pickUnit(item)">Assign</v-btn> + <v-btn + v-if="item.column_concept" + :title="item.column_concept.uri" + color="secondary" + small + @click="pickUnit(item)"> + {{ item.column_concept.name }} + </v-btn> </template> </v-data-table> </v-row> </v-expansion-panel-content> </v-expansion-panel> </v-expansion-panels> - + <v-dialog + v-model="unitDialog" + max-width="600px"> + <DialogsColumnUnit :concept="unit" :table-id="tableDetails.id" @close="closed" /> + </v-dialog> <v-dialog v-model="dialogDelete" max-width="640"> <v-card> <v-card-title class="headline"> @@ -155,6 +167,8 @@ export default { error: false, tables: [], panel: null, + unit: null, + unitDialog: false, database: { exchange: null, tables: [] @@ -215,6 +229,11 @@ export default { this.loadDatabase() }, methods: { + pickUnit (item) { + this.unit = item.column_concept + this.unitDialog = true + console.debug('select', this.unit) + }, async loadDatabase () { try { this.loading = true @@ -243,6 +262,10 @@ export default { console.debug('table details', this.tableDetails) } }, + closed (data) { + console.debug('closed dialog', data) + this.unitDialog = false + }, /** * if tableId is given, open the table after refresh */ diff --git a/fda-ui/components/dialogs/ColumnUnit.vue b/fda-ui/components/dialogs/ColumnUnit.vue index afee4a60dbefc6f531e7ce34bd2b37ad73d47122..24fde4976dd943eb00d806106ffb7160fac42227 100644 --- a/fda-ui/components/dialogs/ColumnUnit.vue +++ b/fda-ui/components/dialogs/ColumnUnit.vue @@ -1,25 +1,8 @@ <template> - <v-dialog - v-model="dialog" - max-width="600px"> - <template v-slot:activator="{ on, attrs }"> - <span v-if="column.column_concept" :title="column.column_concept.uri"> - {{ column.column_concept.name }} - </span> - <v-btn - class="ml-2" - icon - small - v-bind="attrs" - v-on="on"> - <v-icon color="secondary"> - mdi-pencil-outline - </v-icon> - </v-btn> - </template> + <div> <v-card> <v-card-title> - <span class="text-h5">Column Unit</span> + Assign Unit of Measurement </v-card-title> <v-card-text> <v-autocomplete @@ -65,10 +48,10 @@ <v-list-item-subtitle>{{ model.comment }}</v-list-item-subtitle> </v-list-item-content> </v-list-item> - <v-list-item v-if="uri" three-line> + <v-list-item v-if="model.uri" three-line> <v-list-item-content> <v-list-item-title>URI</v-list-item-title> - <v-list-item-subtitle>{{ uri }}</v-list-item-subtitle> + <v-list-item-subtitle>{{ model.uri }}</v-list-item-subtitle> </v-list-item-content> </v-list-item> </v-list> @@ -76,27 +59,29 @@ <v-card-actions> <v-spacer /> <v-btn - color="blue darken-1" - text - @click="dialog = false"> - Close + class="mb-2 mr-2" + @click="cancel"> + Cancel </v-btn> <v-btn - color="blue darken-1" - text - :disabled="!model || !uri" + color="primary" + class="mb-2" + :disabled="!model" @click="save"> Save </v-btn> </v-card-actions> </v-card> - </v-dialog> + </div> </template> <script> export default { props: { - column: { type: Object, default: () => ({}) }, + concept: { + type: Object, + default: () => ({}) + }, tableId: { type: Number, default: () => -1 } }, data () { @@ -104,7 +89,11 @@ export default { dialog: false, isLoading: false, saved: false, - model: null, + model: { + name: null, + uri: null, + symbol: null + }, uri: null, search: null, entries: [] @@ -125,18 +114,8 @@ export default { } }, watch: { - async model (val) { - this.uri = null - this.saved = false - if (!val) { return } - try { - const res = await this.$axios.get(`/api/units/uri/${val.name}`) - this.uri = res.data.URI - console.log(this.uri) - } catch (err) { - this.$toast.error(`Could not load URI of unit "${val.name}"`) - console.log(err) - } + concept (newVal, oldVal) { + this.loadConcept(newVal) }, async search (val) { if (this.isLoading) { return } @@ -156,22 +135,36 @@ export default { } }, mounted () { - if (this.column.column_concept) { - const { name, uri } = this.column.column_concept - console.log(this.column.column_concept) - this.model = { - name, - uri - } - } + this.loadConcept(this.concept) }, methods: { + cancel () { + this.$emit('close', { + success: false + }) + }, + async loadConcept (concept) { + if (!concept) { + return + } + this.model = concept + console.debug('load concept', concept) + try { + const res = await this.$axios.get(`/api/units/uri/${concept.name}`) + this.model.uri = res.data.URI + } catch (err) { + this.$toast.error(`Could not load URI of unit "${concept.name}"`) + console.log(err) + } + }, async save () { + const payload = { + name: this.model.name, + uri: this.model.uri + } try { - await this.$axios.post('/api/units/saveconcept', { - name: this.model.name, - uri: this.uri - }) + console.debug('save', payload) + await this.$axios.post('/api/units/saveconcept', payload) } catch (error) { const { status } = error.response if (status !== 201 && status !== 400) { @@ -190,8 +183,9 @@ export default { this.column.column_concept.name = this.model.name this.dialog = false this.saved = true - this.$nextTick(() => { - this.$emit('save', this.tableId) + this.$emit('close', { + success: true, + concept: res.data }) console.debug('column', this.column) } catch (err) { diff --git a/fda-ui/components/dialogs/TimeTravel.vue b/fda-ui/components/dialogs/TimeTravel.vue index 7c3e940100d1ba619f16a35006489ac21d1235f3..0e506801dfc10d43e3b067a5ef1fc89dfea9967c 100644 --- a/fda-ui/components/dialogs/TimeTravel.vue +++ b/fda-ui/components/dialogs/TimeTravel.vue @@ -92,10 +92,20 @@ export default { computed: { loadingColor () { return this.error ? 'red lighten-2' : 'primary' + }, + token () { + return this.$store.state.token + }, + config () { + if (this.token === null) { + return {} + } + return { + headers: { Authorization: `Bearer ${this.token}` } + } } }, mounted () { - console.log('mounted') this.loadHistory() }, methods: { @@ -120,22 +130,14 @@ export default { this.cancel() }, pick () { - this.$parent.$parent.$parent.$parent.version = this.formatDate() - this.cancel() - }, - formatDate () { - if (this.datetime === null || this.datetime === undefined || this.datetime === '') { - return null - } - console.debug('selected date', this.datetime) - return Date.parse(this.datetime) + this.$emit('close', { + time: this.datetime + }) }, async loadHistory () { try { this.loading = true - const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/table/${this.$route.params.table_id}/history`, { - headers: this.requestHeaders - }) + const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/table/${this.$route.params.table_id}/history`, this.config) this.error = false this.chartData.labels = res.data.map(function (d, idx) { if (idx === 0) { diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/index.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/index.vue index 022231f0b0b6a107ac8eeddaa4206d0a0dad8420..229c195476198aa1e05f2a62fd195537c9a72742 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/index.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/index.vue @@ -15,7 +15,7 @@ <v-btn color="primary" :disabled="!token" class="mr-2" @click="addTuple"> <v-icon left>mdi-plus</v-icon> Add </v-btn> - <v-btn v-if="canEdit" :disabled="!token" color="warn" class="mr-2 mb-1" @click="editTupleDialog = true"> + <v-btn v-if="canEdit" :disabled="!token" color="warning" class="mr-2 mb-1" @click="editTupleDialog = true"> <v-icon left>mdi-pencil</v-icon> Edit </v-btn> <v-btn v-if="canDelete" :disabled="!token" color="error" class="mr-2 mb-1" @click="deleteItems"> @@ -28,7 +28,7 @@ <v-icon left>mdi-cloud-upload</v-icon> Import csv </v-btn> <v-btn :disabled="error" class="ml-2 mb-1" :loading="downloadLoading" @click.stop="download"> - <v-icon left>mdi-download</v-icon> Data .csv + <v-icon left>mdi-download</v-icon> Download csv </v-btn> <v-btn v-if="false" @@ -54,7 +54,7 @@ <v-dialog v-model="pickVersionDialog" max-width="640"> - <TimeTravel ref="timeTravel" @close="pickVersionDialog = false" /> + <TimeTravel ref="timeTravel" @close="pickVersion" /> </v-dialog> </v-toolbar-title> </v-toolbar> @@ -152,7 +152,13 @@ export default { if (this.version === null) { return null } - return formatTimestampUTCLabel(this.version) + return this.version + ' (UTC)' + }, + versionISO () { + if (this.version === null) { + return null + } + return this.version.substring(0, 10) + 'T' + this.version.substring(11, 19) + 'Z' }, canEdit () { if (this.selection.length !== 1) { return false } @@ -209,6 +215,13 @@ export default { pick () { this.pickVersionDialog = true }, + pickVersion (event) { + console.debug('closed', event) + if (event.time) { + this.version = event.time + } + this.pickVersionDialog = false + }, async deleteItems () { if (this.selection.length < 1) { return @@ -264,7 +277,7 @@ export default { let url = `/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/table/${this.$route.params.table_id}/data?page=${this.options.page - 1}&size=${this.options.itemsPerPage}` if (this.version !== null) { console.info('versioning active', this.version) - url += `×tamp=${new Date(this.version).toISOString()}` + url += `×tamp=${this.versionISO}` } const res = await this.$axios.get(url, this.config) this.total = parseInt(res.headers['fda-count'])