account menu complete
This commit is contained in:
@@ -32,11 +32,10 @@ angular.module('app.frontend')
|
||||
this.updateOfflineStatus();
|
||||
|
||||
this.findErrors = function() {
|
||||
this.error = syncManager.error;
|
||||
this.error = syncManager.syncStatus.error;
|
||||
}
|
||||
this.findErrors();
|
||||
|
||||
|
||||
this.accountMenuPressed = function() {
|
||||
this.serverData = {};
|
||||
this.showAccountMenu = !this.showAccountMenu;
|
||||
|
||||
@@ -92,7 +92,7 @@ angular.module('app.frontend')
|
||||
|
||||
this.handleAuthResponse = function(response, email, url, authParams, mk) {
|
||||
localStorage.setItem("server", url);
|
||||
localStorage.setItem("user", JSON.stringify(response.plain()));
|
||||
localStorage.setItem("user", JSON.stringify(response.plain().user));
|
||||
localStorage.setItem("auth_params", JSON.stringify(_.omit(authParams, ["pw_nonce"])));
|
||||
localStorage.setItem("mk", mk);
|
||||
localStorage.setItem("jwt", response.token);
|
||||
@@ -243,10 +243,8 @@ angular.module('app.frontend')
|
||||
items: items
|
||||
}
|
||||
|
||||
if(ek.name == SNKeyName) {
|
||||
// auth params are only needed when encrypted with a standard file key
|
||||
data["auth_params"] = this.getAuthParams();
|
||||
}
|
||||
// auth params are only needed when encrypted with a standard file key
|
||||
data["auth_params"] = this.getAuthParams();
|
||||
|
||||
return makeTextFile(JSON.stringify(data, null, 2 /* pretty print */));
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ class AccountMenu {
|
||||
|
||||
$scope.formData = {url: syncManager.serverURL};
|
||||
$scope.user = authManager.user;
|
||||
$scope.server = syncManager.serverURL;
|
||||
|
||||
$scope.syncStatus = syncManager.syncStatus;
|
||||
|
||||
$scope.changePasswordPressed = function() {
|
||||
$scope.showNewPasswordForm = !$scope.showNewPasswordForm;
|
||||
@@ -37,14 +40,14 @@ class AccountMenu {
|
||||
console.log("logging in with url", $scope.formData.url);
|
||||
$timeout(function(){
|
||||
authManager.login($scope.formData.url, $scope.formData.email, $scope.formData.user_password, function(response){
|
||||
$scope.formData.status = null;
|
||||
if(!response || response.error) {
|
||||
$scope.formData.status = null;
|
||||
var error = response ? response.error : {message: "An unknown error occured."}
|
||||
if(!response || (response && !response.didDisplayAlert)) {
|
||||
alert(error.message);
|
||||
}
|
||||
} else {
|
||||
window.location.reload();
|
||||
$scope.onAuthSuccess();
|
||||
}
|
||||
});
|
||||
})
|
||||
@@ -55,17 +58,23 @@ class AccountMenu {
|
||||
|
||||
$timeout(function(){
|
||||
authManager.register($scope.formData.url, $scope.formData.email, $scope.formData.user_password, function(response){
|
||||
$scope.formData.status = null;
|
||||
if(!response || response.error) {
|
||||
$scope.formData.status = null;
|
||||
var error = response ? response.error : {message: "An unknown error occured."}
|
||||
alert(error.message);
|
||||
} else {
|
||||
window.location.reload();
|
||||
$scope.onAuthSuccess();
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
$scope.onAuthSuccess = function() {
|
||||
syncManager.markAllItemsDirtyAndSaveOffline(function(){
|
||||
window.location.reload();
|
||||
})
|
||||
}
|
||||
|
||||
$scope.destroyLocalData = function() {
|
||||
if(!confirm("Are you sure you want to end your session? This will delete all local items and extensions.")) {
|
||||
return;
|
||||
@@ -79,24 +88,16 @@ class AccountMenu {
|
||||
|
||||
/* Import/Export */
|
||||
|
||||
$scope.archiveFormData = {encryption_type: $scope.user ? 'mk' : 'ek'};
|
||||
$scope.archiveFormData = {encrypted: $scope.user ? true : false};
|
||||
$scope.user = authManager.user;
|
||||
|
||||
$scope.downloadDataArchive = function() {
|
||||
if($scope.archiveFormData.encryption_type == 'ek') {
|
||||
if(!$scope.archiveFormData.ek) {
|
||||
alert("You must set an encryption key to export the data encrypted.")
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var link = document.createElement('a');
|
||||
link.setAttribute('download', 'notes.json');
|
||||
|
||||
var ek = $scope.archiveFormData.encryption_type == 'ek' ? $scope.archiveFormData.ek : null;
|
||||
var encrypted = $scope.archiveFormData.encryption_type != 'none';
|
||||
var ek = $scope.archiveFormData.encrypted ? syncManager.masterKey : null;
|
||||
|
||||
link.href = authManager.itemsDataFile(encrypted, ek);
|
||||
link.href = authManager.itemsDataFile(ek);
|
||||
link.click();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,10 @@ class SyncManager {
|
||||
return localStorage.getItem("server") || "http://localhost:3000";
|
||||
}
|
||||
|
||||
get masterKey() {
|
||||
return localStorage.getItem("mk");
|
||||
}
|
||||
|
||||
writeItemsToLocalStorage(items, offlineOnly, callback) {
|
||||
var params = items.map(function(item) {
|
||||
var itemParams = new ItemParams(item, null);
|
||||
@@ -49,13 +53,21 @@ class SyncManager {
|
||||
}
|
||||
}
|
||||
|
||||
markAllItemsDirtyAndSaveOffline(callback) {
|
||||
var items = this.modelManager.allItems;
|
||||
for(var item of items) {
|
||||
item.setDirty(true);
|
||||
}
|
||||
this.writeItemsToLocalStorage(items, false, callback);
|
||||
}
|
||||
|
||||
get syncURL() {
|
||||
return this.serverURL + "/items/sync";
|
||||
}
|
||||
|
||||
sync(callback, options = {}) {
|
||||
|
||||
if(this.syncOpInProgress) {
|
||||
if(this.syncStatus.syncOpInProgress) {
|
||||
this.repeatOnCompletion = true;
|
||||
console.log("Sync op in progress; returning.");
|
||||
return;
|
||||
@@ -74,7 +86,7 @@ class SyncManager {
|
||||
var isContinuationSync = this.needsMoreSync;
|
||||
|
||||
this.repeatOnCompletion = false;
|
||||
this.syncOpInProgress = true;
|
||||
this.syncStatus.syncOpInProgress = true;
|
||||
|
||||
let submitLimit = 100;
|
||||
var subItems = allDirtyItems.slice(0, submitLimit);
|
||||
@@ -103,7 +115,7 @@ class SyncManager {
|
||||
|
||||
request.post().then(function(response) {
|
||||
this.modelManager.clearDirtyItems(subItems);
|
||||
this.error = null;
|
||||
this.syncStatus.error = null;
|
||||
this.syncToken = response.sync_token;
|
||||
this.cursorToken = response.cursor_token;
|
||||
|
||||
@@ -119,7 +131,7 @@ class SyncManager {
|
||||
this.writeItemsToLocalStorage(saved, false, null);
|
||||
this.writeItemsToLocalStorage(retrieved, false, null);
|
||||
|
||||
this.syncOpInProgress = false;
|
||||
this.syncStatus.syncOpInProgress = false;
|
||||
this.syncStatus.current += subItems.length;
|
||||
|
||||
if(this.cursorToken || this.repeatOnCompletion || this.needsMoreSync) {
|
||||
@@ -135,8 +147,8 @@ class SyncManager {
|
||||
console.log("Sync error: ", response);
|
||||
var error = response.data ? response.data.error : {message: "Could not connect to server."};
|
||||
|
||||
this.syncOpInProgress = false;
|
||||
this.error = error;
|
||||
this.syncStatus.syncOpInProgress = false;
|
||||
this.syncStatus.error = error;
|
||||
this.writeItemsToLocalStorage(allDirtyItems, false, null);
|
||||
|
||||
this.$rootScope.$broadcast("sync:error", error);
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
margin-top: 15px !important;
|
||||
}
|
||||
|
||||
.mt-25 {
|
||||
margin-top: 25px !important;
|
||||
}
|
||||
|
||||
.mb-10 {
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
@@ -54,22 +58,54 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
.medium-v-space {
|
||||
height: 12px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.large-v-space {
|
||||
height: 24px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.medium-padding {
|
||||
padding: 10px !important;
|
||||
}
|
||||
|
||||
.large-padding {
|
||||
padding: 15px !important;
|
||||
padding: 22px !important;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
.blue {
|
||||
color: $blue-color;
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.normal {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.fake-link {
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
color: $blue-color;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-bar {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
@@ -114,6 +150,11 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 0px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px !important;
|
||||
margin-top: 4px !important;
|
||||
@@ -122,6 +163,7 @@
|
||||
|
||||
h4 {
|
||||
margin-bottom: 0px !important;
|
||||
font-size: 13px !important;
|
||||
}
|
||||
|
||||
section {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
.panel.panel-default.panel-right.account-data-menu
|
||||
.panel-body
|
||||
|
||||
-# If not user
|
||||
.panel-body.large-padding
|
||||
%div{"ng-if" => "!user"}
|
||||
%p Enter your <a href="https://standardnotes.org" target="_blank">Standard File</a> account information. You can also register for free using the default server address.
|
||||
.small-v-space
|
||||
@@ -26,31 +24,38 @@
|
||||
%p{"style" => "font-size: 13px; text-align: center;"}
|
||||
Because notes are locally encrypted using a secret key derived from your password, there's no way to decrypt these notes if you forget your password.
|
||||
For this reason, Standard Notes cannot offer a password reset option. You <strong>must</strong> make sure to store or remember your password.
|
||||
-# End if not user
|
||||
|
||||
-# If user
|
||||
%div{"ng-if" => "user"}
|
||||
%label Local Encryption
|
||||
%h2 {{user.email}}
|
||||
%p {{server}}
|
||||
|
||||
%p.bold.mt-10.blue{"delay-hide" => "true", "show" => "syncStatus.syncOpInProgress", "delay" => "1000"} Syncing: {{syncStatus.current}}/{{syncStatus.total}}
|
||||
%p.bold.mt-10.red.block{"ng-if" => "syncStatus.error"} Error syncing: {{syncStatus.error.message}}
|
||||
|
||||
.medium-v-space
|
||||
|
||||
%h4 Local Encryption
|
||||
%p Notes are encrypted locally before being sent to the server. Neither the server owner nor an intrusive entity can decrypt your locally encrypted notes.
|
||||
%label Status:
|
||||
{{encryptionStatusForNotes()}}
|
||||
-# End if user
|
||||
%div.mt-5
|
||||
%label Status:
|
||||
{{encryptionStatusForNotes()}}
|
||||
|
||||
.mt-5{"ng-if" => "user"}
|
||||
%label{"ng-if" => "user"}
|
||||
%input{"type" => "radio", "ng-model" => "archiveFormData.encrypted", "ng-value" => "true", "ng-change" => "archiveFormData.encrypted = true"}
|
||||
Encrypted
|
||||
%label
|
||||
%input{"type" => "radio", "ng-model" => "archiveFormData.encrypted", "ng-value" => "false", "ng-change" => "archiveFormData.encrypted = false"}
|
||||
Decrypted
|
||||
%a{"ng-click" => "downloadDataArchive()"} Download Data Archive
|
||||
.mt-25{"ng-if" => "!importData.loading"}
|
||||
%h4 Data Archives
|
||||
.mt-5{"ng-if" => "user"}
|
||||
%label.normal.inline{"ng-if" => "user"}
|
||||
%input{"type" => "radio", "ng-model" => "archiveFormData.encrypted", "ng-value" => "true", "ng-change" => "archiveFormData.encrypted = true"}
|
||||
Encrypted
|
||||
%label.normal.inline
|
||||
%input{"type" => "radio", "ng-model" => "archiveFormData.encrypted", "ng-value" => "false", "ng-change" => "archiveFormData.encrypted = false"}
|
||||
Decrypted
|
||||
|
||||
%a.block{"ng-click" => "downloadDataArchive()"} Download Data Archive
|
||||
|
||||
%label.block.mt-5
|
||||
%input{"type" => "file", "style" => "display: none;", "file-change" => "->", "handler" => "ctrl.importFileSelected(files)"}
|
||||
.fake-link Import Data from Archive
|
||||
|
||||
%div{"ng-if" => "!importData.loading"}
|
||||
%label#import-archive
|
||||
%input{"type" => "file", "style" => "display: none;", "file-change" => "->", "handler" => "importFileSelected(files)"}
|
||||
%a.disabled
|
||||
%span
|
||||
Import Data from Archive
|
||||
%div{"ng-if" => "importData.requestPassword"}
|
||||
Enter the account password associated with the import file.
|
||||
%input{"type" => "text", "ng-model" => "importData.password"}
|
||||
@@ -58,4 +63,4 @@
|
||||
|
||||
.spinner{"ng-if" => "importData.loading"}
|
||||
|
||||
%a{"ng-click" => "destroyLocalData()"} Destroy all local data
|
||||
%a.block.mt-25.red{"ng-click" => "destroyLocalData()"} Destroy all local data
|
||||
|
||||
Reference in New Issue
Block a user