handlebars

This commit is contained in:
Antelle 2015-12-17 00:50:45 +03:00
parent 5b3fe89304
commit fa7c6d6913
70 changed files with 377 additions and 298 deletions

View File

@ -191,6 +191,7 @@ module.exports = function(grunt) {
_: 'underscore/underscore-min.js',
zepto: 'zepto/zepto.min.js',
jquery: 'zepto/zepto.min.js',
hbs: 'handlebars/runtime.js',
kdbxweb: 'kdbxweb/dist/kdbxweb.js',
dropbox: 'dropbox/lib/dropbox.min.js',
baron: 'baron/baron.min.js',
@ -201,7 +202,7 @@ module.exports = function(grunt) {
},
module: {
loaders: [
{ test: /\.html$/, loader: StringReplacePlugin.replace('ejs', { replacements: [{
{ test: /\.hbs$/, loader: StringReplacePlugin.replace('handlebars-loader', { replacements: [{
pattern: /\r?\n\s*/g,
replacement: function() { return '\n'; }
}]})},
@ -254,7 +255,7 @@ module.exports = function(grunt) {
debounceDelay: 500
},
scripts: {
files: ['app/scripts/**/*.js', 'app/templates/**/*.html'],
files: ['app/scripts/**/*.js', 'app/templates/**/*.hbs'],
tasks: ['webpack']
},
styles: {

View File

@ -10,12 +10,12 @@ var AppModel = require('./models/app-model'),
ThemeChanger = require('./util/theme-changer');
$(function() {
require('./mixins/view');
if (location.href.indexOf('state=') >= 0) {
DropboxLink.receive();
return;
}
require('./mixins/view');
require('./helpers');
KeyHandler.init();
IdleTracker.init();

View File

@ -0,0 +1,30 @@
'use strict';
var Handlebars = require('hbs');
Handlebars.registerHelper('cmp', function(lvalue, rvalue, op, options) {
var cond;
switch (op) {
case '<':
cond = lvalue < rvalue;
break;
case '>':
cond = lvalue > rvalue;
break;
case '>=':
cond = lvalue >= rvalue;
break;
case '<=':
cond = lvalue <= rvalue;
break;
case '===':
case '==':
cond = lvalue === rvalue;
break;
case '!==':
case '!=':
cond = lvalue !== rvalue;
break;
}
return cond ? options.fn(this) : options.inverse(this);
});

View File

@ -0,0 +1,7 @@
'use strict';
var Handlebars = require('hbs');
Handlebars.registerHelper('ifemptyoreq', function(lvalue, rvalue, options) {
return !lvalue || lvalue === rvalue ? options.fn(this) : options.inverse(this);
});

View File

@ -0,0 +1,7 @@
'use strict';
var Handlebars = require('hbs');
Handlebars.registerHelper('ifeq', function(lvalue, rvalue, options) {
return lvalue === rvalue ? options.fn(this) : options.inverse(this);
});

View File

@ -0,0 +1,7 @@
'use strict';
var Handlebars = require('hbs');
Handlebars.registerHelper('ifneq', function(lvalue, rvalue, options) {
return lvalue !== rvalue ? options.fn(this) : options.inverse(this);
});

View File

@ -0,0 +1,6 @@
'use strict';
require('./cmp');
require('./ifeq');
require('./ifneq');
require('./ifemptyoreq');

View File

@ -22,7 +22,7 @@ var Backbone = require('backbone'),
var AppView = Backbone.View.extend({
el: 'body',
template: require('templates/app.html'),
template: require('templates/app.hbs'),
events: {
'contextmenu': 'contextmenu',

View File

@ -5,7 +5,7 @@ var Backbone = require('backbone'),
FeatureDetector = require('../../util/feature-detector');
var DetailsAttachmentView = Backbone.View.extend({
template: require('templates/details/details-attachment.html'),
template: require('templates/details/details-attachment.hbs'),
events: {
},

View File

@ -9,7 +9,7 @@ var Backbone = require('backbone'),
FieldViewReadOnlyRaw = require('../fields/field-view-read-only-raw');
var DetailsHistoryView = Backbone.View.extend({
template: require('templates/details/details-history.html'),
template: require('templates/details/details-history.hbs'),
events: {
'click .details__history-close': 'closeHistory',

View File

@ -23,9 +23,9 @@ var Backbone = require('backbone'),
kdbxweb = require('kdbxweb');
var DetailsView = Backbone.View.extend({
template: require('templates/details/details.html'),
emptyTemplate: require('templates/details/details-empty.html'),
groupTemplate: require('templates/details/details-group.html'),
template: require('templates/details/details.hbs'),
emptyTemplate: require('templates/details/details-empty.hbs'),
groupTemplate: require('templates/details/details-group.hbs'),
fieldViews: null,
views: null,

View File

@ -3,7 +3,7 @@
var Backbone = require('backbone');
var DropdownView = Backbone.View.extend({
template: require('templates/dropdown.html'),
template: require('templates/dropdown.hbs'),
events: {
'click .dropdown__item': 'itemClick'

View File

@ -5,7 +5,7 @@ var Backbone = require('backbone'),
CopyPaste = require('../../comp/copy-paste');
var FieldView = Backbone.View.extend({
template: require('templates/details/field.html'),
template: require('templates/details/field.hbs'),
events: {
'click .details__field-label': 'fieldLabelClick',

View File

@ -7,7 +7,7 @@ var Backbone = require('backbone'),
UpdateModel = require('../models/update-model');
var FooterView = Backbone.View.extend({
template: require('templates/footer.html'),
template: require('templates/footer.hbs'),
events: {
'click .footer__db-item': 'showFile',

View File

@ -11,7 +11,7 @@ var DefaultGenOpts = {
var GeneratorView = Backbone.View.extend({
el: 'body',
template: require('templates/generator.html'),
template: require('templates/generator.hbs'),
events: {
'click': 'click',

View File

@ -6,7 +6,7 @@ var Backbone = require('backbone'),
baron = require('baron');
var GrpView = Backbone.View.extend({
template: require('templates/grp.html'),
template: require('templates/grp.hbs'),
events: {
'click .grp__icon': 'showIconsSelect',

View File

@ -8,7 +8,7 @@ var Backbone = require('backbone'),
var logger = new Logger('icon-select-view');
var IconSelectView = Backbone.View.extend({
template: require('templates/icon-select.html'),
template: require('templates/icon-select.hbs'),
events: {
'click .icon-select__icon': 'iconClick',

View File

@ -7,7 +7,7 @@ var Backbone = require('backbone'),
FeatureDetector = require('../util/feature-detector');
var ListSearchView = Backbone.View.extend({
template: require('templates/list-search.html'),
template: require('templates/list-search.hbs'),
events: {
'keydown .list__search-field': 'inputKeyDown',

View File

@ -10,8 +10,8 @@ var Backbone = require('backbone'),
baron = require('baron');
var ListView = Backbone.View.extend({
template: require('templates/list.html'),
emptyTemplate: require('templates/list-empty.html'),
template: require('templates/list.hbs'),
emptyTemplate: require('templates/list-empty.hbs'),
events: {
'click .list__item': 'itemClick',
@ -84,7 +84,7 @@ var ListView = Backbone.View.extend({
getItemsTemplate: function() {
if (this.model.settings.get('tableView')) {
return require('templates/list-table.html');
return require('templates/list-table.hbs');
} else {
return this.renderPlainItems;
}
@ -96,9 +96,9 @@ var ListView = Backbone.View.extend({
getItemTemplate: function() {
if (this.model.settings.get('tableView')) {
return require('templates/list-item-table.html');
return require('templates/list-item-table.hbs');
} else {
return require('templates/list-item-short.html');
return require('templates/list-item-short.hbs');
}
},

View File

@ -7,7 +7,7 @@ var Backbone = require('backbone'),
DragDropInfo = require('../../comp/drag-drop-info');
var MenuItemView = Backbone.View.extend({
template: require('templates/menu/menu-item.html'),
template: require('templates/menu/menu-item.hbs'),
events: {
'mouseover': 'mouseover',

View File

@ -8,7 +8,7 @@ var Backbone = require('backbone'),
baron = require('baron');
var MenuSectionView = Backbone.View.extend({
template: require('templates/menu/menu-section.html'),
template: require('templates/menu/menu-section.hbs'),
events: {},

View File

@ -7,7 +7,7 @@ var Backbone = require('backbone'),
AppSettingsModel = require('../../models/app-settings-model');
var MenuView = Backbone.View.extend({
template: require('templates/menu/menu.html'),
template: require('templates/menu/menu.hbs'),
events: {},

View File

@ -7,7 +7,7 @@ var Backbone = require('backbone'),
var ModalView = Backbone.View.extend({
el: 'body',
template: require('templates/modal.html'),
template: require('templates/modal.hbs'),
events: {
'click .modal__buttons button': 'buttonClick',

View File

@ -10,7 +10,7 @@ var Backbone = require('backbone'),
var logger = new Logger('open-view');
var OpenView = Backbone.View.extend({
template: require('templates/open.html'),
template: require('templates/open.hbs'),
events: {
'change .open__file-ctrl': 'fileSelected',

View File

@ -5,7 +5,7 @@ var Backbone = require('backbone'),
Links = require('../../const/links');
var SettingsAboutView = Backbone.View.extend({
template: require('templates/settings/settings-about.html'),
template: require('templates/settings/settings-about.hbs'),
render: function() {
this.renderTemplate({

View File

@ -13,7 +13,7 @@ var Backbone = require('backbone'),
FileSaver = require('filesaver');
var SettingsAboutView = Backbone.View.extend({
template: require('templates/settings/settings-file.html'),
template: require('templates/settings/settings-file.hbs'),
events: {
'click .settings__file-button-save-default': 'saveDefault',

View File

@ -11,7 +11,7 @@ var Backbone = require('backbone'),
Links = require('../../const/links');
var SettingsGeneralView = Backbone.View.extend({
template: require('templates/settings/settings-general.html'),
template: require('templates/settings/settings-general.hbs'),
events: {
'change .settings__general-theme': 'changeTheme',
@ -43,6 +43,9 @@ var SettingsGeneralView = Backbone.View.extend({
},
render: function() {
var updateReady = UpdateModel.instance.get('updateStatus') === 'ready',
updateFound = UpdateModel.instance.get('updateStatus') === 'found',
updateManual = UpdateModel.instance.get('updateManual');
this.renderTemplate({
themes: this.allThemes,
activeTheme: AppSettingsModel.instance.get('theme'),
@ -61,9 +64,11 @@ var SettingsGeneralView = Backbone.View.extend({
autoUpdate: Updater.getAutoUpdateType(),
updateInProgress: Updater.updateInProgress(),
updateInfo: this.getUpdateInfo(),
updateReady: UpdateModel.instance.get('updateStatus') === 'ready',
updateFound: UpdateModel.instance.get('updateStatus') === 'found',
updateManual: UpdateModel.instance.get('updateManual'),
updateWaitingReload: updateReady && !Launcher,
showUpdateBlock: Launcher && !updateManual,
updateReady: updateReady,
updateFound: updateFound,
updateManual: updateManual,
releaseNotesLink: Links.ReleaseNotes,
colorfulIcons: AppSettingsModel.instance.get('colorfulIcons')
});

View File

@ -5,7 +5,7 @@ var Backbone = require('backbone'),
Links = require('../../const/links');
var SettingsHelpView = Backbone.View.extend({
template: require('templates/settings/settings-help.html'),
template: require('templates/settings/settings-help.hbs'),
render: function() {
var appInfo = 'KeeWeb v' + RuntimeInfo.version + ' (' + RuntimeInfo.commit + ', ' + RuntimeInfo.buildDate + ')\n' +

View File

@ -4,7 +4,7 @@ var Backbone = require('backbone'),
FeatureDetector = require('../../util/feature-detector');
var SettingsShortcutsView = Backbone.View.extend({
template: require('templates/settings/settings-shortcuts.html'),
template: require('templates/settings/settings-shortcuts.hbs'),
render: function() {
this.renderTemplate({

View File

@ -7,7 +7,7 @@ var Backbone = require('backbone'),
baron = require('baron');
var SettingsView = Backbone.View.extend({
template: require('templates/settings/settings.html'),
template: require('templates/settings/settings.hbs'),
views: null,

View File

@ -13,12 +13,12 @@
<span class="details__colors-popup-item violet-color fa fa-bookmark-o" data-color="violet"></span>
</span>
</i>
<h1 class="details__header-title"><%- title || '(no title)' %></h1>
<% if (customIcon) { %>
<div class="details__header-icon details__header-icon--icon" style="background-image: url(<%= customIcon %>)" title="Change icon"></div>
<% } else { %>
<i class="details__header-icon fa fa-<%= icon %>" title="Change icon"></i>
<% } %>
<h1 class="details__header-title">{{#if title}}{{title}}{{else}}(no title){{/if}}</h1>
{{#if customIcon}}
<div class="details__header-icon details__header-icon--icon" style="background-image: url({{{customIcon}}})" title="Change icon"></div>
{{else}}
<i class="details__header-icon fa fa-{{icon}}" title="Change icon"></i>
{{/if}}
</div>
<div class="details__body">
<div class="scroller">
@ -30,17 +30,19 @@
<div class="scroller__bar-wrapper"><div class="scroller__bar"></div></div>
</div>
<div class="details__buttons">
<% if (deleted) { %><i class="details__buttons-trash-del fa fa-minus-circle" title="Delete permanently"></i>
<% } else { %><i class="details__buttons-trash fa fa-trash-o" title="Delete"></i><% } %>
{{#if deleted~}}
<i class="details__buttons-trash-del fa fa-minus-circle" title="Delete permanently"></i>
{{~else~}}
<i class="details__buttons-trash fa fa-trash-o" title="Delete"></i>
{{~/if~}}
<div class="details__attachments">
<% attachments.forEach(function(attachment, ix) { %>
<div class="details__attachment" data-id="<%= ix %>"><i class="fa fa-<%= attachment.icon %>"></i> <%- attachment.title %></div>
<% }); %>
<% if (!attachments.length) { %>
<div class="details__attachment-add">
<span class="details__attachment-add-title">drag attachments here</span> <i class="fa fa-paperclip"></i>
</div>
<% } %>
{{#each attachments as |attachment ix|}}
<div class="details__attachment" data-id="{{ix}}"><i class="fa fa-{{attachment.icon}}"></i> {{attachment.title}}</div>
{{else}}
<div class="details__attachment-add">
<span class="details__attachment-add-title">drag attachments here</span> <i class="fa fa-paperclip"></i>
</div>
{{/each}}
</div>
</div>
<div class="details__dropzone">

View File

@ -0,0 +1,9 @@
<div class="details__field
{{~#if editable}} details__field--editable{{/if~}}
{{~#if multiline}} details__field--multiline{{/if~}}
{{~#if canEditTitle}} details__field--can-edit-title{{/if~}}
">
<div class="details__field-label">{{title}}</div>
<div class="details__field-value">
</div>
</div>

View File

@ -1,8 +0,0 @@
<div class="details__field <%= editable ? 'details__field--editable' : ''
%> <%= multiline ? 'details__field--multiline' : ''
%> <%= canEditTitle ? 'details__field--can-edit-title' : ''
%>">
<div class="details__field-label"><%- title %></div>
<div class="details__field-value">
</div>
</div>

View File

@ -0,0 +1,8 @@
<div class="dropdown">
{{#each options as |option|}}
<div class="dropdown__item {{#if option.active}}dropdown__item--active{{/if}}" data-value="{{option.value}}">
<i class="fa fa-{{option.icon}} dropdown__item-icon"></i>
<span class="dropdown__item-text">{{option.text}}</span>
</div>
{{/each}}
</div>

View File

@ -1,8 +0,0 @@
<div class="dropdown">
<% options.forEach(function(option) { %>
<div class="dropdown__item <%= option.active ? 'dropdown__item--active' : '' %>" data-value="<%- option.value %>">
<i class="fa fa-<%= option.icon %> dropdown__item-icon"></i>
<span class="dropdown__item-text"><%= option.text %></span>
</div>
<% }); %>
</div>

26
app/templates/footer.hbs Normal file
View File

@ -0,0 +1,26 @@
<div class="footer">
{{#each files.models as |file|}}
<div class="footer__db footer__db-item {{#unless file.attributes.open}}footer__db--dimmed{{/unless}}" data-file-id="{{file.cid}}">
<i class="fa fa-{{#if file.attributes.open}}unlock{{else}}lock{{/if}}"></i> {{file.attributes.name}}
{{#if file.attributes.syncing~}}
<i class="fa fa-refresh fa-spin footer__db-sign"></i>
{{~else if file.attributes.syncError~}}
<i class="fa {{#if file.attributes.modified}}fa-circle{{else}}fa-circle-thin{{/if}} footer__db-sign footer__db-sign--error"
title="Sync error: {{file.attributes.syncError}}"></i>
{{~else if file.attributes.modified~}}
<i class="fa fa-circle footer__db-sign"></i>
{{~/if}}
</div>
{{/each}}
<div class="footer__db footer__db--dimmed footer__db--expanded footer__db-open"><i class="fa fa-plus"></i> Open / New</div>
<div class="footer__btn footer__btn-help"><i class="fa fa-question"></i></div>
<div class="footer__btn footer__btn-settings">
{{#if updateAvailable}}
<i class="fa fa-bell footer__update-icon"></i>
{{else}}
<i class="fa fa-cog"></i>
{{/if}}
</div>
<div class="footer__btn footer__btn-generate"><i class="fa fa-bolt"></i></div>
<div class="footer__btn footer__btn-lock"><i class="fa fa-lock"></i></div>
</div>

View File

@ -1,22 +0,0 @@
<div class="footer">
<% files.forEach(function(file) { %>
<div class="footer__db footer__db-item <%= file.get('open') ? '' : 'footer__db--dimmed' %>" data-file-id="<%= file.cid %>">
<i class="fa fa-<%= file.get('open') ? 'unlock' : 'lock' %>"></i> <%- file.get('name') %>
<% if (file.get('syncing')) { %><i class="fa fa-refresh fa-spin footer__db-sign"></i><% }
else if (file.get('syncError')) { %><i class="fa <%= file.get('modified') ? 'fa-circle' : 'fa-circle-thin' %> footer__db-sign footer__db-sign--error"
title="Sync error: <%- file.get('syncError') %>"></i><% }
else if (file.get('modified')) { %><i class="fa fa-circle footer__db-sign"></i><% } %>
</div>
<% }); %>
<div class="footer__db footer__db--dimmed footer__db--expanded footer__db-open"><i class="fa fa-plus"></i> Open / New</div>
<div class="footer__btn footer__btn-help"><i class="fa fa-question"></i></div>
<div class="footer__btn footer__btn-settings">
<% if (updateAvailable) { %>
<i class="fa fa-bell footer__update-icon"></i>
<% } else { %>
<i class="fa fa-cog"></i>
<% } %>
</div>
<div class="footer__btn footer__btn-generate"><i class="fa fa-bolt"></i></div>
<div class="footer__btn footer__btn-lock"><i class="fa fa-lock"></i></div>
</div>

View File

@ -0,0 +1,22 @@
<div class="gen">
<div>Length: <span class="gen__length-range-val">{{opt.length}}</span></div>
<input type="range" class="gen__length-range" value="13" min="0" max="25" />
<div>
<div class="gen__check"><input type="checkbox" id="gen__check-upper"
data-id="upper" {{#if opt.upper}}checked{{/if}}><label for="gen__check-upper">ABC</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-lower"
data-id="lower" {{#if opt.lower}}checked{{/if}}><label for="gen__check-lower">abc</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-digits"
data-id="digits" {{#if opt.digits}}checked{{/if}}><label for="gen__check-digits">123</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-special"
data-id="special" {{#if opt.special}}checked{{/if}}><label for="gen__check-special">!@#</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-brackets"
data-id="brackets" {{#if opt.brackets}}checked{{/if}}><label for="gen__check-brackets">({&lt;</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-high"
data-id="high" {{#if opt.high}}checked{{/if}}><label for="gen__check-high">äæ±</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-ambiguous"
data-id="ambiguous" {{#if opt.ambiguous}}checked{{/if}}><label for="gen__check-ambiguous">0Oo</label></div>
</div>
<div class="gen__result">password</div>
<div class="gen__btn-wrap"><button class="gen__btn-ok">{{btnTitle}}</button></div>
</div>

View File

@ -1,22 +0,0 @@
<div class="gen">
<div>Length: <span class="gen__length-range-val"><%= opt.length %></span></div>
<input type="range" class="gen__length-range" value="13" min="0" max="25" />
<div>
<div class="gen__check"><input type="checkbox" id="gen__check-upper"
data-id="upper" <%= opt.upper ? 'checked' : '' %>><label for="gen__check-upper">ABC</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-lower"
data-id="lower" <%= opt.lower ? 'checked' : '' %>><label for="gen__check-lower">abc</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-digits"
data-id="digits" <%= opt.digits ? 'checked' : '' %>><label for="gen__check-digits">123</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-special"
data-id="special" <%= opt.special ? 'checked' : '' %>><label for="gen__check-special">!@#</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-brackets"
data-id="brackets" <%= opt.brackets ? 'checked' : '' %>><label for="gen__check-brackets">({&lt;</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-high"
data-id="high" <%= opt.high ? 'checked' : '' %>><label for="gen__check-high">äæ±</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-ambiguous"
data-id="ambiguous" <%= opt.ambiguous ? 'checked' : '' %>><label for="gen__check-ambiguous">0Oo</label></div>
</div>
<div class="gen__result">password</div>
<div class="gen__btn-wrap"><button class="gen__btn-ok"><%= btnTitle %></button></div>
</div>

View File

@ -6,27 +6,27 @@
<h1>Group</h1>
<div class="grp__field">
<label for="grp__field-title">Name:</label>
<input type="text" class="input-base" id="grp__field-title" value="<%- title %>" size="50" maxlength="1024"
required <%= readonly ? 'readonly' : '' %> />
<input type="text" class="input-base" id="grp__field-title" value="{{title}}" size="50" maxlength="1024"
required {{#if readonly}}readonly{{/if}} />
</div>
<% if (!readonly) { %>
{{#unless readonly}}
<div>
<input type="checkbox" class="input-base" id="grp__check-search" <%= enableSearching ? 'checked' : '' %> />
<input type="checkbox" class="input-base" id="grp__check-search" {{#if enableSearching}}checked{{/if}} />
<label for="grp__check-search">Enable searching entries in this group</label>
</div>
<% } %>
{{/unless}}
<label>Icon:</label>
<% if (customIcon) { %>
<img src="<%= customIcon %>" class="grp__icon grp__icon--image" />
<% } else { %>
<i class="fa fa-<%- icon %> grp__icon"></i>
<% } %>
{{#if customIcon}}
<img src="{{{customIcon}}}" class="grp__icon grp__icon--image" />
{{else}}
<i class="fa fa-{{icon}} grp__icon"></i>
{{/if}}
<div class="grp__icons"></div>
</div>
<div class="scroller__bar-wrapper"><div class="scroller__bar"></div></div>
<% if (!readonly) { %>
{{#unless readonly}}
<div class="grp__buttons">
<i class="grp__buttons-trash fa fa-trash-o"></i>
</div>
<% } %>
{{/unless}}
</div>

View File

@ -1,26 +1,26 @@
<div class="icon-select">
<div class="icon-select__items">
<% icons.forEach(function(icon, ix) { %>
<i class="fa fa-<%= icon %> icon-select__icon <%= ix === sel ? 'icon-select__icon--active' : '' %>" data-val="<%= ix %>"></i>
<% }); %>
{{#each icons as |icon ix|}}
<i class="fa fa-{{icon}} icon-select__icon {{#ifeq ix sel}}icon-select__icon--active{{/ifeq}}" data-val="{{ix}}"></i>
{{/each}}
</div>
<div class="icon-select__items icon-select__items--custom">
<input type="file" class="icon-select__file-input hide-by-pos" accept="image/*" />
<% if (canDownloadFavicon) { %>
{{#if canDownloadFavicon}}
<span class="icon-select__icon icon-select__icon-btn icon-select__icon-download"
data-val="special" data-special="download" title="Download and use website favicon">
<i class="fa fa-cloud-download"></i>
</span>
<% } %>
{{/if}}
<span class="icon-select__icon icon-select__icon-btn icon-select__icon-select"
data-val="special" data-special="select" title="Select custom icon">
<i class="fa fa-ellipsis-h"></i>
</span>
<% Object.keys(customIcons).forEach(function(ci) { %>
<span class="icon-select__icon icon-select__icon-btn icon-select__icon-custom <%= ci === sel ? 'icon-select__icon--active' : '' %>"
data-val="<%- ci %>">
<img src="<%= customIcons[ci] %>" />
{{#each customIcons as |icon ci|}}
<span class="icon-select__icon icon-select__icon-btn icon-select__icon-custom {{#ifeq ci sel}}icon-select__icon--active{{/ifeq}}"
data-val="{{ci}}">
<img src="{{{icon}}}" />
</span>
<% }); %>
{{/each}}
</div>
</div>

View File

@ -0,0 +1,8 @@
<div class="list__item {{#if active}}list__item--active{{/if}} {{#if expired}}list__item--expired{{/if}}" id="{{id}}" draggable="true">
{{#if customIcon~}}
<img src="{{{customIcon}}}" class="list__item-icon list__item-icon--custom {{#if color}}{{color}}{{/if}}" />
{{~else~}}
<i class="fa fa-{{icon}} {{#if color}}{{color}}-color{{/if}} list__item-icon"></i>
{{~/if}}
<span class="list__item-title">{{#if title}}{{title}}{{else}}(no title){{/if}}</span><span class="list__item-descr thin">{{description}}</span>
</div>

View File

@ -1,5 +0,0 @@
<div class="list__item <%= active ? 'list__item--active' : '' %> <%= expired ? 'list__item--expired' : '' %>" id="<%= id %>" draggable="true">
<% if (customIcon) { %><img src="<%= customIcon %>" class="list__item-icon list__item-icon--custom <%= color || '' %>" /><% }
else { %><i class="fa fa-<%= icon %> <%= color ? color+'-color' : '' %> list__item-icon"></i><% } %>
<span class="list__item-title"><%- title || '(no title)' %></span><span class="list__item-descr thin"><%- description %></span>
</div>

View File

@ -0,0 +1,14 @@
<tr class="list__item list__item--table {{#if active}}list__item--active{{/if}} {{#if expired}}list__item--expired{{/if}}" id="{{id}}" draggable="true">
<td>
{{~#if customIcon~}}
<img src="{{{customIcon}}}" class="list__item-icon list__item-icon--custom {{#if color}}{{color}}{{/if}}" />
{{~else~}}
<i class="fa fa-{{icon}} {{#if color}}{{color}}-color{{/if}} list__item-icon"></i>
{{~/if~}}
</td>
<td>{{#if title}}{{title}}{{else}}(no title){{/if}}</td>
<td>{{user}}</td>
<td>{{url}}</td>
<td>{{tags}}</td>
<td>{{notes}}</td>
</tr>

View File

@ -1,9 +0,0 @@
<tr class="list__item list__item--table <%= active ? 'list__item--active' : '' %> <%= expired ? 'list__item--expired' : '' %>" id="<%= id %>" draggable="true">
<td><% if (customIcon) { %><img src="<%= customIcon %>" class="list__item-icon list__item-icon--custom <%= color || '' %>" /><% }
else { %><i class="fa fa-<%= icon %> <%= color ? color+'-color' : '' %> list__item-icon"></i><% } %></td>
<td><%- title || '(no title)' %></td>
<td><%- user %></td>
<td><%- url %></td>
<td><%- tags %></td>
<td><%- notes %></td>
</tr>

View File

@ -10,6 +10,6 @@
</tr>
</thead>
<tbody>
<%= items %>
{{{items}}}
</tbody>
</table>

View File

@ -0,0 +1,25 @@
<div class="menu__item
{{~#if active}} menu__item--active{{/if~}}
{{~#if disabled}} menu__item--disabled{{/if~}}
{{~#if options.length}} menu__item--with-options {{/if~}}
{{~#if cls}} {{cls}}{{/if~}}
">
<div class="menu__item-body" {{#if drag}}draggable="true"{{/if}}>
{{#if customIcon~}}
<img src="{{{customIcon}}}" class="menu__item-icon menu__item-icon--image" />
{{~else~}}
<i class="menu__item-icon fa {{#if icon}}fa-{{icon}}{{else}}menu__item-icon--no-icon{{/if}}"></i>
{{~/if}}
<span class="menu__item-title">{{#if title}}{{title}}{{else}}(no title){{/if}}</span>
{{#if options}}
<div class="menu__item-options">
{{#each options.models as |opt|}}
<div class="menu__item-option {{#if opt.attributes.cls}}{{opt.attributes.cls}}{{/if}}"
data-value="{{opt.attributes.value}}">{{opt.attributes.title}}</div>
{{/each}}
</div>
{{/if}}
{{#if editable}}<i class="menu__item-edit fa fa-cog"></i>{{/if}}
{{#ifeq filterKey 'trash'}}<i class="menu__item-empty-trash fa fa-minus-circle" title="Empty Trash"></i>{{/ifeq}}
</div>
</div>

View File

@ -1,25 +0,0 @@
<div class="menu__item <%=
active ? 'menu__item--active' : '' %> <%=
disabled ? 'menu__item--disabled' : '' %> <%=
options && options.length ? 'menu__item--with-options' : '' %> <%=
cls ? cls : '' %>">
<div class="menu__item-body" <%= drag ? 'draggable="true"' : '' %>>
<% if (customIcon) { %><img src="<%= customIcon %>" class="menu__item-icon menu__item-icon--image" /><% }
else { %><i class="menu__item-icon fa <%= icon ? 'fa-' + icon : 'menu__item-icon--no-icon' %>"></i><% }
%><span class="menu__item-title"><%- title || '(no title)' %></span>
<% if (options) { %>
<div class="menu__item-options">
<% options.forEach(function(option) { %>
<div class="menu__item-option <%= option.get('cls') ? option.get('cls') : '' %>"
data-value="<%- option.get('value') %>"><%- option.get('title') %></div>
<% }); %>
</div>
<% } %>
<% if (typeof editable !== 'undefined') { %>
<i class="menu__item-edit fa fa-cog"></i>
<% } %>
<% if (filterKey === 'trash') { %>
<i class="menu__item-empty-trash fa fa-minus-circle" title="Empty Trash"></i>
<% } %>
</div>
</div>

View File

@ -0,0 +1,9 @@
<div class="menu__section
{{~#if scrollable}} menu__section--scrollable{{/if~}}
{{~#if grow}} menu__section--grow{{/if~}}
{{~#if drag}} menu__section--drag{{/if~}}
">
{{~#if scrollable}}
<div class="scroller"></div><div class="scroller__bar-wrapper"><div class="scroller__bar"></div></div>
{{/if}}
</div>

View File

@ -1,8 +0,0 @@
<div class="menu__section <%=
scrollable ? 'menu__section--scrollable' : '' %> <%=
grow ? 'menu__section--grow' : '' %> <%=
drag ? 'menu__section--drag' : '' %>">
<% if (scrollable) { %>
<div class="scroller"></div><div class="scroller__bar-wrapper"><div class="scroller__bar"></div></div>
<% } %>
</div>

18
app/templates/modal.hbs Normal file
View File

@ -0,0 +1,18 @@
<div class="modal modal--hidden">
<div class="modal__content">
<i class="modal__icon fa fa-{{icon}}"></i>
<div class="modal__header">{{{header}}}</div>
<div class="modal__body">
{{{body}}}
{{#if checkbox}}
<div class="modal__check-wrap"><input type="checkbox" id="modal__check" /><label for="modal__check">{{checkbox}}</label></div>
{{/if}}
</div>
<div class="modal__buttons">
{{#each buttons as |btn|}}
<button class="{{#unless btn.result}}btn-error{{/unless}} {{#if btn.error}}btn-error{{/if}}"
data-result="{{btn.result}}">{{btn.title}}</button>
{{/each}}
</div>
</div>
</div>

View File

@ -1,17 +0,0 @@
<div class="modal modal--hidden">
<div class="modal__content">
<i class="modal__icon fa fa-<%= icon %>"></i>
<div class="modal__header"><%= header %></div>
<div class="modal__body">
<%= body %>
<% if (typeof checkbox !== 'undefined') { %>
<div class="modal__check-wrap"><input type="checkbox" id="modal__check" /><label for="modal__check"><%- checkbox %></label></div>
<% } %>
</div>
<div class="modal__buttons">
<% buttons.forEach(function(btn) { %>
<button class="<%= btn.result && !btn.error ? '' : 'btn-error' %>" data-result="<%= btn.result %>"><%= btn.title %></button>
<% }); %>
</div>
</div>
</div>

View File

@ -36,13 +36,13 @@
</div>
</div>
<div class="open__last">
<% lastOpenFiles.forEach(function(file) { %>
<div class="open__last-item" data-id="<%- file.id %>">
<i class="fa fa-<%= file.icon %> open__last-item-icon"></i>
<span class="open__last-item-text"><%- file.name %></span>
{{#each lastOpenFiles as |file|}}
<div class="open__last-item" data-id="{{file.id}}">
<i class="fa fa-{{file.icon}} open__last-item-icon"></i>
<span class="open__last-item-text">{{file.name}}</span>
<i class="fa fa-times open__last-item-icon-del"></i>
</div>
<% }); %>
{{/each}}
</div>
</div>
<div class="open__dropzone">

View File

@ -1,8 +1,8 @@
<div>
<h1><i class="fa fa-info"></i> About KeeWeb v<%= version %></h1>
<h1><i class="fa fa-info"></i> About KeeWeb v{{version}}</h1>
<p>This is an open-source app created by <a href="http://antelle.net" target="_blank">Antelle</a> and licensed under
<a href="<%= licenseLink %>" target="_blank">MIT</a>.
The source code and issues are <a href="<%= repoLink %>" target="_blank">on GitHub <i class="fa fa-github-alt"></i></a>.</p>
<a href="{{licenseLink}}" target="_blank">MIT</a>.
The source code and issues are <a href="{{repoLink}}" target="_blank">on GitHub <i class="fa fa-github-alt"></i></a>.</p>
<p>This app is built with these awesome tools:</p>
<h3>Libraries</h3>
<ul>
@ -11,6 +11,7 @@
<li><a href="http://underscorejs.org/" target="_blank">underscore</a><span class="muted-color">, utility-belt library for JavaScript</span></li>
<li><a href="http://zeptojs.com/" target="_blank">zepto.js</a><span class="muted-color">, a minimalist JavaScript library for modern browsers,
with a jQuery-compatible API</span></li>
<li><a href="http://handlebarsjs.com/" target="_blank">handlebars</a><span class="muted-color">, semantic templates</span></li>
<li><a href="https://github.com/dropbox/dropbox-js" target="_blank">dropbox-js</a><span class="muted-color">, unofficial JavaScript library for
the Dropbox Core API</span></li>
</ul>

View File

@ -1,32 +1,29 @@
<div>
<h1><i class="fa fa-lock"></i> <%- name %></h1>
<% if (storage) { %>
<% if (storage === 'file') { %>
<p>File path: <%- path %></p>
<% } else if (storage === 'dropbox') { %>
<p>This file is opened from Dropbox.</p>
<% } %>
<% } else { %>
<h1><i class="fa fa-lock"></i> {{name}}</h1>
{{#if storage}}
{{#ifeq storage 'file'}}<p>File path: {{path}}</p>{{/ifeq}}
{{#ifeq storage 'dropbox'}}<p>This file is opened from Dropbox.</p>{{/ifeq}}
{{else}}
<p>This file is stored in internal app storage.</p>
<% if (!supportFiles) { %>
<p>Want to work seamlessly with local files? <a href="<%= desktopLink %>" target="_blank">Download a desktop app</a></p>
<% } %>
<% } %>
{{#unless supportFiles}}
<p>Want to work seamlessly with local files? <a href="{{desktopLink}}" target="_blank">Download a desktop app</a></p>
{{/unless}}
{{/if}}
<div class="settings__file-buttons">
<% if (!storage || storage === 'file') { %><button class="settings__file-button-save-default">Save</button><% } %>
<button class="settings__file-button-save-dropbox <%= storage !== 'dropbox' ? 'btn-silent' : '' %>"
<%= syncing ? 'disabled' : '' %>>Sync with Dropbox</button>
<% if (storage !== 'file') { %><button class="settings__file-button-save-file btn-silent">Save to file</button><% } %>
{{#ifemptyoreq storage 'file'}}<button class="settings__file-button-save-default">Save</button>{{/ifemptyoreq}}
<button class="settings__file-button-save-dropbox {{#ifneq storage 'dropbox'}}btn-silent{{/ifneq}}"
{{#if syncing}}disabled{{/if}}>Sync with Dropbox</button>
{{#ifneq storage 'file'}}<button class="settings__file-button-save-file btn-silent">Save to file</button>{{/ifneq}}
<button class="settings__file-button-export-xml btn-silent">Export to XML</button>
<button class="settings__file-button-close btn-silent">Close</button>
</div>
<% if (storage) { %>
{{#if storage}}
<h2>Sync</h2>
<div>Last sync: <%= syncDate || 'unknown' %> <%= syncing ? '(sync in progress...)' : '' %></div>
<% if (syncError) { %><div>Sync error: <%- syncError %></div><% } %>
<% } %>
<div>Last sync: {{#if syncDate}}{{syncDate}}{{else}}unknown{{/if}} {{#if syncing}}(sync in progress...){{/if}}</div>
{{#if syncError}}<div>Sync error: {{syncError}}</div>{{/if}}
{{/if}}
<h2>Settings</h2>
<label for="settings__file-master-pass" class="settings__file-master-pass-label input-base">Master password:
@ -34,7 +31,7 @@
<i class="fa fa-warning"></i> password was changed; leave the field blank to use old password
</span>
</label>
<input type="password" class="settings__input input-base" id="settings__file-master-pass" value="<%= password %>" />
<input type="password" class="settings__input input-base" id="settings__file-master-pass" value="{{password}}" />
<label for="settings__file-key-file">Key file:</label>
<select class="settings__select settings__select-no-margin input-base" id="settings__file-key-file"></select>
<a id="settings__file-file-select-link">Select a key file</a>
@ -42,21 +39,21 @@
<h2>Names</h2>
<label for="settings__file-name">Name:</label>
<input type="text" class="settings__input input-base" id="settings__file-name" value="<%- name %>" required />
<input type="text" class="settings__input input-base" id="settings__file-name" value="{{name}}" required />
<label for="settings__file-def-user">Default username:</label>
<input type="text" class="settings__input input-base" id="settings__file-def-user" value="<%- defaultUser %>" />
<input type="text" class="settings__input input-base" id="settings__file-def-user" value="{{defaultUser}}" />
<h2>History</h2>
<div>
<input type="checkbox" class="settings__input input-base" id="settings__file-trash" <%- recycleBinEnabled ? 'checked' : '' %> />
<input type="checkbox" class="settings__input input-base" id="settings__file-trash" {{#if recycleBinEnabled}}checked{{/if}}> />
<label for="settings__file-trash">Enable trash</label>
</div>
<label for="settings__file-hist-len">History length, keep last records per entry:</label>
<input type="text" pattern="\d+" required class="settings__input input-base" id="settings__file-hist-len" value="<%= historyMaxItems %>" />
<input type="text" pattern="\d+" required class="settings__input input-base" id="settings__file-hist-len" value="{{historyMaxItems}}" />
<label for="settings__file-hist-size">History size, total MB per file:</label>
<input type="text" pattern="\d+" required class="settings__input input-base" id="settings__file-hist-size" value="<%= historyMaxSize %>" />
<input type="text" pattern="\d+" required class="settings__input input-base" id="settings__file-hist-size" value="{{historyMaxSize}}" />
<h2>Advanced</h2>
<label for="settings__file-key-rounds">Key encryption rounds:</label>
<input type="text" pattern="\d+" required class="settings__input input-base" id="settings__file-key-rounds" value="<%= keyEncryptionRounds %>" />
<input type="text" pattern="\d+" required class="settings__input input-base" id="settings__file-key-rounds" value="{{keyEncryptionRounds}}" />
</div>

View File

@ -1,109 +1,109 @@
<div>
<h1><i class="fa fa-cog"></i> General Settings</h1>
<% if (updateReady && !canAutoUpdate) { %>
{{#if updateWaitingReload}}
<h2 class="action-color">Update</h2>
<div>New app version was released and downloaded. <a href="<%= releaseNotesLink %>" target="_blank">View release notes</a></div>
<div>New app version was released and downloaded. <a href="{{releaseNotesLink}}" target="_blank">View release notes</a></div>
<div class="settings__general-update-buttons">
<button class="settings__general-restart-btn">Reload to update</button>
</div>
<% } else if (updateManual) { %>
{{else if updateManual}}
<h2 class="action-color">Update</h2>
<div>New version has been released. It will check for updates and install them automatically
but auto-upgrading from your version is impossible.</div>
<div class="settings__general-update-buttons">
<button class="settings__general-download-update-btn">Download update</button>
</div>
<% } %>
<% if (canAutoUpdate && !updateManual) { %>
{{/if}}
{{#if showUpdateBlock}}
<h2>Update</h2>
<div>
<select class="settings__general-auto-update settings__select input-base">
<option value="install" <%= autoUpdate === 'install' ? 'selected' : '' %>>Download and install automatically</option>
<option value="check" <%= autoUpdate === 'check' ? 'selected' : '' %>>Check but don't install</option>
<option value="" <%= autoUpdate ? '' : 'selected' %>>Never check for updates</option>
<option value="install" {{#ifeq autoUpdate 'install'}}selected{{/ifeq}}>Download and install automatically</option>
<option value="check" {{#ifeq autoUpdate 'check'}}selected{{/ifeq}}>Check but don't install</option>
<option value="" {{#unless autoUpdate}}selected{{/unless}}>Never check for updates</option>
</select>
<div><%- updateInfo %></div>
<a href="<%= releaseNotesLink %>" target="_blank">View release notes</a>
<div>{{updateInfo}}</div>
<a href="{{releaseNotesLink}}" target="_blank">View release notes</a>
</div>
<div class="settings__general-update-buttons">
<% if (updateInProgress) { %>
{{#if updateInProgress}}
<button class="settings__general-update-btn btn-silent" disabled>Checking for updates</button>
<% } else { %>
{{else}}
<button class="settings__general-update-btn btn-silent">Check for updates</button>
<% } %>
<% if (updateReady) { %><button class="settings__general-restart-btn">Restart to update</button><% } %>
<% if (updateFound) { %><button class="settings__general-update-found-btn">Download update and restart</button><% } %>
{{/if}}
{{#if updateReady}}<button class="settings__general-restart-btn">Restart to update</button>{{/if}}
{{#if updateFound}}<button class="settings__general-update-found-btn">Download update and restart</button>{{/if}}
</div>
<% } %>
{{/if}}
<h2>Appearance</h2>
<div>
<label for="settings__general-theme">Theme:</label>
<select class="settings__general-theme settings__select input-base" id="settings__general-theme">
<% _.forEach(themes, function(name, key) { %>
<option value="<%= key %>" <%= key === activeTheme ? 'selected' : '' %>><%- name %></option>
<% }); %>
{{#each themes as |name key|}}
<option value="{{key}}" {{#ifeq key activeTheme}}selected{{/ifeq}}>{{name}}</option>
{{/each}}
</select>
</div>
<div>
<input type="checkbox" class="settings__input input-base settings__general-expand" id="settings__general-expand" <%- expandGroups ? 'checked' : '' %> />
<input type="checkbox" class="settings__input input-base settings__general-expand" id="settings__general-expand" {{#if expandGroups}}checked{{/if}} />
<label for="settings__general-expand">Show entries from all subgroups</label>
</div>
<% if (canSetTableView) { %>
{{#if canSetTableView}}
<div>
<input type="checkbox" class="settings__input input-base settings__general-table-view" id="settings__general-table-view" <%- tableView ? 'checked' : '' %> />
<input type="checkbox" class="settings__input input-base settings__general-table-view" id="settings__general-table-view" {{#if tableView}}checked{{/if}} />
<label for="settings__general-table-view">Entries list table view</label>
</div>
<% } %>
{{/if}}
<div>
<input type="checkbox" class="settings__input input-base settings__general-colorful-icons" id="settings__general-colorful-icons" <%- colorfulIcons ? 'checked' : '' %> />
<input type="checkbox" class="settings__input input-base settings__general-colorful-icons" id="settings__general-colorful-icons" {{#if colorfulIcons}}checked{{/if}} />
<label for="settings__general-colorful-icons">Colorful custom icons in list</label>
</div>
<h2>Function</h2>
<div>
<input type="checkbox" class="settings__input input-base settings__general-auto-save" id="settings__general-auto-save"
<%- autoSave ? 'checked' : '' %> />
{{#if autoSave}}checked{{/if}} />
<label for="settings__general-auto-save">Automatically save and sync</label>
</div>
<div>
<label for="settings__general-idle-minutes">Auto-lock if the app is inactive:</label>
<select class="settings__general-idle-minutes settings__select input-base" id="settings__general-idle-minutes">
<option value="0" <%= idleMinutes <= 0 ? 'selected' : '' %>>Don't auto-lock</option>
<option value="5" <%= idleMinutes === 5 ? 'selected' : '' %>>In 5 minutes</option>
<option value="10" <%= idleMinutes === 10 ? 'selected' : '' %>>In 10 minutes</option>
<option value="15" <%= idleMinutes === 15 ? 'selected' : '' %>>In 15 minutes</option>
<option value="60" <%= idleMinutes === 60 ? 'selected' : '' %>>In an hour</option>
<option value="0" {{#cmp idleMinutes 0 '<='}}selected{{/cmp}}>Don't auto-lock</option>
<option value="5" {{#ifeq idleMinutes 5}}selected{{/ifeq}}>In 5 minutes</option>
<option value="10" {{#ifeq idleMinutes 10}}selected{{/ifeq}}>In 10 minutes</option>
<option value="15" {{#ifeq idleMinutes 15}}selected{{/ifeq}}>In 15 minutes</option>
<option value="60" {{#ifeq idleMinutes 60}}selected{{/ifeq}}>In an hour</option>
</select>
</div>
<% if (canClearClipboard) { %>
{{#if canClearClipboard}}
<div>
<label for="settings__general-clipboard">Clear clipboard after copy:</label>
<select class="settings__general-clipboard settings__select input-base" id="settings__general-clipboard">
<option value="0" <%= clipboardSeconds ? '' : 'selected' %>>Don't clear</option>
<option value="5" <%= clipboardSeconds === 5 ? 'selected' : '' %>>In 5 seconds</option>
<option value="10" <%= clipboardSeconds === 10 ? 'selected' : '' %>>In 10 seconds</option>
<option value="15" <%= clipboardSeconds === 15 ? 'selected' : '' %>>In 15 seconds</option>
<option value="60" <%= clipboardSeconds === 60 ? 'selected' : '' %>>In a minute</option>
<option value="0" {{#unless clipboardSeconds}}selected{{/unless}}>Don't clear</option>
<option value="5" {{#ifeq clipboardSeconds 5}}selected{{/ifeq}}>In 5 seconds</option>
<option value="10" {{#ifeq clipboardSeconds 10}}selected{{/ifeq}}>In 10 seconds</option>
<option value="15" {{#ifeq clipboardSeconds 15}}selected{{/ifeq}}>In 15 seconds</option>
<option value="60" {{#ifeq clipboardSeconds 60}}selected{{/ifeq}}>In a minute</option>
</select>
</div>
<% } %>
<% if (canMinimize) { %>
{{/if}}
{{#if canMinimize}}
<div>
<input type="checkbox" class="settings__input input-base settings__general-minimize" id="settings__general-minimize"
<%- minimizeOnClose ? 'checked' : '' %> />
{{#if minimizeOnClose}}checked{{/if}} />
<label for="settings__general-minimize">Minimize app instead of close</label>
</div>
<div>
<input type="checkbox" class="settings__input input-base settings__general-lock-on-minimize" id="settings__general-lock-on-minimize"
<%- lockOnMinimize ? 'checked' : '' %> />
{{#if lockOnMinimize}}checked{{/if}} />
<label for="settings__general-lock-on-minimize">Auto-lock on minimize</label>
</div>
<% } %>
{{/if}}
<% if (devTools) { %>
{{#if devTools}}
<h2>Advanced</h2>
<a class="settings__general-dev-tools-link">Show dev tools</a>
<% } %>
{{/if}}
</div>

View File

@ -6,18 +6,18 @@
The file format is 100% compatible and should be understood by both apps.
</p>
<h2>Problems?</h2>
<p>If something goes wrong, please, <a href="<%= issueLink %>" target="_blank">open an issue on GitHub</a>
<p>If something goes wrong, please, <a href="{{issueLink}}" target="_blank">open an issue on GitHub</a>
or <a href="http://antelle.net/" target="_blank">contact a developer</a> directly.
</p>
<p>App information:</p>
<pre class="settings__pre input-base"><%= appInfo %></pre>
<pre class="settings__pre input-base">{{appInfo}}</pre>
<h2>Other platforms</h2>
<ul>
<li>
<i class="fa fa-windows"></i>
<i class="fa fa-apple"></i>
<i class="fa fa-linux"></i>
<a href="<%= desktopLink %>" target="_blank">Desktop apps</a>
<a href="{{desktopLink}}" target="_blank">Desktop apps</a>
</li>
<li>
<i class="fa fa-chrome"></i>
@ -25,7 +25,7 @@
<i class="fa fa-opera"></i>
<i class="fa fa-compass"></i>
<i class="fa fa-internet-explorer"></i>
<a href="<%= webAppLink %>" target="_blank">Web app</a>
<a href="{{webAppLink}}" target="_blank">Web app</a>
</li>
</ul>
<h2>Updates <i class="fa fa-twitter"></i></h2>

View File

@ -0,0 +1,16 @@
<div>
<h1><i class="fa fa-keyboard-o"></i> Shortcuts</h1>
<div><span class="shortcut">{{{cmd}}}A</span> or <span class="shortcut">{{{alt}}}A</span> show all items</div>
<div><span class="shortcut">{{{alt}}}C</span> show items with colors</div>
<div><span class="shortcut">{{{alt}}}D</span> go to trash</div>
<div><span class="shortcut">{{{cmd}}}F</span> search, or just start typing</div>
<div><span class="shortcut">esc</span> clear search</div>
<div><span class="shortcut">⏎</span> go to entry</div>
<div><span class="shortcut">{{{cmd}}}C</span> copy password or selected field</div>
<div><span class="shortcut">&uarr;</span> go to previous item</div>
<div><span class="shortcut">&darr;</span> go to next item</div>
<div><span class="shortcut">{{{alt}}}N</span> create entry</div>
<div><span class="shortcut">{{{cmd}}}O</span> open / new</div>
<div><span class="shortcut">{{{cmd}}}S</span> save</div>
<div><span class="shortcut">{{{cmd}}}G</span> generate</div>
</div>

View File

@ -1,16 +0,0 @@
<div>
<h1><i class="fa fa-keyboard-o"></i> Shortcuts</h1>
<div><span class="shortcut"><%= cmd %>A</span> or <span class="shortcut"><%= alt %>A</span> show all items</div>
<div><span class="shortcut"><%= alt %>C</span> show items with colors</div>
<div><span class="shortcut"><%= alt %>D</span> go to trash</div>
<div><span class="shortcut"><%= cmd %>F</span> search, or just start typing</div>
<div><span class="shortcut">esc</span> clear search</div>
<div><span class="shortcut"></span> go to entry</div>
<div><span class="shortcut"><%= cmd %>C</span> copy password or selected field</div>
<div><span class="shortcut">&uarr;</span> go to previous item</div>
<div><span class="shortcut">&darr;</span> go to next item</div>
<div><span class="shortcut"><%= alt %>N</span> create entry</div>
<div><span class="shortcut"><%= cmd %>O</span> open / new</div>
<div><span class="shortcut"><%= cmd %>S</span> save</div>
<div><span class="shortcut"><%= cmd %>G</span> generate</div>
</div>

View File

@ -8,7 +8,6 @@
"devDependencies": {
"base64-loader": "^1.0.0",
"cssnano": "^3.3.2",
"ejs-loader": "^0.2.1",
"electron-builder": "^2.1.1",
"exports-loader": "^0.6.2",
"grunt": "^0.4.5",
@ -27,6 +26,8 @@
"grunt-sass": "^1.1.0",
"grunt-string-replace": "^1.2.0",
"grunt-webpack": "^1.0.11",
"handlebars": "^4.0.5",
"handlebars-loader": "^1.1.4",
"load-grunt-tasks": "^3.2.0",
"string-replace-webpack-plugin": "0.0.2",
"time-grunt": "^1.2.1",