Merge remote-tracking branch 'origin/master' into develop/2.5
This commit is contained in:
commit
7c24b850fb
@ -330,13 +330,13 @@
|
|||||||
"name": "Web Camera Input",
|
"name": "Web Camera Input",
|
||||||
"descriptor": {
|
"descriptor": {
|
||||||
"type": "latest",
|
"type": "latest",
|
||||||
"sizeX": 9.5,
|
"sizeX": 7.5,
|
||||||
"sizeY": 6.5,
|
"sizeY": 3,
|
||||||
"resources": [],
|
"resources": [],
|
||||||
"templateHtml": "<tb-web-camera-widget ctx=\"ctx\">\n</tb-web-camera-widget>",
|
"templateHtml": "<tb-web-camera-widget ctx=\"ctx\">\n</tb-web-camera-widget>",
|
||||||
"templateCss": "#container {\n overflow: auto;\n}\n\n.tbDatasource-container {\n margin: 5px;\n padding: 8px;\n}\n\n.tbDatasource-title {\n font-size: 1.200rem;\n font-weight: 500;\n padding-bottom: 10px;\n}\n\n.tbDatasource-table {\n width: 100%;\n box-shadow: 0 0 10px #ccc;\n border-collapse: collapse;\n white-space: nowrap;\n font-size: 1.000rem;\n color: #757575;\n}\n\n.tbDatasource-table td {\n position: relative;\n border-top: 1px solid rgba(0, 0, 0, 0.12);\n border-bottom: 1px solid rgba(0, 0, 0, 0.12);\n padding: 0px 18px;\n box-sizing: border-box;\n}",
|
"templateCss": "",
|
||||||
"controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}\n\nself.onDataUpdated = function() {\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onDestroy = function() {\n}\n",
|
"controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}\n\nself.onDataUpdated = function() {\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onDestroy = function() {\n}\n",
|
||||||
"settingsSchema": "{}",
|
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Web Camera\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"imageFormat\": {\n \"title\": \"Image Format\",\n \"type\": \"string\",\n \"default\": \"image/png\"\n },\n \"imageQuality\":{\n \"title\":\"Image quality that use lossy compression such as jpeg and webp\",\n \"type\":\"number\",\n \"default\": 0.92,\n \"min\": 0,\n \"max\": 1\n },\n \"maxWidth\": {\n \"title\": \"The maximal image width\",\n \"type\": \"number\",\n \"default\": 640\n }, \n \"maxHeight\": {\n \"title\": \"The maximal image heigth\",\n \"type\": \"number\",\n \"default\": 480\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n {\n \"key\": \"imageFormat\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"image/jpeg\",\n \"label\": \"JPEG\"\n },\n {\n \"value\": \"image/png\",\n \"label\": \"PNG\"\n },\n {\n \"value\": \"image/webp\",\n \"label\": \"WEBP\"\n }\n ]\n },\n \"imageQuality\",\n \"maxWidth\",\n \"maxHeight\"\n ]\n}",
|
||||||
"dataKeySettingsSchema": "{}\n",
|
"dataKeySettingsSchema": "{}\n",
|
||||||
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Web Camera Input\",\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"displayTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
|
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Web Camera Input\",\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"displayTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -201,6 +201,7 @@ public class AuthController extends BaseController {
|
|||||||
@ResponseBody
|
@ResponseBody
|
||||||
public JsonNode activateUser(
|
public JsonNode activateUser(
|
||||||
@RequestBody JsonNode activateRequest,
|
@RequestBody JsonNode activateRequest,
|
||||||
|
@RequestParam(required = false, defaultValue = "true") boolean sendActivationMail,
|
||||||
HttpServletRequest request) throws ThingsboardException {
|
HttpServletRequest request) throws ThingsboardException {
|
||||||
try {
|
try {
|
||||||
String activateToken = activateRequest.get("activateToken").asText();
|
String activateToken = activateRequest.get("activateToken").asText();
|
||||||
@ -215,11 +216,13 @@ public class AuthController extends BaseController {
|
|||||||
String loginUrl = String.format("%s/login", baseUrl);
|
String loginUrl = String.format("%s/login", baseUrl);
|
||||||
String email = user.getEmail();
|
String email = user.getEmail();
|
||||||
|
|
||||||
|
if (sendActivationMail) {
|
||||||
try {
|
try {
|
||||||
mailService.sendAccountActivatedEmail(loginUrl, email);
|
mailService.sendAccountActivatedEmail(loginUrl, email);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.info("Unable to send account activation email [{}]", e.getMessage());
|
log.info("Unable to send account activation email [{}]", e.getMessage());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser);
|
JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser);
|
||||||
JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser);
|
JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser);
|
||||||
|
|||||||
@ -277,6 +277,7 @@ public class DefaultMailService implements MailService {
|
|||||||
} else {
|
} else {
|
||||||
message = exception.getMessage();
|
message = exception.getMessage();
|
||||||
}
|
}
|
||||||
|
log.warn("Unable to send mail: {}", message);
|
||||||
return new ThingsboardException(String.format("Unable to send mail: %s", message),
|
return new ThingsboardException(String.format("Unable to send mail: %s", message),
|
||||||
ThingsboardErrorCode.GENERAL);
|
ThingsboardErrorCode.GENERAL);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -435,6 +435,10 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
|
|||||||
if (user.authority === 'CUSTOMER_USER') {
|
if (user.authority === 'CUSTOMER_USER') {
|
||||||
entityId.id = user.customerId;
|
entityId.id = user.customerId;
|
||||||
}
|
}
|
||||||
|
} else if (entityType === types.aliasEntityType.current_tenant){
|
||||||
|
let user = userService.getCurrentUser();
|
||||||
|
entityId.entityType = types.entityType.tenant;
|
||||||
|
entityId.id = user.tenantId;
|
||||||
}
|
}
|
||||||
return entityId;
|
return entityId;
|
||||||
}
|
}
|
||||||
@ -806,6 +810,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
|
|||||||
entityTypes.dashboard = types.entityType.dashboard;
|
entityTypes.dashboard = types.entityType.dashboard;
|
||||||
if (useAliasEntityTypes) {
|
if (useAliasEntityTypes) {
|
||||||
entityTypes.current_customer = types.aliasEntityType.current_customer;
|
entityTypes.current_customer = types.aliasEntityType.current_customer;
|
||||||
|
entityTypes.current_tenant = types.aliasEntityType.current_tenant;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'CUSTOMER_USER':
|
case 'CUSTOMER_USER':
|
||||||
|
|||||||
@ -85,9 +85,12 @@ function LoginService($http, $q) {
|
|||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function activate(activateToken, password) {
|
function activate(activateToken, password, sendActivationMail) {
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
var url = '/api/noauth/activate';
|
var url = '/api/noauth/activate';
|
||||||
|
if(sendActivationMail === true || sendActivationMail === false) {
|
||||||
|
url += '?sendActivationMail=' + sendActivationMail;
|
||||||
|
}
|
||||||
$http.post(url, {activateToken: activateToken, password: password}).then(function success(response) {
|
$http.post(url, {activateToken: activateToken, password: password}).then(function success(response) {
|
||||||
deferred.resolve(response);
|
deferred.resolve(response);
|
||||||
}, function fail() {
|
}, function fail() {
|
||||||
|
|||||||
@ -408,7 +408,8 @@ export default angular.module('thingsboard.types', [])
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
aliasEntityType: {
|
aliasEntityType: {
|
||||||
current_customer: "CURRENT_CUSTOMER"
|
current_customer: "CURRENT_CUSTOMER",
|
||||||
|
current_tenant: "CURRENT_TENANT"
|
||||||
},
|
},
|
||||||
entityTypeTranslations: {
|
entityTypeTranslations: {
|
||||||
"DEVICE": {
|
"DEVICE": {
|
||||||
@ -474,6 +475,10 @@ export default angular.module('thingsboard.types', [])
|
|||||||
"CURRENT_CUSTOMER": {
|
"CURRENT_CUSTOMER": {
|
||||||
type: 'entity.type-current-customer',
|
type: 'entity.type-current-customer',
|
||||||
list: 'entity.type-current-customer'
|
list: 'entity.type-current-customer'
|
||||||
|
},
|
||||||
|
"CURRENT_TENANT": {
|
||||||
|
type: 'entity.type-current-tenant',
|
||||||
|
list: 'entity.type-current-tenant'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
entityField: {
|
entityField: {
|
||||||
|
|||||||
@ -83,9 +83,9 @@ class ThingsboardAceEditor extends React.Component {
|
|||||||
fixAceEditor(editor);
|
fixAceEditor(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
onToggleFull(groupId) {
|
onToggleFull() {
|
||||||
this.setState({ isFull: !this.state.isFull });
|
this.setState({ isFull: !this.state.isFull });
|
||||||
this.props.onToggleFullscreen(groupId);
|
this.props.onToggleFullscreen();
|
||||||
this.updateAceEditorSize = true;
|
this.updateAceEditorSize = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ class ThingsboardAceEditor extends React.Component {
|
|||||||
<div className="title-panel">
|
<div className="title-panel">
|
||||||
<label>{this.props.mode}</label>
|
<label>{this.props.mode}</label>
|
||||||
<FlatButton style={ styles.tidyButtonStyle } className="tidy-button" label={'Tidy'} onTouchTap={this.onTidy}/>
|
<FlatButton style={ styles.tidyButtonStyle } className="tidy-button" label={'Tidy'} onTouchTap={this.onTidy}/>
|
||||||
<FlatButton style={ styles.tidyButtonStyle } className="tidy-button" label={this.state.isFull ? 'Exit fullscreen' : 'Fullscreen'} onTouchTap={() => this.onToggleFull(this.props.groupId)}/>
|
<FlatButton style={ styles.tidyButtonStyle } className="tidy-button" label={this.state.isFull ? 'Exit fullscreen' : 'Fullscreen'} onTouchTap={this.onToggleFull}/>
|
||||||
</div>
|
</div>
|
||||||
<AceEditor mode={this.props.mode}
|
<AceEditor mode={this.props.mode}
|
||||||
height={this.state.isFull ? "100%" : "150px"}
|
height={this.state.isFull ? "100%" : "150px"}
|
||||||
|
|||||||
@ -131,7 +131,7 @@ class ThingsboardArray extends React.Component {
|
|||||||
}
|
}
|
||||||
let forms = this.props.form.items.map(function(form, index){
|
let forms = this.props.form.items.map(function(form, index){
|
||||||
var copy = this.copyWithIndex(form, i);
|
var copy = this.copyWithIndex(form, i);
|
||||||
return this.props.builder(copy, this.props.groupId, this.props.model, index, this.props.onChange, this.props.onColorClick, this.props.onIconClick, this.props.onToggleFullscreen, this.props.mapper, this.props.builder);
|
return this.props.builder(copy, this.props.model, index, this.props.onChange, this.props.onColorClick, this.props.onIconClick, this.props.onToggleFullscreen, this.props.mapper, this.props.builder);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
arrays.push(
|
arrays.push(
|
||||||
<li key={keys[i]} className="list-group-item">
|
<li key={keys[i]} className="list-group-item">
|
||||||
|
|||||||
@ -19,7 +19,7 @@ class ThingsboardFieldSet extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
let forms = this.props.form.items.map(function(form, index){
|
let forms = this.props.form.items.map(function(form, index){
|
||||||
return this.props.builder(form, this.props.groupId, this.props.model, index, this.props.onChange, this.props.onColorClick, this.props.onIconClick, this.props.onToggleFullscreen, this.props.mapper, this.props.builder);
|
return this.props.builder(form, this.props.model, index, this.props.onChange, this.props.onColorClick, this.props.onIconClick, this.props.onToggleFullscreen, this.props.mapper, this.props.builder);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -40,9 +40,6 @@ class ThingsboardSchemaForm extends React.Component {
|
|||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
|
||||||
groupId: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.mapper = {
|
this.mapper = {
|
||||||
'number': ThingsboardNumber,
|
'number': ThingsboardNumber,
|
||||||
@ -88,15 +85,12 @@ class ThingsboardSchemaForm extends React.Component {
|
|||||||
this.props.onIconClick(event);
|
this.props.onIconClick(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
onToggleFullscreen(groupId) {
|
onToggleFullscreen() {
|
||||||
this.setState({
|
|
||||||
groupId: groupId
|
|
||||||
});
|
|
||||||
this.props.onToggleFullscreen();
|
this.props.onToggleFullscreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
builder(form, groupId, model, index, onChange, onColorClick, onIconClick, onToggleFullscreen, mapper) {
|
builder(form, model, index, onChange, onColorClick, onIconClick, onToggleFullscreen, mapper) {
|
||||||
var type = form.type;
|
var type = form.type;
|
||||||
let Field = this.mapper[type];
|
let Field = this.mapper[type];
|
||||||
if(!Field) {
|
if(!Field) {
|
||||||
@ -109,21 +103,21 @@ class ThingsboardSchemaForm extends React.Component {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return <Field model={model} groupId={groupId} form={form} key={index} onChange={onChange} onColorClick={onColorClick} onIconClick={onIconClick} onToggleFullscreen={onToggleFullscreen} mapper={mapper} builder={this.builder}/>
|
return <Field model={model} form={form} key={index} onChange={onChange} onColorClick={onColorClick} onIconClick={onIconClick} onToggleFullscreen={onToggleFullscreen} mapper={mapper} builder={this.builder}/>
|
||||||
}
|
}
|
||||||
|
|
||||||
createSchema(theForm, groupId) {
|
createSchema(theForm) {
|
||||||
let merged = utils.merge(this.props.schema, theForm, this.props.ignore, this.props.option);
|
let merged = utils.merge(this.props.schema, theForm, this.props.ignore, this.props.option);
|
||||||
let mapper = this.mapper;
|
let mapper = this.mapper;
|
||||||
if(this.props.mapper) {
|
if(this.props.mapper) {
|
||||||
mapper = _.merge(this.mapper, this.props.mapper);
|
mapper = _.merge(this.mapper, this.props.mapper);
|
||||||
}
|
}
|
||||||
let forms = merged.map(function(form, index) {
|
let forms = merged.map(function(form, index) {
|
||||||
return this.builder(form, groupId, this.props.model, index, this.onChange, this.onColorClick, this.onIconClick, this.onToggleFullscreen, mapper);
|
return this.builder(form, this.props.model, index, this.onChange, this.onColorClick, this.onIconClick, this.onToggleFullscreen, mapper);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
let formClass = 'SchemaForm';
|
let formClass = 'SchemaForm';
|
||||||
if (this.props.isFullscreen && groupId === this.state.groupId) {
|
if (this.props.isFullscreen) {
|
||||||
formClass += ' SchemaFormFullscreen';
|
formClass += ' SchemaFormFullscreen';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +130,7 @@ class ThingsboardSchemaForm extends React.Component {
|
|||||||
if(this.props.groupInfoes&&this.props.groupInfoes.length>0){
|
if(this.props.groupInfoes&&this.props.groupInfoes.length>0){
|
||||||
let content=[];
|
let content=[];
|
||||||
for(let info of this.props.groupInfoes){
|
for(let info of this.props.groupInfoes){
|
||||||
let forms = this.createSchema(this.props.form[info.formIndex], info.formIndex);
|
let forms = this.createSchema(this.props.form[info.formIndex]);
|
||||||
let item = <ThingsboardSchemaGroup key={content.length} forms={forms} info={info}></ThingsboardSchemaGroup>;
|
let item = <ThingsboardSchemaGroup key={content.length} forms={forms} info={info}></ThingsboardSchemaGroup>;
|
||||||
content.push(item);
|
content.push(item);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,15 +24,12 @@ $input-label-float-scale: .75 !default;
|
|||||||
.tb-fullscreen {
|
.tb-fullscreen {
|
||||||
[name="ReactSchemaForm"] {
|
[name="ReactSchemaForm"] {
|
||||||
.SchemaForm {
|
.SchemaForm {
|
||||||
display: none;
|
|
||||||
|
|
||||||
&.SchemaFormFullscreen {
|
&.SchemaFormFullscreen {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
display: block;
|
|
||||||
|
|
||||||
> div:not(.fullscreen-form-field) {
|
> div:not(.fullscreen-form-field) {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
|
|||||||
@ -152,7 +152,7 @@ export default function WidgetController($scope, $state, $timeout, $window, $ocL
|
|||||||
var entityInfo = getActiveEntityInfo();
|
var entityInfo = getActiveEntityInfo();
|
||||||
var entityId = entityInfo ? entityInfo.entityId : null;
|
var entityId = entityInfo ? entityInfo.entityId : null;
|
||||||
var entityName = entityInfo ? entityInfo.entityName : null;
|
var entityName = entityInfo ? entityInfo.entityName : null;
|
||||||
var entityLabel = entityInfo && entityInfo.label ? entityInfo.label : null;
|
var entityLabel = entityInfo && entityInfo.entityLabel ? entityInfo.entityLabel : null;
|
||||||
handleWidgetAction($event, this.descriptor, entityId, entityName, null, entityLabel);
|
handleWidgetAction($event, this.descriptor, entityId, entityName, null, entityLabel);
|
||||||
}
|
}
|
||||||
widgetContext.customHeaderActions.push(headerAction);
|
widgetContext.customHeaderActions.push(headerAction);
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<md-dialog aria-label="{{ 'dashboard.manage-states' | translate }}" style="width: 620px;">
|
<md-dialog aria-label="{{ 'dashboard.manage-states' | translate }}" style="min-width: 600px;">
|
||||||
<form name="theForm" ng-submit="vm.save()">
|
<form name="theForm" ng-submit="vm.save()">
|
||||||
<md-toolbar>
|
<md-toolbar>
|
||||||
<div class="md-toolbar-tools">
|
<div class="md-toolbar-tools">
|
||||||
@ -72,7 +72,7 @@
|
|||||||
</md-toolbar>
|
</md-toolbar>
|
||||||
<md-table-container>
|
<md-table-container>
|
||||||
<table md-table>
|
<table md-table>
|
||||||
<thead fix-head md-head md-order="vm.query.order" md-on-reorder="vm.onReorder">
|
<thead md-head md-order="vm.query.order" md-on-reorder="vm.onReorder">
|
||||||
<tr md-row>
|
<tr md-row>
|
||||||
<th md-column md-order-by="name"><span translate>dashboard.state-name</span></th>
|
<th md-column md-order-by="name"><span translate>dashboard.state-name</span></th>
|
||||||
<th md-column md-order-by="id"><span translate>dashboard.state-id</span></th>
|
<th md-column md-order-by="id"><span translate>dashboard.state-id</span></th>
|
||||||
|
|||||||
@ -22,13 +22,14 @@ import entitySelectTemplate from './entity-select.tpl.html';
|
|||||||
/* eslint-enable import/no-unresolved, import/default */
|
/* eslint-enable import/no-unresolved, import/default */
|
||||||
|
|
||||||
/*@ngInject*/
|
/*@ngInject*/
|
||||||
export default function EntitySelect($compile, $templateCache, entityService) {
|
export default function EntitySelect($compile, $templateCache, entityService, types) {
|
||||||
|
|
||||||
var linker = function (scope, element, attrs, ngModelCtrl) {
|
var linker = function (scope, element, attrs, ngModelCtrl) {
|
||||||
var template = $templateCache.get(entitySelectTemplate);
|
var template = $templateCache.get(entitySelectTemplate);
|
||||||
element.html(template);
|
element.html(template);
|
||||||
|
|
||||||
scope.tbRequired = angular.isDefined(scope.tbRequired) ? scope.tbRequired : false;
|
scope.tbRequired = angular.isDefined(scope.tbRequired) ? scope.tbRequired : false;
|
||||||
|
scope.entityTypeCurrentTenant = types.aliasEntityType.current_tenant;
|
||||||
|
|
||||||
var entityTypes = entityService.prepareAllowedEntityTypesList(scope.allowedEntityTypes, scope.useAliasEntityTypes);
|
var entityTypes = entityService.prepareAllowedEntityTypesList(scope.allowedEntityTypes, scope.useAliasEntityTypes);
|
||||||
|
|
||||||
@ -48,7 +49,8 @@ export default function EntitySelect($compile, $templateCache, entityService) {
|
|||||||
scope.updateView = function () {
|
scope.updateView = function () {
|
||||||
if (!scope.disabled) {
|
if (!scope.disabled) {
|
||||||
var value = ngModelCtrl.$viewValue;
|
var value = ngModelCtrl.$viewValue;
|
||||||
if (scope.model && scope.model.entityType && scope.model.entityId) {
|
if (scope.model && scope.model.entityType &&
|
||||||
|
(scope.model.entityId || scope.model.entityType === scope.entityTypeCurrentTenant)) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
value = {};
|
value = {};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
allowed-entity-types="allowedEntityTypes"
|
allowed-entity-types="allowedEntityTypes"
|
||||||
ng-model="model.entityType">
|
ng-model="model.entityType">
|
||||||
</tb-entity-type-select>
|
</tb-entity-type-select>
|
||||||
<tb-entity-autocomplete flex ng-if="model.entityType"
|
<tb-entity-autocomplete flex ng-if="model.entityType && model.entityType !== entityTypeCurrentTenant"
|
||||||
the-form="theForm"
|
the-form="theForm"
|
||||||
ng-disabled="disabled"
|
ng-disabled="disabled"
|
||||||
tb-required="tbRequired"
|
tb-required="tbRequired"
|
||||||
|
|||||||
@ -770,6 +770,7 @@
|
|||||||
"list-of-rulenodes": "{ count, plural, 1 {Jeden uzel pravidla} other {Seznam # uzlů pravidel} }",
|
"list-of-rulenodes": "{ count, plural, 1 {Jeden uzel pravidla} other {Seznam # uzlů pravidel} }",
|
||||||
"rulenode-name-starts-with": "Uzly pravidel, jejichž název začíná '{{prefix}}'",
|
"rulenode-name-starts-with": "Uzly pravidel, jejichž název začíná '{{prefix}}'",
|
||||||
"type-current-customer": "Stávající zákazník",
|
"type-current-customer": "Stávající zákazník",
|
||||||
|
"type-current-tenant": "Stávající tenant",
|
||||||
"search": "Vyhledat entity",
|
"search": "Vyhledat entity",
|
||||||
"selected-entities": "{ count, plural, 1 {1 entita} other {# entit} } zvoleno",
|
"selected-entities": "{ count, plural, 1 {1 entita} other {# entit} } zvoleno",
|
||||||
"entity-name": "Název entity",
|
"entity-name": "Název entity",
|
||||||
|
|||||||
@ -811,6 +811,7 @@
|
|||||||
"list-of-rulenodes": "{ count, plural, 1 {One rule node} other {List of # rule nodes} }",
|
"list-of-rulenodes": "{ count, plural, 1 {One rule node} other {List of # rule nodes} }",
|
||||||
"rulenode-name-starts-with": "Rule nodes whose names start with '{{prefix}}'",
|
"rulenode-name-starts-with": "Rule nodes whose names start with '{{prefix}}'",
|
||||||
"type-current-customer": "Current Customer",
|
"type-current-customer": "Current Customer",
|
||||||
|
"type-current-tenant": "Current Tenant",
|
||||||
"search": "Search entities",
|
"search": "Search entities",
|
||||||
"selected-entities": "{ count, plural, 1 {1 entity} other {# entities} } selected",
|
"selected-entities": "{ count, plural, 1 {1 entity} other {# entities} } selected",
|
||||||
"entity-name": "Entity name",
|
"entity-name": "Entity name",
|
||||||
|
|||||||
@ -809,6 +809,7 @@
|
|||||||
"list-of-rulenodes": "{ count, plural, 1 {Одно правило} other {Список из # правил} }",
|
"list-of-rulenodes": "{ count, plural, 1 {Одно правило} other {Список из # правил} }",
|
||||||
"rulenode-name-starts-with": "Правила, чьи названия начинаются с '{{prefix}}'",
|
"rulenode-name-starts-with": "Правила, чьи названия начинаются с '{{prefix}}'",
|
||||||
"type-current-customer": "Текущий клиент",
|
"type-current-customer": "Текущий клиент",
|
||||||
|
"type-current-tenant": "Текущий владелец",
|
||||||
"search": "Поиск объектов",
|
"search": "Поиск объектов",
|
||||||
"selected-entities": "Выбран(ы) { count, plural, 1 {1 объект} few {# объекта} other {# объектов} }",
|
"selected-entities": "Выбран(ы) { count, plural, 1 {1 объект} few {# объекта} other {# объектов} }",
|
||||||
"entity-name": "Название объекта",
|
"entity-name": "Название объекта",
|
||||||
|
|||||||
@ -942,6 +942,7 @@
|
|||||||
"list-of-rulenodes": "{ count, plural, 1 {Одне правило} other {Список # правил} }",
|
"list-of-rulenodes": "{ count, plural, 1 {Одне правило} other {Список # правил} }",
|
||||||
"rulenode-name-starts-with": "Список правил, імена яких починаються '{{prefix}}'",
|
"rulenode-name-starts-with": "Список правил, імена яких починаються '{{prefix}}'",
|
||||||
"type-current-customer": "Поточний клієнт",
|
"type-current-customer": "Поточний клієнт",
|
||||||
|
"type-current-tenant": "Поточний власник",
|
||||||
"search": "Пошук сутностей",
|
"search": "Пошук сутностей",
|
||||||
"selected-entities": "{ count, plural, 1 {1 сутність} other {# сутності} } вибрано",
|
"selected-entities": "{ count, plural, 1 {1 сутність} other {# сутності} } вибрано",
|
||||||
"entity-name": "Ім'я сутності",
|
"entity-name": "Ім'я сутності",
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import logoSvg from '../../svg/logo_title_white.svg';
|
|||||||
/* eslint-enable import/no-unresolved, import/default */
|
/* eslint-enable import/no-unresolved, import/default */
|
||||||
|
|
||||||
/*@ngInject*/
|
/*@ngInject*/
|
||||||
export default function LoginController(toast, loginService, userService, types, $state/*, $rootScope, $log, $translate*/) {
|
export default function LoginController(toast, loginService, userService, types, $state, $stateParams/*, $rootScope, $log, $translate*/) {
|
||||||
var vm = this;
|
var vm = this;
|
||||||
|
|
||||||
vm.logoSvg = logoSvg;
|
vm.logoSvg = logoSvg;
|
||||||
@ -32,6 +32,12 @@ export default function LoginController(toast, loginService, userService, types,
|
|||||||
|
|
||||||
vm.login = login;
|
vm.login = login;
|
||||||
|
|
||||||
|
if ($stateParams.username && $stateParams.password) {
|
||||||
|
vm.user.name = $stateParams.username;
|
||||||
|
vm.user.password = $stateParams.password;
|
||||||
|
doLogin();
|
||||||
|
}
|
||||||
|
|
||||||
function doLogin() {
|
function doLogin() {
|
||||||
loginService.login(vm.user).then(function success(response) {
|
loginService.login(vm.user).then(function success(response) {
|
||||||
var token = response.data.token;
|
var token = response.data.token;
|
||||||
|
|||||||
@ -25,7 +25,7 @@ import createPasswordTemplate from './create-password.tpl.html';
|
|||||||
/*@ngInject*/
|
/*@ngInject*/
|
||||||
export default function LoginRoutes($stateProvider) {
|
export default function LoginRoutes($stateProvider) {
|
||||||
$stateProvider.state('login', {
|
$stateProvider.state('login', {
|
||||||
url: '/login',
|
url: '/login?username&password',
|
||||||
module: 'public',
|
module: 'public',
|
||||||
views: {
|
views: {
|
||||||
"@": {
|
"@": {
|
||||||
|
|||||||
@ -52,6 +52,11 @@ function WebCameraWidgetController($element, $scope, $window, types, utils, attr
|
|||||||
let canvas = null;
|
let canvas = null;
|
||||||
let photoCamera = null;
|
let photoCamera = null;
|
||||||
let dataKeyType = "";
|
let dataKeyType = "";
|
||||||
|
let width = 640;
|
||||||
|
let height = 480;
|
||||||
|
|
||||||
|
const DEFAULT_IMAGE_TYPE = 'image/jpeg';
|
||||||
|
const DEFAULT_IMAGE_QUALITY = 0.92;
|
||||||
|
|
||||||
vm.getStream = getStream;
|
vm.getStream = getStream;
|
||||||
vm.createPhoto = createPhoto;
|
vm.createPhoto = createPhoto;
|
||||||
@ -79,6 +84,8 @@ function WebCameraWidgetController($element, $scope, $window, types, utils, attr
|
|||||||
vm.isEntityDetected = true;
|
vm.isEntityDetected = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
width = vm.ctx.settings.maxWidth ? vm.ctx.settings.maxWidth : 640;
|
||||||
|
height = vm.ctx.settings.maxHeight ? vm.ctx.settings.maxWidth : 480;
|
||||||
if (datasource.dataKeys.length) {
|
if (datasource.dataKeys.length) {
|
||||||
$scope.currentKey = datasource.dataKeys[0].name;
|
$scope.currentKey = datasource.dataKeys[0].name;
|
||||||
dataKeyType = datasource.dataKeys[0].type;
|
dataKeyType = datasource.dataKeys[0].type;
|
||||||
@ -93,6 +100,24 @@ function WebCameraWidgetController($element, $scope, $window, types, utils, attr
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getVideoAspectRatio() {
|
||||||
|
if (videoElement.videoWidth && videoElement.videoWidth > 0 &&
|
||||||
|
videoElement.videoHeight && videoElement.videoHeight > 0) {
|
||||||
|
return videoElement.videoWidth / videoElement.videoHeight;
|
||||||
|
}
|
||||||
|
return width / height;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.videoWidth = function() {
|
||||||
|
const videoRatio = getVideoAspectRatio();
|
||||||
|
return Math.min(width, height * videoRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.videoHeight = function() {
|
||||||
|
const videoRatio = getVideoAspectRatio();
|
||||||
|
return Math.min(height, width / videoRatio);
|
||||||
|
}
|
||||||
|
|
||||||
function hasGetUserMedia() {
|
function hasGetUserMedia() {
|
||||||
return !!($window.navigator.mediaDevices && $window.navigator.mediaDevices.getUserMedia);
|
return !!($window.navigator.mediaDevices && $window.navigator.mediaDevices.getUserMedia);
|
||||||
}
|
}
|
||||||
@ -157,10 +182,12 @@ function WebCameraWidgetController($element, $scope, $window, types, utils, attr
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createPhoto() {
|
function createPhoto() {
|
||||||
canvas.width = videoElement.videoWidth;
|
canvas.width = vm.videoWidth();
|
||||||
canvas.height = videoElement.videoHeight;
|
canvas.height = vm.videoHeight();
|
||||||
canvas.getContext('2d').drawImage(videoElement, 0, 0);
|
canvas.getContext('2d').drawImage(videoElement, 0, 0, vm.videoWidth(), vm.videoHeight());
|
||||||
vm.previewPhoto = canvas.toDataURL('image/png');
|
const mimeType = vm.ctx.settings.imageFormat ? vm.ctx.settings.imageFormat : DEFAULT_IMAGE_TYPE;
|
||||||
|
const quality = vm.ctx.settings.imageQuality ? vm.ctx.settings.imageQuality : DEFAULT_IMAGE_QUALITY;
|
||||||
|
vm.previewPhoto = canvas.toDataURL(mimeType, quality);
|
||||||
vm.isPreviewPhoto = true;
|
vm.isPreviewPhoto = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user