From 8d134af27feb42ee035fd4cb3bda830ae8db3a4c Mon Sep 17 00:00:00 2001 From: xiayifan Date: Mon, 1 Feb 2021 14:53:33 +0800 Subject: [PATCH] UI adaptation status of mind-explain restful api --- .../explain/conterfactual-interpretation.vue | 59 ++-- .../ui/src/views/explain/saliency-map.vue | 294 +++++++++--------- 2 files changed, 175 insertions(+), 178 deletions(-) diff --git a/mindinsight/ui/src/views/explain/conterfactual-interpretation.vue b/mindinsight/ui/src/views/explain/conterfactual-interpretation.vue index 436823fd..a5251284 100644 --- a/mindinsight/ui/src/views/explain/conterfactual-interpretation.vue +++ b/mindinsight/ui/src/views/explain/conterfactual-interpretation.vue @@ -294,14 +294,20 @@ export default { imageIndex: 0, curSampleData: {}, }, - dataWaitCount: 2, // Number of waiting times when no data is available dataWaitTimer: null, // No data available timer + // Status of metaData request + status: { + pendding: 'PENDING', + loading: 'LOADING', + loaded: 'LOADED', + stop: 'STOP', + }, }; }, computed: {}, watch: {}, created() { - this.getHOCData(); + this.getMetaData(); }, mounted() { if (!this.trainId) { @@ -343,13 +349,29 @@ export default { !res || !res.data || !res.data.classes || - !res.data.classes.length || !res.data.saliency ) { + this.initOver = true; return; } - this.labelLlist = [this.emptyLabelSelect].concat(res.data.classes); - this.minConfidence = res.data.saliency.min_confidence; + const status = res.data.status; + // IF status is not loaded, delay 500ms and request again + const delayTime = 500; + if (status !== this.status.loaded) { + if (this.dataWaitTimer) { + clearTimeout(this.dataWaitTimer); + this.dataWaitTimer = null; + } + this.dataWaitTimer = setTimeout(() => { + this.getMetaData(); + }, delayTime); + } else { + this.labelLlist = [this.emptyLabelSelect].concat(res.data.classes); + this.minConfidence = res.data.saliency.min_confidence; + this.getHOCData(); + } + }, () => { + this.initOver = true; }, ); }, @@ -370,29 +392,16 @@ export default { } RequestService.queryHOCData(params).then( (res) => { + this.initOver = true; if (!res || !res.data) { - this.initOver = true; + this.pageData.totalNum = 0; + this.resetIniitData(); return; } - if (!res.data.count && !this.initOver && this.dataWaitCount) { - this.dataWaitCount--; - if (this.dataWaitTimer) { - clearTimeout(this.dataWaitTimer); - this.dataWaitTimer = null; - } - this.dataWaitTimer = setTimeout(() => { - this.getHOCData(); - }, 1500); - } else { - if (!this.initOver) { - this.getMetaData(); - } - this.initOver = true; - this.pageData.totalNum = res.data.count; - this.fullData = res.data.samples; - this.curSelectedDataIndex = 0; - this.formateCurrentHOCData(); - } + this.pageData.totalNum = res.data.count; + this.fullData = res.data.samples; + this.curSelectedDataIndex = 0; + this.formateCurrentHOCData(); }, () => { this.pageData.totalNum = 0; diff --git a/mindinsight/ui/src/views/explain/saliency-map.vue b/mindinsight/ui/src/views/explain/saliency-map.vue index de5aa39e..a5ad4284 100644 --- a/mindinsight/ui/src/views/explain/saliency-map.vue +++ b/mindinsight/ui/src/views/explain/saliency-map.vue @@ -1,5 +1,5 @@
+ v-if="!hasData"> + v-if="isLoading"> {{ $t('public.dataLoading') }} + :empty-text="$t('public.noData')"> + v-show="hasData">
{ this.queryParameters.offset = val - 1; - this.queryPageInfo(this.queryParameters).then(); + this.queryPageInfo(this.queryParameters); this.pageChangeTimer = null; }, this.pageChangeDelay); }, @@ -494,7 +496,7 @@ export default { this.queryParameters.sorted_name = val; this.pageInfo.currentPage = 1; this.queryParameters.offset = this.pageInfo.currentPage - 1; - this.queryPageInfo(this.queryParameters).then(); + this.queryPageInfo(this.queryParameters); }, /** * The logic of click the explainer method canvas @@ -512,66 +514,78 @@ export default { /** * Request basic information of train * @param {Object} params Parameters of the request basic information of train interface + * @return {Promise} */ queryTrainInfo(params) { - requestService - .queryTrainInfo(params) - .then( - (res) => { - if (res && res.data) { - if (res.data.saliency) { - this.minConfidence = res.data.saliency.min_confidence - ? res.data.saliency.min_confidence - : '--'; - this.hasMetric = res.data.saliency.metrics.length - ? true - : false; - this.allExplainers = this.arrayToCheckBox( - res.data.saliency.explainers, - ); - } - if (res.data.classes) { - const truthLabels = []; - for (let i = 0; i < res.data.classes.length; i++) { - truthLabels.push(res.data.classes[i].label); - } - this.truthLabels = truthLabels; - } - if (res.data.uncertainty) { - this.uncertaintyEnabled = res.data.uncertainty.enabled - ? true - : false; - // The sort by uncertainty only valid when uncertaintyEnabled is true - if (this.uncertaintyEnabled) { - this.sortedNames.push({ - label: this.$t('explain.byUncertainty'), - value: UNCERTAINTY, + return new Promise((resolve, reject) => { + requestService + .queryTrainInfo(params) + .then( + (res) => { + if (res && res.data) { + const status = res.data.status.toUpperCase(); + if (status !== STATUS.LOADED) { + resolve({ + again: true, + continue: false, + }); + } else { + // status === 'LOADED' + this.processTrainInfo(res.data); + resolve({ + again: false, + continue: true, }); } + } else { + resolve({ + again: false, + continue: false, + }); } - } - this.ifNoData = false; - this.ifLoading = false; - }, - () => { - this.ifNoData = false; - this.ifLoading = false; - this.ifError = true; - }, - ) - .catch(() => { - this.ifNoData = false; - this.ifLoading = false; - this.ifError = true; + }, + ) + .catch((error) => { + reject(error); + }); + }); + }, + /** + * The logic of process train info + * @param {Object} data + */ + processTrainInfo(data) { + const truthLabels = []; + for (let i = 0; i < data.classes.length; i++) { + truthLabels.push(data.classes[i].label); + } + this.truthLabels = truthLabels; + if (data.saliency) { + this.minConfidence = data.saliency.min_confidence; + this.hasMetric = data.saliency.metrics.length ? true : false; + this.allExplainers = this.arrayToCheckBox( + data.saliency.explainers, + ); + } + if (data.uncertainty) { + this.uncertaintyEnabled = data.uncertainty.enabled ? true : false; + // The sort by uncertainty only valid when uncertaintyEnabled is true + if (this.uncertaintyEnabled) { + this.sortedNames.push({ + label: this.$t('explain.byUncertainty'), + value: UNCERTAINTY, }); + } + } }, /** * The complete logic of table update when any condition changed * @param {Object} params The main parameters * @param {Object} supParams The supplymentary parameters + * @param {Boolean} first If first query * @return {Promise} */ - updateTable(params, supParams) { + updateTable(params, supParams, first = false) { const paramsTemp = JSON.parse(JSON.stringify(params)); for (const attr in paramsTemp) { if ({}.hasOwnProperty.call(paramsTemp, attr)) { @@ -588,70 +602,49 @@ export default { } } Object.assign(paramsTemp, supParams); - return this.queryPageInfo(paramsTemp); + return this.queryPageInfo(paramsTemp, first); }, /** * Request page table information * @param {Object} params Parameters of the request page information interface - * @return {Promise} + * @param {Boolean} first If first query */ - queryPageInfo(params) { + queryPageInfo(params, first = false) { params.train_id = decodeURIComponent(params.train_id); this.queryParameters = params; - return new Promise((resolve) => { - requestService - .queryPageInfo(params) - .then( - (res) => { - // Make sure the offset of response is equal to offset of request - if (params.offset === this.queryParameters.offset) { - if (res && res.data && res.data.samples) { - this.tableData = this.processTableData(res.data.samples); - this.pageInfo.total = res.data.count ? res.data.count : 0; - if (!res.data.count) { - // 3: Prediction type has three valid values - // When length === 3 || length === 0, means search without type limit - const typeLimit = - params.prediction_types.length !== 3 && - params.prediction_types.length !== 0; - if (params.labels || typeLimit) { - // With label or type limit - this.emptyText = this.$t('public.noData'); - } else { - // Without limit - if (this.requestTime === this.requestLimit) { - this.emptyText = this.$t('public.noData'); - } else { - this.emptyText = this.$t('explain.noData'); - } - } - resolve(false); + requestService + .queryPageInfo(params) + .then( + (res) => { + // Make sure the offset of response is equal to offset of request + if (params.offset === this.queryParameters.offset) { + if (res && res.data) { + if (!res.data.count) { + if (first) { + this.isLoading = false; } else { - resolve(true); + this.tableData = this.processTableData(res.data.samples); + this.pageInfo.total = 0; } } else { - this.pageInfo.total = 0; + this.tableData = this.processTableData(res.data.samples); + this.pageInfo.total = res.data.count; + this.hasData = true; } } - }, - () => { - this.ifNoData = false; - this.ifLoading = false; - this.ifError = true; - }, - ) - .catch(() => { - this.ifNoData = false; - this.ifLoading = false; - this.ifError = true; - }); - }); + } + }, + () => { + this.isLoading = false; + }, + ) + .catch(() => { + this.isLoading = false; + }); }, /** * Process the original table data * @param {Object} samples The original table data - * @param {number | boolean} minConfidence The min confindence - * If min confidence is lost, replace with type except number, such as 'false', 'null' * @return {Object} The processed table data */ processTableData(samples) { @@ -735,55 +728,50 @@ export default { query: {id: this.trainID}, }); }, + /** + * The logic of init page + */ initPage() { - return new Promise((resolve) => { - this.updateTable(this.baseQueryParameters, { - limit: this.pageInfo.pageSize, - offset: this.pageInfo.currentPage - 1, - }).then((hasData) => { - // If has data now - if (hasData) { - const params = { - train_id: this.trainID, - }; - this.queryTrainInfo(params); - resolve(true); - } else { - resolve(false); - } - }); - }); + const params = { + train_id: this.trainID, + }; + this.queryTrainInfo(params) + .then( + (res) => { + if (res.again) { + // Request again + setTimeout(() => { + this.initPage(); + }, this.requestDelay); + } else { + // No need to request again + if (res.continue) { + this.updateTable(this.baseQueryParameters, { + limit: this.pageInfo.pageSize, + offset: this.pageInfo.currentPage - 1, + }, true); + } else { + this.isLoading = false; + } + } + }, + () => { + // Has error + this.isLoading = false; + }) + .catch(() => { + this.isLoading = false; + }); }, }, created() { if (!this.$route.query.id) { this.$message.error(this.$t('trainingDashboard.invalidId')); - this.ifError = true; + this.isLoading = false; return; } this.trainID = this.$route.query.id; - this.initPage().then((hasData) => { - this.requestTime = 1; - if (!hasData) { - this.requestTimer = setInterval(() => { - this.initPage().then((hasDataNow) => { - this.requestTime++; - if (hasDataNow) { - clearInterval(this.requestTimer); - } else { - if (this.requestTime === this.requestLimit) { - // Still has no data - this.ifLoading = false; - clearInterval(this.requestTimer); - } - } - }); - }, this.requestDelay); - } - }); - }, - destroyed() { - clearInterval(this.requestTimer); + this.initPage(); }, mounted() { // Change the page title