Skip to content

Commit

Permalink
feat(device): add transfer capabilties (#446)
Browse files Browse the repository at this point in the history
* feat(device): add transfer capabilties

Add transfer view and functionality to edit device page

* Add basic claim functionality to dashboard

* Refresh devices after claiming

* Remove unused variables

* Add form and use pattern for validation

* Wrap input-group in form-group

* Add alert on errors

* Reorganize dashboard styling

* Style transfer settings page

* Add translation keys
  • Loading branch information
mpfeil authored Sep 6, 2022
1 parent cb78b8e commit da4bc8d
Show file tree
Hide file tree
Showing 9 changed files with 273 additions and 5 deletions.
1 change: 1 addition & 0 deletions app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@
<script src="scripts/controllers/account.box.edit.script.js"></script>
<script src="scripts/controllers/account.box.edit.mqtt.js"></script>
<script src="scripts/controllers/account.box.edit.ttn.js"></script>
<script src="scripts/controllers/account.box.edit.transfer.js"></script>
<script src="scripts/controllers/account.box.dataupload.js"></script>
<script src="scripts/services/account.js"></script>
<script src="scripts/services/directus.js"></script>
Expand Down
10 changes: 10 additions & 0 deletions app/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,16 @@
},
},
})
.state('account.edit.transfer', {
url: '/transfer',
views: {
edit: {
controller: 'EditBoxTransferController',
controllerAs: 'transfer',
templateUrl: 'views/account.box.edit.transfer.html',
},
},
})
.state('account.dashboard', {
url: '',
views: {
Expand Down
79 changes: 79 additions & 0 deletions app/scripts/controllers/account.box.edit.transfer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
(function () {
'use strict';

angular
.module('openSenseMapApp')
.controller('EditBoxTransferController', EditBoxTransferController);

EditBoxTransferController.$inject = ['boxData', 'moment', 'AccountService'];

function EditBoxTransferController (boxData, moment, AccountService) {
var vm = this;
vm.device = {};
vm.deviceName = '';
vm.data = {};
vm.tokenExists = false;
vm.expiration = '1';

vm.transferDevice = transferDevice;
vm.revokeToken = revokeToken;

activate();

////

function activate () {
if (angular.isDefined(boxData)) {
angular.copy(boxData, vm.device);

return AccountService.getTransferToken(vm.device._id)
.then(function (response) {
if (response.data) {
angular.copy(response.data, vm.data);
vm.tokenExists = true;
}
})
.catch(function (error) {
console.log(error);
});
}
}

function transferDevice () {

var payload = {
boxId: vm.device._id,
date: moment.utc().add(vm.expiration, 'd')
.toDate()
};

return AccountService.transferDevice(payload)
.then(function (response) {
angular.copy(response.data, vm.data);
vm.tokenExists = true;
})
.catch(function (error) {
console.log(error);
});
}

function revokeToken () {
var payload = {
boxId: vm.device._id,
token: vm.data.token
};

return AccountService.revokeToken(payload)
.then(function (response) {
if (response.status === 204) {
angular.copy({}, vm.data);
vm.tokenExists = false;
}
})
.catch(function (error) {
console.log(error);
});
}

}
})();
34 changes: 34 additions & 0 deletions app/scripts/controllers/account.dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
vm.boxes = [];
vm.listStyle = 'tiles';
vm.orderByProperty = 'createdAt';
vm.claimToken = '';
vm.claimPattern = /^[a-z0-9]*$/;
vm.errorMessage = '';

vm.claimDevice = claimDevice;
vm.closeAlert = closeAlert;

activate();

Expand Down Expand Up @@ -47,6 +53,34 @@
});
}

function claimDevice () {
var payload = {
token: vm.claimToken
};



return AccountService.claimDevice(payload)
.then(function () {

// Clear token field
vm.claimToken = '';

return getUsersBoxes()
.then(function () {
// console.log('refreshed boxes');
});
})
.catch(function (error) {
console.log(error);
vm.errorMessage = error.message;
});
}

function closeAlert () {
vm.errorMessage = '';
}

