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 new file mode 100644 index 0000000000000000000000000000000000000000..ef988c97c0ec5b75ef9a7c8a753da509a41bd347 --- /dev/null +++ b/fda-authentication-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -0,0 +1,20 @@ +package at.tuwien.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JacksonConfig { + + @Bean + public ObjectMapper objectMapper() { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + return objectMapper; + } + +} diff --git a/fda-broker-service/services/src/main/java/at/tuwien/config/JacksonConfig.java b/fda-broker-service/services/src/main/java/at/tuwien/config/JacksonConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..ef988c97c0ec5b75ef9a7c8a753da509a41bd347 --- /dev/null +++ b/fda-broker-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -0,0 +1,20 @@ +package at.tuwien.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JacksonConfig { + + @Bean + public ObjectMapper objectMapper() { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + return objectMapper; + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..ef988c97c0ec5b75ef9a7c8a753da509a41bd347 --- /dev/null +++ b/fda-container-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -0,0 +1,20 @@ +package at.tuwien.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JacksonConfig { + + @Bean + public ObjectMapper objectMapper() { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + return objectMapper; + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..ef988c97c0ec5b75ef9a7c8a753da509a41bd347 --- /dev/null +++ b/fda-database-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -0,0 +1,20 @@ +package at.tuwien.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JacksonConfig { + + @Bean + public ObjectMapper objectMapper() { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + return objectMapper; + } + +} diff --git a/fda-document-service/services/src/main/java/at/tuwien/config/JacksonConfig.java b/fda-document-service/services/src/main/java/at/tuwien/config/JacksonConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..ef988c97c0ec5b75ef9a7c8a753da509a41bd347 --- /dev/null +++ b/fda-document-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -0,0 +1,20 @@ +package at.tuwien.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JacksonConfig { + + @Bean + public ObjectMapper objectMapper() { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + return objectMapper; + } + +} diff --git a/fda-gateway-service/gateway/src/main/java/at/tuwien/gatewayservice/config/JacksonConfig.java b/fda-gateway-service/gateway/src/main/java/at/tuwien/gatewayservice/config/JacksonConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..7e45ccb10b2d43025c913853a906ba004e66137a --- /dev/null +++ b/fda-gateway-service/gateway/src/main/java/at/tuwien/gatewayservice/config/JacksonConfig.java @@ -0,0 +1,20 @@ +package at.tuwien.gatewayservice.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JacksonConfig { + + @Bean + public ObjectMapper objectMapper() { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + return objectMapper; + } + +} diff --git a/fda-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java b/fda-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java index 722d78f4618795774b8bf97df38e26f499855f93..c7a664474bdf86a661f5157bc0e3f777b2862f5e 100644 --- a/fda-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java +++ b/fda-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java @@ -51,7 +51,8 @@ public class IdentifierEndpoint { final Identifier identifier = identifierService.find(containerId, databaseId, qid); log.info("Found identifier with id {} filtered by query id {}", identifier.getId(), qid); log.debug("found identifier {} filtered by query id {}", identifier, qid); - return ResponseEntity.ok(List.of(identifierMapper.identifierToIdentifierDto(identifier))); + final IdentifierDto dto = identifierMapper.identifierToIdentifierDto(identifier); + return ResponseEntity.ok(List.of(dto)); } final List<Identifier> identifiers = identifierService.findAll(containerId, databaseId); log.info("Found {} identifiers", identifiers.size()); 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 9d59953bb99cafd6743522fbc6f665c15c1cedf5..ef988c97c0ec5b75ef9a7c8a753da509a41bd347 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 @@ -1,7 +1,7 @@ package at.tuwien.config; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -11,10 +11,10 @@ public class JacksonConfig { @Bean public ObjectMapper objectMapper() { - return new ObjectMapper() - .findAndRegisterModules() - .registerModule(new JavaTimeModule()) - .registerModule(new Jdk8Module()); + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + return objectMapper; } } diff --git a/fda-identifier-service/services/src/main/java/at/tuwien/mapper/DocumentMapper.java b/fda-identifier-service/services/src/main/java/at/tuwien/mapper/DocumentMapper.java index 9c76041270dbd1f5236a9f0546c7613f6c6e956b..1a0dfe0049dfb948ba83bff0af6474a9c2a19920 100644 --- a/fda-identifier-service/services/src/main/java/at/tuwien/mapper/DocumentMapper.java +++ b/fda-identifier-service/services/src/main/java/at/tuwien/mapper/DocumentMapper.java @@ -78,6 +78,27 @@ public interface DocumentMapper { .append("</language>"); } builder.append("<resourceType resourceTypeGeneral=\"Dataset\">Dataset</resourceType>"); + if (data.getRelated().size() > 0) { + builder.append("<relatedIdentifiers>"); + data.getRelated() + .forEach(related -> { + builder.append("<relatedIdentifier"); + if (related.getType() != null) { + builder.append(" relatedIdentifierType=\"") + .append(related.getType()) + .append("\""); + } + if (related.getRelation() != null) { + builder.append(" relationType=\"") + .append(related.getRelation()) + .append("\""); + } + builder.append(">") + .append(related.getValue()) + .append("</relatedIdentifier>"); + }); + builder.append("</relatedIdentifiers>"); + } if (database.getLicense() != null) { builder.append("<rightsList><rights xml:lang=\"en-US\" schemeURI=\"https://spdx.org/licenses/\" ") .append("rightsIdentifierScheme=\"SPDX\" rightsIdentifier=\"") diff --git a/fda-identifier-service/services/src/main/java/at/tuwien/mapper/IdentifierMapper.java b/fda-identifier-service/services/src/main/java/at/tuwien/mapper/IdentifierMapper.java index 5ead18d3ed943bea0507603f15ad9a34ca10afde..6d4f8e53f0b77697ec8ce8f39cab2b7e6cdc3cdf 100644 --- a/fda-identifier-service/services/src/main/java/at/tuwien/mapper/IdentifierMapper.java +++ b/fda-identifier-service/services/src/main/java/at/tuwien/mapper/IdentifierMapper.java @@ -17,6 +17,10 @@ public interface IdentifierMapper { @Transactional Identifier identifierCreateDtoToIdentifier(IdentifierCreateDto data); + /* keep */ + @Transactional + RelatedIdentifierDto relatedIdentifierToRelatedIdentifierDto(RelatedIdentifier data); + @Transactional Identifier identifierDtoToIdentifier(IdentifierDto data); diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/container/ContainerCreateRequestDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/container/ContainerCreateRequestDto.java index 053cde186502fdcb68cce12967422ae6ac271aad..e859f85b1b08a6aa59d771f752d9bf83d312703c 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/container/ContainerCreateRequestDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/container/ContainerCreateRequestDto.java @@ -1,11 +1,9 @@ package at.tuwien.api.container; -import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.Parameter; import lombok.*; import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; @Getter @Setter diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseDto.java index 277f4894b8da3a96e14f32741b3cbe5beee000db..3acfa9b4890a41b1ed47aa2a9c9315469b318ecb 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseDto.java @@ -30,6 +30,10 @@ public class DatabaseDto { @Parameter(name = "database name", example = "Weather Australia") private String name; + @NotBlank + @Parameter(name = "database exchange") + private String exchange; + @NotNull @Parameter(name = "database creator") private UserDto creator; diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java index 2a0bdececa8c52507ea444827da75fc20494697a..a7f852c7748a75d6f4cd3f35aa4b447a8cf9e8e6 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java @@ -37,14 +37,6 @@ public class ColumnCreateDto { @Parameter(name = "date format id", example = "1") private Long dfid; - @JsonProperty("decimal_digits_before") - @Parameter(name = "decimal digits before point", example = "3") - private Long decimalDigitsBefore; - - @JsonProperty("decimal_digits_after") - @Parameter(name = "decimal digits after point", example = "0") - private Long decimalDigitsAfter; - @NotNull @Parameter(name = "unique", example = "true") private Boolean unique = false; diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/CreatorCreateDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/CreatorCreateDto.java index e7f8db2ebe7be5e1f4183439941cf89b6701bc6e..40ea15199ef4e13071c94341a4cf64415e8043c9 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/CreatorCreateDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/CreatorCreateDto.java @@ -5,6 +5,7 @@ import lombok.Builder; import lombok.Data; import lombok.Getter; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; import javax.validation.constraints.NotBlank; @@ -12,6 +13,7 @@ import javax.validation.constraints.NotBlank; @Getter @Setter @Builder +@Jacksonized public class CreatorCreateDto { @NotBlank diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierCreateDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierCreateDto.java index 350cf84aa7745c38ed9fb06a899d823250f90395..76c0d1098212ef0ef6d7cc472332c8dd93c272bb 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierCreateDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierCreateDto.java @@ -6,6 +6,7 @@ import lombok.Builder; import lombok.Data; import lombok.Getter; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @@ -16,6 +17,7 @@ import java.util.List; @Getter @Setter @Builder +@Jacksonized public class IdentifierCreateDto { @NotNull diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java index ee0c22f4bc9d96d374da7ea550910213caf16c8f..148e0571274fbe11b36663c3d9d1bbd74efcc99f 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java @@ -50,10 +50,9 @@ public class IdentifierDto { @Parameter(name = "query normalized") private String queryNormalized; - @NotNull - @JsonProperty("related_identifiers") + @JsonProperty("related") @Parameter(name = "related identifiers") - private List<RelatedIdentifierDto> relatedIdentifiers; + private List<RelatedIdentifierDto> related; @NotBlank @JsonProperty("query_hash") diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierCreateDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierCreateDto.java index 209dfcc69dae48bc8eb30696606efa6d0732ef8a..2b31e9a3a22511bdd8b1e887c6f034b2b662f6b6 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierCreateDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierCreateDto.java @@ -2,6 +2,7 @@ package at.tuwien.api.identifier; import io.swagger.v3.oas.annotations.Parameter; import lombok.*; +import lombok.extern.jackson.Jacksonized; import javax.validation.constraints.NotNull; @@ -9,6 +10,7 @@ import javax.validation.constraints.NotNull; @Getter @Setter @Builder +@Jacksonized public class RelatedIdentifierCreateDto { @NotNull diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierDto.java index a298962badb9cee25bb6227ca195fa4eaa0b207d..52d95bf5906c6897627ba4cca1218f0b1b442b5b 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierDto.java @@ -1,6 +1,7 @@ package at.tuwien.api.identifier; import at.tuwien.api.user.UserDto; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.Parameter; import lombok.*; @@ -17,6 +18,7 @@ public class RelatedIdentifierDto { @NotNull private Long id; + @JsonIgnore @NotNull private Long iid; @@ -31,6 +33,7 @@ public class RelatedIdentifierDto { private RelationTypeDto relation; @ToString.Exclude + @JsonIgnore @NotNull private UserDto creator; diff --git a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java index b4539dfd45fcfdc80395bb991ef4fdbdb3613de7..79b63f356195bda542b25fda24e5c2a7a77a37dd 100644 --- a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java +++ b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java @@ -88,6 +88,12 @@ public class Identifier { @Enumerated(EnumType.STRING) private VisibilityType visibility = VisibilityType.SELF; + @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) + @JoinColumns({ + @JoinColumn(name = "iid", referencedColumnName = "id", insertable = false, updatable = false) + }) + private List<RelatedIdentifier> related; + @Column private String doi; 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 new file mode 100644 index 0000000000000000000000000000000000000000..ef988c97c0ec5b75ef9a7c8a753da509a41bd347 --- /dev/null +++ b/fda-query-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -0,0 +1,20 @@ +package at.tuwien.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JacksonConfig { + + @Bean + public ObjectMapper objectMapper() { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + return objectMapper; + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..ef988c97c0ec5b75ef9a7c8a753da509a41bd347 --- /dev/null +++ b/fda-table-service/services/src/main/java/at/tuwien/config/JacksonConfig.java @@ -0,0 +1,20 @@ +package at.tuwien.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JacksonConfig { + + @Bean + public ObjectMapper objectMapper() { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + return objectMapper; + } + +} diff --git a/fda-ui/components/TableList.vue b/fda-ui/components/TableList.vue index 827f0b698fdfa360148671117e9d7af2268c8bad..eda1a482accfa0af826e58b51ab090b73c5acd9f 100644 --- a/fda-ui/components/TableList.vue +++ b/fda-ui/components/TableList.vue @@ -7,7 +7,7 @@ </v-card-title> </v-card> <v-expansion-panels v-if="!loading && tables.length > 0" v-model="panel" accordion> - <v-expansion-panel v-for="(item,i) in tables" :key="i" @click="details(item.id, true)"> + <v-expansion-panel v-for="(item,i) in tables" :key="i" @click="details(item.id)"> <v-expansion-panel-header> {{ item.name }} </v-expansion-panel-header> @@ -16,12 +16,9 @@ <v-col> <v-list dense> <v-list-item> - <v-list-item-icon> - <v-icon>mdi-fingerprint</v-icon> - </v-list-item-icon> <v-list-item-content> <v-list-item-title> - ID + Table ID </v-list-item-title> <v-list-item-content> {{ tableDetails.id }} @@ -29,12 +26,9 @@ </v-list-item-content> </v-list-item> <v-list-item> - <v-list-item-icon> - <v-icon>mdi-information-variant</v-icon> - </v-list-item-icon> <v-list-item-content> <v-list-item-title> - Internal Name + Table Internal Name </v-list-item-title> <v-list-item-content> {{ tableDetails.internal_name }} @@ -42,48 +36,36 @@ </v-list-item-content> </v-list-item> <v-list-item> - <v-list-item-icon> - <v-icon>mdi-table</v-icon> - </v-list-item-icon> <v-list-item-content> <v-list-item-title> - Columns + AMQP Exchange </v-list-item-title> <v-list-item-content> - {{ tableDetails.columns.length }} + {{ database.exchange }} </v-list-item-content> </v-list-item-content> </v-list-item> <v-list-item> - <v-list-item-icon> - <v-icon>mdi-road-variant</v-icon> - </v-list-item-icon> <v-list-item-content> <v-list-item-title> - AMQP Exchange + AMQP Routing Key </v-list-item-title> <v-list-item-content> - {{ database.exchange }} + {{ tableDetails.topic }} </v-list-item-content> </v-list-item-content> </v-list-item> <v-list-item> - <v-list-item-icon> - <v-icon>mdi-road-variant</v-icon> - </v-list-item-icon> <v-list-item-content> <v-list-item-title> - AMQP Routing Key + Table Creation </v-list-item-title> <v-list-item-content> - {{ tableDetails.topic }} + {{ creation }} </v-list-item-content> </v-list-item-content> </v-list-item> <v-list-item> - <v-list-item-icon> - <v-icon>mdi-notebook-outline</v-icon> - </v-list-item-icon> <v-list-item-content> <v-list-item-title> Description @@ -98,8 +80,11 @@ </v-row> <v-row dense> <v-col> - <v-btn color="secondary" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${item.id}`"> - View + <v-btn :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${item.id}`"> + View Data + </v-btn> + <v-btn color="secondary" class="ml-2" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/query/create?tid=${item.id}`"> + Build Query </v-btn> </v-col> <v-col class="align-right"> @@ -121,6 +106,9 @@ <template v-slot:item.unique="{ item }"> <span v-if="item.unique">●</span> {{ item.unique }} </template> + <template v-slot:item.column_type="{ item }"> + {{ columnName(item) }} + </template> <template v-slot:item.is_primary_key="{ item }"> <span v-if="item.is_primary_key">●</span> {{ item.is_primary_key }} </template> @@ -159,6 +147,8 @@ </template> <script> +import { format } from 'date-fns' + export default { data () { return { @@ -167,23 +157,38 @@ export default { tables: [], panel: null, database: { - exchange: null + exchange: null, + tables: [] }, tableDetails: { id: null, internal_name: null, description: null, topic: null, - columns: [] + columns: [], + created: null }, dialogDelete: false, - headers: [{ value: 'name', text: 'Name' }, + headers: [ + { value: 'name', text: 'Name' }, { value: 'column_type', text: 'Type' }, { value: 'column_concept', text: 'Unit of Measurement' }, { value: 'is_primary_key', text: 'Primary Key' }, { value: 'unique', text: 'Unique' }, { value: 'is_null_allowed', text: 'Nullable' }, - { value: 'auto_generated', text: 'Sequence' }] + { value: 'auto_generated', text: 'Sequence' } + ], + columnTypes: [ + // { value: 'ENUM', text: 'Enumeration' }, // Disabled for now, not implemented, #145 + { value: 'BOOLEAN', text: 'Boolean' }, + { value: 'NUMBER', text: 'Number' }, + { value: 'BLOB', text: 'Binary Large Object' }, + { value: 'DATE', text: 'Date' }, + { value: 'TIMESTAMP', text: 'Timestamp' }, + { value: 'DECIMAL', text: 'Decimal' }, + { value: 'STRING', text: 'Character Varying' }, + { value: 'TEXT', text: 'Text' } + ] } }, computed: { @@ -200,13 +205,15 @@ export default { return { headers: { Authorization: `Bearer ${this.token}` } } + }, + creation () { + return this.formatDate(this.tableDetails.created) } }, mounted () { console.debug('mounted', this.$store.state.table) this.$root.$on('table-create', this.refresh) this.loadDatabase() - this.loadTables() }, methods: { async loadDatabase () { @@ -215,40 +222,29 @@ export default { const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}`, this.config) this.database = res.data console.debug('database', this.database) - this.error = false + this.tables = this.database.tables + console.debug('tables', this.tables) } catch (err) { this.error = true this.$toast.error('Could not get database details.') } this.loading = false }, - async loadTables () { - 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.config) - this.tables = res.data - console.debug('tables', this.tables) - this.error = false - } catch (err) { - this.error = true - this.$toast.error('Failed to load tables.') + columnName (column) { + const filter = this.columnTypes.filter(t => t.value === column.column_type) + if (filter.length > 0) { + return filter[0].text } - this.loading = false + return column.column_type }, - async details (tableId, clicked = false) { - // don't fetch details when we click-close an open accordion - if (clicked && this.tables[this.panel] && this.tables[this.panel].id === tableId) { - return - } - try { - const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/table/${tableId}`, this.config) - this.tableDetails = res.data - this.$store.commit('SET_TABLE', this.tableDetails) - } catch (err) { - this.tableDetails = undefined - this.$toast.error('Could not get table details.') + details (tableId) { + const select = this.tables.filter(t => t.id === tableId) + if (select.length > 0) { + this.tableDetails = select[0] } - this.$forceUpdate() + }, + formatDate (d) { + return format(new Date(d), 'dd.MM.yyyy HH:mm:ss') }, /** * if tableId is given, open the table after refresh diff --git a/fda-ui/components/TableSchema.vue b/fda-ui/components/TableSchema.vue index 5a1b8edff50e7d3aad8c5a39a9a637b3ae3b0675..fc4b9f43876110377cc464291feafa7b7269c27d 100644 --- a/fda-ui/components/TableSchema.vue +++ b/fda-ui/components/TableSchema.vue @@ -184,7 +184,6 @@ export default { null_allowed, primary_key, check_expression: null, - date_format: null, foreign_key: null, references: null, unique diff --git a/fda-ui/components/dialogs/CreateDB.vue b/fda-ui/components/dialogs/CreateDB.vue index 256257255a44a5bea540c7d4d9fe494f6369e185..f02383958669e1eb17ba1e32b69610939f0094c9 100644 --- a/fda-ui/components/dialogs/CreateDB.vue +++ b/fda-ui/components/dialogs/CreateDB.vue @@ -14,7 +14,7 @@ </v-alert> <v-text-field id="database" - v-model="database" + v-model="createContainer.name" name="database" label="Name *" autofocus @@ -22,7 +22,7 @@ required /> <v-textarea id="description" - v-model="description" + v-model="createDatabase.description" name="description" rows="2" label="Description *" @@ -40,7 +40,7 @@ required /> <v-checkbox id="public" - v-model="isPublic" + v-model="createDatabase.is_public" name="public" label="Public" /> </v-card-text> @@ -75,12 +75,18 @@ export default { valid: false, loading: false, error: false, - database: null, - description: null, - isPublic: true, engine: null, engines: [], - container: null + createContainer: { + name: null, + repository: null, + tag: null + }, + createDatabase: { + name: null, + description: null, + is_public: true + } } }, computed: { @@ -89,6 +95,16 @@ export default { }, token () { return this.$store.state.token + }, + config () { + if (this.token === null) { + return { + headers: {} + } + } + return { + headers: { Authorization: `Bearer ${this.token}` } + } } }, mounted () { @@ -133,14 +149,9 @@ export default { try { this.loading = true this.error = false - res = await this.$axios.post('/api/container', { - name: this.database.trim(), - description: this.description.trim(), - repository: this.engine.repository, - tag: this.engine.tag - }, { - headers: { Authorization: `Bearer ${this.token}` } - }) + this.createContainer.repository = this.engine.repository + this.createContainer.tag = this.engine.tag + res = await this.$axios.post('/api/container', this.createContainer, this.config) containerId = res.data.id console.debug('created container', res.data) this.loading = false @@ -161,10 +172,7 @@ export default { try { this.loading = true this.error = false - res = await this.$axios.put(`/api/container/${containerId}`, - { action: 'START' }, { - headers: { Authorization: `Bearer ${this.token}` } - }) + res = await this.$axios.put(`/api/container/${containerId}`, { action: 'START' }, this.config) console.debug('started container', res.data) } catch (err) { this.error = true @@ -179,15 +187,10 @@ export default { // wait for it to finish this.loading = true this.error = false + this.createDatabase.name = this.createContainer.name for (let i = 0; i < 5; i++) { try { - res = await this.$axios.post(`/api/container/${containerId}/database`, { - name: this.database.trim(), - description: this.description.trim(), - is_public: this.isPublic - }, { - headers: { Authorization: `Bearer ${this.token}` } - }) + res = await this.$axios.post(`/api/container/${containerId}/database`, this.createDatabase, this.config) console.debug('created database', res) break } catch (err) { diff --git a/fda-ui/components/dialogs/EditDB.vue b/fda-ui/components/dialogs/EditDB.vue index 7aa5c4f4e7f293b7287e2cd8c6e78e447f7a355d..3d3d8b09be961dd56b16cf5e1041f88e13bfedf8 100644 --- a/fda-ui/components/dialogs/EditDB.vue +++ b/fda-ui/components/dialogs/EditDB.vue @@ -14,7 +14,7 @@ label="Public" /> <v-text-field id="publisher" - v-model="database.publisher" + v-model="modify.publisher" name="publisher" label="Publisher *" autofocus @@ -22,7 +22,7 @@ required /> <v-textarea id="description" - v-model="database.description" + v-model="modify.description" name="description" rows="2" label="Description *" @@ -30,7 +30,7 @@ required /> <v-select id="language" - v-model="database.language" + v-model="modify.language" name="language" label="Language *" :items="languages" @@ -40,7 +40,7 @@ required /> <v-text-field id="publication-year" - v-model.number="database.publication_year" + v-model.number="modify.publication_year" name="publication_year" label="Publication Year *" type="number" @@ -48,7 +48,7 @@ required /> <v-select id="license" - v-model="database.license" + v-model="modify.license" name="license" label="License *" :items="licenses" @@ -133,6 +133,7 @@ export default { this.modify.is_public = this.database.is_public this.modify.publisher = this.database.publisher this.modify.description = this.database.description + this.modify.publication_year = this.database.publication_year this.modify.language = this.database.language this.modify.license = this.database.license }, @@ -158,7 +159,7 @@ export default { async updateDatabase () { try { this.loading = true - const res = await this.$axios.put(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}`, this.database, this.config) + const res = await this.$axios.put(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}`, this.modify, this.config) this.database = res.data console.debug('database', this.database) this.$toast.success('Successfully updated the database.') diff --git a/fda-ui/components/query/Builder.vue b/fda-ui/components/query/Builder.vue index 58ff864a9533f08310a2cbcf27132e183f08ec10..1f09b63c647129bf35df86e4ed05d5a17301d6f5 100644 --- a/fda-ui/components/query/Builder.vue +++ b/fda-ui/components/query/Builder.vue @@ -70,20 +70,22 @@ </v-tab-item> </v-tabs-items> </v-card> - <div> - <v-row> - <v-col> - <QueryResults ref="queryResults" v-model="queryId" /> - </v-col> - </v-row> - <v-row> - <v-col> - <v-btn v-if="queryId" color="blue-grey white--text" :to="`/container/${$route.params.container_id}/database/${databaseId}/query/${queryId}`"> - More - </v-btn> - </v-col> - </v-row> - </div> + <v-card flat> + <v-card-text> + <v-row> + <v-col> + <QueryResults ref="queryResults" v-model="queryId" /> + </v-col> + </v-row> + <v-row v-if="queryId"> + <v-col> + <v-btn color="blue-grey white--text" :to="`/container/${$route.params.container_id}/database/${databaseId}/query/${queryId}`"> + More + </v-btn> + </v-col> + </v-row> + </v-card-text> + </v-card> </div> </template> @@ -165,8 +167,10 @@ export default { this.queryId = null } }, - beforeMount () { + mounted () { this.loadTables() + .then(() => this.selectTable()) + .then(() => this.loadColumns()) }, methods: { async loadTables () { @@ -180,6 +184,20 @@ export default { this.$toast.error('Could not list table.') } }, + selectTable () { + if (this.$route.query.tid === undefined) { + return + } + const tid = parseInt(this.$route.query.tid) + const selection = this.tables.filter(t => t.id === tid) + if (selection.length > 0) { + this.table = selection[0] + console.info('Preselect table with id', tid) + console.debug('preselected table', this.table) + } else { + console.warn('Failed to find table with id', tid) + } + }, execute () { this.$refs.queryResults.executeFirstTime(this) }, diff --git a/fda-ui/pages/container/_container_id/database/_database_id/info.vue b/fda-ui/pages/container/_container_id/database/_database_id/info.vue index 3117779cf9609536d772aa5d69a0017e89839986..75d4a7546369287465b9cbcbfaa914dc522a96f7 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/info.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/info.vue @@ -35,7 +35,19 @@ </v-list-item-title> <v-list-item-content> <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" /> - <span v-if="!loading">{{ creator }}</span> + <span v-if="!loading"> + {{ creator }} + <sup> + <v-icon v-if="database.creator.email_verified" small color="primary">mdi-check-decagram</v-icon> + </sup> + </span> + </v-list-item-content> + <v-list-item-title class="mt-2"> + Created + </v-list-item-title> + <v-list-item-content> + <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" /> + <span v-if="!loading">{{ created }}</span> </v-list-item-content> <v-list-item-title class="mt-2"> Language @@ -67,7 +79,7 @@ v-model="editDbDialog" persistent max-width="640"> - <EditDB :database="database" @close-dialog="editDbDialog = false" /> + <EditDB :database="database" @close-dialog="closeDialog" /> </v-dialog> </v-card-text> </v-card> @@ -182,6 +194,10 @@ export default { } this.loading = false }, + closeDialog () { + this.loadDatabase() + this.editDbDialog = false + }, formatDate (d) { return format(new Date(d), 'dd.MM.yyyy HH:mm:ss') } diff --git a/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue b/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue index e154bc74bc9d6febb3510621365264915ef86f63..68b7614777f7335f0dd239dbd058bd73f1b2d36c 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue @@ -1,10 +1,14 @@ <template> <div> + <v-progress-linear v-if="loadingDatabase || loadingIdentifier || loadingQuery" /> <v-toolbar flat> - <v-toolbar-title>{{ identifier.title }}</v-toolbar-title> + <v-toolbar-title> + <v-skeleton-loader v-if="loadingIdentifier" type="text" class="skeleton-small" /> + <span v-if="!loadingIdentifier">{{ identifier.title }}</span> + </v-toolbar-title> <v-spacer /> <v-toolbar-title> - <v-btn v-if="!identifier.id && !loading" color="secondary" class="mr-2" :disabled="!execution || !token" @click.stop="openDialog()"> + <v-btn v-if="!identifier.id && !loadingIdentifier" color="secondary" class="mr-2" :disabled="!execution || !token" @click.stop="openDialog()"> <v-icon left>mdi-fingerprint</v-icon> Persist </v-btn> <v-btn v-if="result_visibility" color="primary" :loading="downloadLoading" @click.stop="download"> @@ -15,7 +19,7 @@ </v-btn> </v-toolbar-title> </v-toolbar> - <v-card v-if="!loading" flat> + <v-card flat> <v-card-title> Query Information </v-card-title> @@ -30,20 +34,30 @@ Database Visibility </v-list-item-title> <v-list-item-content> - <span v-if="database_visibility">Public</span> - <span v-if="!database_visibility">Private</span> + <v-skeleton-loader v-if="loadingDatabase" type="text" class="skeleton-small" /> + <span v-if="!loadingDatabase && database_visibility">Public</span> + <span v-if="!loadingDatabase && !database_visibility">Private</span> </v-list-item-content> <v-list-item-title class="mt-2"> Database Name </v-list-item-title> <v-list-item-content> - {{ database.name }} + <v-skeleton-loader v-if="loadingDatabase" type="text" class="skeleton-small" /> + <span v-if="!loadingDatabase">{{ database.name }}</span> + </v-list-item-content> + <v-list-item-title v-if="database.publisher" class="mt-2"> + Database Publisher + </v-list-item-title> + <v-list-item-content v-if="database.publisher"> + <v-skeleton-loader v-if="loadingDatabase" type="text" class="skeleton-small" /> + <span v-if="!loadingDatabase">{{ database.publisher }}</span> </v-list-item-content> <v-list-item-title v-if="database.license" class="mt-2"> Database License </v-list-item-title> <v-list-item-content v-if="database.license"> - <a :href="database.license.uri">{{ database.license.identifier }}</a> + <v-skeleton-loader v-if="loadingDatabase" type="text" class="skeleton-xsmall" /> + <a v-if="!loadingDatabase" :href="database.license.uri">{{ database.license.identifier }}</a> </v-list-item-content> </v-list-item-content> </v-list-item> @@ -74,7 +88,7 @@ Creators </v-list-item-title> <v-list-item-content> - <span v-for="(creator, i) in identifier.creators" :key="i" class="mt-1"> + <span v-for="(creator, i) in identifier.creators" :key="`c-${i}`" class="mt-1"> <OrcidIcon v-if="creator.orcid" :orcid="creator.orcid" /> {{ creator.name }} <sup v-if="creator.affiliation">{{ creator.affiliation }}</sup> </span> @@ -85,6 +99,33 @@ <v-list-item-content> {{ identifier.publication_year }} </v-list-item-content> + <v-list-item-title v-if="identifier.related.length > 0" class="mt-2"> + Related Identifiers + </v-list-item-title> + <v-list-item-content v-if="identifier.related.length > 0"> + <div v-for="(rel, i) in identifier.related" :key="`r-${i}`"> + <span v-if="rel.type === 'DOI'"> + {{ rel.type }}: <a :href="`https://doi.org/${rel.value}`" target="_blank">{{ rel.value }}</a> + <span v-if="rel.relation">({{ rel.relation }})</span> + </span> + <span v-if="rel.type === 'URL'"> + {{ rel.type }}: <a :href="`${rel.value}`" target="_blank">{{ rel.value }}</a> + <span v-if="rel.relation">({{ rel.relation }})</span> + </span> + <span v-if="rel.type === 'arXiv'"> + {{ rel.type }}: <a :href="`https://arxiv.org/abs/${rel.value}`" target="_blank">{{ rel.value }}</a> + <span v-if="rel.relation">({{ rel.relation }})</span> + </span> + <span v-if="rel.type === 'EISSN'"> + {{ rel.type }}: <a :href="`https://portal.issn.org/resource/ISSN/${rel.value}`" target="_blank">{{ rel.value }}</a> + <span v-if="rel.relation">({{ rel.relation }})</span> + </span> + <span v-if="rel.type !== 'DOI' && rel.type !== 'URL' && rel.type !== 'arXiv' && rel.type !== 'EISSN'"> + {{ rel.type }}: {{ rel.value }} + <span v-if="rel.relation">({{ rel.relation }})</span> + </span> + </div> + </v-list-item-content> </v-list-item-content> </v-list-item> <v-list-item> @@ -96,31 +137,36 @@ Query Statement </v-list-item-title> <v-list-item-content> - <pre>{{ query.query }}</pre> + <v-skeleton-loader v-if="loadingQuery" type="text" class="skeleton-large" /> + <pre v-if="!loadingQuery">{{ query.query }}</pre> </v-list-item-content> <v-list-item-title class="mt-2"> Query Hash </v-list-item-title> <v-list-item-content> - <pre>{{ query_hash }}</pre> + <v-skeleton-loader v-if="loadingQuery" type="text" class="skeleton-medium" /> + <pre v-if="!loadingQuery">{{ query_hash }}</pre> </v-list-item-content> <v-list-item-title class="mt-2"> Query Creator </v-list-item-title> <v-list-item-content> - {{ creator }} + <v-skeleton-loader v-if="loadingQuery" type="text" class="skeleton-small" /> + <span v-if="!loadingQuery">{{ creator }}</span> </v-list-item-content> <v-list-item-title class="mt-2"> Query Execution </v-list-item-title> <v-list-item-content> - {{ execution }} + <v-skeleton-loader v-if="loadingQuery" type="text" class="skeleton-small" /> + <span v-if="!loadingQuery">{{ execution }}</span> </v-list-item-content> <v-list-item-title class="mt-2"> Query Creation </v-list-item-title> <v-list-item-content> - {{ query_creation }} + <v-skeleton-loader v-if="loadingQuery" type="text" class="skeleton-small" /> + <span v-if="!loadingQuery">{{ query_creation }}</span> </v-list-item-content> </v-list-item-content> </v-list-item> @@ -133,25 +179,30 @@ Result Visibility </v-list-item-title> <v-list-item-content> - {{ result_visibility_icon ? 'Public' : 'Private' }} + <v-skeleton-loader v-if="metadataLoading" type="text" class="skeleton-xsmall" /> + <span v-if="!metadataLoading">{{ result_visibility_icon ? 'Public' : 'Private' }}</span> </v-list-item-content> <v-list-item-title class="mt-2"> Result Hash </v-list-item-title> <v-list-item-content> - <pre>{{ result_hash }}</pre> + <v-skeleton-loader v-if="metadataLoading" type="text" class="skeleton-medium" /> + <pre v-if="!metadataLoading">{{ result_hash }}</pre> </v-list-item-content> <v-list-item-title class="mt-2"> Result Number </v-list-item-title> <v-list-item-content> - {{ result_number }} + <v-skeleton-loader v-if="metadataLoading" type="text" class="skeleton-xsmall" /> + <span v-if="!metadataLoading">{{ result_number }}</span> </v-list-item-content> </v-list-item-content> </v-list-item> </v-list> </v-card-text> - <QueryResults id="query-results" ref="queryResults" v-model="query.id" :query-id="query.id" class="mt-0 mb-0" /> + <v-card-text> + <QueryResults id="query-results" ref="queryResults" v-model="query.id" :query-id="query.id" class="mt-0 mb-0" /> + </v-card-text> </v-card> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> <v-dialog @@ -209,6 +260,7 @@ export default { result_number: null, execution: null, publication_year: null, + related: [], doi: null, creators: [] }, @@ -227,7 +279,9 @@ export default { }, persistQueryExists: false, persistQueryDialog: false, - loading: true, + loadingDatabase: false, + loadingIdentifier: false, + loadingQuery: false, metadataLoading: false, downloadLoading: false, error: false, @@ -368,7 +422,7 @@ export default { this.downloadLoading = false }, async loadQuery () { - this.loading = true + this.loadingQuery = true try { const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/query/${this.$route.params.query_id}`, this.config) console.debug('query', res.data) @@ -380,10 +434,10 @@ export default { } this.error = true } - this.loading = false + this.loadingQuery = false }, async loadDatabase () { - this.loading = true + this.loadingDatabase = true try { const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}`, this.config) console.debug('database', res.data) @@ -395,13 +449,13 @@ export default { } this.error = true } - this.loading = false + this.loadingDatabase = false }, async loadMetadata () { if (!this.query.id) { return } - this.loading = true + this.loadingIdentifier = true try { const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/identifier?qid=${this.$route.params.query_id}`, this.config) this.identifier = res.data[0] @@ -413,7 +467,7 @@ export default { this.$toast.error('Could not load identifier') } } - this.loading = false + this.loadingIdentifier = false }, openDialog () { this.persistQueryDialog = true @@ -435,4 +489,16 @@ pre { .v-card__text { font-size: initial; } +.skeleton-large .v-skeleton-loader__text { + width: 400px; +} +.skeleton-medium .v-skeleton-loader__text { + width: 200px; +} +.skeleton-small .v-skeleton-loader__text { + width: 100px; +} +.skeleton-xsmall .v-skeleton-loader__text { + width: 50px; +} </style> 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 b1544e766c45184118eab448ca9307f48c30efa6..87650d442df2af8988db507a2aee841f0f3d43f0 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 @@ -12,15 +12,18 @@ </v-toolbar-title> <v-spacer /> <v-toolbar-title> - <v-btn color="primary" :disabled="!token" class="mr-2 white--text" @click="addTuple"> + <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="amber darken-2" class="mr-2 white--text" @click="editTupleDialog = true"> + <v-btn v-if="canEdit" :disabled="!token" color="warn" class="mr-2" @click="editTupleDialog = true"> <v-icon left>mdi-pencil</v-icon> Edit </v-btn> - <v-btn v-if="canDelete" :disabled="!token" color="red darken-2" class="mr-2 white--text" @click="deleteItems"> + <v-btn v-if="canDelete" :disabled="!token" color="error" class="mr-2" @click="deleteItems"> <v-icon left>mdi-delete</v-icon> Delete<span v-if="selection.length > 1"> {{ selection.length }}</span> </v-btn> + <v-btn :disabled="!token" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/query/create?tid=${$route.params.table_id}`" color="secondary" class="mr-2" @click="deleteItems"> + <v-icon left>mdi-wrench</v-icon> Query Builder + </v-btn> <v-btn :disabled="!token" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${$route.params.table_id}/import`"> <v-icon left>mdi-cloud-upload</v-icon> Import csv </v-btn> diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue index 2fcb0ea63afd5a562681e12aa2b4d56b22620c07..425213eedfc85f6cd6fee579f0d4b80a51fad23c 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue @@ -163,11 +163,9 @@ </v-stepper-step> <v-stepper-content step="5"> - Proceed to table view. <div class="mt-2"> - <v-btn :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${newTableId}`" outlined> - <v-icon>mdi-table</v-icon> - View + <v-btn color="secondary" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${newTableId}`"> + View Table </v-btn> </div> </v-stepper-content> @@ -231,17 +229,6 @@ export default { file: null, url: null, columns: [], - columnTypes: [ - // { value: 'ENUM', text: 'Enumeration' }, // Disabled for now, not implemented, #145 - { value: 'BOOLEAN', text: 'Boolean' }, - { value: 'NUMBER', text: 'Number' }, - { value: 'BLOB', text: 'Binary Large Object' }, - { value: 'DATE', text: 'Date' }, - { value: 'TIMESTAMP', text: 'Timestamp' }, - { value: 'DECIMAL', text: 'Decimal' }, - { value: 'STRING', text: 'Character Varying' }, - { value: 'TEXT', text: 'Text' } - ], newTableId: 42 // FIXME ??? } }, diff --git a/fda-ui/pages/container/index.vue b/fda-ui/pages/container/index.vue index 48bd38d99337650e4fa5e5061a0ecb1536bc9173..8ed348186732b8f9288978ba8f70cefcab0673be 100644 --- a/fda-ui/pages/container/index.vue +++ b/fda-ui/pages/container/index.vue @@ -42,6 +42,9 @@ <td> <span v-if="item.database">{{ formatCreator(item.database.creator) }}</span> <v-skeleton-loader v-if="!item.database" type="text" width="100" class="mt-1" /> + <sup v-if="item.database"> + <v-icon v-if="item.database.creator.email_verified" small color="primary">mdi-check-decagram</v-icon> + </sup> </td> <td>{{ formatDate(item.created) }}</td> </tr> diff --git a/fda-ui/pages/user/index.vue b/fda-ui/pages/user/index.vue index 26727913aa7c636dde7d77f3168e29fc8753771c..0132bde47541160ef5029806735b6b2b92d318ff 100644 --- a/fda-ui/pages/user/index.vue +++ b/fda-ui/pages/user/index.vue @@ -5,9 +5,8 @@ <v-toolbar-title> <v-skeleton-loader v-if="loading || error" type="text" width="200" /> <span v-if="!loading && !error"> - {{ name }} <sup> - <v-icon v-if="user.email_verified" color="primary" title="E-Mail verified" small>mdi-shield-check</v-icon> - <v-icon v-if="!user.email_verified" color="accent" title="E-Mail not yet verified" small>mdi-alert-decagram</v-icon> + {{ name }} <sup v-if="user.email_verified"> + <v-icon color="primary" title="E-Mail verified" small>mdi-check-decagram</v-icon> </sup> </span> </v-toolbar-title> diff --git a/fda-ui/server-middleware/index.js b/fda-ui/server-middleware/index.js index 819f649f24a9ac7eb00f1d5a9a1b95e9475c7b19..ee55f841cd59a37a1d580bfab9de631620155b3d 100644 --- a/fda-ui/server-middleware/index.js +++ b/fda-ui/server-middleware/index.js @@ -55,7 +55,6 @@ app.post('/table_from_csv', upload.single('file'), async (req, res) => { return { name: k, type: v, - date_format: null, check_expression: null, foreign_key: null, references: null,