mirror of
https://github.com/moparisthebest/mail
synced 2024-11-22 17:02:17 -05:00
Use url query params to trak state in the app
This commit is contained in:
parent
95cbe0ea11
commit
4622ebd8d9
@ -35,8 +35,7 @@ var axe = require('axe-logger'),
|
|||||||
WriteCtrl = require('./controller/app/write'),
|
WriteCtrl = require('./controller/app/write'),
|
||||||
NavigationCtrl = require('./controller/app/navigation'),
|
NavigationCtrl = require('./controller/app/navigation'),
|
||||||
ActionBarCtrl = require('./controller/app/action-bar'),
|
ActionBarCtrl = require('./controller/app/action-bar'),
|
||||||
StatusDisplayCtrl = require('./controller/app/status-display'),
|
StatusDisplayCtrl = require('./controller/app/status-display');
|
||||||
backButtonUtil = require('./util/backbutton-handler');
|
|
||||||
|
|
||||||
// include angular modules
|
// include angular modules
|
||||||
require('./app-config');
|
require('./app-config');
|
||||||
@ -109,24 +108,11 @@ app.config(function($routeProvider, $animateProvider) {
|
|||||||
templateUrl: 'tpl/login-privatekey-download.html',
|
templateUrl: 'tpl/login-privatekey-download.html',
|
||||||
controller: LoginPrivateKeyDownloadCtrl
|
controller: LoginPrivateKeyDownloadCtrl
|
||||||
});
|
});
|
||||||
|
$routeProvider.when('/account', {
|
||||||
//
|
|
||||||
// main app routes
|
|
||||||
//
|
|
||||||
|
|
||||||
var accountRoute = {
|
|
||||||
templateUrl: 'tpl/desktop.html',
|
templateUrl: 'tpl/desktop.html',
|
||||||
controller: NavigationCtrl
|
controller: NavigationCtrl,
|
||||||
};
|
reloadOnSearch: false // don't reload controllers in main app when query params change
|
||||||
|
});
|
||||||
$routeProvider.when('/account', accountRoute);
|
|
||||||
$routeProvider.when('/account/:folderIndex', accountRoute);
|
|
||||||
$routeProvider.when('/account/:folderIndex/:uid', accountRoute);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Default route
|
|
||||||
//
|
|
||||||
|
|
||||||
$routeProvider.otherwise({
|
$routeProvider.otherwise({
|
||||||
redirectTo: '/login'
|
redirectTo: '/login'
|
||||||
});
|
});
|
||||||
@ -138,10 +124,6 @@ app.config(function($routeProvider, $animateProvider) {
|
|||||||
app.run(function($rootScope) {
|
app.run(function($rootScope) {
|
||||||
// global state... inherited to all child scopes
|
// global state... inherited to all child scopes
|
||||||
$rootScope.state = {};
|
$rootScope.state = {};
|
||||||
|
|
||||||
// attach the back button handler to the root scope
|
|
||||||
backButtonUtil.attachHandler($rootScope);
|
|
||||||
|
|
||||||
// attach fastclick
|
// attach fastclick
|
||||||
FastClick.attach(document.body);
|
FastClick.attach(document.body);
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,7 @@ var ActionBarCtrl = function($scope, email, dialog, statusDisplay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// close read state
|
// close read state
|
||||||
$scope.state.read.open = false;
|
$scope.state.read.toggle(false);
|
||||||
|
|
||||||
statusDisplay.update('Moving message...');
|
statusDisplay.update('Moving message...');
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ var ActionBarCtrl = function($scope, email, dialog, statusDisplay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// close read state
|
// close read state
|
||||||
$scope.state.read.open = false;
|
$scope.state.read.toggle(false);
|
||||||
|
|
||||||
statusDisplay.update('Deleting message...');
|
statusDisplay.update('Deleting message...');
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ var ActionBarCtrl = function($scope, email, dialog, statusDisplay) {
|
|||||||
|
|
||||||
// close read state
|
// close read state
|
||||||
if (!keepOpen) {
|
if (!keepOpen) {
|
||||||
$scope.state.read.open = false;
|
$scope.state.read.toggle(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var originalState = message.unread;
|
var originalState = message.unread;
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var searchTimeout, firstSelect;
|
var searchTimeout;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Constants
|
// Constants
|
||||||
//
|
//
|
||||||
|
|
||||||
var INIT_DISPLAY_LEN = 20,
|
var INIT_DISPLAY_LEN = 50,
|
||||||
SCROLL_DISPLAY_LEN = 10,
|
SCROLL_DISPLAY_LEN = 10,
|
||||||
FOLDER_TYPE_INBOX = 'Inbox',
|
FOLDER_TYPE_INBOX = 'Inbox',
|
||||||
NOTIFICATION_INBOX_TIMEOUT = 5000;
|
NOTIFICATION_INBOX_TIMEOUT = 5000;
|
||||||
|
|
||||||
var MailListCtrl = function($scope, $timeout, $location, $routeParams, $filter, statusDisplay, notification, email, keychain, dialog, search, dummy) {
|
var MailListCtrl = function($scope, $timeout, $location, $filter, statusDisplay, notification, email, keychain, dialog, search, dummy) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Init
|
// Init
|
||||||
@ -24,6 +24,30 @@ var MailListCtrl = function($scope, $timeout, $location, $routeParams, $filter,
|
|||||||
*/
|
*/
|
||||||
$scope.pendingNotifications = [];
|
$scope.pendingNotifications = [];
|
||||||
|
|
||||||
|
//
|
||||||
|
// url/history handling
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the route to a message which will go to read mode
|
||||||
|
*/
|
||||||
|
$scope.navigate = function(message) {
|
||||||
|
$location.search('uid', message.uid);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.loc = $location;
|
||||||
|
$scope.$watch('(loc.search()).uid', function(uid) {
|
||||||
|
if (typeof uid === 'undefined') {
|
||||||
|
// no uid specified in url... select no message
|
||||||
|
$scope.select();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// select the message specified by the uid in the url
|
||||||
|
$scope.select(_.findWhere(currentFolder().messages, {
|
||||||
|
uid: typeof uid === 'string' ? parseInt(uid, 10) : uid
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
// scope functions
|
// scope functions
|
||||||
//
|
//
|
||||||
@ -50,10 +74,6 @@ var MailListCtrl = function($scope, $timeout, $location, $routeParams, $filter,
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.navigate = function(message) {
|
|
||||||
$location.path('/account/' + $routeParams.folderIndex + '/' + message.uid);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when clicking on an message list item
|
* Called when clicking on an message list item
|
||||||
*/
|
*/
|
||||||
@ -66,11 +86,10 @@ var MailListCtrl = function($scope, $timeout, $location, $routeParams, $filter,
|
|||||||
|
|
||||||
$scope.state.mailList.selected = message;
|
$scope.state.mailList.selected = message;
|
||||||
|
|
||||||
if (!firstSelect) {
|
if ($location.search().dev) {
|
||||||
// only toggle to read view on 2nd select in mobile mode
|
// stop here in dev mode
|
||||||
$scope.state.read.toggle(true);
|
return;
|
||||||
}
|
}
|
||||||
firstSelect = false;
|
|
||||||
|
|
||||||
keychain.refreshKeyForUserId({
|
keychain.refreshKeyForUserId({
|
||||||
userId: message.from[0].address
|
userId: message.from[0].address
|
||||||
@ -102,11 +121,6 @@ var MailListCtrl = function($scope, $timeout, $location, $routeParams, $filter,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var selectedMessage = _.findWhere(currentFolder().messages, {
|
|
||||||
uid: $routeParams.uid
|
|
||||||
});
|
|
||||||
$scope.select(selectedMessage);
|
|
||||||
|
|
||||||
$scope.flag = function(message, flagged) {
|
$scope.flag = function(message, flagged) {
|
||||||
$scope.state.actionBar.flagMessage(message, flagged);
|
$scope.state.actionBar.flagMessage(message, flagged);
|
||||||
};
|
};
|
||||||
@ -141,7 +155,7 @@ var MailListCtrl = function($scope, $timeout, $location, $routeParams, $filter,
|
|||||||
$scope.searchText = undefined;
|
$scope.searchText = undefined;
|
||||||
|
|
||||||
// in development, display dummy mail objects
|
// in development, display dummy mail objects
|
||||||
if ($routeParams.dev) {
|
if ($location.search().dev) {
|
||||||
statusDisplay.update('Last update: ', new Date());
|
statusDisplay.update('Last update: ', new Date());
|
||||||
currentFolder().messages = dummy.listMails();
|
currentFolder().messages = dummy.listMails();
|
||||||
return;
|
return;
|
||||||
@ -157,15 +171,9 @@ var MailListCtrl = function($scope, $timeout, $location, $routeParams, $filter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sort message by uid
|
// sort message by uid
|
||||||
currentFolder().messages.sort(byUidDescending);
|
messages.sort(byUidDescending);
|
||||||
// set display buffer to first messages
|
// set display buffer to first messages
|
||||||
$scope.displayMessages = currentFolder().messages.slice(0, INIT_DISPLAY_LEN);
|
$scope.displayMessages = messages.slice(0, INIT_DISPLAY_LEN);
|
||||||
|
|
||||||
// Shows the next message based on the uid of the currently selected element
|
|
||||||
if (currentFolder().messages.indexOf(currentMessage()) === -1) {
|
|
||||||
firstSelect = true; // reset first selection
|
|
||||||
$scope.navigate($scope.displayMessages[0]);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -300,16 +308,12 @@ var MailListCtrl = function($scope, $timeout, $location, $routeParams, $filter,
|
|||||||
title: title,
|
title: title,
|
||||||
message: message,
|
message: message,
|
||||||
onClick: function() {
|
onClick: function() {
|
||||||
// force toggle into read mode when notification is clicked
|
|
||||||
firstSelect = false;
|
|
||||||
|
|
||||||
// remove from pending notificatiosn
|
// remove from pending notificatiosn
|
||||||
var index = $scope.pendingNotifications.indexOf(note);
|
var index = $scope.pendingNotifications.indexOf(note);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
$scope.pendingNotifications.splice(index, 1);
|
$scope.pendingNotifications.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
// open the message
|
||||||
// mark message as read
|
|
||||||
$scope.navigate(_.findWhere(currentFolder().messages, {
|
$scope.navigate(_.findWhere(currentFolder().messages, {
|
||||||
uid: unreadMsgs[0].uid
|
uid: unreadMsgs[0].uid
|
||||||
}));
|
}));
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var backBtnHandler = require('../../util/backbutton-handler');
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Constants
|
// Constants
|
||||||
//
|
//
|
||||||
@ -13,21 +11,17 @@ var NOTIFICATION_SENT_TIMEOUT = 2000;
|
|||||||
// Controller
|
// Controller
|
||||||
//
|
//
|
||||||
|
|
||||||
var NavigationCtrl = function($scope, $routeParams, $location, account, email, outbox, notification, appConfig, dialog, dummy) {
|
var NavigationCtrl = function($scope, $location, account, email, outbox, notification, appConfig, dialog, dummy) {
|
||||||
if (!$routeParams.dev && !account.isLoggedIn()) {
|
if (!$location.search().dev && !account.isLoggedIn()) {
|
||||||
$location.path('/'); // init app
|
$location.path('/'); // init app
|
||||||
return;
|
return;
|
||||||
} else if (!$routeParams.folderIndex) {
|
|
||||||
$location.path('/account/0'); // navigate to default account's inbox by default
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var folderIndex = $routeParams.folderIndex,
|
var str = appConfig.string,
|
||||||
str = appConfig.string,
|
|
||||||
config = appConfig.config;
|
config = appConfig.config;
|
||||||
|
|
||||||
//
|
//
|
||||||
// scope functions
|
// scope state
|
||||||
//
|
//
|
||||||
|
|
||||||
$scope.state.nav = {
|
$scope.state.nav = {
|
||||||
@ -37,6 +31,36 @@ var NavigationCtrl = function($scope, $routeParams, $location, account, email, o
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// url/history handling
|
||||||
|
//
|
||||||
|
|
||||||
|
$scope.loc = $location;
|
||||||
|
|
||||||
|
// nav open/close state url watcher
|
||||||
|
$scope.$watch('(loc.search()).nav', function(open) {
|
||||||
|
// synchronize the url to the scope state
|
||||||
|
$scope.state.nav.toggle(!!open);
|
||||||
|
});
|
||||||
|
$scope.$watch('state.nav.open', function(value) {
|
||||||
|
// synchronize the scope state to the url
|
||||||
|
$location.search('nav', value ? true : null);
|
||||||
|
});
|
||||||
|
|
||||||
|
// lightbox state url watcher
|
||||||
|
$scope.$watch('(loc.search()).lightbox', function(value) {
|
||||||
|
// synchronize the url to the scope state
|
||||||
|
$scope.state.lightbox = (value) ? value : undefined;
|
||||||
|
});
|
||||||
|
$scope.$watch('state.lightbox', function(value) {
|
||||||
|
// synchronize the scope state to the url
|
||||||
|
$location.search('lightbox', value ? value : null);
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// scope functions
|
||||||
|
//
|
||||||
|
|
||||||
$scope.openFolder = function(folder) {
|
$scope.openFolder = function(folder) {
|
||||||
$scope.state.nav.currentFolder = folder;
|
$scope.state.nav.currentFolder = folder;
|
||||||
$scope.state.nav.toggle(false);
|
$scope.state.nav.toggle(false);
|
||||||
@ -76,16 +100,22 @@ var NavigationCtrl = function($scope, $routeParams, $location, account, email, o
|
|||||||
// Start
|
// Start
|
||||||
//
|
//
|
||||||
|
|
||||||
// handle back button
|
|
||||||
backBtnHandler.start();
|
|
||||||
// init folders
|
// init folders
|
||||||
initializeFolders();
|
initializeFolders();
|
||||||
|
|
||||||
// select current folder on init
|
// folder index url watcher
|
||||||
if ($scope.account.folders && $scope.account.folders.length > folderIndex) {
|
$scope.$watch('(loc.search()).folder', function(folderIndex) {
|
||||||
// navigate to the selected folder index
|
if (typeof folderIndex === 'undefined') {
|
||||||
$scope.openFolder($scope.account.folders[folderIndex]);
|
$location.search('folder', 0); // navigate to inbox by default
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
// select current folder
|
||||||
|
folderIndex = typeof folderIndex === 'string' ? parseInt(folderIndex, 10) : folderIndex;
|
||||||
|
if ($scope.account.folders && $scope.account.folders.length > folderIndex) {
|
||||||
|
// navigate to the selected folder index
|
||||||
|
$scope.openFolder($scope.account.folders[folderIndex]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// connect imap/smtp clients on first startup
|
// connect imap/smtp clients on first startup
|
||||||
account.onConnect(function(err) {
|
account.onConnect(function(err) {
|
||||||
@ -107,7 +137,7 @@ var NavigationCtrl = function($scope, $routeParams, $location, account, email, o
|
|||||||
|
|
||||||
function initializeFolders() {
|
function initializeFolders() {
|
||||||
// create dummy folder in dev environment only
|
// create dummy folder in dev environment only
|
||||||
if ($routeParams.dev) {
|
if ($location.search().dev) {
|
||||||
$scope.$root.account = {};
|
$scope.$root.account = {};
|
||||||
$scope.account.folders = dummy.listFolders();
|
$scope.account.folders = dummy.listFolders();
|
||||||
return;
|
return;
|
||||||
|
@ -4,10 +4,14 @@
|
|||||||
// Controller
|
// Controller
|
||||||
//
|
//
|
||||||
|
|
||||||
var ReadCtrl = function($scope, email, invitation, outbox, pgp, keychain, appConfig, download, auth, dialog) {
|
var ReadCtrl = function($scope, $location, email, invitation, outbox, pgp, keychain, appConfig, download, auth, dialog) {
|
||||||
|
|
||||||
var str = appConfig.string;
|
var str = appConfig.string;
|
||||||
|
|
||||||
|
//
|
||||||
|
// scope state
|
||||||
|
//
|
||||||
|
|
||||||
// set default value so that the popover height is correct on init
|
// set default value so that the popover height is correct on init
|
||||||
$scope.keyId = 'No key found.';
|
$scope.keyId = 'No key found.';
|
||||||
|
|
||||||
@ -18,7 +22,32 @@ var ReadCtrl = function($scope, email, invitation, outbox, pgp, keychain, appCon
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// url/history handling
|
||||||
|
//
|
||||||
|
|
||||||
|
// read state url watcher
|
||||||
|
$scope.loc = $location;
|
||||||
|
$scope.$watch('(loc.search()).uid', function(uid) {
|
||||||
|
// synchronize the url to the scope state
|
||||||
|
$scope.state.read.toggle(!!uid);
|
||||||
|
});
|
||||||
|
$scope.$watch('state.read.open', function(value) {
|
||||||
|
// close read mode by navigating to folder view
|
||||||
|
if (!value) {
|
||||||
|
$location.search('uid', null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// scope functions
|
||||||
|
//
|
||||||
|
|
||||||
$scope.getKeyId = function(address) {
|
$scope.getKeyId = function(address) {
|
||||||
|
if ($location.search().dev || !address) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$scope.keyId = 'Searching...';
|
$scope.keyId = 'Searching...';
|
||||||
keychain.getReceiverPublicKey(address, function(err, pubkey) {
|
keychain.getReceiverPublicKey(address, function(err, pubkey) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -41,7 +70,7 @@ var ReadCtrl = function($scope, email, invitation, outbox, pgp, keychain, appCon
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.$watch('state.mailList.selected', function(mail) {
|
$scope.$watch('state.mailList.selected', function(mail) {
|
||||||
if (!mail) {
|
if ($location.search().dev || !mail) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
var axe = require('axe-logger'),
|
|
||||||
DEBUG_TAG = 'backbutton handler';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The back button handler introduces meaningful behavior fo rthe back button:
|
|
||||||
* if there's an open lightbox, close it;
|
|
||||||
* if the reader is open in mobile mode, close it;
|
|
||||||
* if the navigation is open, close it;
|
|
||||||
* if there's nothing else open, shut down the app;
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
var backBtnHandler = {
|
|
||||||
attachHandler: function(scope) {
|
|
||||||
this.scope = scope;
|
|
||||||
},
|
|
||||||
start: function() {
|
|
||||||
document.addEventListener("backbutton", handleBackButton, false);
|
|
||||||
},
|
|
||||||
stop: function() {
|
|
||||||
document.removeEventListener("backbutton", handleBackButton, false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function handleBackButton(event) {
|
|
||||||
axe.debug(DEBUG_TAG, 'back button pressed');
|
|
||||||
|
|
||||||
// this disarms the default behavior which we NEVER want
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
if (backBtnHandler.scope.state.lightbox) {
|
|
||||||
// closes the lightbox (error msgs, writer, ...)
|
|
||||||
backBtnHandler.scope.state.lightbox = undefined;
|
|
||||||
axe.debug(DEBUG_TAG, 'lightbox closed');
|
|
||||||
backBtnHandler.scope.$apply();
|
|
||||||
} else if (backBtnHandler.scope.state.read && backBtnHandler.scope.state.read.open) {
|
|
||||||
// closes the reader
|
|
||||||
backBtnHandler.scope.state.read.toggle(false);
|
|
||||||
axe.debug(DEBUG_TAG, 'reader closed');
|
|
||||||
backBtnHandler.scope.$apply();
|
|
||||||
} else if (backBtnHandler.scope.state.nav && backBtnHandler.scope.state.nav.open) {
|
|
||||||
// closes the navigation
|
|
||||||
backBtnHandler.scope.state.nav.toggle(false);
|
|
||||||
axe.debug(DEBUG_TAG, 'navigation closed');
|
|
||||||
backBtnHandler.scope.$apply();
|
|
||||||
} else {
|
|
||||||
// exits the app
|
|
||||||
navigator.app.exitApp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = backBtnHandler;
|
|
@ -7,7 +7,7 @@
|
|||||||
<ul class="nav__folders">
|
<ul class="nav__folders">
|
||||||
<li ng-repeat="folder in account.folders" ng-if="folder.wellknown" ng-hide="folder.type === 'Outbox' && folder.count < 1"
|
<li ng-repeat="folder in account.folders" ng-if="folder.wellknown" ng-hide="folder.type === 'Outbox' && folder.count < 1"
|
||||||
class="nav__folder" ng-class="{'nav__folder--open': state.nav.currentFolder === folder}">
|
class="nav__folder" ng-class="{'nav__folder--open': state.nav.currentFolder === folder}">
|
||||||
<a href="#/account/{{$index}}">
|
<a href="#/account?folder={{$index}}">
|
||||||
<svg ng-if="folder.type === 'Inbox'" role="presentation">
|
<svg ng-if="folder.type === 'Inbox'" role="presentation">
|
||||||
<use xlink:href="#icon-inbox" />
|
<use xlink:href="#icon-inbox" />
|
||||||
</svg>
|
</svg>
|
||||||
@ -38,7 +38,7 @@
|
|||||||
<ul class="nav__folders">
|
<ul class="nav__folders">
|
||||||
<li ng-repeat="folder in account.folders" ng-if="!folder.wellknown"
|
<li ng-repeat="folder in account.folders" ng-if="!folder.wellknown"
|
||||||
class="nav__folder" ng-class="{'nav__folder--open': state.nav.currentFolder === folder}">
|
class="nav__folder" ng-class="{'nav__folder--open': state.nav.currentFolder === folder}">
|
||||||
<a href="#/account/{{$index}}">
|
<a href="#/account?folder={{$index}}">
|
||||||
<svg role="presentation"><use xlink:href="#icon-folder" /></svg>
|
<svg role="presentation"><use xlink:href="#icon-folder" /></svg>
|
||||||
{{folder.name}}
|
{{folder.name}}
|
||||||
<span ng-show="folder.count > 0" class="nav__counter">{{folder.count}}</span>
|
<span ng-show="folder.count > 0" class="nav__counter">{{folder.count}}</span>
|
||||||
|
Loading…
Reference in New Issue
Block a user