$scope.$watch('dashboard.listStyle', function (value) {
LocalStorageService.setValue(localStorageKey, value);
});
Expand Down
52 changes: 51 additions & 1 deletion app/scripts/services/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@
deleteMeasurement: deleteMeasurement,
postNewBox: postNewBox,
deleteAccount: deleteAccount,
compileSketch: compileSketch
compileSketch: compileSketch,
transferDevice: transferDevice,
revokeToken: revokeToken,
getTransferToken: getTransferToken,
claimDevice: claimDevice
};

return service;
Expand Down Expand Up @@ -246,5 +250,51 @@
})
.catch(failed);
}

function getTransferToken (boxId) {
return $http
.get(app.API_URL + '/boxes/transfer/' + boxId, {
auth: true,
})
.then(function (response) {
return response.data;
})
.catch(failed);
}

function transferDevice (data) {
return $http.post(app.API_URL + '/boxes/transfer', data, {
auth: true,
})
.then(function (response) {
return response.data;
})
.catch(failed);
}

function revokeToken (data) {
return $http
.delete(app.API_URL + '/boxes/transfer', {
auth: true,
data: data,
headers: {
'Content-type': 'application/json;charset=utf-8',
},
})
.then(function (response) {
return response;
})
.catch(failed);
}

function claimDevice (data) {
return $http.post(app.API_URL + '/boxes/claim', data, {
auth: true
})
.then(function (response) {
return response.data;
})
.catch(failed);
}
}
})();
1 change: 1 addition & 0 deletions app/scripts/services/authenticationInterceptor.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
});

return deferred.promise;
case 400:
case 404:
return $q.reject(response);
default:
Expand Down
1 change: 1 addition & 0 deletions app/views/account.box.edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<li ng-class="{'active': edit.tabActive.script}" ng-click="edit.changeActiveTab('script')"><a ui-sref="account.edit.script"><i class="fa fa-file-text-o fa-fw"></i> {{'EDIT_SCRIPT'|translate}}</a></li>
<li ng-class="{'active': edit.tabActive.mqtt}" ng-click="edit.changeActiveTab('mqtt')"><a ui-sref="account.edit.mqtt"><i class="fa fa-wifi fa-fw"></i> {{'EDIT_MQTTOPTIONS'|translate}}</a></li>
<li ng-class="{'active': edit.tabActive.ttn}" ng-click="edit.changeActiveTab('ttn')"><a ui-sref="account.edit.ttn"><i class="fa fa-cloud-upload fa-fw"></i> {{'EDIT_TTN'|translate}}</a></li>
<li ng-class="{'active': edit.tabActive.transfer}" ng-click="edit.changeActiveTab('transfer')"><a ui-sref="account.edit.transfer"><i class="fa fa-exchange fa-fw"></i> {{'EDIT_TRANSFER'|translate}}</a></li>
</ul>
</div>
<div class="col-lg-9 col-md-9">
Expand Down
62 changes: 62 additions & 0 deletions app/views/account.box.edit.transfer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<div class="transferSettings">
<div class="row">
<div class="col-md-6 col-lg-6">
<h2 style="margin-top: 0px; margin-bottom: 0px">{{'EDIT_TRANSFER'|translate}}</h2>
</div>
</div>

<hr>

<div class="row">
<div class="col-md-6 col-lg-6">

<div uib-alert class="alert-warning">
<p>
<span class="fa fa-exclamation-circle" aria-hidden="true"></span>
{{'TRANSFER_NOTICE' | translate}}
</p>
<hr>
<p ng-bind-html="'TRANSFER_INFORMATION'|translate"></p>
</div>

<div ng-show="transfer.tokenExists" style="border: 1px solid grey; border-radius: 6px;">
<div style="min-height: inherit; padding: 8px; box-sizing: border-box;">
<div style="display: flex; float: right; box-sizing: border-box;">
<button ng-click="transfer.revokeToken()" class="btn btn-danger">{{'REVOKE' | translate}}</button>
</div>
<small style="margin-right: 8px; float: right;">
{{'CREATED_AT' | translate}}: {{transfer.data.createdAt | amUtc | amLocal | amDateFormat:'l LTS'}}
</small>
<span>Token:</span>
<code>{{transfer.data.token}} <button osem-clipboard class="btn-toClipboard" text="transfer.data.token" title="Copy to Clipboard"><i class="fa fa-clipboard"></i></button></code>
<div>
<span>{{'EXPIRES_AT' | translate}}: {{transfer.data.expiresAt | amUtc | amLocal | amDateFormat:'l LTS'}}</span>
</div>
</div>
</div>

