Fixed UX/autoreload issues in import screen

This commit is contained in:
Eliot Berriot 2019-01-02 15:19:45 +01:00
parent 55c4a05b31
commit 73d8dd9a45
No known key found for this signature in database
GPG Key ID: DD6965E2476E5C27
5 changed files with 37 additions and 43 deletions

View File

@ -1,9 +1,22 @@
<template> <template>
<table class="ui compact very basic single line unstackable table"> <table class="ui compact very basic single line unstackable table">
<thead> <thead>
<tr v-if="actionUrl && actions.length > 0"> <tr>
<th colspan="1000"> <th colspan="1000">
<div class="ui small form"> <div v-if="refreshable" class="right floated">
<span v-if="needsRefresh">
<translate>Content have been updated, click refresh to see up-to-date content</translate>
</span>
<button
@click="$emit('refresh')"
class="ui basic icon button"
:title="labels.refresh"
:aria-label="labels.refresh">
<i class="refresh icon"></i>
</button>
</div>
<div class="ui small left floated form" v-if="actionUrl && actions.length > 0">
<div class="ui inline fields"> <div class="ui inline fields">
<div class="field"> <div class="field">
<label><translate>Actions</translate></label> <label><translate>Actions</translate></label>
@ -132,6 +145,8 @@ export default {
props: { props: {
actionUrl: {type: String, required: false, default: null}, actionUrl: {type: String, required: false, default: null},
idField: {type: String, required: false, default: 'id'}, idField: {type: String, required: false, default: 'id'},
refreshable: {type: Boolean, required: false, default: false},
needsRefresh: {type: Boolean, required: false, default: false},
objectsData: {type: Object, required: true}, objectsData: {type: Object, required: true},
actions: {type: Array, required: true, default: () => { return [] }}, actions: {type: Array, required: true, default: () => { return [] }},
filters: {type: Object, required: false, default: () => { return {} }}, filters: {type: Object, required: false, default: () => { return {} }},
@ -244,13 +259,18 @@ export default {
let self = this let self = this
return this.objectsData.results.map((o) => { return this.objectsData.results.map((o) => {
let custom = self.customObjects.filter((co) => { let custom = self.customObjects.filter((co) => {
return self.getId(co) == self.getId(o) return self.getId(co) === self.getId(o)
})[0] })[0]
if (custom) { if (custom) {
return custom return custom
} }
return o return o
}) })
},
labels () {
return {
refresh: this.$gettext('Refresh table content')
}
} }
}, },
watch: { watch: {

View File

@ -115,7 +115,8 @@
</div> </div>
<div :class="['ui', 'bottom', 'attached', 'segment', {hidden: currentTab != 'processing'}]"> <div :class="['ui', 'bottom', 'attached', 'segment', {hidden: currentTab != 'processing'}]">
<library-files-table <library-files-table
:key="String(processTimestamp)" :needs-refresh="needsRefresh"
@fetch-start="needsRefresh = false"
:filters="{import_reference: importReference}" :filters="{import_reference: importReference}"
:custom-objects="Object.values(uploads.objects)"></library-files-table> :custom-objects="Object.values(uploads.objects)"></library-files-table>
</div> </div>
@ -142,6 +143,7 @@ export default {
this.$router.replace({ query: { import: importReference } }); this.$router.replace({ query: { import: importReference } });
return { return {
files: [], files: [],
needsRefresh: false,
currentTab: "summary", currentTab: "summary",
uploadUrl: "/api/v1/uploads/", uploadUrl: "/api/v1/uploads/",
importReference, importReference,
@ -199,31 +201,6 @@ export default {
value: this.uploadedFilesCount + this.finishedJobs value: this.uploadedFilesCount + this.finishedJobs
}); });
}, },
disconnect() {
if (!this.bridge) {
return;
}
this.bridge.socket.close(1000, "goodbye", { keepClosed: true });
},
openWebsocket() {
this.disconnect();
let self = this;
let token = this.$store.state.auth.token;
const bridge = new WebSocketBridge();
this.bridge = bridge;
let url = this.$store.getters["instance/absoluteUrl"](
`api/v1/activity?token=${token}`
);
url = url.replace("http://", "ws://");
url = url.replace("https://", "wss://");
bridge.connect(url);
bridge.listen(function(event) {
self.handleEvent(event);
});
bridge.socket.addEventListener("open", function() {
console.log("Connected to WebSocket");
});
},
handleImportEvent(event) { handleImportEvent(event) {
let self = this; let self = this;
if (event.upload.import_reference != self.importReference) { if (event.upload.import_reference != self.importReference) {
@ -232,17 +209,10 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
self.uploads[event.old_status] -= 1; self.uploads[event.old_status] -= 1;
self.uploads[event.new_status] += 1; self.uploads[event.new_status] += 1;
self.uploads.objects[event.upload.uuid] = event.track_file; self.uploads.objects[event.upload.uuid] = event.upload;
self.triggerReload(); self.needsRefresh = true
}); });
}, }
triggerReload: _.throttle(
function() {
this.processTimestamp = new Date();
},
10000,
{ leading: true }
)
}, },
computed: { computed: {
labels() { labels() {

View File

@ -49,8 +49,8 @@ export default {
}) })
}, },
websocketEvent ({state}, event) { websocketEvent ({state}, event) {
console.log('Dispatching websocket event', event)
let handlers = state.websocketEventsHandlers[event.type] let handlers = state.websocketEventsHandlers[event.type]
console.log('Dispatching websocket event', event, handlers)
if (!handlers) { if (!handlers) {
return return
} }

View File

@ -145,7 +145,6 @@ export default {
if (toNull && !newValue) { if (toNull && !newValue) {
newValue = null newValue = null
} }
console.log(newValue, typeof newValue)
let params = {} let params = {}
if (attr === "permissions") { if (attr === "permissions") {
params["permissions"] = {} params["permissions"] = {}

View File

@ -46,7 +46,10 @@
:objects-data="result" :objects-data="result"
:custom-objects="customObjects" :custom-objects="customObjects"
:actions="actions" :actions="actions"
:refreshable="true"
:needs-refresh="needsRefresh"
:action-url="'uploads/action/'" :action-url="'uploads/action/'"
@refresh="fetchData"
:filters="actionFilters"> :filters="actionFilters">
<template slot="header-cells"> <template slot="header-cells">
<th><translate>Title</translate></th> <th><translate>Title</translate></th>
@ -133,6 +136,7 @@ export default {
mixins: [OrderingMixin, TranslationsMixin], mixins: [OrderingMixin, TranslationsMixin],
props: { props: {
filters: {type: Object, required: false}, filters: {type: Object, required: false},
needsRefresh: {type: Boolean, required: false, default: false},
defaultQuery: {type: String, default: ''}, defaultQuery: {type: String, default: ''},
customObjects: {type: Array, required: false, default: () => { return [] }} customObjects: {type: Array, required: false, default: () => { return [] }}
}, },
@ -199,12 +203,13 @@ export default {
} }
}, },
fetchData () { fetchData () {
this.$emit('fetch-start')
let params = _.merge({ let params = _.merge({
'page': this.page, 'page': this.page,
'page_size': this.paginateBy, 'page_size': this.paginateBy,
'ordering': this.getOrderingAsString(), 'ordering': this.getOrderingAsString(),
'q': this.search.query 'q': this.search.query
}, {}) }, this.filters || {})
let self = this let self = this
self.isLoading = true self.isLoading = true
self.checked = [] self.checked = []
@ -302,7 +307,7 @@ export default {
search (newValue) { search (newValue) {
this.page = 1 this.page = 1
this.fetchData() this.fetchData()
}, }
} }
} }
</script> </script>