未验证 提交 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 @@
entry: flake8
language: system
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 = {
// override/add rules settings here, such as:
'vue/no-unused-vars': 'warn',
'max-len': ["warn", 120],
"vue/prop-name-casing": ["error"],
'vue/script-indent': 'error',
}
}
......@@ -73,6 +73,7 @@
"stylus": "^0.54.5",
"stylus-loader": "^3.0.1",
"url-loader": "^0.5.8",
"vue-eslint-parser": "^2.0.3",
"vue-jest": "^1.0.2",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
......
......@@ -11,22 +11,22 @@
import AppMenu from './common/component/AppMenu';
export default {
name: 'App',
components: {
AppMenu,
},
data() {
return {
initialRoute: 'scalars',
};
},
created() {
if (location.hash && location.hash != '#/') {
this.initialRoute = /(\#\/)(\w*)([?|&]{0,1})/.exec(location.hash)[2];
} else {
location.hash = '#/scalars';
}
},
name: 'App',
components: {
AppMenu,
},
data() {
return {
initialRoute: 'scalars',
};
},
created() {
if (location.hash && location.hash != '#/') {
this.initialRoute = /(\#\/)(\w*)([?|&]{0,1})/.exec(location.hash)[2];
} else {
location.hash = '#/scalars';
}
},
};
</script>
......
......@@ -38,127 +38,127 @@ import Config from './ui/Config';
import AudioPanelContainer from './ui/AudioPanelContainer';
export default {
name: 'Images',
components: {
'ui-config': Config,
'ui-audio-container': AudioPanelContainer,
},
data() {
name: 'Images',
components: {
'ui-config': Config,
'ui-audio-container': AudioPanelContainer,
},
data() {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
isActualImageSize: false,
runs: [],
running: true,
},
filteredTagsList: [],
};
},
computed: {
runsItems() {
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
isActualImageSize: false,
runs: [],
running: true,
},
filteredTagsList: [],
name: item,
value: item,
};
});
},
computed: {
runsItems() {
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));
tagsList() {
let tags = this.tags;
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
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);
}
});
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
filteredConfig() {
let config = this.config || {};
let filteredConfig = {};
Object.keys(config).forEach((key) => {
let val = config[key];
filteredConfig[key] = val;
});
return filteredConfig;
},
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
},
created() {
getPluginAudioTags().then(({errno, data}) => {
this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
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);
}
});
getRuns().then(({errno, data}) => {
this.runsArray = data;
this.config.runs = data;
});
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
mounted() {
autoAdjustHeight();
filteredConfig() {
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) {
this.throttledFilterTagsList();
},
},
created() {
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) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
};
</script>
......
......@@ -3,7 +3,7 @@ import {router} from 'san-router';
import Audio from './Audio';
router.add({
target: '#content',
rule: '/audio',
Component: Audio,
target: '#content',
rule: '/audio',
Component: Audio,
});
......@@ -31,99 +31,99 @@ import {getPluginAudioAudio} from '../../service';
const intervalTime = 30;
export default {
props: ['tagInfo', 'runs', 'running', 'runsItems'],
computed: {
steps() {
let data = this.data || [];
return data.length - 1;
},
props: ['tagInfo', 'runs', 'running', 'runsItems'],
computed: {
steps() {
let data = this.data || [];
return data.length - 1;
},
filters: {
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);
},
},
filters: {
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,
},
audioData: {},
data: [],
},
data() {
return {
currentIndex: 0,
slider: {
value: '0',
label: '',
min: 0,
step: 1,
},
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();
}, intervalTime * 1000);
},
mounted() {
if (this.running) {
this.startInterval();
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;
}
});
},
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>
<style lang="stylus">
......
......@@ -29,41 +29,41 @@ import AudioPanel from './AudioPanel';
import {cloneDeep, flatten} from 'lodash';
export default {
props: ['config', 'runsItems', 'tagList', 'title'],
components: {
'ui-audio': AudioPanel,
'ui-expand-panel': ExpandPanel,
props: ['config', 'runsItems', 'tagList', 'title'],
components: {
'ui-audio': AudioPanel,
'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() {
let list = this.filteredRunsList || [];
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);
},
filteredPageList() {
let list = this.filteredRunsList || [];
return list.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
total() {
let list = this.filteredRunsList || [];
return list.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
},
};
</script>
<style lang="stylus">
......
......@@ -32,19 +32,19 @@
<script>
export default {
props: {
runsItems: Array,
config: Object,
},
data() {
return {
};
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
props: {
runsItems: Array,
config: Object,
},
data() {
return {
};
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
},
};
</script>
......
......@@ -22,58 +22,58 @@
<script>
export default {
props: ['initialRoute'],
name: 'AppMenu',
data() {
return {
selected: this.initialRoute,
items: [
{
url: '/scalars',
title: 'SCALARS',
name: 'scalars',
},
{
url: '/images',
title: 'IMAGES',
name: 'images',
},
{
url: '/audio',
title: 'AUDIO',
name: 'audio',
},
{
url: '/histograms',
title: 'HISTOGRAMS',
name: 'histograms',
},
{
url: '/graphs',
title: 'GRAPHS',
name: 'graphs',
},
{
url: '/texts',
title: 'TEXTS',
name: 'texts',
},
/* // Hide the top menu
props: ['initialRoute'],
name: 'AppMenu',
data() {
return {
selected: this.initialRoute,
items: [
{
url: '/scalars',
title: 'SCALARS',
name: 'scalars',
},
{
url: '/images',
title: 'IMAGES',
name: 'images',
},
{
url: '/audio',
title: 'AUDIO',
name: 'audio',
},
{
url: '/histograms',
title: 'HISTOGRAMS',
name: 'histograms',
},
{
url: '/graphs',
title: 'GRAPHS',
name: 'graphs',
},
{
url: '/texts',
title: 'TEXTS',
name: 'texts',
},
/* // Hide the top menu
{
url: '/HighDimensional',
title: 'HighDimensional',
name: 'HighDimensional'
}
*/
],
};
},
methods: {
handleItemClick: function(item) {
this.selected = item.name;
this.$router.push(item.url);
},
],
};
},
methods: {
handleItemClick: function(item) {
this.selected = item.name;
this.$router.push(item.url);
},
},
};
</script>
......
......@@ -22,20 +22,20 @@
</template>
<script>
export default {
props: {
title: String,
info: Number,
},
computed: {
iconName() {
return this.isShow ? 'expand_less' : 'expand_more';
},
},
data() {
return {
isShow: true,
};
props: {
title: String,
info: Number,
},
computed: {
iconName() {
return this.isShow ? 'expand_less' : 'expand_more';
},
},
data() {
return {
isShow: true,
};
},
};
</script>
<style lang="stylus">
......
......@@ -11,10 +11,10 @@ const instances = [];
* @return {number} final top dist
*/
function calcTopDist(topDist = 16) {
for (let i = 0, len = instances.length; i < len; i++) {
topDist += (instances[i].vm.el.offsetHeight + 16);
}
return topDist;
for (let i = 0, len = instances.length; i < len; i++) {
topDist += (instances[i].vm.el.offsetHeight + 16);
}
return topDist;
}
/**
......@@ -24,28 +24,28 @@ function calcTopDist(topDist = 16) {
* @return {NotificationItem} instance
*/
const notification = function(options = {}) {
options.top = calcTopDist(options.offset);
const {onClose, onClick} = options;
delete options.onClick;
delete options.onClose;
delete options.offset;
const instance = {
vm: new NotificationItem({
data: options,
}),
id: `notification_${seed++}`,
};
options.top = calcTopDist(options.offset);
const {onClose, onClick} = options;
delete options.onClick;
delete options.onClose;
delete options.offset;
const instance = {
vm: new NotificationItem({
data: options,
}),
id: `notification_${seed++}`,
};
if (typeof onClick === 'function') {
instance.vm.on('itemClick', onClick);
}
instance.vm.on('close', () => {
notification.close(instance.id, onClose);
});
instance.vm.attach(document.body);
if (typeof onClick === 'function') {
instance.vm.on('itemClick', onClick);
}
instance.vm.on('close', () => {
notification.close(instance.id, onClose);
});
instance.vm.attach(document.body);
instances.push(instance);
return instance.vm;
instances.push(instance);
return instance.vm;
};
/**
......@@ -55,44 +55,44 @@ const notification = function(options = {}) {
* @param {Function} onClose cusmtom func
*/
notification.close = function(id, onClose) {
let index;
let removedHeight;
let len = instances.length;
for (let i = 0; i < len; i++) {
if (id === instances[i].id) {
if (typeof onClose === 'function') {
onClose(instances[i]);
}
index = i;
removedHeight = instances[i].vm.el.offsetHeight;
// distroy instance
instances[i].vm.dispose();
instances[i] = null;
// reomve instance fron instances
instances.splice(i, 1);
break;
}
let index;
let removedHeight;
let len = instances.length;
for (let i = 0; i < len; i++) {
if (id === instances[i].id) {
if (typeof onClose === 'function') {
onClose(instances[i]);
}
index = i;
removedHeight = instances[i].vm.el.offsetHeight;
// distroy instance
instances[i].vm.dispose();
instances[i] = null;
// reomve instance fron instances
instances.splice(i, 1);
break;
}
// change the left notification's height
if (len > 1) {
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`;
}
}
// change the left notification's height
if (len > 1) {
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
['success', 'warning', 'info', 'error'].forEach((type) => {
notification[type] = (options) => {
if (typeof options === 'string') {
options = {
message: options,
};
}
options = options || {};
options.type = type;
return notification(options);
};
notification[type] = (options) => {
if (typeof options === 'string') {
options = {
message: options,
};
}
options = options || {};
options.type = type;
return notification(options);
};
});
export default notification;
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 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;
containerLeftEl.style.height = containerHeight + 'px';
containerRightEl.style.height = containerHeight + 'px';
});
});
}
......@@ -3,19 +3,19 @@ import FileSaver from 'file-saver';
const aoaToSheet = XLSX.utils.aoa_to_sheet;
const saveAs = FileSaver.saveAs;
function s2ab(s) {
if (typeof ArrayBuffer !== 'undefined') {
let buf = new ArrayBuffer(s.length);
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);
if (typeof ArrayBuffer !== 'undefined') {
let buf = new ArrayBuffer(s.length);
let view = new Uint8Array(buf);
for (let i = 0; i !== s.length; ++i) {
buf[i] = s.charCodeAt(i) & 0xFF;
view[i] = s.charCodeAt(i) & 0xFF;
}
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) {
* @param {string} name filename
*/
export const generateXLSXandAutoDownload = function(data, name) {
let wopts = {
bookType: 'xlsx',
bookSST: false,
type: 'binary',
};
let ws = aoaToSheet(data);
let wb = {
SheetNames: ['Export'],
Sheets: {},
Props: {},
};
wb.Sheets.Export = ws;
let wbout = XLSX.write(wb, wopts);
saveAs(
new Blob(
[s2ab(wbout)],
{
type: 'application/octet-stream',
}
),
name + '.xlsx' || 'sheetjs.xlsx'
);
let wopts = {
bookType: 'xlsx',
bookSST: false,
type: 'binary',
};
let ws = aoaToSheet(data);
let wb = {
SheetNames: ['Export'],
Sheets: {},
Props: {},
};
wb.Sheets.Export = ws;
let wbout = XLSX.write(wb, wopts);
saveAs(
new Blob(
[s2ab(wbout)],
{
type: 'application/octet-stream',
}
),
name + '.xlsx' || 'sheetjs.xlsx'
);
};
/**
......@@ -58,13 +58,13 @@ export const generateXLSXandAutoDownload = function(data, name) {
* @param {string} name filename
*/
export const generateJsonAndDownload = function(data, name) {
saveAs(
new Blob(
[s2ab(JSON.stringify(data, null, ' '))],
{
type: 'application/octet-stream',
}
),
name + '.json' || 'json.json'
);
saveAs(
new Blob(
[s2ab(JSON.stringify(data, null, ' '))],
{
type: 'application/octet-stream',
}
),
name + '.json' || 'json.json'
);
};
......@@ -6,35 +6,35 @@ const STATUS = 'status';
const STATUSINFO = 'msg';
const instance = axios.create({
baseURL: '/',
timeout: 30000,
baseURL: '/',
timeout: 30000,
});
// for better ux, don't send the error msg because there will be too mutch error
const responseErrorStatus = (response) => {
const data = response.data;
// if (data[STATUS] !== 0) {
// Notification.error(data[STATUSINFO]);
// return Promise.reject(data);
// }
return data;
const data = response.data;
// if (data[STATUS] !== 0) {
// Notification.error(data[STATUSINFO]);
// return Promise.reject(data);
// }
return data;
};
// for better ux, don't send the error msg because there will be too mutch error
const responseNetError = (error) => {
// Notification.error('net error');
return Promise.reject(error);
// Notification.error('net error');
return Promise.reject(error);
};
// post from
const formInstance = axios.create({
baseURL: '/',
timeout: 3000,
transformRequest: [(data) => qs.stringify(data)],
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json,application/vnd.ms-excel',
},
baseURL: '/',
timeout: 3000,
transformRequest: [(data) => qs.stringify(data)],
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json,application/vnd.ms-excel',
},
});
......@@ -43,10 +43,10 @@ formInstance.interceptors.response.use(responseErrorStatus, responseNetError);
instance.interceptors.response.use(responseErrorStatus, responseNetError);
export const makeService = (url, opt = {method: 'get'}) => (params = {}) => {
if (opt.method === 'delete' || opt.method === 'get') {
params = {params};
}
return instance[opt.method](url, params);
if (opt.method === 'delete' || opt.method === 'get') {
params = {params};
}
return instance[opt.method](url, params);
};
export const makeFormService = (url, method = 'post') => (params = {}) => formInstance[method](url, params);
import quantile from './quantile';
export {
quantile,
quantile,
};
export default function(x) {
return x === null ? NaN : +x;
return x === null ? NaN : +x;
}
import number from './number';
export default function(values, p, valueof) {
if (valueof == null) {
return valueof = number;
}
let n = values.length;
if (!(n)) {
return;
}
if ((p = +p) <= 0 || n < 2) {
return +valueof(values[0], 0, values);
}
if (p >= 1) {
return +valueof(values[n - 1], n - 1, values);
}
let i = (n - 1) * p;
let i0 = Math.floor(i);
let value0 = +valueof(values[i0], i0, values);
let value1 = +valueof(values[i0 + 1], i0 + 1, values);
return value0 + (value1 - value0) * (i - i0);
if (valueof == null) {
return valueof = number;
}
let n = values.length;
if (!(n)) {
return;
}
if ((p = +p) <= 0 || n < 2) {
return +valueof(values[0], 0, values);
}
if (p >= 1) {
return +valueof(values[n - 1], n - 1, values);
}
let i = (n - 1) * p;
let i0 = Math.floor(i);
let value0 = +valueof(values[i0], i0, values);
let value1 = +valueof(values[i0 + 1], i0 + 1, values);
return value0 + (value1 - value0) * (i - i0);
}
import {router} from 'san-router';
export function routeTo(url, params = {}) {
let paramsArr = Object.keys(params).map((key) => `${key}=${params[key]}`);
let urlParams = (url.indexOf('?') > -1 ? '&' : '?') + paramsArr.join('&');
let paramsArr = Object.keys(params).map((key) => `${key}=${params[key]}`);
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';
export default {
components: {
'ui-config': Config,
'ui-chart': Chart,
components: {
'ui-config': Config,
'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',
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;
},
handleDownload() {
this.download = {fitScreen: true};
},
handleDownload() {
this.download = {fitScreen: true};
},
},
};
</script>
......
......@@ -3,7 +3,7 @@ import {router} from 'san-router';
import Graph from './Graph';
router.add({
target: '#content',
rule: '/graphs',
Component: Graph,
target: '#content',
rule: '/graphs',
Component: Graph,
});
......@@ -7,271 +7,271 @@
</template>
<script>
// libs
import echarts from 'echarts';
import {
dragMovelHandler,
tansformElement,
relativeMove,
} from './dragHelper';
// service
import {getPluginGraphsGraph} from '../../service';
// https://github.com/taye/interact.js
import interact from 'interactjs';
// for d3 drawing
import * as d3 from 'd3';
export default {
props: {
'fitScreen': {
type: Function,
required: true,
},
'download': {
type: Function,
required: true,
},
'scale': {
type: Number,
default: 1,
},
'curNode': {
type: Object,
default: {},
}},
computed: {
computedWidth() {
let scale = this.scale;
return Math.floor(scale * 2 * 700);
},
},
data() {
return {
myCY: null,
graphUrl: '',
};
},
watch: {
fitScreen: function(val) {
this.clearDragedTransform(this.getBigImgEl());
this.clearDragedTransform(this.getSmallImgDragHandler());
},
download: function(val) {
if (this.myCY) {
let aEl = document.createElement('a');
aEl.href = this.myCY.png();
aEl.download = 'graph.png';
aEl.click();
}
},
},
mounted() {
this.getOriginChartsData();
let chartScope = this;
getPluginGraphsGraph().then(({errno, data}) => {
let graphData = data.data;
// d3 svg drawing
let g = new dagreD3.graphlib.Graph()
.setGraph({})
.setDefaultEdgeLabel(function() {
return {};
});
// eslint-disable-next-line
import echarts from 'echarts';
import {
dragMovelHandler,
tansformElement,
relativeMove,
} from './dragHelper';
// service
import {getPluginGraphsGraph} from '../../service';
// https://github.com/taye/interact.js
import interact from 'interactjs';
// for d3 drawing
import * as d3 from 'd3';
export default {
props: {
'fitScreen': {
type: Function,
required: true,
},
'download': {
type: Function,
required: true,
},
'scale': {
type: Number,
default: 1,
},
'curNode': {
type: Object,
default: {},
}},
computed: {
computedWidth() {
let scale = this.scale;
return Math.floor(scale * 2 * 700);
},
},
data() {
return {
myCY: null,
graphUrl: '',
};
},
watch: {
fitScreen: function(val) {
this.clearDragedTransform(this.getBigImgEl());
this.clearDragedTransform(this.getSmallImgDragHandler());
},
download: function(val) {
if (this.myCY) {
let aEl = document.createElement('a');
aEl.href = this.myCY.png();
aEl.download = 'graph.png';
aEl.click();
}
},
},
mounted() {
this.getOriginChartsData();
let chartScope = this;
getPluginGraphsGraph().then(({errno, data}) => {
let graphData = data.data;
// d3 svg drawing
let g = new dagreD3.graphlib.Graph()
.setGraph({})
.setDefaultEdgeLabel(function() {
return {};
});
// eslint-disable-next-line
let render = new dagreD3.render();
let nodeKeys = [];
let buildInputNodeLabel = function(inputNode) {
// TODO(daming-lu): need more complex compound node
let nodeLabel = 'id: ' + inputNode['name'] + '\n'
+ 'type: ' + inputNode['data_type'] + '\n'
+ 'dims: ' + inputNode['shape'].join(' x ');
return nodeLabel;
};
// add input nodes
for (let i=0; i<graphData['input'].length; ++i) {
let curInputNode = graphData['input'][i];
let nodeKey = curInputNode['name'];
g.setNode(
nodeKey,
{
label: buildInputNodeLabel(curInputNode),
class: 'input',
style: 'stroke: #A3D39C; stroke-width: 3px; ' +
'stroke-dasharray: 5, 5;',
labelStyle: 'font-size: 0.8em;',
}
);
nodeKeys.push(nodeKey);
}
// add operator nodes then add edges from inputs to operator and from operator to output
for (let i=0; i<graphData['node'].length; ++i) {
let curOperatorNode = graphData['node'][i];
let nodeKey = 'opNode_' + i;
// add operator node
let curOpLabel = curOperatorNode['opType'];
g.setNode(
nodeKey,
{
label: curOpLabel + ' '.repeat(Math.floor(curOpLabel.length/5)),
class: 'operator',
style: 'opacity: 0.5;',
}
);
nodeKeys.push(nodeKey);
// add output node
let outputNodeKey = curOperatorNode['output'][0];
let outputPadding = ' '.repeat(Math.floor(outputNodeKey.length/2));
g.setNode(
outputNodeKey,
{
label: outputNodeKey + outputPadding,
class: 'output',
style: 'opacity: 0.5;' +
'stroke-width: 2px; ' +
'stroke-dasharray: 5, 5;',
shape: 'diamond',
}
);
nodeKeys.push(outputNodeKey);
// add edges from inputs to node and from node to output
for (let e=0; e<curOperatorNode['input'].length; ++e) {
g.setEdge(curOperatorNode['input'][e], nodeKey);
}
g.setEdge(nodeKey, curOperatorNode['output'][0]);
}
// TODO(daming-lu): add prettier styles to diff nodes
let svg = d3.select('svg')
.attr('font-family', 'sans-serif')
.attr('font-size', '28px');
render(d3.select('svg g'), g);
// 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.selectAll('.node').on('click', function(d, i) {
chartScope.curNode = g.node(d);
let nodeType = chartScope.curNode.class;
let nodeInfo = null;
if (nodeType === 'operator') {
let opIndex = d.slice(7); // remove prefix "opNode_"
nodeInfo = graphData.node[opIndex];
} else if (nodeType === 'input') {
nodeInfo = graphData.input[d-1];
} else {
nodeInfo = 'output';
}
chartScope.$emit('curNodeUpdated',
{
'nodeType': nodeType,
'nodeInfo': nodeInfo,
});
});
});
let nodeKeys = [];
let buildInputNodeLabel = function(inputNode) {
// TODO(daming-lu): need more complex compound node
let nodeLabel = 'id: ' + inputNode['name'] + '\n'
+ 'type: ' + inputNode['data_type'] + '\n'
+ 'dims: ' + inputNode['shape'].join(' x ');
return nodeLabel;
};
// add input nodes
for (let i=0; i<graphData['input'].length; ++i) {
let curInputNode = graphData['input'][i];
let nodeKey = curInputNode['name'];
g.setNode(
nodeKey,
{
label: buildInputNodeLabel(curInputNode),
class: 'input',
style: 'stroke: #A3D39C; stroke-width: 3px; ' +
'stroke-dasharray: 5, 5;',
labelStyle: 'font-size: 0.8em;',
}
);
nodeKeys.push(nodeKey);
}
// add operator nodes then add edges from inputs to operator and from operator to output
for (let i=0; i<graphData['node'].length; ++i) {
let curOperatorNode = graphData['node'][i];
let nodeKey = 'opNode_' + i;
// add operator node
let curOpLabel = curOperatorNode['opType'];
g.setNode(
nodeKey,
{
label: curOpLabel + ' '.repeat(Math.floor(curOpLabel.length/5)),
class: 'operator',
style: 'opacity: 0.5;',
}
);
nodeKeys.push(nodeKey);
// add output node
let outputNodeKey = curOperatorNode['output'][0];
let outputPadding = ' '.repeat(Math.floor(outputNodeKey.length/2));
g.setNode(
outputNodeKey,
{
label: outputNodeKey + outputPadding,
class: 'output',
style: 'opacity: 0.5;' +
'stroke-width: 2px; ' +
'stroke-dasharray: 5, 5;',
shape: 'diamond',
}
);
nodeKeys.push(outputNodeKey);
// add edges from inputs to node and from node to output
for (let e=0; e<curOperatorNode['input'].length; ++e) {
g.setEdge(curOperatorNode['input'][e], nodeKey);
}
g.setEdge(nodeKey, curOperatorNode['output'][0]);
}
// TODO(daming-lu): add prettier styles to diff nodes
let svg = d3.select('svg')
.attr('font-family', 'sans-serif')
.attr('font-size', '28px');
render(d3.select('svg g'), g);
// 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.selectAll('.node').on('click', function(d, i) {
chartScope.curNode = g.node(d);
let nodeType = chartScope.curNode.class;
let nodeInfo = null;
if (nodeType === 'operator') {
let opIndex = d.slice(7); // remove prefix "opNode_"
nodeInfo = graphData.node[opIndex];
} else if (nodeType === 'input') {
nodeInfo = graphData.input[d-1];
} else {
nodeInfo = 'output';
}
chartScope.$emit('curNodeUpdated',
{
'nodeType': nodeType,
'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() {
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);
});
},
});
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);
});
},
});
},
});
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);
});
},
});
},
},
};
</script>
<style lang="stylus">
.node rect
......
......@@ -54,15 +54,15 @@
<script>
export default {
props: ['config', 'curNode'],
methods: {
handleFitScreen() {
this.$emit('fitScreen');
},
handleDownload() {
this.$emit('download');
},
props: ['config', 'curNode'],
methods: {
handleFitScreen() {
this.$emit('fitScreen');
},
handleDownload() {
this.$emit('download');
},
},
};
</script>
<style lang="stylus">
......
export const dragMovelHandler = (event, callback) => {
let target = event.target;
// keep the dragged position in the data-x/data-y attributes
let x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
let y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
callback(target, x, y);
let target = event.target;
// keep the dragged position in the data-x/data-y attributes
let x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
let y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
callback(target, x, y);
};
export const tansformElement = (target, x, y) => {
// translate the element
target.style.webkitTransform = target.style.transform
// translate the element
target.style.webkitTransform = target.style.transform
= 'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
};
export const relativeMove = ({triggerEl, x, y}, relativeEl) => {
let {offsetWidth: tWidth, offsetHeight: tHeight} = triggerEl;
let {offsetWidth: rWidth, offsetHeight: rHeight} = relativeEl;
let {offsetWidth: tWidth, offsetHeight: tHeight} = triggerEl;
let {offsetWidth: rWidth, offsetHeight: rHeight} = relativeEl;
let rX = (x / tWidth) * rWidth;
let rY = (y / tHeight) * rHeight;
let rX = (x / tWidth) * rWidth;
let rY = (y / tHeight) * rHeight;
tansformElement(relativeEl, -rX, -rY);
tansformElement(relativeEl, -rX, -rY);
};
......@@ -26,56 +26,56 @@ import Config from './ui/Config';
import Chart from './ui/Chart';
export default {
components: {
'ui-config': Config,
'ui-chart': Chart,
components: {
'ui-config': Config,
'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',
data() {
return {
config: {
searchText: '',
displayWordLabel: true,
dimension: '2',
reduction: 'tsne',
running: true,
},
embedding_data: [],
};
'config.reduction': function(val) {
this.fetchDatasets();
},
created() {
this.fetchDatasets();
},
watch: {
'config.dimension': function(val) {
this.fetchDatasets();
},
'config.reduction': function(val) {
this.fetchDatasets();
},
},
mounted() {
autoAdjustHeight();
},
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;
},
mounted() {
autoAdjustHeight();
},
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 ++) {
vector_data[i].push(labels[i]);
}
for ( let i = 0; i < vector_data.length; i ++) {
vector_data[i].push(labels[i]);
}
this.embedding_data = vector_data;
});
},
this.embedding_data = vector_data;
});
},
},
};
</script>
......
......@@ -14,179 +14,179 @@ import echarts from 'echarts';
import 'echarts-gl';
export default {
props: ['config', 'displayWordLabel', 'searchText', 'embedding_data', 'dimension'],
data() {
return {
width: 900,
height: 600,
};
props: ['config', 'displayWordLabel', 'searchText', 'embedding_data', 'dimension'],
data() {
return {
width: 900,
height: 600,
};
},
computed: {
computedStyle() {
return 'height:' + this.height + 'px;' +
'width:' + this.width + 'px;';
},
computed: {
computedStyle() {
return 'height:' + this.height + 'px;' +
'width:' + this.width + 'px;';
},
},
created() {},
mounted() {
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.setDisplayWordLabel();
} else {
this.set3DChartOptions();
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.setDisplayWordLabel();
} else {
this.set3DChartOptions();
this.setDisplayWordLabel();
}
},
searchText: function(val) {
// Filter the data that has the hasPrefix
let matched_words = [];
if (val != '') {
val = val.toLowerCase();
searchText: function(val) {
// Filter the data that has the hasPrefix
let matched_words = [];
if (val != '') {
val = val.toLowerCase();
function hasPrefix(value) {
let word = value[value.length - 1];
return (typeof word == 'string' && word.toLowerCase().startsWith(val));
}
function hasPrefix(value) {
let word = value[value.length - 1];
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
this.myChart.setOption({
series: [{
// Grab the 'matched' series data
name: 'matched',
data: matched_words,
}],
});
},
// Update the matched series data
this.myChart.setOption({
series: [{
// Grab the 'matched' series data
name: 'matched',
data: matched_words,
}],
});
},
methods: {
createChart() {
// Initialize the eChartBox
let el = this.$refs.chartBox;
this.myChart = echarts.init(el);
},
set2DChartOptions() {
let typeD = 'normal';
let option = {
xAxis: {},
yAxis: {},
series: [{
name: 'all',
symbolSize: 10,
data: this.embedding_data,
type: 'scatter',
},
{
name: 'matched',
animation: false,
symbolSize: 10,
data: [],
itemStyle: {
normal: {
opacity: 1,
},
},
label: {
normal: {
show: true,
formatter: function(param) {
return param.data[param.data.length - 1];
},
position: 'top',
},
},
type: 'scatter',
},
],
};
this.myChart.setOption(option);
},
set3DChartOptions() {
let symbolSize = 2.5;
let option3d = {
grid3D: {},
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);
},
methods: {
createChart() {
// Initialize the eChartBox
let el = this.$refs.chartBox;
this.myChart = echarts.init(el);
},
set2DChartOptions() {
let typeD = 'normal';
let option = {
xAxis: {},
yAxis: {},
series: [{
name: 'all',
symbolSize: 10,
data: this.embedding_data,
type: 'scatter',
},
{
name: 'matched',
animation: false,
symbolSize: 10,
data: [],
itemStyle: {
normal: {
opacity: 1,
},
},
label: {
normal: {
show: true,
formatter: function(param) {
return param.data[param.data.length - 1];
},
position: 'top',
},
},
type: 'scatter',
},
],
};
this.myChart.setOption(option);
},
set3DChartOptions() {
let symbolSize = 2.5;
let option3d = {
grid3D: {},
xAxis3D: {
type: 'category',
},
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,
},
},
}],
});
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() {
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>
......
......@@ -54,19 +54,19 @@
<script>
export default {
props: {
runsItems: Array,
config: Object,
},
data() {
return {
};
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
props: {
runsItems: Array,
config: Object,
},
data() {
return {
};
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
},
};
</script>
......
......@@ -35,118 +35,118 @@ import {debounce, flatten, uniq} from 'lodash';
import autoAdjustHeight from '../common/util/autoAdjustHeight';
export default {
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
},
computed: {
runsItems() {
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return {
name: item,
value: item,
};
});
},
computed: {
runsItems() {
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return {
name: item,
value: item,
};
});
},
tagsList() {
let tags = this.tags;
tagsList() {
let tags = this.tags;
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
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
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
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
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
},
data() {
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
horizontal: 'step',
chartType: 'offset',
runs: [],
running: true,
},
filteredTagsList: [],
tagList,
tag,
group: tag.split('/')[0],
};
});
},
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;
});
},
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);
}
});
mounted() {
autoAdjustHeight();
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
},
},
data() {
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) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
let filtedTagsList = tagsList.filter((item) => regExp.test(item.tag));
this.filteredTagsList = filtedTagsList;
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
let filtedTagsList = tagsList.filter((item) => regExp.test(item.tag));
this.filteredTagsList = filtedTagsList;
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
};
</script>
......
import {min, max, range} from 'lodash';
export function tansformBackendData(histogramData) {
let [time, step, items] = histogramData;
return {
time,
step,
min: min(items.map(([left, right, count]) => left)),
max: max(items.map(([left, right, count]) => right)),
items: items.map(([left, right, count]) => ({left, right, count})),
};
let [time, step, items] = histogramData;
return {
time,
step,
min: min(items.map(([left, right, count]) => left)),
max: max(items.map(([left, right, count]) => right)),
items: items.map(([left, right, count]) => ({left, right, count})),
};
}
export function computeNewHistogram(histogram, min, max, binsNum = 30) {
if (max === min) {
// Create bins even if all the data has a single value.
max = min * 1.1 + 1;
min = min / 1.1 - 1;
if (max === min) {
// Create bins even if all the data has a single value.
max = 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;
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};
});
return {x: binLeft, dx: stepWidth, y: yValue};
});
}
export function tansformToVisData(tempData, time, step) {
return tempData.map(function(dataItem) {
return [time, step, dataItem.x + dataItem.dx / 2, Math.floor(dataItem.y)];
});
return tempData.map(function(dataItem) {
return [time, step, dataItem.x + dataItem.dx / 2, Math.floor(dataItem.y)];
});
}
export function originDataToChartData(originData) {
let tempData = originData.map(tansformBackendData);
let globalMin = min(tempData.map(({min}) => min));
let globalMax = max(tempData.map(({max}) => max));
let chartData = tempData.map(function(item) {
let histoBins = computeNewHistogram(item, globalMin, globalMax);
let {time, step} = item;
return {
time,
step,
items: tansformToVisData(histoBins, time, step),
};
});
let tempData = originData.map(tansformBackendData);
let globalMin = min(tempData.map(({min}) => min));
let globalMax = max(tempData.map(({max}) => max));
let chartData = tempData.map(function(item) {
let histoBins = computeNewHistogram(item, globalMin, globalMax);
let {time, step} = item;
return {
min: globalMin,
max: globalMax,
chartData,
time,
step,
items: tansformToVisData(histoBins, time, step),
};
});
return {
min: globalMin,
max: globalMax,
chartData,
};
}
......@@ -3,7 +3,7 @@ import {router} from 'san-router';
import Histogram from './Histogram';
router.add({
target: '#content',
rule: '/histograms',
Component: Histogram,
target: '#content',
rule: '/histograms',
Component: Histogram,
});
此差异已折叠。
......@@ -31,50 +31,50 @@ import Chart from './Chart';
import {cloneDeep, flatten} from 'lodash';
export default {
props: ['config', 'runsItems', 'tagList', 'title'],
props: ['config', 'runsItems', 'tagList', 'title'],
components: {
'ui-chart': Chart,
'ui-expand-panel': ExpandPanel,
components: {
'ui-chart': Chart,
'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() {
let list = this.filteredRunsList;
let currentPage = this.currentPage;
let pageSize = this.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);
},
filteredPageList() {
let list = this.filteredRunsList;
let currentPage = this.currentPage;
let pageSize = this.pageSize;
return list.slice((currentPage - 1) * pageSize, currentPage * pageSize);
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 4,
};
total() {
let list = this.filteredRunsList || [];
return list.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 4,
};
},
methods: {
handlePageChange({pageNum}) {
this.currentPage = pageNum;
},
methods: {
handlePageChange({pageNum}) {
this.currentPage = pageNum;
},
},
};
</script>
<style lang="stylus">
......
......@@ -42,27 +42,27 @@
</template>
<script>
export default {
props: ['config', 'runsItems'],
data() {
return {
chartTypeItems: [
{
name: 'Overlay',
value: 'overlay',
},
{
name: 'Offset',
value: 'offset',
},
],
};
},
methods: {
toggleAllRuns() {
let running = this.config.running;
this.config.running = !running;
props: ['config', 'runsItems'],
data() {
return {
chartTypeItems: [
{
name: 'Overlay',
value: 'overlay',
},
{
name: 'Offset',
value: 'offset',
},
],
};
},
methods: {
toggleAllRuns() {
let running = this.config.running;
this.config.running = !running;
},
},
};
</script>
<style lang="stylus">
......
......@@ -38,128 +38,128 @@ import Config from './ui/Config';
import ChartPage from './ui/ChartPage';
export default {
name: 'Images',
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
},
data() {
name: 'Images',
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
},
data() {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
isActualImageSize: false,
runs: [],
running: true,
},
filteredTagsList: [],
};
},
computed: {
runsItems() {
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
isActualImageSize: false,
runs: [],
running: true,
},
filteredTagsList: [],
name: item,
value: item,
};
});
},
computed: {
runsItems() {
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));
tagsList() {
let tags = this.tags;
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
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);
}
});
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
filteredConfig() {
let tansformArr = ['isActualImageSize'];
let config = this.config || {};
let filteredConfig = {};
Object.keys(config).forEach((key) => {
let val = config[key];
filteredConfig[key] = val;
});
return filteredConfig;
},
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
},
created() {
getPluginImagesTags().then(({errno, data}) => {
this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
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);
}
});
getRuns().then(({errno, data}) => {
this.runsArray = data;
this.config.runs = data;
});
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
mounted() {
autoAdjustHeight();
filteredConfig() {
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) {
this.throttledFilterTagsList();
},
},
created() {
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) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
};
</script>
......
......@@ -3,7 +3,7 @@ import {router} from 'san-router';
import Images from './Images';
router.add({
target: '#content',
rule: '/images',
Component: Images,
target: '#content',
rule: '/images',
Component: Images,
});
......@@ -30,41 +30,41 @@ import Image from './Image';
import {cloneDeep, flatten} from 'lodash';
export default {
props: ['config', 'runsItems', 'tagList', 'title'],
components: {
'ui-image': Image,
'ui-expand-panel': ExpandPanel,
props: ['config', 'runsItems', 'tagList', 'title'],
components: {
'ui-image': Image,
'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() {
let list = this.filteredRunsList || [];
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);
},
filteredPageList() {
let list = this.filteredRunsList || [];
return list.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
total() {
let list = this.filteredRunsList || [];
return list.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
},
};
</script>
<style lang="stylus">
......
......@@ -37,19 +37,19 @@
<script>
export default {
props: {
runsItems: Array,
config: Object,
},
data() {
return {
};
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
props: {
runsItems: Array,
config: Object,
},
data() {
return {
};
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
},
};
</script>
......
......@@ -32,111 +32,111 @@ const defaultImgHeight = 300;
const intervalTime = 30;
export default {
props: ['tagInfo', 'isActualImageSize', 'runs', 'running', 'runsItems'],
computed: {
steps() {
let data = this.data || [];
return data.length - 1;
},
imageWidth() {
return this.isActualImageSize ? this.imgData.width : defaultImgWidth;
},
imageHeight() {
return this.isActualImageSize ? this.imgData.height : defaultImgHeight;
},
props: ['tagInfo', 'isActualImageSize', 'runs', 'running', 'runsItems'],
computed: {
steps() {
let data = this.data || [];
return data.length - 1;
},
filters: {
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);
},
imageWidth() {
return this.isActualImageSize ? this.imgData.width : defaultImgWidth;
},
data() {
return {
currentIndex: 0,
slider: {
value: '0',
label: '',
min: 0,
step: 1,
},
imgData: {},
data: [],
height: defaultImgHeight,
weight: defaultImgWidth,
};
},
created() {
this.getOriginChartsData();
imageHeight() {
return this.isActualImageSize ? this.imgData.height : defaultImgHeight;
},
mounted() {
if (this.running) {
this.startInterval();
}
},
filters: {
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() {
this.stopInterval();
},
beforeDestroy() {
this.stopInterval();
},
watch: {
running: function(val) {
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 */
},
watch: {
running: function(val) {
val ? this.startInterval() : this.stopInterval();
},
methods: {
stopInterval() {
clearInterval(this.getOringDataInterval);
},
// get origin data per {{intervalTime}} seconds
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;
}
});
},
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: {
stopInterval() {
clearInterval(this.getOringDataInterval);
},
// get origin data per {{intervalTime}} seconds
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>
<style lang="stylus">
......
......@@ -7,17 +7,17 @@ import router from '@/router';
Vue.config.productionTip = false;
Vue.use(Vuetify, {
theme: {
primary: '#008c99',
accent: '#008c99',
toolbox_icon: '#999999',
},
theme: {
primary: '#008c99',
accent: '#008c99',
toolbox_icon: '#999999',
},
});
/* eslint-disable no-new */
new Vue({
el: '#root',
router,
components: {App},
template: '<App/>',
el: '#root',
router,
components: {App},
template: '<App/>',
});
......@@ -37,120 +37,120 @@ import Config from './ui/Config';
import ChartPage from './ui/ChartPage';
export default {
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
},
data() {
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
},
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 {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
smoothing: 0.6,
horizontal: 'step',
sortingMethod: 'default',
outlier: false,
runs: [],
running: true,
},
filteredTagsList: [],
name: item,
value: item,
};
});
},
computed: {
runsItems() {
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return {
name: item,
value: item,
};
});
},
tagsList() {
let tags = this.tags;
tagsList() {
let tags = this.tags;
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
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
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
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);
}
});
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
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
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
created() {
getPluginScalarsTags().then(({errno, data}) => {
this.tags = data;
},
created() {
getPluginScalarsTags().then(({errno, data}) => {
this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
// 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();
},
getRuns().then(({errno, data}) => {
this.runsArray = data;
this.config.runs = data;
});
},
mounted() {
autoAdjustHeight();
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
};
</script>
......
......@@ -3,13 +3,13 @@ import {router} from 'san-router';
import Scalar from './Scalars';
router.add({
target: '#content',
rule: '/',
Component: Scalar,
target: '#content',
rule: '/',
Component: Scalar,
});
router.add({
target: '#content',
rule: '/scalars',
Component: Scalar,
target: '#content',
rule: '/scalars',
Component: Scalar,
});
此差异已折叠。
......@@ -34,42 +34,42 @@ import Chart from './Chart';
import {cloneDeep} from 'lodash';
export default {
components: {
'ui-chart': Chart,
'ui-expand-panel': ExpandPanel,
// 'ui-pagination': Pagination
components: {
'ui-chart': Chart,
'ui-expand-panel': ExpandPanel,
// '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'],
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;
});
},
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);
},
filteredTagList() {
let tagList = this.filteredRunsList || [];
return tagList.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
total() {
let tagList = this.tagList || [];
return tagList.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
},
};
</script>
<style lang="stylus">
......
......@@ -76,44 +76,44 @@
<script>
export default {
props: {
runsItems: Array,
config: Object,
},
data() {
return {
horizontalItems: [
{
name: 'Step',
value: 'step',
},
{
name: 'Relative',
value: 'relative',
},
{
name: '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;
props: {
runsItems: Array,
config: Object,
},
data() {
return {
horizontalItems: [
{
name: 'Step',
value: 'step',
},
{
name: 'Relative',
value: 'relative',
},
{
name: '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;
},
},
};
</script>
......
......@@ -38,126 +38,126 @@ import Config from './ui/Config';
import ChartPage from './ui/ChartPage';
export default {
name: 'Texts',
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
},
data() {
name: 'Texts',
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
},
data() {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
runs: [],
running: true,
},
filteredTagsList: [],
};
},
computed: {
runsItems() {
let runsArray = this.runsArray || [];
return runsArray.map((item) => {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
runs: [],
running: true,
},
filteredTagsList: [],
name: item,
value: item,
};
});
},
computed: {
runsItems() {
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));
tagsList() {
let tags = this.tags;
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
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);
}
});
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
filteredConfig() {
let config = this.config || {};
let filteredConfig = {};
Object.keys(config).forEach((key) => {
let val = config[key];
filteredConfig[key] = val;
});
return filteredConfig;
},
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
},
created() {
getPluginTextsTags().then(({errno, data}) => {
this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
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);
}
});
getRuns().then(({errno, data}) => {
this.runsArray = data;
this.config.runs = data;
});
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
mounted() {
autoAdjustHeight();
filteredConfig() {
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) {
this.throttledFilterTagsList();
},
},
created() {
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) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
};
</script>
......
......@@ -3,7 +3,7 @@ import {router} from 'san-router';
import Texts from './Texts';
router.add({
target: '#content',
rule: '/texts',
Component: Texts,
target: '#content',
rule: '/texts',
Component: Texts,
});
此差异已折叠。
......@@ -31,40 +31,40 @@ import Chart from './Chart';
import {cloneDeep, flatten} from 'lodash';
export default {
components: {
'ui-chart': Chart,
'ui-expand-panel': ExpandPanel,
components: {
'ui-chart': Chart,
'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'],
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() {
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);
},
filteredPageList() {
let list = this.filteredRunsList || [];
return list.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
total() {
let tagList = this.tagList || [];
return tagList.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
},
};
</script>
<style lang="stylus">
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册