<div ng-hide="transfer.tokenExists">
<form name="tokenForm" novalidate>
<div class="form-group">
<label for="expiration">{{'EXPIRATION' | translate}}</label>
<select class="form-control" ng-model="transfer.expiration" ng-change="transfer.changeExpiration()" name="expiration" id="expiration">
<option value="1">1 {{'DAY' | translate}}</option>
<option value="7">7 {{'DAYS' | translate}}</option>
<option value="30">30 {{'DAYS' | translate}}</option>
<option value="60">60 {{'DAYS' | translate}}</option>
<option value="90">90 {{'DAYS' | translate}}</option>
</select>
</div>
<div class="form-group" >
<label class="control-label" translate="TRANSFER_INPUT_LABEL" translate-value-name="{{transfer.device.name}}"></label>
<input type="text" name="name" id="name" class="form-control" ng-model="transfer.deviceName" required>
</div>
<div class="form-group">
<button ng-disabled="transfer.deviceName !== transfer.device.name" ng-click="transfer.transferDevice()" class="btn btn-danger col-md-12">{{'TRANSFER_BUTTON_TEXT' | translate}}</button>
</div>
</form>
</div>
</div>
</div>

</div>
38 changes: 34 additions & 4 deletions app/views/account.dashboard.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<div class="container">
<div class="row">
<div class="col-lg-12 col-sm-12 col-md-12" style="padding-top: 15px;">
<div class="thumbnail">
<!-- First row with stats and token transfer -->
<div class="row" style="display: flex; flex-wrap: wrap;">
<div class="col-lg-6 col-sm-12 col-md-12" style="margin-bottom: 30px;">
<div class="thumbnail" style="height: 100%;">
<div class="caption">
<h3 translate="REGISTERED_BOXES" translate-values="{count: dashboard.boxes.length}"></h3>
<p>{{'REGISTERED_BOXES_INFO' | translate}}</p>
Expand All @@ -16,6 +17,35 @@ <h3 translate="REGISTERED_BOXES" translate-values="{count: dashboard.boxes.lengt
</div>
</div>

<div class="col-lg-6 col-sm-12 col-md-12" style="margin-bottom: 30px;">
<div class="thumbnail" style="height: 100%;">
<div class="caption">
<h3>{{'CLAIM_HEADER' | translate}}</h3>
<form name="claimForm" novalidate>
<div class="form-group">
<label for="token" ng-bind-html="'CLAIM_INFORMATION'|translate"></label>
<div class="input-group">
<input type="text" name="token" id="token" class="form-control" placeholder="Token" ng-model="dashboard.claimToken" ng-pattern="dashboard.claimPattern" maxlength="12">
<span class="input-group-btn">
<button class="btn btn-primary" type="button" ng-click="dashboard.claimDevice()" ng-disabled="dashboard.claimToken === ''">{{'CLAIM_DEVICE' | translate}}</button>
</span>
</div><!-- /input-group -->
<span class="help-block" ng-show="claimForm.token.$error.pattern">{{'CLAIM_VALID_TOKEN' | translate}}</span><br>
</div>
</form>
<div class="alert alert-danger alert-dismissible" role="alert" ng-show="dashboard.errorMessage">
<button type="button" class="close" data-dismiss="alert" aria-label="Close" ng-click="dashboard.closeAlert()">
<span aria-hidden="true">&times;</span>
</button>
{{dashboard.errorMessage}}
</div>
</div>
</div>
</div>
</div>

<!-- Second row with options for device list -->
<div class="row">
<div class="col-sm-4 col-sm-offset-8 clearfix">
<div class="btn-group pull-right">
<label class="btn btn-default" ng-model="dashboard.listStyle" uib-btn-radio="'tiles'">
Expand All @@ -37,8 +67,8 @@ <h3 translate="REGISTERED_BOXES" translate-values="{count: dashboard.boxes.lengt
</button>
</div>
</div>

</div>

<div class="row" ng-show="dashboard.listStyle==='tiles'">
<div class="col-lg-6" ng-repeat="box in dashboard.boxes | orderBy: dashboard.orderByProperty"
style="padding-top: 15px;">
Expand Down

0 comments on commit da4bc8d

Please sign in to comment.