|
- <!--
- Copyright 2020 Huawei Technologies Co., Ltd.All Rights Reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
- <template>
- <div class="cl-slickgrid-container">
- <div class="data-show-container">
- <div v-show="incorrectData"
- class="error-msg-container">
- {{$t('components.gridIncorrectDataError')}}
- </div>
- <div v-show="!incorrectData && requestError"
- class="error-msg-container">
- {{errorMsg}}
- </div>
- <div v-show="!fullData.length && updated && !incorrectData && !requestError"
- class="error-msg-container">
- {{$t('components.gridTableNoData')}}
- </div>
- <div :id="itemId"
- v-show="!!fullData.length && !incorrectData"
- class="grid-item"></div>
- </div>
- <div class="operate-container"
- v-if="showOperate && (fullData.length || requestError)">
- <div class="filter-container"
- v-if="showFilterInput"
- @keyup.enter="filterChange">
- <div class="filter-input-title">{{$t('components.dimsFilterInputTitle')}}
- <span :title="$t('components.dimsFilterInputTip')"
- class="el-icon-warning"></span>
- </div>
- <div v-for="(item, itemIndex) in filterArr"
- :key="itemIndex">
- <el-input class="filter-input long-input"
- :class="item.showError ? 'error-border' : ''"
- v-model="item.model"></el-input>
- <span class="input-behind"
- v-if="itemIndex === filterArr.length - 1">{{$t('symbols.slashes')}}</span>
- <span class="input-behind"
- v-else>{{$t('symbols.point')}}</span>
- </div>
- <el-button class="filter-check"
- size="mini"
- v-if="!!filterArr.length"
- @click="filterChange">
- <i class="el-icon-check"></i>
- </el-button>
- <span class="filter-incorrect-text"
- v-if="!filterCorrect">{{$t('components.inCorrectInput')}}</span>
- </div>
- <div class="shape-wrap">
- <span>{{ $t('tensors.dimension') }} {{ shape }}</span>
- </div>
- <div class="accuracy-container">
- {{$t('components.gridAccuracy')}}<el-select v-model="accuracy"
- class="select-item"
- @change="accuracyChange">
- <el-option v-for="item in accuracyArr"
- :key="item.label"
- :label="item.label"
- :value="item.value"></el-option>
- </el-select>
- </div>
- </div>
- </div>
- </template>
-
- <script>
- import 'slickgrid/css/smoothness/jquery-ui-1.11.3.custom.css';
- import 'slickgrid/slick.grid.css';
- import 'slickgrid/lib/jquery-3.1.0';
- import 'slickgrid/lib/jquery-ui-1.9.2';
- import 'slickgrid/lib/jquery.event.drag-2.3.0.js';
- import 'slickgrid/slick.core.js';
- import 'slickgrid/slick.dataview.js';
- import 'slickgrid/slick.grid.js';
- export default {
- props: {
- // Table data
- fullData: {
- type: Array,
- default() {
- return [];
- },
- },
- // Display operation Bar
- showOperate: {
- type: Boolean,
- default: true,
- },
- showFilterInput: {
- type: Boolean,
- default: true,
- },
- // Display full screen
- fullScreen: {
- type: Boolean,
- default: false,
- },
- gridType: {
- type: String,
- default: 'value',
- },
- },
- data() {
- return {
- itemId: '', // Dom id
- gridObj: null, // Slickgrid object
- columnsData: [], // Column information
- columnsLength: 0, // Column length
- filterArr: [], // Dimension selection array
- formateData: [], // Formatted data
- formateArr: [], // Formatted array
- statistics: {}, // Object contain maximun and minimun
- accuracy: 10, // Accuracy value
- incorrectData: false, // Wheather the dimension is correctly selected
- updated: false, // Updated
- scrollTop: false, // Wheather scroll to the top
- filterCorrect: true, // Wheather the dimension input is correct
- requestError: false, // Exceeded the specification
- errorMsg: '', // Error message
- viewResizeFlag: false, // Size reset flag
- // Accuray options
- accuracyArr: [
- {label: 0, value: 0},
- {label: 1, value: 1},
- {label: 2, value: 2},
- {label: 3, value: 3},
- {label: 4, value: 4},
- {label: 5, value: 5},
- {label: 6, value: 6},
- {label: 7, value: 7},
- {label: 8, value: 8},
- {label: 9, value: 9},
- {label: 10, value: 10},
- ],
- // Table configuration items
- optionObj: {
- enableColumnReorder: false,
- enableCellNavigation: true,
- frozenColumn: 0,
- frozenRow: 0,
- },
- gridTypeKeys: {
- value: 'value',
- compare: 'compare',
- },
- tableStartIndex: {
- rowStartIndex: 0,
- colStartIndex: 0,
- },
- shape: '',
- };
- },
- computed: {},
- watch: {
- showFilterInput(newValue, oldValue) {
- this.resizeView();
- },
- },
- mounted() {
- this.init();
- },
- methods: {
- /**
- * Initialize
- */
- init() {
- this.itemId = `${new Date().getTime()}` + `${this.$store.state.componentsCount}`;
- this.$store.commit('componentsNum');
- },
- /**
- * Initialize dimension selection
- * @param {Array} dimension Dimension array
- * @param {String} filterStr Dimension String
- */
- initializeFilterArr(dimension, filterStr) {
- this.filterCorrect = true;
- if (!filterStr) {
- this.filterArr = [];
- return;
- }
- const tempFilterArr = filterStr.slice(1, filterStr.length - 1).split(',');
- const tempArr = [];
- const multiDimsArr = [];
- for (let i = 0; i < tempFilterArr.length; i++) {
- tempArr.push({
- model: tempFilterArr[i],
- max: dimension[i] - 1,
- showError: false,
- });
- if (tempFilterArr[i].indexOf(':') !== -1) {
- const curFilterArr = tempFilterArr[i].split(':');
- if (curFilterArr[0]) {
- let startIndex = Number(curFilterArr[0]);
- startIndex = startIndex < 0 ? dimension[i] + startIndex : startIndex;
- multiDimsArr.push(startIndex);
- } else {
- multiDimsArr.push(0);
- }
- }
- }
- this.filterArr = tempArr;
- if (!multiDimsArr.length) {
- this.tableStartIndex = {
- rowStartIndex: 0,
- colStartIndex: 0,
- };
- } else if (multiDimsArr.length >= 2) {
- this.tableStartIndex = {
- rowStartIndex: multiDimsArr[0],
- colStartIndex: multiDimsArr[1],
- };
- } else {
- this.tableStartIndex = {
- rowStartIndex: 0,
- colStartIndex: multiDimsArr[0],
- };
- }
- },
- /**
- * Initialize column information
- */
- formateColumnsData() {
- this.columnsData = [
- {
- id: -1,
- name: ' ',
- field: -1,
- width: 100,
- headerCssClass: 'headerStyle',
- },
- ];
- const columnSample = this.formateData[0];
- if (columnSample) {
- columnSample.forEach((num, numIndex) => {
- const order = numIndex + this.tableStartIndex.colStartIndex;
- this.columnsData.push({
- id: order,
- name: order,
- field: order,
- width: 100,
- headerCssClass: 'headerStyle',
- formatter:
- this.gridType === this.gridTypeKeys.compare ? this.formateCompareColor : this.formateValueColor,
- });
- });
- } else {
- this.columnsData = [];
- }
- },
- /**
- * Setting the Background color of data
- * @param {Number} row
- * @param {Number} cell
- * @param {String} value,
- * @param {Object} columnDef
- * @param {Object} dataContext
- * @return {String}
- */
- formateValueColor(row, cell, value, columnDef, dataContext) {
- if (!cell || !value || isNaN(value) || value === Infinity || value === -Infinity) {
- return value;
- } else if (value < 0) {
- return `<span class="table-item-span" style="background:rgba(227, 125, 41, ${
- value / this.statistics.overall_min
- })">${value}</span>`;
- } else {
- return `<span class="table-item-span" style="background:rgba(0, 165, 167, ${
- value / this.statistics.overall_max
- })">${value}</span>`;
- }
- },
- /**
- * Setting the background color of data
- * @param {Number} row
- * @param {Number} cell
- * @param {String} value,
- * @param {Object} columnDef
- * @param {Object} dataContext
- * @return {String}
- */
- formateCompareColor(row, cell, value, columnDef, dataContext) {
- if (value instanceof Array && value.length >= 3) {
- const valueNum = value[2];
- if (!cell || !valueNum || isNaN(valueNum) || valueNum === Infinity || valueNum === -Infinity) {
- return `<span class="table-item-span" title="${value[0]}→${value[1]}">${valueNum}</span>`;
- } else if (valueNum < 0) {
- return `<span class="table-item-span" title="${value[0]}→${
- value[1]
- }" style="background:rgba(227, 125, 41, ${valueNum / this.statistics.overall_min})">${valueNum}</span>`;
- } else {
- return `<span class="table-item-span" title="${value[0]}→${value[1]}" style="background:rgba(0, 165, 167, ${
- valueNum / this.statistics.overall_max
- })">${valueNum}</span>`;
- }
- } else {
- return value;
- }
- },
- calcForArrDims(array) {
- let dims = 0;
- let curValue = array;
- while (curValue instanceof Array && dims <= 3) {
- dims++;
- curValue = curValue[0];
- }
- return dims;
- },
- /**
- * Convetring raw data into table data
- */
- formateGridArray() {
- const dims = this.calcForArrDims(this.fullData);
- if (dims > 3) {
- this.formateData = [[[]]];
- this.columnsData = [];
- } else if (dims === 0) {
- this.formateData = [[this.fullData]];
- } else if (dims === 1) {
- this.formateData = [this.fullData];
- } else {
- this.formateData = this.fullData;
- }
- if (this.gridType === this.gridTypeKeys.compare && dims === 2) {
- this.formateData = [this.formateData];
- }
- const tempArr = [];
- if (this.gridType === this.gridTypeKeys.compare) {
- this.formateData.forEach((outerData, outerIndex) => {
- const tempData = {
- '-1': outerIndex + this.tableStartIndex.rowStartIndex,
- };
- outerData.forEach((innerData, innerIndex) => {
- const innerOrder = innerIndex + this.tableStartIndex.colStartIndex;
- const tempArr = [];
- innerData.forEach((innerValue) => {
- if (isNaN(innerValue) || innerValue === 'Infinity' || innerValue === '-Infinity') {
- tempArr.push(innerValue);
- } else {
- tempArr.push(innerValue.toFixed(this.accuracy));
- }
- });
- tempData[innerOrder] = tempArr;
- });
- tempArr.push(tempData);
- });
- } else {
- this.formateData.forEach((outerData, outerIndex) => {
- const tempData = {
- '-1': outerIndex + this.tableStartIndex.rowStartIndex,
- };
- outerData.forEach((innerData, innerIndex) => {
- const innerOrder = innerIndex + this.tableStartIndex.colStartIndex;
- if (isNaN(innerData) || innerData === 'Infinity' || innerData === '-Infinity') {
- tempData[innerOrder] = innerData;
- } else {
- tempData[innerOrder] = innerData.toFixed(this.accuracy);
- }
- });
- tempArr.push(tempData);
- });
- }
- this.formateArr = tempArr;
- },
- /**
- * Update the table
- */
- updateGrid() {
- this.$nextTick(() => {
- if (!this.gridObj) {
- this.gridObj = new Slick.Grid(`#${this.itemId}`, this.formateArr, this.columnsData, this.optionObj);
- this.columnsLength = this.columnsData.length;
- }
- this.gridObj.setData(this.formateArr, this.scrollTop);
- this.scrollTop = false;
- const columnsLength = this.columnsData.length;
- if (this.columnsLength !== columnsLength || this.viewResizeFlag) {
- this.gridObj.setColumns(this.columnsData);
- this.columnsLength = columnsLength;
- this.viewResizeFlag = false;
- }
- this.gridObj.render();
- });
- },
- /**
- * Accuracy changed
- * @param {Number} value The value after changed
- */
- accuracyChange(value) {
- this.formateGridArray();
- if (!this.requestError && !this.incorrectData) {
- this.updateGrid();
- }
- },
- /**
- * Dimension selection changed
- */
- filterChange() {
- // filter condition
- let filterCorrect = true;
- let incorrectData = false;
- let limitCount = 2;
- const tempArr = [];
- this.filterArr.forEach((filter) => {
- let value = filter.model.trim();
- if (!isNaN(value)) {
- if (value < -(filter.max + 1) || value > filter.max || value === '' || value % 1) {
- filter.showError = true;
- filterCorrect = false;
- } else {
- filter.showError = false;
- value = Number(value);
- }
- } else if (value.indexOf(':') !== -1) {
- const tempResult = this.checkCombinatorialInput(filter);
- if (tempResult) {
- filter.showError = false;
- if (!limitCount) {
- incorrectData = true;
- } else {
- limitCount--;
- }
- } else {
- filter.showError = true;
- filterCorrect = false;
- }
- } else {
- filter.showError = true;
- filterCorrect = false;
- }
- tempArr.push(value);
- });
- this.filterCorrect = filterCorrect;
- if (incorrectData && filterCorrect) {
- this.incorrectData = true;
- return;
- } else {
- this.incorrectData = false;
- }
- if (filterCorrect) {
- this.viewResizeFlag = true;
- this.$emit('martixFilterChange', tempArr);
- }
- },
- /**
- * Check combinatorial input
- * @param {Object} filter Filter item
- * @return {Boolean} Verification result
- */
- checkCombinatorialInput(filter) {
- const value = filter.model.trim();
- const tempArr = value.split(':');
- const startValue = tempArr[0];
- const endValue = tempArr[1];
- const limitCount = 2;
- if (!!startValue && (isNaN(startValue) || startValue < -(filter.max + 1) || startValue > filter.max)) {
- return false;
- }
- if (
- !!endValue &&
- (isNaN(endValue) || endValue <= -(filter.max + 1) || endValue > filter.max + 1 || !Number(endValue))
- ) {
- return false;
- }
- if (tempArr.length > limitCount) {
- return false;
- } else if (!startValue && !endValue) {
- return true;
- } else if (!!startValue && !!endValue) {
- const sv = startValue < 0 ? filter.max + Number(startValue) + 1 : Number(startValue);
- const ev = endValue < 0 ? filter.max + Number(endValue) + 1 : Number(endValue);
- if (ev <= sv) {
- return false;
- } else {
- return true;
- }
- } else {
- return true;
- }
- },
- /**
- * Updating Table Data
- * @param {Boolean} newDataFlag Wheather data is updated
- * @param {Array} dimension Array of dimension
- * @param {Object} statistics Object contains maximun and minimun
- * @param {String} filterStr String of dimension selection
- */
- updateGridData(newDataFlag, dimension, statistics, filterStr) {
- this.shape = dimension;
- this.updated = true;
- this.requestError = false;
- this.$nextTick(() => {
- if (!this.fullData || !this.fullData.length) {
- return;
- }
- if (newDataFlag) {
- this.viewResizeFlag = true;
- this.initializeFilterArr(dimension, filterStr);
- this.scrollTop = true;
- } else if (!this.filterArr.length && dimension && filterStr) {
- this.initializeFilterArr(dimension, filterStr);
- }
- if (newDataFlag || this.statistics.overall_max === undefined) {
- this.statistics = statistics;
- }
- this.formateGridArray();
- this.formateColumnsData();
- if (!this.incorrectData) {
- this.updateGrid();
- }
- });
- },
- /**
- * Update the view Size
- */
- resizeView() {
- if (this.gridObj) {
- if (this.incorrectData || this.requestError) {
- this.viewResizeFlag = true;
- } else {
- this.$nextTick(() => {
- this.gridObj.resizeCanvas();
- this.gridObj.render();
- });
- }
- }
- },
- /**
- * Expand/Collapse in full screen
- */
- toggleFullScreen() {
- this.$emit('toggleFullScreen');
- },
- /**
- * Show error message
- * @param {String} errorMsg Error message
- * @param {Array} dimension Array of dimension
- * @param {String} filterStr String of dimension selection
- * @param {Boolean} isUpdate Whether to reset
- */
- showRequestErrorMessage(errorMsg, dimension, filterStr, isUpdate) {
- this.shape = dimension;
- this.errorMsg = errorMsg;
- if ((!this.filterArr.length && dimension && filterStr) || isUpdate) {
- this.initializeFilterArr(dimension, filterStr);
- }
- this.requestError = true;
- },
- },
- destroyed() {},
- };
- </script>
- <style lang="scss">
- .cl-slickgrid-container {
- width: 100%;
- height: 100%;
- display: flex;
- flex-direction: column;
- .data-show-container {
- width: 100%;
- flex: 1;
- .grid-item {
- width: 100%;
- height: 100%;
- ::-webkit-scrollbar-button {
- z-index: 200;
- width: 10px;
- height: 10px;
- background: #fff;
- cursor: pointer;
- }
- ::-webkit-scrollbar-button:horizontal:single-button:start {
- background-image: url('../assets/images/scroll-btn-left.png');
- background-position: center;
- }
- ::-webkit-scrollbar-button:horizontal:single-button:end {
- background-image: url('../assets/images/scroll-btn-right.png');
- background-position: center;
- }
- ::-webkit-scrollbar-button:vertical:single-button:start {
- background-image: url('../assets/images/scroll-btn-up.png');
- background-position: center;
- }
- ::-webkit-scrollbar-button:vertical:single-button:end {
- background-image: url('../assets/images/scroll-btn-down.png');
- background-position: center;
- }
- ::-webkit-scrollbar-thumb {
- background-color: #bac5cc;
- }
- ::-webkit-scrollbar {
- width: 10px;
- height: 10px;
- }
- }
- .error-msg-container {
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- }
- .info-show-container {
- width: 100%;
- }
- .operate-container {
- width: 100%;
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
- z-index: 9;
- flex-wrap: wrap;
- .full-screen-icon {
- float: right;
- margin-left: 15px;
- height: 100%;
- line-height: 34px;
- cursor: pointer;
- :hover {
- color: #00a5a7;
- }
- }
- .active-color {
- color: #00a5a7;
- }
- .filter-container {
- float: left;
- flex-wrap: wrap;
- display: flex;
- .filter-input-title {
- line-height: 34px;
- margin-right: 10px;
- }
- .error-border {
- input {
- border-color: red;
- }
- }
- .filter-input {
- text-align: center;
- }
- .long-input {
- width: 120px;
- }
- .input-behind {
- padding: 0 5px;
- }
- .filter-incorrect-text {
- margin-left: 10px;
- line-height: 32px;
- color: red;
- }
- }
- .shape-wrap {
- float: left;
- line-height: 34px;
- margin-left: 10px;
- }
- .accuracy-container {
- float: right;
- .select-item {
- width: 65px;
- margin-left: 5px;
- }
- }
- }
- }
- .slick-cell,
- .slick-headerrow-column,
- .slick-footerrow-column {
- padding: 0;
- border-top: none;
- border-left: none;
- text-align: center;
- }
-
- .ui-widget-content {
- background: none;
- }
- .headerStyle {
- vertical-align: middle;
- text-align: center;
- }
- .filter-check {
- font-size: 18px;
- color: #00a5a7;
- cursor: pointer;
- }
- .table-item-span {
- display: block;
- width: 100%;
- height: 100%;
- text-align: center;
- }
- </style>
|