Skip to content
Snippets Groups Projects
Verified Commit 53e09452 authored by Martin Weise's avatar Martin Weise
Browse files

Hotfix the UI

parent 2d7a7ec8
No related branches found
No related tags found
1 merge request!365Hotfix/ui view
......@@ -21,7 +21,6 @@ import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto;
import at.tuwien.api.database.table.constraints.unique.UniqueDto;
import at.tuwien.api.user.UserDto;
import at.tuwien.config.QueryConfig;
import at.tuwien.exception.QueryNotFoundException;
import at.tuwien.exception.TableNotFoundException;
import org.apache.hadoop.shaded.com.google.common.hash.Hashing;
import org.apache.hadoop.shaded.org.apache.commons.io.FileUtils;
......@@ -199,17 +198,13 @@ public interface DataMapper {
return view;
}
default QueryDto resultSetToQueryDto(@NotNull ResultSet data) throws SQLException, QueryNotFoundException {
default QueryDto resultSetToQueryDto(@NotNull ResultSet data) throws SQLException {
/* note that next() is called outside this mapping function */
return QueryDto.builder()
final QueryDto subset = QueryDto.builder()
.id(data.getLong(1))
.created(LocalDateTime.parse(data.getString(2), mariaDbFormatter)
.atZone(ZoneId.of("UTC"))
.toInstant())
.creator(UserDto.builder()
.id(UUID.fromString(data.getString(3)))
.build())
.createdBy(UUID.fromString(data.getString(3)))
.query(data.getString(4))
.queryHash(data.getString(5))
.resultHash(data.getString(6))
......@@ -219,6 +214,13 @@ public interface DataMapper {
.atZone(ZoneId.of("UTC"))
.toInstant())
.build();
if (data.getString(3) != null) {
subset.setCreator(UserDto.builder()
.id(UUID.fromString(data.getString(3)))
.build());
subset.setCreatedBy(UUID.fromString(data.getString(3)));
}
return subset;
}
default List<TableHistoryDto> resultSetToTableHistory(ResultSet resultSet) throws SQLException {
......
......@@ -119,7 +119,7 @@ public interface MariaDbMapper {
}
default String queryStoreCreateTableRawQuery() {
final String statement = "CREATE TABLE `qs_queries` ( `id` bigint not null primary key default nextval(`qs_queries_seq`), `created` datetime not null default now(), `executed` datetime not null default now(), `created_by` varchar(36) not null, `query` text not null, `query_normalized` text not null, `is_persisted` boolean not null, `query_hash` varchar(255) not null, `result_hash` varchar(255), `result_number` bigint) WITH SYSTEM VERSIONING;";
final String statement = "CREATE TABLE `qs_queries` ( `id` bigint not null primary key default nextval(`qs_queries_seq`), `created` datetime not null default now(), `executed` datetime not null default now(), `created_by` varchar(36), `query` text not null, `query_normalized` text not null, `is_persisted` boolean not null, `query_hash` varchar(255) not null, `result_hash` varchar(255), `result_number` bigint) WITH SYSTEM VERSIONING;";
log.trace("mapped create query store table statement: {}", statement);
return statement;
}
......
......@@ -180,8 +180,6 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
}
final QueryDto query = dataMapper.resultSetToQueryDto(resultSet);
query.setIdentifiers(metadataServiceGateway.getIdentifiers(database.getId(), queryId));
query.setCreator(database.getOwner());
query.setDatabaseId(database.getId());
return query;
} catch (SQLException e) {
log.error("Failed to find query with id {}: {}", queryId, e.getMessage());
......
......@@ -20,7 +20,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -92,7 +91,7 @@ public class AccessEndpoint {
schema = @Schema(implementation = ApiErrorDto.class))}),
})
public ResponseEntity<DatabaseAccessDto> create(@NotNull @PathVariable("databaseId") Long databaseId,
@org.hibernate.validator.constraints.UUID @PathVariable("userId") UUID userId,
@PathVariable("userId") UUID userId,
@Valid @RequestBody UpdateDatabaseAccessDto data,
@NotNull Principal principal) throws NotAllowedException, DataServiceException,
DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException,
......@@ -155,7 +154,7 @@ public class AccessEndpoint {
schema = @Schema(implementation = ApiErrorDto.class))}),
})
public ResponseEntity<Void> update(@NotNull @PathVariable("databaseId") Long databaseId,
@org.hibernate.validator.constraints.UUID @PathVariable("userId") UUID userId,
@PathVariable("userId") UUID userId,
@Valid @RequestBody UpdateDatabaseAccessDto data,
@NotNull Principal principal) throws NotAllowedException,
DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException,
......@@ -200,7 +199,7 @@ public class AccessEndpoint {
schema = @Schema(implementation = ApiErrorDto.class))}),
})
public ResponseEntity<DatabaseAccessDto> find(@NotNull @PathVariable("databaseId") Long databaseId,
@org.hibernate.validator.constraints.UUID @PathVariable("userId") UUID userId,
@PathVariable("userId") UUID userId,
@NotNull Principal principal) throws DatabaseNotFoundException,
UserNotFoundException, AccessNotFoundException, NotAllowedException {
log.debug("endpoint get database access, databaseId={}, userId={}, principal.name={}", databaseId, userId,
......@@ -257,7 +256,7 @@ public class AccessEndpoint {
schema = @Schema(implementation = ApiErrorDto.class))}),
})
public ResponseEntity<Void> revoke(@NotNull @PathVariable("databaseId") Long databaseId,
@org.hibernate.validator.constraints.UUID @PathVariable("userId") UUID userId,
@PathVariable("userId") UUID userId,
@NotNull Principal principal) throws NotAllowedException, DataServiceException,
DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException,
SearchServiceException, SearchServiceConnectionException {
......
......@@ -18,13 +18,15 @@ export default {
props: {
type: {
type: String,
default: () => 'query' /* query or view */
default: () => 'query' /* query, view or table */
},
loading: {
type: Boolean,
default: () => {
return false
}
default: () => false
},
timestamp: {
type: String,
default: () => new Date().toISOString()
}
},
data () {
......@@ -106,6 +108,25 @@ export default {
.finally(() => {
this.loadingExecute = false
})
} else if (this.type === 'table') {
const tableService = useTableService()
tableService.getData(this.$route.params.database_id, id, (this.options.page - 1), this.options.itemsPerPage, this.timestamp)
.then((result) => {
this.mapResults(result)
this.id = id
this.loadingExecute = false
})
.catch(({code}) => {
this.loadingExecute = false
const toast = useToastInstance()
if (typeof code !== 'string') {
return
}
toast.error(this.$t(code))
})
.finally(() => {
this.loadingExecute = false
})
} else {
const viewService = useViewService()
viewService.reExecuteData(this.$route.params.database_id, id, this.options.page - 1, this.options.itemsPerPage)
......@@ -150,6 +171,24 @@ export default {
.finally(() => {
this.loadingCount = false
})
} else if (this.type === 'table') {
const tableService = useTableService()
tableService.getCount(this.$route.params.database_id, id, this.timestamp)
.then((count) => {
this.total = count
this.loadingCount = false
})
.catch(({code}) => {
this.loadingCount = false
const toast = useToastInstance()
if (typeof code !== 'string') {
return
}
toast.error(this.$t(code))
})
.finally(() => {
this.loadingCount = false
})
} else {
const viewService = useViewService()
viewService.reExecuteCount(this.$route.params.database_id, id)
......
......@@ -30,7 +30,7 @@
width="50%" />
</v-list>
<v-list
v-else
v-else-if="subset"
lines="two"
dense>
<v-list-item
......@@ -40,6 +40,7 @@
{{ database.is_public ? $t('toolbars.database.public') : $t('toolbars.database.private') }}
</v-list-item>
<v-list-item
v-if="subset.creator"
:title="$t('pages.subset.creator.title')"
density="compact">
<UserBadge :user="subset.creator" :other-user="user" />
......
......@@ -54,9 +54,6 @@
@click.stop="pick" />
</v-toolbar>
<TimeDrift />
<v-card
elevation="0"
tile>
<v-card
v-if="error"
variant="flat">
......@@ -64,27 +61,13 @@
{{ $t('error.table.connection') }}
</v-card-text>
</v-card>
<v-data-table-server
v-if="!error"
v-model="selection"
flat
:show-select="canModify"
return-object
:headers="headers"
:items="rows"
:items-length="total"
:loading="loadingData || loadingCount"
:options.sync="options"
:footer-props="footerProps"
:items-per-page-options="footerProps.itemsPerPageOptions"
@update:options="loadData">
<template
v-for="(blobColumn, idx) in blobColumns"
v-slot:[blobColumn]="{ item }">
<BlobDownload
:blob="item[blobColumn.substring(5)]" />
</template>
</v-data-table-server>
<v-card tile>
<QueryResults
id="query-results"
ref="queryResults"
type="table"
:timestamp="versionISO || lastReload.toISOString()"
class="mt-0 mb-0" />
</v-card>
<v-dialog
v-model="pickVersionDialog"
......@@ -122,14 +105,16 @@
import TableHistory from '@/components/table/TableHistory.vue'
import TimeDrift from '@/components/TimeDrift.vue'
import TableToolbar from '@/components/table/TableToolbar.vue'
import {formatTimestampUTC, formatDateUTC, formatTimestamp} from '@/utils'
import { formatTimestamp } from '@/utils'
import { useUserStore } from '@/stores/user'
import { useCacheStore } from '@/stores/cache'
import EditTuple from '@/components/dialogs/EditTuple.vue'
import BlobDownload from '@/components/table/BlobDownload.vue'
import QueryResults from '@/components/subset/Results.vue'
export default {
components: {
QueryResults,
BlobDownload,
EditTuple,
TableHistory,
......@@ -142,6 +127,7 @@ export default {
loadingData: false,
loadingCount: false,
loadingDelete: false,
loadingTable: false,
addTupleDialog: false,
editTupleDialog: false,
total: 0,
......@@ -282,18 +268,11 @@ export default {
},
watch: {
version () {
this.loadCount()
this.reload()
},
table (newTable, oldTable) {
if (newTable !== oldTable && oldTable === null) {
this.loadProperties()
}
}
},
mounted () {
this.loadProperties()
this.loadCount()
this.reload()
},
methods: {
addTuple () {
......@@ -402,74 +381,10 @@ export default {
}
this.pickVersionDialog = false
},
loadProperties () {
if (!this.table || this.headers.length > 0) {
return
}
try {
this.headers = []
this.table.columns.map((c) => {
return {
value: c.internal_name,
title: c.internal_name,
sortable: false
}
}).forEach(header => this.headers.push(header))
this.dateColumns = this.table.columns.filter(c => (c.column_type === 'date' || c.column_type === 'timestamp'))
console.debug('date columns are', this.dateColumns)
} catch ({code}) {
const toast = useToastInstance()
toast.error(this.$t(code))
}
this.loading = false
},
reload () {
this.lastReload = new Date()
this.loadData({ page: this.options.page, itemsPerPage: this.options.itemsPerPage, sortBy: null})
},
loadCount() {
this.loadingCount = true
const tableService = useTableService()
tableService.getCount(this.$route.params.database_id, this.$route.params.table_id, (this.versionISO || this.lastReload.toISOString()))
.then((count) => {
this.total = count
this.loadingCount = false
})
.catch(({code}) => {
this.loadingCount = false
const toast = useToastInstance()
toast.error(this.$t(code))
})
},
loadData({ page, itemsPerPage, sortBy }) {
this.options.page = page
this.options.itemsPerPage = itemsPerPage
const tableService = useTableService()
this.loadingData = true
tableService.getData(this.$route.params.database_id, this.$route.params.table_id, (page - 1), itemsPerPage, (this.versionISO || this.lastReload.toISOString()))
.then((data) => {
this.rows = data.result.map((row) => {
for (const col in row) {
const column = this.table.columns.filter(c => c.internal_name === col)[0]
const columnDefinition = this.dateColumns.filter(c => c.internal_name === col)
if (columnDefinition.length > 0) {
if (columnDefinition[0].column_type === 'date') {
row[col] = formatDateUTC(row[col])
} else if (columnDefinition[0].column_type === 'timestamp') {
row[col] = formatTimestampUTC(row[col])
}
}
}
return row
})
this.loadingData = false
})
.catch(({code, message}) => {
this.error = true
this.loadingData = false
const toast = useToastInstance()
toast.error(this.$t(code) + ": " + message)
})
this.$refs.queryResults.reExecute(Number(this.$route.params.table_id))
this.$refs.queryResults.reExecuteCount(Number(this.$route.params.table_id))
},
isFileField (column) {
return ['blob', 'longblob', 'mediumblob', 'tinyblob'].includes(column.column_type)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment