Add lib stepper and integration

This commit is contained in:
Vladyslav_Prykhodko 2019-05-24 15:58:13 +03:00
parent 07cd8b9978
commit 3f30e3d74f
5 changed files with 246 additions and 177 deletions

View File

@ -64,6 +64,7 @@
"jstree-bootstrap-theme": "^1.0.1",
"leaflet": "^1.0.3",
"leaflet-providers": "^1.1.17",
"material-steppers": "^2.0.0",
"material-ui": "^0.16.1",
"material-ui-number-input": "^5.0.16",
"md-color-picker": "0.2.6",

View File

@ -179,15 +179,15 @@ function DeviceService($http, $q, $window, userService, attributeService, custom
let promise = "";
let statisticalInfo = {};
for (let i = 0; i < attributesType.length; i++) {
let attrribute = attributesType[i];
if (deviceRelation.attributes[attrribute] && deviceRelation.attributes[attrribute].length !== 0) {
promise = attributeService.saveEntityAttributes(types.entityType.device, deviceId, types.attributesScope[attrribute].value, deviceRelation.attributes[attrribute], config).then(function () {
let attribute = attributesType[i];
if (deviceRelation.attributes[attribute] && deviceRelation.attributes[attribute].length !== 0) {
promise = attributeService.saveEntityAttributes(types.entityType.device, deviceId, types.attributesScope[attribute].value, deviceRelation.attributes[attribute], config).then(function () {
statisticalInfo.create = {
[attrribute]: deviceRelation.attributes[attributesType[i]].length
[attribute]: deviceRelation.attributes[attribute].length
};
}, function () {
statisticalInfo.error = {
[attrribute]: deviceRelation.attributes[attributesType[i]].length
[attribute]: deviceRelation.attributes[attribute].length
};
});
allPromise.push(promise);
@ -234,7 +234,9 @@ function DeviceService($http, $q, $window, userService, attributeService, custom
device: 1
};
saveDeviceRelarion(response.id.id, deviceParameters, config).then(function success(response) {
delete Object.assign(response, {update: response.create}).create;
if(response.create) {
delete Object.assign(response, {update: response.create}).create;
}
angular.merge(statisticalInfo, response);
deferred.resolve(statisticalInfo);
});

View File

@ -54,6 +54,8 @@ import react from 'ngreact';
import '@flowjs/ng-flow/dist/ng-flow-standalone.min';
import 'ngFlowchart/dist/ngFlowchart';
import 'jstree/dist/jstree.min';
import 'material-steppers/dist/material-steppers';
import 'material-steppers/dist/material-steppers.css'
import 'jstree-bootstrap-theme/dist/themes/proton/style.min.css';
import 'typeface-roboto';
import 'font-awesome/css/font-awesome.min.css';
@ -127,6 +129,7 @@ angular.module('thingsboard', [
react.name,
'flow',
'flowchart',
'mdSteppers',
thingsboardThirdpartyFix,
thingsboardTranslateHandler,
thingsboardLogin,

View File

@ -16,14 +16,16 @@
import './import-dialog.scss';
/*@ngInject*/
export default function ImportDialogCsvController($scope, $mdDialog, toast, importTitle, importFileLabel, entityType, importExport, types, $timeout, $q) {
export default function ImportDialogCsvController($scope, $mdDialog, toast, importTitle, importFileLabel, entityType, importExport, types, $mdStepper) {
var vm = this;
vm.cancel = cancel;
vm.importFromJson = importFromJson;
vm.finishExport = finishExport;
vm.fileAdded = fileAdded;
vm.clearFile = clearFile;
vm.nextStep = nextStep;
vm.previousStep = previousStep;
vm.addDevices = addDevices;
vm.importParams = {
@ -32,69 +34,28 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo
isHeader: true
};
vm.selectedStep = 0;
vm.stepProgress = 1;
vm.maxStep = 3;
vm.showBusyText = false;
vm.stepData = [
{ step: 1, completed: false, optional: false, data: {} },
{ step: 2, completed: false, optional: false, data: {} },
{ step: 3, completed: false, optional: false, data: {} },
];
vm.enableNextStep = function nextStep() {
//do not exceed into max step
if (vm.selectedStep >= vm.maxStep) {
return;
}
//do not increment vm.stepProgress when submitting from previously completed step
if (vm.selectedStep === vm.stepProgress - 1) {
vm.stepProgress = vm.stepProgress + 1;
}
vm.selectedStep = vm.selectedStep + 1;
};
vm.moveToPreviousStep = function moveToPreviousStep() {
if (vm.selectedStep > 0) {
vm.selectedStep = vm.selectedStep - 1;
}
};
vm.submitCurrentStep = function submitCurrentStep(stepData, isSkip) {
var deferred = $q.defer();
vm.showBusyText = true;
if (!stepData.completed && !isSkip) {
//simulate $http
$timeout(function () {
vm.showBusyText = false;
deferred.resolve({ status: 200, statusText: 'success', data: {} });
//move to next step when success
stepData.completed = true;
vm.enableNextStep();
}, 1000)
} else {
vm.showBusyText = false;
vm.enableNextStep();
}
};
vm.importTitle = importTitle;
vm.importFileLabel = importFileLabel;
vm.entityType = entityType;
vm.isVertical = true;
vm.isLinear = true;
vm.isAlternative = false;
vm.isMobileStepText = true;
vm.columnsParam = [];
vm.parseData = [];
vm.delimiters = [{
key: ',',
value: ','
},{
}, {
key: ';',
value: ';'
},{
}, {
key: '|',
value: '|'
},{
}, {
key: '\t',
value: 'Tab'
}];
@ -107,11 +68,11 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo
reader.onload = function (event) {
$scope.$apply(function () {
if (event.target.result) {
$scope.theForm.$setDirty();
vm.theFormStep1.$setDirty();
var importCSV = event.target.result;
if (importCSV && importCSV.length > 0) {
try {
parseCSV(importCSV);
vm.importData = importCSV;
vm.fileName = $file.name;
} catch (err) {
vm.fileName = null;
@ -126,12 +87,15 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo
}
function parseCSV(importData) {
var columnParam = {};
var config = {
delim: vm.importParams.delim,
header: vm.importParams.isHeader
};
parseData = importExport.convertCSVToJson(importData, config);
return importExport.convertCSVToJson(importData, config);
}
function createColumnsData(parseData) {
var columnParam = {};
for (var i = 0; i < parseData.headers.length; i++) {
if (vm.importParams.isHeader && parseData.headers[i].search(/^(name|type)$/im) === 0) {
columnParam = {
@ -150,24 +114,14 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo
}
}
function addDevices () {
var arrayParam = [{type: "ENTITY_FIELD", key: "name", sampleData: "Device 1"}, {type: "ENTITY_FIELD", key: "type", sampleData: "test"}, {type: "SERVER_ATTRIBUTE", key: "test", sampleData: "test"}, {type: "TIMESERIES", key: "testBoolean", sampleData: false}, {type: "SHARED_ATTRIBUTE", key: "testNumber", sampleData: 123}]; // eslint-disable-line
var data = {headers: ["Device 1", "test", "test", "FALSE", "123"],
rows:[["Device 1", "test", "test", false, 123.5]]};
// rows:[["Device 1", "test", "test", false, 123],
// ["Device 2", "test", "test", false, 124],
// ["Device 3", "test", "test", false, 125],
// ["Device 4", "test", "test", false, 126],
// ["Device 5", "test", "test", false, 127]]};
arrayParam = vm.columnsParam;
data = parseData;
var arrayData = [];
function addDevices(importData, parameterColumns) {
var entitysData = [];
var config = {
ignoreErrors: true,
resendRequest: true
};
for (var i = 0; i < data.rows.length; i ++) {
var obj = {
for (var i = 0; i < importData.rows.length; i++) {
var entityData = {
name: "",
type: "",
attributes: {
@ -176,58 +130,86 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo
},
timeseries: []
};
for(var j = 0; j < arrayParam.length; j++){
switch (arrayParam[j].type) {
for (var j = 0; j < parameterColumns.length; j++) {
switch (parameterColumns[j].type) {
case types.entityGroup.columnType.serverAttribute.value:
obj.attributes.server.push({
key: arrayParam[j].key,
value: data.rows[i][j]
entityData.attributes.server.push({
key: parameterColumns[j].key,
value: importData.rows[i][j]
});
break;
case types.entityGroup.columnType.sharedAttribute.value:
obj.attributes.shared.push({
key: arrayParam[j].key,
value: data.rows[i][j]
entityData.attributes.shared.push({
key: parameterColumns[j].key,
value: importData.rows[i][j]
});
break;
case types.entityGroup.columnType.timeseries.value:
obj.timeseries.push({
key: arrayParam[j].key,
value: data.rows[i][j]
entityData.timeseries.push({
key: parameterColumns[j].key,
value: importData.rows[i][j]
});
break;
case types.entityGroup.columnType.entityField.value:
switch (arrayParam[j].key) {
switch (parameterColumns[j].key) {
case types.entityGroup.entityField.name.value:
obj.name = data.rows[i][j];
entityData.name = importData.rows[i][j];
break;
case types.entityGroup.entityField.type.value:
obj.type = data.rows[i][j];
entityData.type = importData.rows[i][j];
break;
}
break;
}
}
arrayData.push(obj);
entitysData.push(entityData);
}
importExport.createMultiEntity(arrayData, vm.entityType, vm.importParams.isUpdate, config).then(function () {
$mdDialog.hide();
importExport.createMultiEntity(entitysData, vm.entityType, vm.importParams.isUpdate, config).then(function (response) {
vm.statistical = response;
$mdStepper('import-stepper').next();
});
}
function clearFile() {
$scope.theForm.$setDirty();
vm.theFormStep1.$setDirty();
vm.fileName = null;
parseData = null;
vm.columnsParam = [];
vm.importData = null;
}
function previousStep() {
let steppers = $mdStepper('import-stepper');
steppers.back();
}
function nextStep(step) {
let steppers = $mdStepper('import-stepper');
switch (step) {
case 2:
steppers.next();
break;
case 3:
parseData = parseCSV(vm.importData);
if (parseData === -1) {
clearFile();
steppers.back();
} else {
createColumnsData(parseData);
steppers.next();
}
break;
case 4:
steppers.next();
addDevices(parseData, vm.columnsParam)
break;
}
}
function cancel() {
$mdDialog.cancel();
}
function importFromJson() {
$scope.theForm.$setPristine();
$mdDialog.hide(vm.importData);
function finishExport() {
$mdDialog.hide();
}
}

View File

@ -16,87 +16,168 @@
-->
<md-dialog aria-label="{{ vm.importTitle | translate }}">
<form name="theForm" ng-submit="vm.importFromJson()">
<md-toolbar>
<div class="md-toolbar-tools">
<h2 translate>{{ vm.importTitle }}</h2>
<span flex></span>
<md-button class="md-icon-button" ng-click="vm.cancel()">
<ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon>
</md-button>
</div>
</md-toolbar>
<md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading"
ng-show="$root.loading"></md-progress-linear>
<span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span>
<md-dialog-content>
<div class="md-dialog-content">
<fieldset ng-disabled="$root.loading">
<div layout="column" layout-padding>
<div class="tb-container">
<label class="tb-label" translate>{{ vm.importFileLabel }}</label>
<div flow-init="{singleFile:true}"
flow-file-added="vm.fileAdded( $file )" class="tb-file-select-container">
<div class="tb-file-clear-container">
<md-button ng-click="vm.clearFile()"
class="tb-file-clear-btn md-icon-button md-primary"
aria-label="{{ 'action.remove' | translate }}">
<md-tooltip md-direction="top">
{{ 'action.remove' | translate }}
</md-tooltip>
<md-icon aria-label="{{ 'action.remove' | translate }}" class="material-icons">
close
</md-icon>
</md-button>
<md-toolbar>
<div class="md-toolbar-tools">
<h2 translate>{{ vm.importTitle }}</h2>
<span flex></span>
<md-button class="md-icon-button" ng-click="vm.cancel()">
<ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon>
</md-button>
</div>
</md-toolbar>
<md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading"
ng-show="$root.loading"></md-progress-linear>
<span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span>
<md-dialog-content>
<md-stepper id="import-stepper" md-mobile-step-text="vm.isMobileStepText" md-vertical="vm.isVertical"
md-linear="vm.isLinear" md-alternative="vm.isAlternative">
<md-step md-label="Select a file">
<md-step-body>
<form name="vm.theFormStep1">
<fieldset ng-disabled="$root.loading">
<div layout="column" layout-padding>
<div class="tb-container">
<label class="tb-label" translate>{{ vm.importFileLabel }}</label>
<div flow-init="{singleFile:true}"
flow-file-added="vm.fileAdded( $file )" class="tb-file-select-container">
<div class="tb-file-clear-container">
<md-button ng-click="vm.clearFile()"
class="tb-file-clear-btn md-icon-button md-primary"
aria-label="{{ 'action.remove' | translate }}">
<md-tooltip md-direction="top">
{{ 'action.remove' | translate }}
</md-tooltip>
<md-icon aria-label="{{ 'action.remove' | translate }}"
class="material-icons">
close
</md-icon>
</md-button>
</div>
<div class="alert tb-flow-drop" flow-drop>
<label for="select" translate>import.drop-file-csv</label>
<input class="file-input" flow-btn
flow-attrs="{accept:'.csv,application/csv,text/csv'}"
id="select">
</div>
</div>
</div>
<div class="alert tb-flow-drop" flow-drop>
<label for="select" translate>import.drop-file-csv</label>
<input class="file-input" flow-btn
flow-attrs="{accept:'.csv,application/csv,text/csv'}" id="select">
<div>
<div ng-show="!vm.fileName" translate>import.no-file</div>
<div ng-show="vm.fileName">{{ vm.fileName }}</div>
</div>
</div>
</div>
<div>
<div ng-show="!vm.fileName" translate>import.no-file</div>
<div ng-show="vm.fileName">{{ vm.fileName }}</div>
</div>
</fieldset>
</form>
</md-step-body>
<md-step-actions layout="row">
<span flex></span>
<md-button ng-disabled="$root.loading" ng-click="vm.cancel()">
{{ 'action.cancel' | translate }}
</md-button>
<md-button class="md-primary md-raised"
ng-disabled="$root.loading || !vm.theFormStep1.$dirty || !vm.theFormStep1.$valid || !vm.importData"
ng-click="vm.nextStep(2);">
Continue
</md-button>
</md-step-actions>
</md-step>
<md-step md-label="Select config import">
<md-step-body>
<div flex layout="row" layout-xs="column">
<md-input-container class="md-block" style="min-width: 120px">
<label translate>CSV delimiter</label>
<md-select ng-model="vm.importParams.delim">
<md-option ng-repeat="delimiter in vm.delimiters" ng-value="delimiter.key">
{{delimiter.value}}
</md-option>
</md-select>
</md-input-container>
<md-input-container class="md-block">
<md-checkbox ng-model="vm.importParams.isHeader" aria-label="Checkbox 1">
First line is header
</md-checkbox>
</md-input-container>
<md-input-container class="md-block">
<md-checkbox ng-model="vm.importParams.isUpdate" aria-label="Checkbox 1">
Update parameters
</md-checkbox>
</md-input-container>
</div>
</fieldset>
<div flex layout="row">
<md-input-container class="md-block" style="min-width: 120px">
<label translate>CSV delimiter</label>
<md-select ng-model="vm.importParams.delim">
<md-option ng-repeat="delimiter in vm.delimiters" ng-value="delimiter.key">
{{delimiter.value}}
</md-option>
</md-select>
</md-input-container>
<md-input-container class="md-block">
<md-checkbox ng-model="vm.importParams.isHeader" aria-label="Checkbox 1">
First line is header
</md-checkbox>
</md-input-container>
<md-input-container class="md-block">
<md-checkbox ng-model="vm.importParams.isUpdate" aria-label="Checkbox 1">
Update parameters
</md-checkbox>
</md-input-container>
</div>
<tb-table-columns-assignment the-form="theForm" columns="vm.columnsParam" entityType="vm.entityType"></tb-table-columns-assignment>
</div>
</md-dialog-content>
<md-dialog-actions layout="row">
<span flex></span>
<md-button ng-disabled="$root.loading" ng-click="vm.addDevices()" style="margin-right:20px;">
Add Device
</md-button>
<md-button ng-disabled="$root.loading || !theForm.$dirty || !theForm.$valid || !vm.importData" type="submit"
class="md-raised md-primary">
{{ 'action.import' | translate }}
</md-button>
<md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel'
| translate }}
</md-button>
</md-dialog-actions>
</form>
</md-step-body>
<md-step-actions layout="row">
<md-button ng-disabled="$root.loading" ng-click="vm.previousStep();">Back
</md-button>
<span flex></span>
<md-button ng-disabled="$root.loading" ng-click="vm.cancel()">
{{ 'action.cancel' | translate }}
</md-button>
<md-button class="md-primary md-raised" ng-disabled="$root.loading" ng-click="vm.nextStep(3);">
Continue
</md-button>
</md-step-actions>
</md-step>
<md-step md-label="Select columns type">
<md-step-body>
<tb-table-columns-assignment columns="vm.columnsParam"
entity-type="vm.entityType"></tb-table-columns-assignment>
</md-step-body>
<md-step-actions layout="row">
<md-button ng-disabled="$root.loading" ng-click="vm.previousStep();">Back
</md-button>
<span flex></span>
<md-button ng-disabled="$root.loading" ng-click="vm.cancel()">
{{ 'action.cancel' | translate }}
</md-button>
<md-button class="md-primary md-raised" ng-disabled="$root.loading" ng-click="vm.nextStep(4);">
Continue
</md-button>
</md-step-actions>
</md-step>
<md-step md-label="Creat new device">
<md-step-body>
<md-progress-linear md-mode="determinate" value="{{vm.determinateValue}}"></md-progress-linear>
</md-step-body>
</md-step>
<md-step md-label="Creat new Entitys">
<md-step-body>
<div flex layout="row" ng-repeat="(key, value) in vm.statistical">
<md-list flex layout="column">
<md-subheader class="md-no-sticky">{{key}}</md-subheader>
<md-list-item class="md-2-line" ng-repeat="(info, infoValue) in vm.statistical[key]" ng-click="null">
<div class="md-list-item-text">
<p>{{ info }}: {{ infoValue }}</p>
</div>
</md-list-item>
</md-list>
</div>
</md-step-body>
<md-step-actions>
<span flex></span>
<md-button ng-disabled="$root.loading" ng-click="vm.cancel()">
{{ 'action.cancel' | translate }}
</md-button>
<md-button class="md-primary md-raised" ng-disabled="$root.loading" ng-click="vm.finishExport();">
Ok
</md-button>
</md-step-actions>
</md-step>
</md-stepper>
</md-dialog-content>
<!--<md-dialog-actions layout="row">-->
<!--<span flex></span>-->
<!--<md-button ng-disabled="$root.loading || !theForm.$dirty || !theForm.$valid || !vm.importData" type="submit"-->
<!--class="md-raised md-primary">-->
<!--{{ 'action.import' | translate }}-->
<!--</md-button>-->
<!--<md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel'-->
<!--| translate }}-->
<!--</md-button>-->
<!--</md-dialog-actions>-->
</md-dialog>