未验证 提交 6dfa1d42 编写于 作者: J Jeff Wang 提交者: GitHub

Eslint precommit (#368)

* Create pre-commit with ESLint

* add vue-eslint-parser

* Add prop-name-casing and script-indent to the eslint rule.

* Update Javascript and Vue files with the proper style

* Comment out ESlint pre-commit first to udpate styles
上级 d64553b6
#!/bin/bash
# if there are no staged changes, we can exit immediately
# this is fast and prevents issues when popping a stash we didn't create
STAGED_CHANGES=`git diff-index --cached HEAD --name-only --diff-filter ACMR`
if [ -z "$STAGED_CHANGES" ]; then
exit 0
fi
# Capture the path to the eslint
cd frontend
ESLINT_EXECUTABLE=$(npm bin)/eslint
cd ..
# Test against with both .js and .vue files
git diff --cached --name-only --diff-filter ACMR | egrep '.(js|vue)$' | xargs $ESLINT_EXECUTABLE --fix
RESULT=$?
[ $RESULT -ne 0 ] && exit 1
exit 0
...@@ -33,3 +33,11 @@ ...@@ -33,3 +33,11 @@
entry: flake8 entry: flake8
language: system language: system
files: \.(py)$ files: \.(py)$
#- repo: local
# hooks:
# - id: eslint-format-checker
# name: eslint-format-checker
# description: Format files with ESLint.
# entry: bash ./.eslint_format.hook
# language: system
...@@ -9,5 +9,7 @@ module.exports = { ...@@ -9,5 +9,7 @@ module.exports = {
// override/add rules settings here, such as: // override/add rules settings here, such as:
'vue/no-unused-vars': 'warn', 'vue/no-unused-vars': 'warn',
'max-len': ["warn", 120], 'max-len': ["warn", 120],
"vue/prop-name-casing": ["error"],
'vue/script-indent': 'error',
} }
} }
...@@ -73,6 +73,7 @@ ...@@ -73,6 +73,7 @@
"stylus": "^0.54.5", "stylus": "^0.54.5",
"stylus-loader": "^3.0.1", "stylus-loader": "^3.0.1",
"url-loader": "^0.5.8", "url-loader": "^0.5.8",
"vue-eslint-parser": "^2.0.3",
"vue-jest": "^1.0.2", "vue-jest": "^1.0.2",
"vue-loader": "^13.3.0", "vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1", "vue-style-loader": "^3.0.1",
......
...@@ -11,22 +11,22 @@ ...@@ -11,22 +11,22 @@
import AppMenu from './common/component/AppMenu'; import AppMenu from './common/component/AppMenu';
export default { export default {
name: 'App', name: 'App',
components: { components: {
AppMenu, AppMenu,
}, },
data() { data() {
return { return {
initialRoute: 'scalars', initialRoute: 'scalars',
}; };
}, },
created() { created() {
if (location.hash && location.hash != '#/') { if (location.hash && location.hash != '#/') {
this.initialRoute = /(\#\/)(\w*)([?|&]{0,1})/.exec(location.hash)[2]; this.initialRoute = /(\#\/)(\w*)([?|&]{0,1})/.exec(location.hash)[2];
} else { } else {
location.hash = '#/scalars'; location.hash = '#/scalars';
} }
}, },
}; };
</script> </script>
......
...@@ -38,127 +38,127 @@ import Config from './ui/Config'; ...@@ -38,127 +38,127 @@ import Config from './ui/Config';
import AudioPanelContainer from './ui/AudioPanelContainer'; import AudioPanelContainer from './ui/AudioPanelContainer';
export default { export default {
name: 'Images', name: 'Images',
components: { components: {
'ui-config': Config, 'ui-config': Config,
'ui-audio-container': AudioPanelContainer, 'ui-audio-container': AudioPanelContainer,
}, },
data() { data() {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
isActualImageSize: false,
runs: [],
running: true,
},
filteredTagsList: [],
};
},
computed: {
runsItems() {
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return { return {
runsArray: [], name: item,
tags: [], value: item,
config: {
groupNameReg: '.*',
isActualImageSize: false,
runs: [],
running: true,
},
filteredTagsList: [],
}; };
});
}, },
computed: { tagsList() {
runsItems() { let tags = this.tags;
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return {
name: item,
value: item,
};
});
},
tagsList() {
let tags = this.tags;
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart let runs = Object.keys(tags);
return allUniqTags.map((tag) => { let tagsArray = runs.map((run) => Object.keys(tags[run]));
let tagList = runs.map((run) => { let allUniqTags = uniq(flatten(tagsArray));
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
},
groupedTags() {
let tagsList = this.tagsList || [];
// put data in group
let groupData = {};
tagsList.forEach((item) => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = [];
groupData[group].push(item);
} else {
groupData[group].push(item);
}
});
// to array // get the data for every chart
let groups = Object.keys(groupData); return allUniqTags.map((tag) => {
return groups.map((group) => { let tagList = runs.map((run) => {
return { return {
group, run,
tags: groupData[group], tag: tags[run][tag],
}; };
}); }).filter((item) => item.tag !== undefined);
}, return {
filteredConfig() { tagList,
let config = this.config || {}; tag,
let filteredConfig = {}; group: tag.split('/')[0],
Object.keys(config).forEach((key) => { };
let val = config[key]; });
filteredConfig[key] = val;
});
return filteredConfig;
},
}, },
created() { groupedTags() {
getPluginAudioTags().then(({errno, data}) => { let tagsList = this.tagsList || [];
this.tags = data; // put data in group
let groupData = {};
// filter when inited tagsList.forEach((item) => {
let groupNameReg = this.config.groupNameReg; let group = item.group;
this.filterTagsList(groupNameReg); if (groupData[group] === undefined) {
}); groupData[group] = [];
groupData[group].push(item);
} else {
groupData[group].push(item);
}
});
getRuns().then(({errno, data}) => { // to array
this.runsArray = data; let groups = Object.keys(groupData);
this.config.runs = data; return groups.map((group) => {
}); return {
group,
tags: groupData[group],
};
});
}, },
mounted() { filteredConfig() {
autoAdjustHeight(); let config = this.config || {};
let filteredConfig = {};
Object.keys(config).forEach((key) => {
let val = config[key];
filteredConfig[key] = val;
});
return filteredConfig;
}, },
watch: { },
'config.groupNameReg': function(val) { created() {
this.throttledFilterTagsList(); getPluginAudioTags().then(({errno, data}) => {
}, this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
getRuns().then(({errno, data}) => {
this.runsArray = data;
this.config.runs = data;
});
},
mounted() {
autoAdjustHeight();
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
}, },
methods: { },
filterTagsList(groupNameReg) { methods: {
if (!groupNameReg) { filterTagsList(groupNameReg) {
this.filteredTagsList = []; if (!groupNameReg) {
return; this.filteredTagsList = [];
} return;
let tagsList = this.tagsList || []; }
let regExp = new RegExp(groupNameReg); let tagsList = this.tagsList || [];
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag)); let regExp = new RegExp(groupNameReg);
}, this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
}, },
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
}; };
</script> </script>
......
...@@ -3,7 +3,7 @@ import {router} from 'san-router'; ...@@ -3,7 +3,7 @@ import {router} from 'san-router';
import Audio from './Audio'; import Audio from './Audio';
router.add({ router.add({
target: '#content', target: '#content',
rule: '/audio', rule: '/audio',
Component: Audio, Component: Audio,
}); });
...@@ -31,99 +31,99 @@ import {getPluginAudioAudio} from '../../service'; ...@@ -31,99 +31,99 @@ import {getPluginAudioAudio} from '../../service';
const intervalTime = 30; const intervalTime = 30;
export default { export default {
props: ['tagInfo', 'runs', 'running', 'runsItems'], props: ['tagInfo', 'runs', 'running', 'runsItems'],
computed: { computed: {
steps() { steps() {
let data = this.data || []; let data = this.data || [];
return data.length - 1; return data.length - 1;
},
}, },
filters: { },
formatTime: function(value) { filters: {
if (!value) { formatTime: function(value) {
return; if (!value) {
} return;
// The value was made in seconds, must convert it to milliseconds }
let time = new Date(value * 1000); // The value was made in seconds, must convert it to milliseconds
let options = { let time = new Date(value * 1000);
weekday: 'short', year: 'numeric', month: 'short', let options = {
day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit', weekday: 'short', year: 'numeric', month: 'short',
}; day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit',
return time.toLocaleDateString('en-US', options); };
}, return time.toLocaleDateString('en-US', options);
}, },
data() { },
return { data() {
currentIndex: 0, return {
slider: { currentIndex: 0,
value: '0', slider: {
label: '', value: '0',
min: 0, label: '',
step: 1, min: 0,
}, step: 1,
audioData: {}, },
data: [], audioData: {},
data: [],
};
},
created() {
this.getOriginAudioData();
},
mounted() {
if (this.running) {
this.startInterval();
}
},
beforeDestroy() {
this.stopInterval();
},
watch: {
running: function(val) {
val ? this.startInterval() : this.stopInterval();
},
currentIndex: function(index) {
if (this.data && this.data[index]) {
let currentAudioInfo = this.data ? this.data[index] : {};
let {query, step, wall_time} = currentAudioInfo;
let url = '/data/plugin/audio/individualAudio?ts=' + wall_time;
let audioSrc = [url, query].join('&');
this.audioData = {
audioSrc,
step,
wall_time,
}; };
}
}, },
created() { },
methods: {
stopInterval() {
clearInterval(this.getOringDataInterval);
},
// get origin data per {{intervalTime}} seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
this.getOriginAudioData(); this.getOriginAudioData();
}, intervalTime * 1000);
}, },
mounted() { getOriginAudioData() {
if (this.running) { // let {run, tag} = this.tagInfo;
this.startInterval(); let run = this.tagInfo.run;
let tag = this.tagInfo.tag;
let {displayName, samples} = tag;
let params = {
run,
tag: displayName,
samples,
};
getPluginAudioAudio(params).then(({status, data}) => {
if (status === 0) {
this.data = data;
this.currentIndex = data.length - 1;
} }
});
}, },
},
beforeDestroy() {
this.stopInterval();
},
watch: {
running: function(val) {
val ? this.startInterval() : this.stopInterval();
},
currentIndex: function(index) {
if (this.data && this.data[index]) {
let currentAudioInfo = this.data ? this.data[index] : {};
let {query, step, wall_time} = currentAudioInfo;
let url = '/data/plugin/audio/individualAudio?ts=' + wall_time;
let audioSrc = [url, query].join('&');
this.audioData = {
audioSrc,
step,
wall_time,
};
}
},
},
methods: {
stopInterval() {
clearInterval(this.getOringDataInterval);
},
// get origin data per {{intervalTime}} seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
this.getOriginAudioData();
}, intervalTime * 1000);
},
getOriginAudioData() {
// let {run, tag} = this.tagInfo;
let run = this.tagInfo.run;
let tag = this.tagInfo.tag;
let {displayName, samples} = tag;
let params = {
run,
tag: displayName,
samples,
};
getPluginAudioAudio(params).then(({status, data}) => {
if (status === 0) {
this.data = data;
this.currentIndex = data.length - 1;
}
});
},
},
}; };
</script> </script>
<style lang="stylus"> <style lang="stylus">
......
...@@ -29,41 +29,41 @@ import AudioPanel from './AudioPanel'; ...@@ -29,41 +29,41 @@ import AudioPanel from './AudioPanel';
import {cloneDeep, flatten} from 'lodash'; import {cloneDeep, flatten} from 'lodash';
export default { export default {
props: ['config', 'runsItems', 'tagList', 'title'], props: ['config', 'runsItems', 'tagList', 'title'],
components: { components: {
'ui-audio': AudioPanel, 'ui-audio': AudioPanel,
'ui-expand-panel': ExpandPanel, 'ui-expand-panel': ExpandPanel,
},
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
}, },
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
},
filteredPageList() { filteredPageList() {
let list = this.filteredRunsList || []; let list = this.filteredRunsList || [];
return list.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize); return list.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
total() {
let list = this.filteredRunsList || [];
return list.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
}, },
data() { total() {
return { let list = this.filteredRunsList || [];
// current page return list.length;
currentPage: 1,
// item per page
pageSize: 8,
};
}, },
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
},
}; };
</script> </script>
<style lang="stylus"> <style lang="stylus">
......
...@@ -32,19 +32,19 @@ ...@@ -32,19 +32,19 @@
<script> <script>
export default { export default {
props: { props: {
runsItems: Array, runsItems: Array,
config: Object, config: Object,
}, },
data() { data() {
return { return {
}; };
}, },
methods: { methods: {
toggleAllRuns() { toggleAllRuns() {
this.config.running = !this.config.running; this.config.running = !this.config.running;
},
}, },
},
}; };
</script> </script>
......
...@@ -22,58 +22,58 @@ ...@@ -22,58 +22,58 @@
<script> <script>
export default { export default {
props: ['initialRoute'], props: ['initialRoute'],
name: 'AppMenu', name: 'AppMenu',
data() { data() {
return { return {
selected: this.initialRoute, selected: this.initialRoute,
items: [ items: [
{ {
url: '/scalars', url: '/scalars',
title: 'SCALARS', title: 'SCALARS',
name: 'scalars', name: 'scalars',
}, },
{ {
url: '/images', url: '/images',
title: 'IMAGES', title: 'IMAGES',
name: 'images', name: 'images',
}, },
{ {
url: '/audio', url: '/audio',
title: 'AUDIO', title: 'AUDIO',
name: 'audio', name: 'audio',
}, },
{ {
url: '/histograms', url: '/histograms',
title: 'HISTOGRAMS', title: 'HISTOGRAMS',
name: 'histograms', name: 'histograms',
}, },
{ {
url: '/graphs', url: '/graphs',
title: 'GRAPHS', title: 'GRAPHS',
name: 'graphs', name: 'graphs',
}, },
{ {
url: '/texts', url: '/texts',
title: 'TEXTS', title: 'TEXTS',
name: 'texts', name: 'texts',
}, },
/* // Hide the top menu /* // Hide the top menu
{ {
url: '/HighDimensional', url: '/HighDimensional',
title: 'HighDimensional', title: 'HighDimensional',
name: 'HighDimensional' name: 'HighDimensional'
} }
*/ */
], ],
}; };
}, },
methods: { methods: {
handleItemClick: function(item) { handleItemClick: function(item) {
this.selected = item.name; this.selected = item.name;
this.$router.push(item.url); this.$router.push(item.url);
},
}, },
},
}; };
</script> </script>
......
...@@ -22,20 +22,20 @@ ...@@ -22,20 +22,20 @@
</template> </template>
<script> <script>
export default { export default {
props: { props: {
title: String, title: String,
info: Number, info: Number,
}, },
computed: { computed: {
iconName() { iconName() {
return this.isShow ? 'expand_less' : 'expand_more'; return this.isShow ? 'expand_less' : 'expand_more';
},
},
data() {
return {
isShow: true,
};
}, },
},
data() {
return {
isShow: true,
};
},
}; };
</script> </script>
<style lang="stylus"> <style lang="stylus">
......
...@@ -11,10 +11,10 @@ const instances = []; ...@@ -11,10 +11,10 @@ const instances = [];
* @return {number} final top dist * @return {number} final top dist
*/ */
function calcTopDist(topDist = 16) { function calcTopDist(topDist = 16) {
for (let i = 0, len = instances.length; i < len; i++) { for (let i = 0, len = instances.length; i < len; i++) {
topDist += (instances[i].vm.el.offsetHeight + 16); topDist += (instances[i].vm.el.offsetHeight + 16);
} }
return topDist; return topDist;
} }
/** /**
...@@ -24,28 +24,28 @@ function calcTopDist(topDist = 16) { ...@@ -24,28 +24,28 @@ function calcTopDist(topDist = 16) {
* @return {NotificationItem} instance * @return {NotificationItem} instance
*/ */
const notification = function(options = {}) { const notification = function(options = {}) {
options.top = calcTopDist(options.offset); options.top = calcTopDist(options.offset);
const {onClose, onClick} = options; const {onClose, onClick} = options;
delete options.onClick; delete options.onClick;
delete options.onClose; delete options.onClose;
delete options.offset; delete options.offset;
const instance = { const instance = {
vm: new NotificationItem({ vm: new NotificationItem({
data: options, data: options,
}), }),
id: `notification_${seed++}`, id: `notification_${seed++}`,
}; };
if (typeof onClick === 'function') { if (typeof onClick === 'function') {
instance.vm.on('itemClick', onClick); instance.vm.on('itemClick', onClick);
} }
instance.vm.on('close', () => { instance.vm.on('close', () => {
notification.close(instance.id, onClose); notification.close(instance.id, onClose);
}); });
instance.vm.attach(document.body); instance.vm.attach(document.body);
instances.push(instance); instances.push(instance);
return instance.vm; return instance.vm;
}; };
/** /**
...@@ -55,44 +55,44 @@ const notification = function(options = {}) { ...@@ -55,44 +55,44 @@ const notification = function(options = {}) {
* @param {Function} onClose cusmtom func * @param {Function} onClose cusmtom func
*/ */
notification.close = function(id, onClose) { notification.close = function(id, onClose) {
let index; let index;
let removedHeight; let removedHeight;
let len = instances.length; let len = instances.length;
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
if (id === instances[i].id) { if (id === instances[i].id) {
if (typeof onClose === 'function') { if (typeof onClose === 'function') {
onClose(instances[i]); onClose(instances[i]);
} }
index = i; index = i;
removedHeight = instances[i].vm.el.offsetHeight; removedHeight = instances[i].vm.el.offsetHeight;
// distroy instance // distroy instance
instances[i].vm.dispose(); instances[i].vm.dispose();
instances[i] = null; instances[i] = null;
// reomve instance fron instances // reomve instance fron instances
instances.splice(i, 1); instances.splice(i, 1);
break; break;
}
} }
// change the left notification's height }
if (len > 1) { // change the left notification's height
for (let i = index; i < len - 1; i++) { if (len > 1) {
instances[i].vm.el.style.top = `${parseInt(instances[i].vm.el.style.top, 10) - removedHeight - 16}px`; for (let i = index; i < len - 1; i++) {
} instances[i].vm.el.style.top = `${parseInt(instances[i].vm.el.style.top, 10) - removedHeight - 16}px`;
} }
}
}; };
// fout type func // fout type func
['success', 'warning', 'info', 'error'].forEach((type) => { ['success', 'warning', 'info', 'error'].forEach((type) => {
notification[type] = (options) => { notification[type] = (options) => {
if (typeof options === 'string') { if (typeof options === 'string') {
options = { options = {
message: options, message: options,
}; };
} }
options = options || {}; options = options || {};
options.type = type; options.type = type;
return notification(options); return notification(options);
}; };
}); });
export default notification; export default notification;
export default function autoAdjustHeight() { export default function autoAdjustHeight() {
// compute the container height // compute the container height
let containerHeight = window.innerHeight - 64;
let containerLeftEl = document.getElementsByClassName('visual-dl-page-left')[0];
let containerRightEl = document.getElementsByClassName('visual-dl-page-right')[0];
containerLeftEl.style.height = containerHeight + 'px';
containerRightEl.style.height = containerHeight + 'px';
window.addEventListener('resize', () => {
let containerHeight = window.innerHeight - 64; let containerHeight = window.innerHeight - 64;
let containerLeftEl = document.getElementsByClassName('visual-dl-page-left')[0];
let containerRightEl = document.getElementsByClassName('visual-dl-page-right')[0];
containerLeftEl.style.height = containerHeight + 'px'; containerLeftEl.style.height = containerHeight + 'px';
containerRightEl.style.height = containerHeight + 'px'; containerRightEl.style.height = containerHeight + 'px';
window.addEventListener('resize', () => { });
let containerHeight = window.innerHeight - 64;
containerLeftEl.style.height = containerHeight + 'px';
containerRightEl.style.height = containerHeight + 'px';
});
} }
...@@ -3,19 +3,19 @@ import FileSaver from 'file-saver'; ...@@ -3,19 +3,19 @@ import FileSaver from 'file-saver';
const aoaToSheet = XLSX.utils.aoa_to_sheet; const aoaToSheet = XLSX.utils.aoa_to_sheet;
const saveAs = FileSaver.saveAs; const saveAs = FileSaver.saveAs;
function s2ab(s) { function s2ab(s) {
if (typeof ArrayBuffer !== 'undefined') { if (typeof ArrayBuffer !== 'undefined') {
let buf = new ArrayBuffer(s.length); let buf = new ArrayBuffer(s.length);
let view = new Uint8Array(buf); let view = new Uint8Array(buf);
for (let i = 0; i !== s.length; ++i) {
view[i] = s.charCodeAt(i) & 0xFF;
}
return buf;
}
let buf = new Array(s.length);
for (let i = 0; i !== s.length; ++i) { for (let i = 0; i !== s.length; ++i) {
buf[i] = s.charCodeAt(i) & 0xFF; view[i] = s.charCodeAt(i) & 0xFF;
} }
return buf; return buf;
}
let buf = new Array(s.length);
for (let i = 0; i !== s.length; ++i) {
buf[i] = s.charCodeAt(i) & 0xFF;
}
return buf;
} }
/** /**
...@@ -26,28 +26,28 @@ function s2ab(s) { ...@@ -26,28 +26,28 @@ function s2ab(s) {
* @param {string} name filename * @param {string} name filename
*/ */
export const generateXLSXandAutoDownload = function(data, name) { export const generateXLSXandAutoDownload = function(data, name) {
let wopts = { let wopts = {
bookType: 'xlsx', bookType: 'xlsx',
bookSST: false, bookSST: false,
type: 'binary', type: 'binary',
}; };
let ws = aoaToSheet(data); let ws = aoaToSheet(data);
let wb = { let wb = {
SheetNames: ['Export'], SheetNames: ['Export'],
Sheets: {}, Sheets: {},
Props: {}, Props: {},
}; };
wb.Sheets.Export = ws; wb.Sheets.Export = ws;
let wbout = XLSX.write(wb, wopts); let wbout = XLSX.write(wb, wopts);
saveAs( saveAs(
new Blob( new Blob(
[s2ab(wbout)], [s2ab(wbout)],
{ {
type: 'application/octet-stream', type: 'application/octet-stream',
} }
), ),
name + '.xlsx' || 'sheetjs.xlsx' name + '.xlsx' || 'sheetjs.xlsx'
); );
}; };
/** /**
...@@ -58,13 +58,13 @@ export const generateXLSXandAutoDownload = function(data, name) { ...@@ -58,13 +58,13 @@ export const generateXLSXandAutoDownload = function(data, name) {
* @param {string} name filename * @param {string} name filename
*/ */
export const generateJsonAndDownload = function(data, name) { export const generateJsonAndDownload = function(data, name) {
saveAs( saveAs(
new Blob( new Blob(
[s2ab(JSON.stringify(data, null, ' '))], [s2ab(JSON.stringify(data, null, ' '))],
{ {
type: 'application/octet-stream', type: 'application/octet-stream',
} }
), ),
name + '.json' || 'json.json' name + '.json' || 'json.json'
); );
}; };
...@@ -6,35 +6,35 @@ const STATUS = 'status'; ...@@ -6,35 +6,35 @@ const STATUS = 'status';
const STATUSINFO = 'msg'; const STATUSINFO = 'msg';
const instance = axios.create({ const instance = axios.create({
baseURL: '/', baseURL: '/',
timeout: 30000, timeout: 30000,
}); });
// for better ux, don't send the error msg because there will be too mutch error // for better ux, don't send the error msg because there will be too mutch error
const responseErrorStatus = (response) => { const responseErrorStatus = (response) => {
const data = response.data; const data = response.data;
// if (data[STATUS] !== 0) { // if (data[STATUS] !== 0) {
// Notification.error(data[STATUSINFO]); // Notification.error(data[STATUSINFO]);
// return Promise.reject(data); // return Promise.reject(data);
// } // }
return data; return data;
}; };
// for better ux, don't send the error msg because there will be too mutch error // for better ux, don't send the error msg because there will be too mutch error
const responseNetError = (error) => { const responseNetError = (error) => {
// Notification.error('net error'); // Notification.error('net error');
return Promise.reject(error); return Promise.reject(error);
}; };
// post from // post from
const formInstance = axios.create({ const formInstance = axios.create({
baseURL: '/', baseURL: '/',
timeout: 3000, timeout: 3000,
transformRequest: [(data) => qs.stringify(data)], transformRequest: [(data) => qs.stringify(data)],
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json,application/vnd.ms-excel', 'Accept': 'application/json,application/vnd.ms-excel',
}, },
}); });
...@@ -43,10 +43,10 @@ formInstance.interceptors.response.use(responseErrorStatus, responseNetError); ...@@ -43,10 +43,10 @@ formInstance.interceptors.response.use(responseErrorStatus, responseNetError);
instance.interceptors.response.use(responseErrorStatus, responseNetError); instance.interceptors.response.use(responseErrorStatus, responseNetError);
export const makeService = (url, opt = {method: 'get'}) => (params = {}) => { export const makeService = (url, opt = {method: 'get'}) => (params = {}) => {
if (opt.method === 'delete' || opt.method === 'get') { if (opt.method === 'delete' || opt.method === 'get') {
params = {params}; params = {params};
} }
return instance[opt.method](url, params); return instance[opt.method](url, params);
}; };
export const makeFormService = (url, method = 'post') => (params = {}) => formInstance[method](url, params); export const makeFormService = (url, method = 'post') => (params = {}) => formInstance[method](url, params);
import quantile from './quantile'; import quantile from './quantile';
export { export {
quantile, quantile,
}; };
export default function(x) { export default function(x) {
return x === null ? NaN : +x; return x === null ? NaN : +x;
} }
import number from './number'; import number from './number';
export default function(values, p, valueof) { export default function(values, p, valueof) {
if (valueof == null) { if (valueof == null) {
return valueof = number; return valueof = number;
} }
let n = values.length; let n = values.length;
if (!(n)) { if (!(n)) {
return; return;
} }
if ((p = +p) <= 0 || n < 2) { if ((p = +p) <= 0 || n < 2) {
return +valueof(values[0], 0, values); return +valueof(values[0], 0, values);
} }
if (p >= 1) { if (p >= 1) {
return +valueof(values[n - 1], n - 1, values); return +valueof(values[n - 1], n - 1, values);
} }
let i = (n - 1) * p; let i = (n - 1) * p;
let i0 = Math.floor(i); let i0 = Math.floor(i);
let value0 = +valueof(values[i0], i0, values); let value0 = +valueof(values[i0], i0, values);
let value1 = +valueof(values[i0 + 1], i0 + 1, values); let value1 = +valueof(values[i0 + 1], i0 + 1, values);
return value0 + (value1 - value0) * (i - i0); return value0 + (value1 - value0) * (i - i0);
} }
import {router} from 'san-router'; import {router} from 'san-router';
export function routeTo(url, params = {}) { export function routeTo(url, params = {}) {
let paramsArr = Object.keys(params).map((key) => `${key}=${params[key]}`); let paramsArr = Object.keys(params).map((key) => `${key}=${params[key]}`);
let urlParams = (url.indexOf('?') > -1 ? '&' : '?') + paramsArr.join('&'); let urlParams = (url.indexOf('?') > -1 ? '&' : '?') + paramsArr.join('&');
router.locator.redirect(urlParams.length > 1 ? `${url}${urlParams}` : url); router.locator.redirect(urlParams.length > 1 ? `${url}${urlParams}` : url);
} }
...@@ -29,33 +29,33 @@ import Chart from './ui/Chart'; ...@@ -29,33 +29,33 @@ import Chart from './ui/Chart';
export default { export default {
components: { components: {
'ui-config': Config, 'ui-config': Config,
'ui-chart': Chart, 'ui-chart': Chart,
},
name: 'Graph',
data() {
return {
config: {
scale: 0.5,
},
fitScreen: {fitScreen: false},
download: {download: false},
curNode: {},
};
},
mounted() {
autoAdjustHeight();
},
methods: {
handleFitScreen() {
this.fitScreen = {fitScreen: true};
this.config.scale = 0.5;
}, },
name: 'Graph', handleDownload() {
data() { this.download = {fitScreen: true};
return {
config: {
scale: 0.5,
},
fitScreen: {fitScreen: false},
download: {download: false},
curNode: {},
};
},
mounted() {
autoAdjustHeight();
},
methods: {
handleFitScreen() {
this.fitScreen = {fitScreen: true};
this.config.scale = 0.5;
},
handleDownload() {
this.download = {fitScreen: true};
},
}, },
},
}; };
</script> </script>
......
...@@ -3,7 +3,7 @@ import {router} from 'san-router'; ...@@ -3,7 +3,7 @@ import {router} from 'san-router';
import Graph from './Graph'; import Graph from './Graph';
router.add({ router.add({
target: '#content', target: '#content',
rule: '/graphs', rule: '/graphs',
Component: Graph, Component: Graph,
}); });
...@@ -7,271 +7,271 @@ ...@@ -7,271 +7,271 @@
</template> </template>
<script> <script>
// libs // libs
import echarts from 'echarts'; import echarts from 'echarts';
import { import {
dragMovelHandler, dragMovelHandler,
tansformElement, tansformElement,
relativeMove, relativeMove,
} from './dragHelper'; } from './dragHelper';
// service // service
import {getPluginGraphsGraph} from '../../service'; import {getPluginGraphsGraph} from '../../service';
// https://github.com/taye/interact.js // https://github.com/taye/interact.js
import interact from 'interactjs'; import interact from 'interactjs';
// for d3 drawing // for d3 drawing
import * as d3 from 'd3'; import * as d3 from 'd3';
export default { export default {
props: { props: {
'fitScreen': { 'fitScreen': {
type: Function, type: Function,
required: true, required: true,
}, },
'download': { 'download': {
type: Function, type: Function,
required: true, required: true,
}, },
'scale': { 'scale': {
type: Number, type: Number,
default: 1, default: 1,
}, },
'curNode': { 'curNode': {
type: Object, type: Object,
default: {}, default: {},
}}, }},
computed: { computed: {
computedWidth() { computedWidth() {
let scale = this.scale; let scale = this.scale;
return Math.floor(scale * 2 * 700); return Math.floor(scale * 2 * 700);
}, },
}, },
data() { data() {
return { return {
myCY: null, myCY: null,
graphUrl: '', graphUrl: '',
}; };
}, },
watch: { watch: {
fitScreen: function(val) { fitScreen: function(val) {
this.clearDragedTransform(this.getBigImgEl()); this.clearDragedTransform(this.getBigImgEl());
this.clearDragedTransform(this.getSmallImgDragHandler()); this.clearDragedTransform(this.getSmallImgDragHandler());
}, },
download: function(val) { download: function(val) {
if (this.myCY) { if (this.myCY) {
let aEl = document.createElement('a'); let aEl = document.createElement('a');
aEl.href = this.myCY.png(); aEl.href = this.myCY.png();
aEl.download = 'graph.png'; aEl.download = 'graph.png';
aEl.click(); aEl.click();
} }
}, },
}, },
mounted() { mounted() {
this.getOriginChartsData(); this.getOriginChartsData();
let chartScope = this; let chartScope = this;
getPluginGraphsGraph().then(({errno, data}) => { getPluginGraphsGraph().then(({errno, data}) => {
let graphData = data.data; let graphData = data.data;
// d3 svg drawing // d3 svg drawing
let g = new dagreD3.graphlib.Graph() let g = new dagreD3.graphlib.Graph()
.setGraph({}) .setGraph({})
.setDefaultEdgeLabel(function() { .setDefaultEdgeLabel(function() {
return {}; return {};
}); });
// eslint-disable-next-line // eslint-disable-next-line
let render = new dagreD3.render(); let render = new dagreD3.render();
let nodeKeys = []; let nodeKeys = [];
let buildInputNodeLabel = function(inputNode) { let buildInputNodeLabel = function(inputNode) {
// TODO(daming-lu): need more complex compound node // TODO(daming-lu): need more complex compound node
let nodeLabel = 'id: ' + inputNode['name'] + '\n' let nodeLabel = 'id: ' + inputNode['name'] + '\n'
+ 'type: ' + inputNode['data_type'] + '\n' + 'type: ' + inputNode['data_type'] + '\n'
+ 'dims: ' + inputNode['shape'].join(' x '); + 'dims: ' + inputNode['shape'].join(' x ');
return nodeLabel; return nodeLabel;
}; };
// add input nodes // add input nodes
for (let i=0; i<graphData['input'].length; ++i) { for (let i=0; i<graphData['input'].length; ++i) {
let curInputNode = graphData['input'][i]; let curInputNode = graphData['input'][i];
let nodeKey = curInputNode['name']; let nodeKey = curInputNode['name'];
g.setNode( g.setNode(
nodeKey, nodeKey,
{ {
label: buildInputNodeLabel(curInputNode), label: buildInputNodeLabel(curInputNode),
class: 'input', class: 'input',
style: 'stroke: #A3D39C; stroke-width: 3px; ' + style: 'stroke: #A3D39C; stroke-width: 3px; ' +
'stroke-dasharray: 5, 5;', 'stroke-dasharray: 5, 5;',
labelStyle: 'font-size: 0.8em;', labelStyle: 'font-size: 0.8em;',
} }
); );
nodeKeys.push(nodeKey); nodeKeys.push(nodeKey);
} }
// add operator nodes then add edges from inputs to operator and from operator to output // add operator nodes then add edges from inputs to operator and from operator to output
for (let i=0; i<graphData['node'].length; ++i) { for (let i=0; i<graphData['node'].length; ++i) {
let curOperatorNode = graphData['node'][i]; let curOperatorNode = graphData['node'][i];
let nodeKey = 'opNode_' + i; let nodeKey = 'opNode_' + i;
// add operator node // add operator node
let curOpLabel = curOperatorNode['opType']; let curOpLabel = curOperatorNode['opType'];
g.setNode( g.setNode(
nodeKey, nodeKey,
{ {
label: curOpLabel + ' '.repeat(Math.floor(curOpLabel.length/5)), label: curOpLabel + ' '.repeat(Math.floor(curOpLabel.length/5)),
class: 'operator', class: 'operator',
style: 'opacity: 0.5;', style: 'opacity: 0.5;',
} }
); );
nodeKeys.push(nodeKey); nodeKeys.push(nodeKey);
// add output node // add output node
let outputNodeKey = curOperatorNode['output'][0]; let outputNodeKey = curOperatorNode['output'][0];
let outputPadding = ' '.repeat(Math.floor(outputNodeKey.length/2)); let outputPadding = ' '.repeat(Math.floor(outputNodeKey.length/2));
g.setNode( g.setNode(
outputNodeKey, outputNodeKey,
{ {
label: outputNodeKey + outputPadding, label: outputNodeKey + outputPadding,
class: 'output', class: 'output',
style: 'opacity: 0.5;' + style: 'opacity: 0.5;' +
'stroke-width: 2px; ' + 'stroke-width: 2px; ' +
'stroke-dasharray: 5, 5;', 'stroke-dasharray: 5, 5;',
shape: 'diamond', shape: 'diamond',
} }
); );
nodeKeys.push(outputNodeKey); nodeKeys.push(outputNodeKey);
// add edges from inputs to node and from node to output // add edges from inputs to node and from node to output
for (let e=0; e<curOperatorNode['input'].length; ++e) { for (let e=0; e<curOperatorNode['input'].length; ++e) {
g.setEdge(curOperatorNode['input'][e], nodeKey); g.setEdge(curOperatorNode['input'][e], nodeKey);
} }
g.setEdge(nodeKey, curOperatorNode['output'][0]); g.setEdge(nodeKey, curOperatorNode['output'][0]);
} }
// TODO(daming-lu): add prettier styles to diff nodes // TODO(daming-lu): add prettier styles to diff nodes
let svg = d3.select('svg') let svg = d3.select('svg')
.attr('font-family', 'sans-serif') .attr('font-family', 'sans-serif')
.attr('font-size', '28px'); .attr('font-size', '28px');
render(d3.select('svg g'), g); render(d3.select('svg g'), g);
// adjust viewBox so that the whole graph can be shown, with scroll bar // adjust viewBox so that the whole graph can be shown, with scroll bar
svg.attr('viewBox', '0 0 ' + g.graph().width + ' ' + g.graph().height); svg.attr('viewBox', '0 0 ' + g.graph().width + ' ' + g.graph().height);
svg.selectAll('.node').on('click', function(d, i) { svg.selectAll('.node').on('click', function(d, i) {
chartScope.curNode = g.node(d); chartScope.curNode = g.node(d);
let nodeType = chartScope.curNode.class; let nodeType = chartScope.curNode.class;
let nodeInfo = null; let nodeInfo = null;
if (nodeType === 'operator') { if (nodeType === 'operator') {
let opIndex = d.slice(7); // remove prefix "opNode_" let opIndex = d.slice(7); // remove prefix "opNode_"
nodeInfo = graphData.node[opIndex]; nodeInfo = graphData.node[opIndex];
} else if (nodeType === 'input') { } else if (nodeType === 'input') {
nodeInfo = graphData.input[d-1]; nodeInfo = graphData.input[d-1];
} else { } else {
nodeInfo = 'output'; nodeInfo = 'output';
} }
chartScope.$emit('curNodeUpdated', chartScope.$emit('curNodeUpdated',
{ {
'nodeType': nodeType, 'nodeType': nodeType,
'nodeInfo': nodeInfo, 'nodeInfo': nodeInfo,
}); });
}); });
}); });
},
methods: {
createChart() {
let el = this.el.getElementsByClassName('visual-dl-chart-box')[0];
this.myChart = echarts.init(el);
},
initChartOption(data) {
this.setChartOptions(data);
},
setChartOptions(data) {
this.myChart.setOption(data);
},
getOriginChartsData() {
getPluginGraphsGraph().then(({status, data}) => {
if (status === 0 && data.url) {
this.graphUrl = data.url;
this.addDragEventForImg();
}
});
},
clearDragedTransform(dragImgEl) {
dragImgEl.style.transform = 'none';
dragImgEl.setAttribute('data-x', 0);
dragImgEl.setAttribute('data-y', 0);
},
getBigImgEl() {
return this.$refs.draggable;
},
getSmallImgEl() {
return this.$refs.small_img;
},
getSmallImgDragHandler() {
return this.$refs.screen_handler;
},
addDragEventForImg() {
let chartScope = this;
// target elements with the "draggable" class
interact('.draggable').draggable({
// enable inertial throwing
inertia: true,
autoScroll: true,
// call this function on every dragmove event
onmove(event) {
dragMovelHandler(event, (target, x, y) => {
tansformElement(target, x, y);
// compute the proportional value
let triggerEl = chartScope.getBigImgEl();
let relativeEl = chartScope.getSmallImgDragHandler();
relativeMove({triggerEl, x, y}, relativeEl);
});
}, },
});
methods: {
createChart() { interact('.screen-handler').draggable({
let el = this.el.getElementsByClassName('visual-dl-chart-box')[0]; // enable inertial throwing
this.myChart = echarts.init(el); inertia: true,
}, autoScroll: true,
restrict: {
initChartOption(data) { restriction: 'parent',
this.setChartOptions(data); endOnly: false,
}, elementRect: {
setChartOptions(data) { top: 0,
this.myChart.setOption(data); left: 0,
}, bottom: 1,
right: 1,
getOriginChartsData() { },
getPluginGraphsGraph().then(({status, data}) => {
if (status === 0 && data.url) {
this.graphUrl = data.url;
this.addDragEventForImg();
}
});
},
clearDragedTransform(dragImgEl) {
dragImgEl.style.transform = 'none';
dragImgEl.setAttribute('data-x', 0);
dragImgEl.setAttribute('data-y', 0);
},
getBigImgEl() {
return this.$refs.draggable;
},
getSmallImgEl() {
return this.$refs.small_img;
},
getSmallImgDragHandler() {
return this.$refs.screen_handler;
},
addDragEventForImg() {
let chartScope = this;
// target elements with the "draggable" class
interact('.draggable').draggable({
// enable inertial throwing
inertia: true,
autoScroll: true,
// call this function on every dragmove event
onmove(event) {
dragMovelHandler(event, (target, x, y) => {
tansformElement(target, x, y);
// compute the proportional value
let triggerEl = chartScope.getBigImgEl();
let relativeEl = chartScope.getSmallImgDragHandler();
relativeMove({triggerEl, x, y}, relativeEl);
});
},
});
interact('.screen-handler').draggable({
// enable inertial throwing
inertia: true,
autoScroll: true,
restrict: {
restriction: 'parent',
endOnly: false,
elementRect: {
top: 0,
left: 0,
bottom: 1,
right: 1,
},
},
// call this function on every dragmove event
onmove(event) {
dragMovelHandler(event, (target, x, y) => {
tansformElement(target, x, y);
// compute the proportional value
let triggerEl = chartScope.getSmallImgEl();
let relativeEl = chartScope.getBigImgEl();
relativeMove({triggerEl, x, y}, relativeEl);
});
},
});
},
}, },
}; // call this function on every dragmove event
onmove(event) {
dragMovelHandler(event, (target, x, y) => {
tansformElement(target, x, y);
// compute the proportional value
let triggerEl = chartScope.getSmallImgEl();
let relativeEl = chartScope.getBigImgEl();
relativeMove({triggerEl, x, y}, relativeEl);
});
},
});
},
},
};
</script> </script>
<style lang="stylus"> <style lang="stylus">
.node rect .node rect
......
...@@ -54,15 +54,15 @@ ...@@ -54,15 +54,15 @@
<script> <script>
export default { export default {
props: ['config', 'curNode'], props: ['config', 'curNode'],
methods: { methods: {
handleFitScreen() { handleFitScreen() {
this.$emit('fitScreen'); this.$emit('fitScreen');
},
handleDownload() {
this.$emit('download');
},
}, },
handleDownload() {
this.$emit('download');
},
},
}; };
</script> </script>
<style lang="stylus"> <style lang="stylus">
......
export const dragMovelHandler = (event, callback) => { export const dragMovelHandler = (event, callback) => {
let target = event.target; let target = event.target;
// keep the dragged position in the data-x/data-y attributes // keep the dragged position in the data-x/data-y attributes
let x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx; let x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
let y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy; let y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
callback(target, x, y); callback(target, x, y);
}; };
export const tansformElement = (target, x, y) => { export const tansformElement = (target, x, y) => {
// translate the element // translate the element
target.style.webkitTransform = target.style.transform target.style.webkitTransform = target.style.transform
= 'translate(' + x + 'px, ' + y + 'px)'; = 'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes // update the posiion attributes
target.setAttribute('data-x', x); target.setAttribute('data-x', x);
target.setAttribute('data-y', y); target.setAttribute('data-y', y);
}; };
export const relativeMove = ({triggerEl, x, y}, relativeEl) => { export const relativeMove = ({triggerEl, x, y}, relativeEl) => {
let {offsetWidth: tWidth, offsetHeight: tHeight} = triggerEl; let {offsetWidth: tWidth, offsetHeight: tHeight} = triggerEl;
let {offsetWidth: rWidth, offsetHeight: rHeight} = relativeEl; let {offsetWidth: rWidth, offsetHeight: rHeight} = relativeEl;
let rX = (x / tWidth) * rWidth; let rX = (x / tWidth) * rWidth;
let rY = (y / tHeight) * rHeight; let rY = (y / tHeight) * rHeight;
tansformElement(relativeEl, -rX, -rY); tansformElement(relativeEl, -rX, -rY);
}; };
...@@ -26,56 +26,56 @@ import Config from './ui/Config'; ...@@ -26,56 +26,56 @@ import Config from './ui/Config';
import Chart from './ui/Chart'; import Chart from './ui/Chart';
export default { export default {
components: { components: {
'ui-config': Config, 'ui-config': Config,
'ui-chart': Chart, 'ui-chart': Chart,
},
name: 'HighDimensional',
data() {
return {
config: {
searchText: '',
displayWordLabel: true,
dimension: '2',
reduction: 'tsne',
running: true,
},
embedding_data: [],
};
},
created() {
this.fetchDatasets();
},
watch: {
'config.dimension': function(val) {
this.fetchDatasets();
}, },
name: 'HighDimensional', 'config.reduction': function(val) {
data() { this.fetchDatasets();
return {
config: {
searchText: '',
displayWordLabel: true,
dimension: '2',
reduction: 'tsne',
running: true,
},
embedding_data: [],
};
}, },
created() { },
this.fetchDatasets(); mounted() {
}, autoAdjustHeight();
watch: { },
'config.dimension': function(val) { methods: {
this.fetchDatasets(); fetchDatasets() {
}, // Fetch the data from the server. Passing dimension and reduction method
'config.reduction': function(val) { let params = {
this.fetchDatasets(); dimension: this.config.dimension,
}, reduction: this.config.reduction,
}, };
mounted() { getHighDimensionalDatasets(params).then(({errno, data}) => {
autoAdjustHeight(); let vector_data = data.embedding;
}, let labels = data.labels;
methods: {
fetchDatasets() {
// Fetch the data from the server. Passing dimension and reduction method
let params = {
dimension: this.config.dimension,
reduction: this.config.reduction,
};
getHighDimensionalDatasets(params).then(({errno, data}) => {
let vector_data = data.embedding;
let labels = data.labels;
for ( let i = 0; i < vector_data.length; i ++) { for ( let i = 0; i < vector_data.length; i ++) {
vector_data[i].push(labels[i]); vector_data[i].push(labels[i]);
} }
this.embedding_data = vector_data; this.embedding_data = vector_data;
}); });
},
}, },
},
}; };
</script> </script>
......
...@@ -14,179 +14,179 @@ import echarts from 'echarts'; ...@@ -14,179 +14,179 @@ import echarts from 'echarts';
import 'echarts-gl'; import 'echarts-gl';
export default { export default {
props: ['config', 'displayWordLabel', 'searchText', 'embedding_data', 'dimension'], props: ['config', 'displayWordLabel', 'searchText', 'embedding_data', 'dimension'],
data() { data() {
return { return {
width: 900, width: 900,
height: 600, height: 600,
}; };
},
computed: {
computedStyle() {
return 'height:' + this.height + 'px;' +
'width:' + this.width + 'px;';
}, },
computed: { },
computedStyle() { created() {},
return 'height:' + this.height + 'px;' + mounted() {
'width:' + this.width + 'px;'; this.createChart();
}, this.myChart.showLoading();
},
created() {},
mounted() {
this.createChart();
this.myChart.showLoading();
this.set2DChartOptions();
this.setDisplayWordLabel();
},
watch: {
embedding_data: function(val) {
this.myChart.hideLoading();
this.myChart.setOption({
series: [{
// Grab the 'matched' series data
name: 'all',
data: val,
}],
});
},
displayWordLabel: function(val) {
this.setDisplayWordLabel();
},
dimension: function(val) {
this.myChart.clear();
this.myChart.showLoading();
if (val === '2') {
this.set2DChartOptions(); this.set2DChartOptions();
this.setDisplayWordLabel(); this.setDisplayWordLabel();
} else {
this.set3DChartOptions();
this.setDisplayWordLabel();
}
}, },
watch: { searchText: function(val) {
embedding_data: function(val) { // Filter the data that has the hasPrefix
this.myChart.hideLoading(); let matched_words = [];
this.myChart.setOption({ if (val != '') {
series: [{ val = val.toLowerCase();
// Grab the 'matched' series data
name: 'all',
data: val,
}],
});
},
displayWordLabel: function(val) {
this.setDisplayWordLabel();
},
dimension: function(val) {
this.myChart.clear();
this.myChart.showLoading();
if (val === '2') {
this.set2DChartOptions();
this.setDisplayWordLabel();
} else {
this.set3DChartOptions();
this.setDisplayWordLabel();
}
},
searchText: function(val) {
// Filter the data that has the hasPrefix
let matched_words = [];
if (val != '') {
val = val.toLowerCase();
function hasPrefix(value) { function hasPrefix(value) {
let word = value[value.length - 1]; let word = value[value.length - 1];
return (typeof word == 'string' && word.toLowerCase().startsWith(val)); return (typeof word == 'string' && word.toLowerCase().startsWith(val));
} }
matched_words = this.embedding_data.filter(hasPrefix); matched_words = this.embedding_data.filter(hasPrefix);
} }
// Update the matched series data // Update the matched series data
this.myChart.setOption({ this.myChart.setOption({
series: [{ series: [{
// Grab the 'matched' series data // Grab the 'matched' series data
name: 'matched', name: 'matched',
data: matched_words, data: matched_words,
}], }],
}); });
},
}, },
methods: { },
createChart() { methods: {
// Initialize the eChartBox createChart() {
let el = this.$refs.chartBox; // Initialize the eChartBox
this.myChart = echarts.init(el); let el = this.$refs.chartBox;
}, this.myChart = echarts.init(el);
set2DChartOptions() { },
let typeD = 'normal'; set2DChartOptions() {
let option = { let typeD = 'normal';
xAxis: {}, let option = {
yAxis: {}, xAxis: {},
series: [{ yAxis: {},
name: 'all', series: [{
symbolSize: 10, name: 'all',
data: this.embedding_data, symbolSize: 10,
type: 'scatter', data: this.embedding_data,
}, type: 'scatter',
{ },
name: 'matched', {
animation: false, name: 'matched',
symbolSize: 10, animation: false,
data: [], symbolSize: 10,
itemStyle: { data: [],
normal: { itemStyle: {
opacity: 1, normal: {
}, opacity: 1,
}, },
label: { },
normal: { label: {
show: true, normal: {
formatter: function(param) { show: true,
return param.data[param.data.length - 1]; formatter: function(param) {
}, return param.data[param.data.length - 1];
position: 'top', },
}, position: 'top',
}, },
type: 'scatter', },
}, type: 'scatter',
], },
}; ],
this.myChart.setOption(option); };
}, this.myChart.setOption(option);
set3DChartOptions() { },
let symbolSize = 2.5; set3DChartOptions() {
let option3d = { let symbolSize = 2.5;
grid3D: {}, let option3d = {
xAxis3D: { grid3D: {},
type: 'category', xAxis3D: {
}, type: 'category',
yAxis3D: {},
xAxis3D: {},
zAxis3D: {},
dataset: {
source: this.embedding_data,
},
series: [
{
name: 'all',
type: 'scatter3D',
symbolSize: symbolSize,
data: [],
},
{
name: 'matched',
animation: false,
symbolSize: symbolSize,
data: [],
label: {
normal: {
show: true,
formatter: function(param) {
return param.data[param.data.length - 1];
},
position: 'top',
},
},
type: 'scatter3D',
},
],
};
this.myChart.setOption(option3d);
}, },
setDisplayWordLabel() { yAxis3D: {},
this.myChart.setOption({ xAxis3D: {},
series: [{ zAxis3D: {},
// Grab the 'all' series data dataset: {
name: 'all', source: this.embedding_data,
label: {
normal: {
show: this.displayWordLabel,
formatter: function(param) {
return param.data[param.data.length - 1];
},
position: 'top',
},
emphasis: {
show: true,
},
},
}],
});
}, },
series: [
{
name: 'all',
type: 'scatter3D',
symbolSize: symbolSize,
data: [],
},
{
name: 'matched',
animation: false,
symbolSize: symbolSize,
data: [],
label: {
normal: {
show: true,
formatter: function(param) {
return param.data[param.data.length - 1];
},
position: 'top',
},
},
type: 'scatter3D',
},
],
};
this.myChart.setOption(option3d);
},
setDisplayWordLabel() {
this.myChart.setOption({
series: [{
// Grab the 'all' series data
name: 'all',
label: {
normal: {
show: this.displayWordLabel,
formatter: function(param) {
return param.data[param.data.length - 1];
},
position: 'top',
},
emphasis: {
show: true,
},
},
}],
});
}, },
},
}; };
</script> </script>
......
...@@ -54,19 +54,19 @@ ...@@ -54,19 +54,19 @@
<script> <script>
export default { export default {
props: { props: {
runsItems: Array, runsItems: Array,
config: Object, config: Object,
}, },
data() { data() {
return { return {
}; };
}, },
methods: { methods: {
toggleAllRuns() { toggleAllRuns() {
this.config.running = !this.config.running; this.config.running = !this.config.running;
},
}, },
},
}; };
</script> </script>
......
...@@ -35,118 +35,118 @@ import {debounce, flatten, uniq} from 'lodash'; ...@@ -35,118 +35,118 @@ import {debounce, flatten, uniq} from 'lodash';
import autoAdjustHeight from '../common/util/autoAdjustHeight'; import autoAdjustHeight from '../common/util/autoAdjustHeight';
export default { export default {
components: { components: {
'ui-config': Config, 'ui-config': Config,
'ui-chart-page': ChartPage, 'ui-chart-page': ChartPage,
},
computed: {
runsItems() {
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return {
name: item,
value: item,
};
});
}, },
computed: { tagsList() {
runsItems() { let tags = this.tags;
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return {
name: item,
value: item,
};
});
},
tagsList() {
let tags = this.tags;
let runs = Object.keys(tags); let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run])); let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray)); let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart // get the data for every chart
return allUniqTags.map((tag) => { return allUniqTags.map((tag) => {
let tagList = runs.map((run) => { let tagList = runs.map((run) => {
return { return {
run, run,
tag: tags[run][tag], tag: tags[run][tag],
}; };
}).filter((item) => item.tag !== undefined); }).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
},
groupedTags() {
let tagsList = this.tagsList || [];
// put data in group
let groupData = {};
tagsList.forEach((item) => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = [];
groupData[group].push(item);
} else {
groupData[group].push(item);
}
});
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
},
data() {
return { return {
runsArray: [], tagList,
tags: [], tag,
config: { group: tag.split('/')[0],
groupNameReg: '.*',
horizontal: 'step',
chartType: 'offset',
runs: [],
running: true,
},
filteredTagsList: [],
}; };
});
}, },
created() { groupedTags() {
getPluginHistogramsTags().then(({errno, data}) => { let tagsList = this.tagsList || [];
this.tags = data; // put data in group
// filter when inited let groupData = {};
let groupNameReg = this.config.groupNameReg; tagsList.forEach((item) => {
this.filterTagsList(groupNameReg); let group = item.group;
}); if (groupData[group] === undefined) {
getRuns().then(({errno, data}) => { groupData[group] = [];
this.runsArray = data; groupData[group].push(item);
this.config.runs = data; } else {
}); groupData[group].push(item);
}, }
});
mounted() { // to array
autoAdjustHeight(); let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
}, },
watch: { },
'config.groupNameReg': function(val) { data() {
this.throttledFilterTagsList(); return {
}, runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
horizontal: 'step',
chartType: 'offset',
runs: [],
running: true,
},
filteredTagsList: [],
};
},
created() {
getPluginHistogramsTags().then(({errno, data}) => {
this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
getRuns().then(({errno, data}) => {
this.runsArray = data;
this.config.runs = data;
});
},
mounted() {
autoAdjustHeight();
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
}, },
methods: { },
filterTagsList(groupNameReg) { methods: {
if (!groupNameReg) { filterTagsList(groupNameReg) {
this.filteredTagsList = []; if (!groupNameReg) {
return; this.filteredTagsList = [];
} return;
let tagsList = this.tagsList || []; }
let regExp = new RegExp(groupNameReg); let tagsList = this.tagsList || [];
let filtedTagsList = tagsList.filter((item) => regExp.test(item.tag)); let regExp = new RegExp(groupNameReg);
this.filteredTagsList = filtedTagsList; let filtedTagsList = tagsList.filter((item) => regExp.test(item.tag));
}, this.filteredTagsList = filtedTagsList;
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
}, },
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
}; };
</script> </script>
......
import {min, max, range} from 'lodash'; import {min, max, range} from 'lodash';
export function tansformBackendData(histogramData) { export function tansformBackendData(histogramData) {
let [time, step, items] = histogramData; let [time, step, items] = histogramData;
return { return {
time, time,
step, step,
min: min(items.map(([left, right, count]) => left)), min: min(items.map(([left, right, count]) => left)),
max: max(items.map(([left, right, count]) => right)), max: max(items.map(([left, right, count]) => right)),
items: items.map(([left, right, count]) => ({left, right, count})), items: items.map(([left, right, count]) => ({left, right, count})),
}; };
} }
export function computeNewHistogram(histogram, min, max, binsNum = 30) { export function computeNewHistogram(histogram, min, max, binsNum = 30) {
if (max === min) { if (max === min) {
// Create bins even if all the data has a single value. // Create bins even if all the data has a single value.
max = min * 1.1 + 1; max = min * 1.1 + 1;
min = min / 1.1 - 1; min = min / 1.1 - 1;
}
let stepWidth = (max - min) / binsNum;
let itemIndex = 0;
return range(min, max, stepWidth).map((binLeft) => {
let binRight = binLeft + stepWidth;
let yValue = 0;
while (itemIndex < histogram.items.length) {
let itemRight = Math.min(max, histogram.items[itemIndex].right);
let itemLeft = Math.max(min, histogram.items[itemIndex].left);
let overlap = Math.min(itemRight, binRight) - Math.max(itemLeft, binLeft);
let count = (overlap / (itemRight - itemLeft)) * histogram.items[itemIndex].count;
yValue += overlap > 0 ? count : 0;
// If `itemRight` is bigger than `binRight`, then this bin is
// finished and there also has data for the next bin, so don't increment
// `itemIndex`.
if (itemRight > binRight) {
break;
}
itemIndex++;
} }
let stepWidth = (max - min) / binsNum; return {x: binLeft, dx: stepWidth, y: yValue};
let itemIndex = 0; });
return range(min, max, stepWidth).map((binLeft) => {
let binRight = binLeft + stepWidth;
let yValue = 0;
while (itemIndex < histogram.items.length) {
let itemRight = Math.min(max, histogram.items[itemIndex].right);
let itemLeft = Math.max(min, histogram.items[itemIndex].left);
let overlap = Math.min(itemRight, binRight) - Math.max(itemLeft, binLeft);
let count = (overlap / (itemRight - itemLeft)) * histogram.items[itemIndex].count;
yValue += overlap > 0 ? count : 0;
// If `itemRight` is bigger than `binRight`, then this bin is
// finished and there also has data for the next bin, so don't increment
// `itemIndex`.
if (itemRight > binRight) {
break;
}
itemIndex++;
}
return {x: binLeft, dx: stepWidth, y: yValue};
});
} }
export function tansformToVisData(tempData, time, step) { export function tansformToVisData(tempData, time, step) {
return tempData.map(function(dataItem) { return tempData.map(function(dataItem) {
return [time, step, dataItem.x + dataItem.dx / 2, Math.floor(dataItem.y)]; return [time, step, dataItem.x + dataItem.dx / 2, Math.floor(dataItem.y)];
}); });
} }
export function originDataToChartData(originData) { export function originDataToChartData(originData) {
let tempData = originData.map(tansformBackendData); let tempData = originData.map(tansformBackendData);
let globalMin = min(tempData.map(({min}) => min)); let globalMin = min(tempData.map(({min}) => min));
let globalMax = max(tempData.map(({max}) => max)); let globalMax = max(tempData.map(({max}) => max));
let chartData = tempData.map(function(item) { let chartData = tempData.map(function(item) {
let histoBins = computeNewHistogram(item, globalMin, globalMax); let histoBins = computeNewHistogram(item, globalMin, globalMax);
let {time, step} = item; let {time, step} = item;
return {
time,
step,
items: tansformToVisData(histoBins, time, step),
};
});
return { return {
min: globalMin, time,
max: globalMax, step,
chartData, items: tansformToVisData(histoBins, time, step),
}; };
});
return {
min: globalMin,
max: globalMax,
chartData,
};
} }
...@@ -3,7 +3,7 @@ import {router} from 'san-router'; ...@@ -3,7 +3,7 @@ import {router} from 'san-router';
import Histogram from './Histogram'; import Histogram from './Histogram';
router.add({ router.add({
target: '#content', target: '#content',
rule: '/histograms', rule: '/histograms',
Component: Histogram, Component: Histogram,
}); });
此差异已折叠。
...@@ -31,50 +31,50 @@ import Chart from './Chart'; ...@@ -31,50 +31,50 @@ import Chart from './Chart';
import {cloneDeep, flatten} from 'lodash'; import {cloneDeep, flatten} from 'lodash';
export default { export default {
props: ['config', 'runsItems', 'tagList', 'title'], props: ['config', 'runsItems', 'tagList', 'title'],
components: { components: {
'ui-chart': Chart, 'ui-chart': Chart,
'ui-expand-panel': ExpandPanel, 'ui-expand-panel': ExpandPanel,
},
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
}, },
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
},
filteredPageList() { filteredPageList() {
let list = this.filteredRunsList; let list = this.filteredRunsList;
let currentPage = this.currentPage; let currentPage = this.currentPage;
let pageSize = this.pageSize; let pageSize = this.pageSize;
return list.slice((currentPage - 1) * pageSize, currentPage * pageSize); return list.slice((currentPage - 1) * pageSize, currentPage * pageSize);
},
total() {
let list = this.filteredRunsList || [];
return list.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
}, },
data() { total() {
return { let list = this.filteredRunsList || [];
// current page return list.length;
currentPage: 1,
// item per page
pageSize: 4,
};
}, },
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 4,
};
},
methods: { methods: {
handlePageChange({pageNum}) { handlePageChange({pageNum}) {
this.currentPage = pageNum; this.currentPage = pageNum;
},
}, },
},
}; };
</script> </script>
<style lang="stylus"> <style lang="stylus">
......
...@@ -42,27 +42,27 @@ ...@@ -42,27 +42,27 @@
</template> </template>
<script> <script>
export default { export default {
props: ['config', 'runsItems'], props: ['config', 'runsItems'],
data() { data() {
return { return {
chartTypeItems: [ chartTypeItems: [
{ {
name: 'Overlay', name: 'Overlay',
value: 'overlay', value: 'overlay',
}, },
{ {
name: 'Offset', name: 'Offset',
value: 'offset', value: 'offset',
},
],
};
},
methods: {
toggleAllRuns() {
let running = this.config.running;
this.config.running = !running;
}, },
],
};
},
methods: {
toggleAllRuns() {
let running = this.config.running;
this.config.running = !running;
}, },
},
}; };
</script> </script>
<style lang="stylus"> <style lang="stylus">
......
...@@ -38,128 +38,128 @@ import Config from './ui/Config'; ...@@ -38,128 +38,128 @@ import Config from './ui/Config';
import ChartPage from './ui/ChartPage'; import ChartPage from './ui/ChartPage';
export default { export default {
name: 'Images', name: 'Images',
components: { components: {
'ui-config': Config, 'ui-config': Config,
'ui-chart-page': ChartPage, 'ui-chart-page': ChartPage,
}, },
data() { data() {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
isActualImageSize: false,
runs: [],
running: true,
},
filteredTagsList: [],
};
},
computed: {
runsItems() {
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return { return {
runsArray: [], name: item,
tags: [], value: item,
config: {
groupNameReg: '.*',
isActualImageSize: false,
runs: [],
running: true,
},
filteredTagsList: [],
}; };
});
}, },
computed: { tagsList() {
runsItems() { let tags = this.tags;
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return {
name: item,
value: item,
};
});
},
tagsList() {
let tags = this.tags;
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart let runs = Object.keys(tags);
return allUniqTags.map((tag) => { let tagsArray = runs.map((run) => Object.keys(tags[run]));
let tagList = runs.map((run) => { let allUniqTags = uniq(flatten(tagsArray));
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
},
groupedTags() {
let tagsList = this.tagsList || [];
// put data in group
let groupData = {};
tagsList.forEach((item) => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = [];
groupData[group].push(item);
} else {
groupData[group].push(item);
}
});
// to array // get the data for every chart
let groups = Object.keys(groupData); return allUniqTags.map((tag) => {
return groups.map((group) => { let tagList = runs.map((run) => {
return { return {
group, run,
tags: groupData[group], tag: tags[run][tag],
}; };
}); }).filter((item) => item.tag !== undefined);
}, return {
filteredConfig() { tagList,
let tansformArr = ['isActualImageSize']; tag,
let config = this.config || {}; group: tag.split('/')[0],
let filteredConfig = {}; };
Object.keys(config).forEach((key) => { });
let val = config[key];
filteredConfig[key] = val;
});
return filteredConfig;
},
}, },
created() { groupedTags() {
getPluginImagesTags().then(({errno, data}) => { let tagsList = this.tagsList || [];
this.tags = data; // put data in group
let groupData = {};
// filter when inited tagsList.forEach((item) => {
let groupNameReg = this.config.groupNameReg; let group = item.group;
this.filterTagsList(groupNameReg); if (groupData[group] === undefined) {
}); groupData[group] = [];
groupData[group].push(item);
} else {
groupData[group].push(item);
}
});
getRuns().then(({errno, data}) => { // to array
this.runsArray = data; let groups = Object.keys(groupData);
this.config.runs = data; return groups.map((group) => {
}); return {
group,
tags: groupData[group],
};
});
}, },
mounted() { filteredConfig() {
autoAdjustHeight(); let tansformArr = ['isActualImageSize'];
let config = this.config || {};
let filteredConfig = {};
Object.keys(config).forEach((key) => {
let val = config[key];
filteredConfig[key] = val;
});
return filteredConfig;
}, },
watch: { },
'config.groupNameReg': function(val) { created() {
this.throttledFilterTagsList(); getPluginImagesTags().then(({errno, data}) => {
}, this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
getRuns().then(({errno, data}) => {
this.runsArray = data;
this.config.runs = data;
});
},
mounted() {
autoAdjustHeight();
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
}, },
methods: { },
filterTagsList(groupNameReg) { methods: {
if (!groupNameReg) { filterTagsList(groupNameReg) {
this.filteredTagsList = []; if (!groupNameReg) {
return; this.filteredTagsList = [];
} return;
let tagsList = this.tagsList || []; }
let regExp = new RegExp(groupNameReg); let tagsList = this.tagsList || [];
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag)); let regExp = new RegExp(groupNameReg);
}, this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
}, },
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
}; };
</script> </script>
......
...@@ -3,7 +3,7 @@ import {router} from 'san-router'; ...@@ -3,7 +3,7 @@ import {router} from 'san-router';
import Images from './Images'; import Images from './Images';
router.add({ router.add({
target: '#content', target: '#content',
rule: '/images', rule: '/images',
Component: Images, Component: Images,
}); });
...@@ -30,41 +30,41 @@ import Image from './Image'; ...@@ -30,41 +30,41 @@ import Image from './Image';
import {cloneDeep, flatten} from 'lodash'; import {cloneDeep, flatten} from 'lodash';
export default { export default {
props: ['config', 'runsItems', 'tagList', 'title'], props: ['config', 'runsItems', 'tagList', 'title'],
components: { components: {
'ui-image': Image, 'ui-image': Image,
'ui-expand-panel': ExpandPanel, 'ui-expand-panel': ExpandPanel,
},
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
}, },
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
},
filteredPageList() { filteredPageList() {
let list = this.filteredRunsList || []; let list = this.filteredRunsList || [];
return list.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize); return list.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
total() {
let list = this.filteredRunsList || [];
return list.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
}, },
data() { total() {
return { let list = this.filteredRunsList || [];
// current page return list.length;
currentPage: 1,
// item per page
pageSize: 8,
};
}, },
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
},
}; };
</script> </script>
<style lang="stylus"> <style lang="stylus">
......
...@@ -37,19 +37,19 @@ ...@@ -37,19 +37,19 @@
<script> <script>
export default { export default {
props: { props: {
runsItems: Array, runsItems: Array,
config: Object, config: Object,
}, },
data() { data() {
return { return {
}; };
}, },
methods: { methods: {
toggleAllRuns() { toggleAllRuns() {
this.config.running = !this.config.running; this.config.running = !this.config.running;
},
}, },
},
}; };
</script> </script>
......
...@@ -32,111 +32,111 @@ const defaultImgHeight = 300; ...@@ -32,111 +32,111 @@ const defaultImgHeight = 300;
const intervalTime = 30; const intervalTime = 30;
export default { export default {
props: ['tagInfo', 'isActualImageSize', 'runs', 'running', 'runsItems'], props: ['tagInfo', 'isActualImageSize', 'runs', 'running', 'runsItems'],
computed: { computed: {
steps() { steps() {
let data = this.data || []; let data = this.data || [];
return data.length - 1; return data.length - 1;
},
imageWidth() {
return this.isActualImageSize ? this.imgData.width : defaultImgWidth;
},
imageHeight() {
return this.isActualImageSize ? this.imgData.height : defaultImgHeight;
},
}, },
filters: { imageWidth() {
formatTime: function(value) { return this.isActualImageSize ? this.imgData.width : defaultImgWidth;
if (!value) {
return;
}
// The value was made in seconds, must convert it to milliseconds
let time = new Date(value * 1000);
let options = {
weekday: 'short', year: 'numeric', month: 'short',
day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit',
};
return time.toLocaleDateString('en-US', options);
},
}, },
data() { imageHeight() {
return { return this.isActualImageSize ? this.imgData.height : defaultImgHeight;
currentIndex: 0,
slider: {
value: '0',
label: '',
min: 0,
step: 1,
},
imgData: {},
data: [],
height: defaultImgHeight,
weight: defaultImgWidth,
};
},
created() {
this.getOriginChartsData();
}, },
mounted() { },
if (this.running) { filters: {
this.startInterval(); formatTime: function(value) {
} if (!value) {
return;
}
// The value was made in seconds, must convert it to milliseconds
let time = new Date(value * 1000);
let options = {
weekday: 'short', year: 'numeric', month: 'short',
day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit',
};
return time.toLocaleDateString('en-US', options);
}, },
},
data() {
return {
currentIndex: 0,
slider: {
value: '0',
label: '',
min: 0,
step: 1,
},
imgData: {},
data: [],
height: defaultImgHeight,
weight: defaultImgWidth,
};
},
created() {
this.getOriginChartsData();
},
mounted() {
if (this.running) {
this.startInterval();
}
},
beforeDestroy() { beforeDestroy() {
this.stopInterval(); this.stopInterval();
}, },
watch: { watch: {
running: function(val) { running: function(val) {
val ? this.startInterval() : this.stopInterval(); val ? this.startInterval() : this.stopInterval();
},
currentIndex: function(index) {
/* eslint-disable fecs-camelcase */
if (this.data && this.data[index]) {
let currentImgInfo = this.data ? this.data[index] : {};
let {height, width, query, step, wall_time} = currentImgInfo;
let url = '/data/plugin/images/individualImage?ts=' + wall_time;
let imgSrc = [url, query].join('&');
this.imgData = {
imgSrc,
height,
width,
step,
wall_time,
};
}
/* eslint-enable fecs-camelcase */
},
}, },
methods: { currentIndex: function(index) {
stopInterval() { /* eslint-disable fecs-camelcase */
clearInterval(this.getOringDataInterval); if (this.data && this.data[index]) {
}, let currentImgInfo = this.data ? this.data[index] : {};
// get origin data per {{intervalTime}} seconds let {height, width, query, step, wall_time} = currentImgInfo;
startInterval() { let url = '/data/plugin/images/individualImage?ts=' + wall_time;
this.getOringDataInterval = setInterval(() => { let imgSrc = [url, query].join('&');
this.getOriginChartsData(); this.imgData = {
}, intervalTime * 1000); imgSrc,
}, height,
getOriginChartsData() { width,
// let {run, tag} = this.tagInfo; step,
let run = this.tagInfo.run; wall_time,
let tag = this.tagInfo.tag; };
let {displayName, samples} = tag; }
let params = { /* eslint-enable fecs-camelcase */
run, },
tag: displayName, },
samples, methods: {
}; stopInterval() {
getPluginImagesImages(params).then(({status, data}) => { clearInterval(this.getOringDataInterval);
if (status === 0) { },
this.data = data; // get origin data per {{intervalTime}} seconds
this.currentIndex = data.length - 1; startInterval() {
} this.getOringDataInterval = setInterval(() => {
}); this.getOriginChartsData();
}, }, intervalTime * 1000);
},
getOriginChartsData() {
// let {run, tag} = this.tagInfo;
let run = this.tagInfo.run;
let tag = this.tagInfo.tag;
let {displayName, samples} = tag;
let params = {
run,
tag: displayName,
samples,
};
getPluginImagesImages(params).then(({status, data}) => {
if (status === 0) {
this.data = data;
this.currentIndex = data.length - 1;
}
});
}, },
},
}; };
</script> </script>
<style lang="stylus"> <style lang="stylus">
......
...@@ -7,17 +7,17 @@ import router from '@/router'; ...@@ -7,17 +7,17 @@ import router from '@/router';
Vue.config.productionTip = false; Vue.config.productionTip = false;
Vue.use(Vuetify, { Vue.use(Vuetify, {
theme: { theme: {
primary: '#008c99', primary: '#008c99',
accent: '#008c99', accent: '#008c99',
toolbox_icon: '#999999', toolbox_icon: '#999999',
}, },
}); });
/* eslint-disable no-new */ /* eslint-disable no-new */
new Vue({ new Vue({
el: '#root', el: '#root',
router, router,
components: {App}, components: {App},
template: '<App/>', template: '<App/>',
}); });
...@@ -37,120 +37,120 @@ import Config from './ui/Config'; ...@@ -37,120 +37,120 @@ import Config from './ui/Config';
import ChartPage from './ui/ChartPage'; import ChartPage from './ui/ChartPage';
export default { export default {
components: { components: {
'ui-config': Config, 'ui-config': Config,
'ui-chart-page': ChartPage, 'ui-chart-page': ChartPage,
}, },
data() { data() {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
smoothing: 0.6,
horizontal: 'step',
sortingMethod: 'default',
outlier: false,
runs: [],
running: true,
},
filteredTagsList: [],
};
},
computed: {
runsItems() {
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return { return {
runsArray: [], name: item,
tags: [], value: item,
config: {
groupNameReg: '.*',
smoothing: 0.6,
horizontal: 'step',
sortingMethod: 'default',
outlier: false,
runs: [],
running: true,
},
filteredTagsList: [],
}; };
});
}, },
computed: { tagsList() {
runsItems() { let tags = this.tags;
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return {
name: item,
value: item,
};
});
},
tagsList() {
let tags = this.tags;
let runs = Object.keys(tags); let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run])); let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray)); let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart // get the data for every chart
return allUniqTags.map((tag) => { return allUniqTags.map((tag) => {
let tagList = runs.map((run) => { let tagList = runs.map((run) => {
return { return {
run, run,
tag: tags[run][tag], tag: tags[run][tag],
}; };
}).filter((item) => item.tag !== undefined); }).filter((item) => item.tag !== undefined);
return { return {
tagList, tagList,
tag, tag,
group: tag.split('/')[0], group: tag.split('/')[0],
}; };
}); });
}, },
groupedTags() { groupedTags() {
let tagsList = this.tagsList || []; let tagsList = this.tagsList || [];
// put data in group // put data in group
let groupData = {}; let groupData = {};
tagsList.forEach((item) => { tagsList.forEach((item) => {
let group = item.group; let group = item.group;
if (groupData[group] === undefined) { if (groupData[group] === undefined) {
groupData[group] = []; groupData[group] = [];
groupData[group].push(item); groupData[group].push(item);
} else { } else {
groupData[group].push(item); groupData[group].push(item);
} }
}); });
// to array // to array
let groups = Object.keys(groupData); let groups = Object.keys(groupData);
return groups.map((group) => { return groups.map((group) => {
return { return {
group, group,
tags: groupData[group], tags: groupData[group],
}; };
}); });
},
}, },
created() { },
getPluginScalarsTags().then(({errno, data}) => { created() {
this.tags = data; getPluginScalarsTags().then(({errno, data}) => {
this.tags = data;
// filter when inited // filter when inited
let groupNameReg = this.config.groupNameReg; let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg); this.filterTagsList(groupNameReg);
}); });
getRuns().then(({errno, data}) => { getRuns().then(({errno, data}) => {
this.runsArray = data; this.runsArray = data;
this.config.runs = data; this.config.runs = data;
}); });
}, },
mounted() { mounted() {
autoAdjustHeight(); autoAdjustHeight();
}, },
watch: { watch: {
'config.groupNameReg': function(val) { 'config.groupNameReg': function(val) {
this.throttledFilterTagsList(); this.throttledFilterTagsList();
},
}, },
methods: { },
filterTagsList(groupNameReg) { methods: {
if (!groupNameReg) { filterTagsList(groupNameReg) {
this.filteredTagsList = []; if (!groupNameReg) {
return; this.filteredTagsList = [];
} return;
let tagsList = this.tagsList || []; }
let regExp = new RegExp(groupNameReg); let tagsList = this.tagsList || [];
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag)); let regExp = new RegExp(groupNameReg);
}, this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
}, },
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
}; };
</script> </script>
......
...@@ -3,13 +3,13 @@ import {router} from 'san-router'; ...@@ -3,13 +3,13 @@ import {router} from 'san-router';
import Scalar from './Scalars'; import Scalar from './Scalars';
router.add({ router.add({
target: '#content', target: '#content',
rule: '/', rule: '/',
Component: Scalar, Component: Scalar,
}); });
router.add({ router.add({
target: '#content', target: '#content',
rule: '/scalars', rule: '/scalars',
Component: Scalar, Component: Scalar,
}); });
此差异已折叠。
...@@ -34,42 +34,42 @@ import Chart from './Chart'; ...@@ -34,42 +34,42 @@ import Chart from './Chart';
import {cloneDeep} from 'lodash'; import {cloneDeep} from 'lodash';
export default { export default {
components: { components: {
'ui-chart': Chart, 'ui-chart': Chart,
'ui-expand-panel': ExpandPanel, 'ui-expand-panel': ExpandPanel,
// 'ui-pagination': Pagination // 'ui-pagination': Pagination
},
props: ['config', 'runsItems', 'tagList', 'title'],
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return list.slice().map((item) => {
item.tagList = item.tagList.filter((one) => runs.includes(one.run));
return item;
});
}, },
props: ['config', 'runsItems', 'tagList', 'title'], filteredTagList() {
computed: { let tagList = this.filteredRunsList || [];
filteredRunsList() { return tagList.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return list.slice().map((item) => {
item.tagList = item.tagList.filter((one) => runs.includes(one.run));
return item;
});
},
filteredTagList() {
let tagList = this.filteredRunsList || [];
return tagList.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
total() {
let tagList = this.tagList || [];
return tagList.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
}, },
data() { total() {
return { let tagList = this.tagList || [];
// current page return tagList.length;
currentPage: 1,
// item per page
pageSize: 8,
};
}, },
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
},
}; };
</script> </script>
<style lang="stylus"> <style lang="stylus">
......
...@@ -76,44 +76,44 @@ ...@@ -76,44 +76,44 @@
<script> <script>
export default { export default {
props: { props: {
runsItems: Array, runsItems: Array,
config: Object, config: Object,
}, },
data() { data() {
return { return {
horizontalItems: [ horizontalItems: [
{ {
name: 'Step', name: 'Step',
value: 'step', value: 'step',
}, },
{ {
name: 'Relative', name: 'Relative',
value: 'relative', value: 'relative',
}, },
{ {
name: 'Wall', name: 'Wall',
value: 'wall', value: 'wall',
},
],
sortingMethodItems: [
'default', 'descending', 'ascending', 'nearest',
],
smoothingValue: this.config.smoothing,
};
},
watch: {
smoothingValue: _.debounce(
function() {
this.config.smoothing = this.smoothingValue;
}, 50
),
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
}, },
],
sortingMethodItems: [
'default', 'descending', 'ascending', 'nearest',
],
smoothingValue: this.config.smoothing,
};
},
watch: {
smoothingValue: _.debounce(
function() {
this.config.smoothing = this.smoothingValue;
}, 50
),
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
}, },
},
}; };
</script> </script>
......
...@@ -38,126 +38,126 @@ import Config from './ui/Config'; ...@@ -38,126 +38,126 @@ import Config from './ui/Config';
import ChartPage from './ui/ChartPage'; import ChartPage from './ui/ChartPage';
export default { export default {
name: 'Texts', name: 'Texts',
components: { components: {
'ui-config': Config, 'ui-config': Config,
'ui-chart-page': ChartPage, 'ui-chart-page': ChartPage,
}, },
data() { data() {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
runs: [],
running: true,
},
filteredTagsList: [],
};
},
computed: {
runsItems() {
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return { return {
runsArray: [], name: item,
tags: [], value: item,
config: {
groupNameReg: '.*',
runs: [],
running: true,
},
filteredTagsList: [],
}; };
});
}, },
computed: { tagsList() {
runsItems() { let tags = this.tags;
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return {
name: item,
value: item,
};
});
},
tagsList() {
let tags = this.tags;
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart let runs = Object.keys(tags);
return allUniqTags.map((tag) => { let tagsArray = runs.map((run) => Object.keys(tags[run]));
let tagList = runs.map((run) => { let allUniqTags = uniq(flatten(tagsArray));
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
},
groupedTags() {
let tagsList = this.tagsList || [];
// put data in group
let groupData = {};
tagsList.forEach((item) => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = [];
groupData[group].push(item);
} else {
groupData[group].push(item);
}
});
// to array // get the data for every chart
let groups = Object.keys(groupData); return allUniqTags.map((tag) => {
return groups.map((group) => { let tagList = runs.map((run) => {
return { return {
group, run,
tags: groupData[group], tag: tags[run][tag],
}; };
}); }).filter((item) => item.tag !== undefined);
}, return {
filteredConfig() { tagList,
let config = this.config || {}; tag,
let filteredConfig = {}; group: tag.split('/')[0],
Object.keys(config).forEach((key) => { };
let val = config[key]; });
filteredConfig[key] = val;
});
return filteredConfig;
},
}, },
created() { groupedTags() {
getPluginTextsTags().then(({errno, data}) => { let tagsList = this.tagsList || [];
this.tags = data; // put data in group
let groupData = {};
// filter when inited tagsList.forEach((item) => {
let groupNameReg = this.config.groupNameReg; let group = item.group;
this.filterTagsList(groupNameReg); if (groupData[group] === undefined) {
}); groupData[group] = [];
groupData[group].push(item);
} else {
groupData[group].push(item);
}
});
getRuns().then(({errno, data}) => { // to array
this.runsArray = data; let groups = Object.keys(groupData);
this.config.runs = data; return groups.map((group) => {
}); return {
group,
tags: groupData[group],
};
});
}, },
mounted() { filteredConfig() {
autoAdjustHeight(); let config = this.config || {};
let filteredConfig = {};
Object.keys(config).forEach((key) => {
let val = config[key];
filteredConfig[key] = val;
});
return filteredConfig;
}, },
watch: { },
'config.groupNameReg': function(val) { created() {
this.throttledFilterTagsList(); getPluginTextsTags().then(({errno, data}) => {
}, this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
getRuns().then(({errno, data}) => {
this.runsArray = data;
this.config.runs = data;
});
},
mounted() {
autoAdjustHeight();
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
}, },
methods: { },
filterTagsList(groupNameReg) { methods: {
if (!groupNameReg) { filterTagsList(groupNameReg) {
this.filteredTagsList = []; if (!groupNameReg) {
return; this.filteredTagsList = [];
} return;
let tagsList = this.tagsList || []; }
let regExp = new RegExp(groupNameReg); let tagsList = this.tagsList || [];
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag)); let regExp = new RegExp(groupNameReg);
}, this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
}, },
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
}; };
</script> </script>
......
...@@ -3,7 +3,7 @@ import {router} from 'san-router'; ...@@ -3,7 +3,7 @@ import {router} from 'san-router';
import Texts from './Texts'; import Texts from './Texts';
router.add({ router.add({
target: '#content', target: '#content',
rule: '/texts', rule: '/texts',
Component: Texts, Component: Texts,
}); });
此差异已折叠。
...@@ -31,40 +31,40 @@ import Chart from './Chart'; ...@@ -31,40 +31,40 @@ import Chart from './Chart';
import {cloneDeep, flatten} from 'lodash'; import {cloneDeep, flatten} from 'lodash';
export default { export default {
components: { components: {
'ui-chart': Chart, 'ui-chart': Chart,
'ui-expand-panel': ExpandPanel, 'ui-expand-panel': ExpandPanel,
},
props: ['config', 'runsItems', 'tagList', 'title'],
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
}, },
props: ['config', 'runsItems', 'tagList', 'title'], filteredPageList() {
computed: { let list = this.filteredRunsList || [];
filteredRunsList() { return list.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
},
filteredPageList() {
let list = this.filteredRunsList || [];
return list.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
total() {
let tagList = this.tagList || [];
return tagList.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
}, },
data() { total() {
return { let tagList = this.tagList || [];
// current page return tagList.length;
currentPage: 1,
// item per page
pageSize: 8,
};
}, },
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
},
}; };
</script> </script>
<style lang="stylus"> <style lang="stylus">
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册