fix #112: entry templates

This commit is contained in:
antelle 2017-05-02 21:22:08 +02:00
parent 5f2eea2c29
commit 0bb7602bf8
8 changed files with 106 additions and 29 deletions

View File

@ -17,6 +17,8 @@
"group": "group",
"noTitle": "no title",
"or": "or",
"history": "history",
"template": "template",
"notImplemented": "Not Implemented",
"saveChanges": "Save changes",
"discardChanges": "Discard changes",
@ -25,7 +27,6 @@
"help": "Help",
"settings": "Settings",
"plugins": "Plugins",
"history": "history",
"cache": "cache",
"file": "file",

View File

@ -313,9 +313,30 @@ const AppModel = Backbone.Model.extend({
return matches.map(m => m[0]);
},
createNewEntry: function() {
getEntryTemplates: function() {
const entryTemplates = [];
this.files.forEach(file => {
file.forEachEntryTemplate(entry => {
entryTemplates.push({ file, entry });
});
});
return entryTemplates;
},
createNewEntry: function(args) {
const sel = this.getFirstSelectedGroup();
return EntryModel.newEntry(sel.group, sel.file);
if (args && args.template) {
if (sel.file !== args.template.file) {
sel.file = args.template.file;
sel.group = args.template.file.get('groups').first();
}
const templateEntry = args.template.entry;
const newEntry = EntryModel.newEntry(sel.group, sel.file);
newEntry.copyFromTemplate(templateEntry);
return newEntry;
} else {
return EntryModel.newEntry(sel.group, sel.file);
}
},
createNewGroup: function() {
@ -724,27 +745,6 @@ const AppModel = Backbone.Model.extend({
});
});
};
const saveToCacheAndStorage = () => {
logger.info('Getting file data for saving');
file.getData((data, err) => {
if (err) { return complete(err); }
if (storage === 'file') {
logger.info('Saving to file storage');
saveToStorage(data);
} else if (!file.get('dirty')) {
logger.info('Saving to storage, skip cache because not dirty');
saveToStorage(data);
} else {
logger.info('Saving to cache');
Storage.cache.save(fileInfo.id, null, data, (err) => {
if (err) { return complete(err); }
file.set('dirty', false);
logger.info('Saved to cache, saving to storage');
saveToStorage(data);
});
}
});
};
const saveToStorage = (data) => {
logger.info('Save data to storage');
Storage[storage].save(path, opts, data, (err, stat) => {
@ -772,6 +772,27 @@ const AppModel = Backbone.Model.extend({
}
}, fileInfo.get('rev'));
};
const saveToCacheAndStorage = () => {
logger.info('Getting file data for saving');
file.getData((data, err) => {
if (err) { return complete(err); }
if (storage === 'file') {
logger.info('Saving to file storage');
saveToStorage(data);
} else if (!file.get('dirty')) {
logger.info('Saving to storage, skip cache because not dirty');
saveToStorage(data);
} else {
logger.info('Saving to cache');
Storage.cache.save(fileInfo.id, null, data, (err) => {
if (err) { return complete(err); }
file.set('dirty', false);
logger.info('Saved to cache, saving to storage');
saveToStorage(data);
});
}
});
};
logger.info('Stat file');
Storage[storage].stat(path, opts, (err, stat) => {
if (err) {

View File

@ -622,6 +622,12 @@ const EntryModel = Backbone.Model.extend({
newEntry._fillByEntry();
this.file.reload();
return newEntry;
},
copyFromTemplate: function(templateEntry) {
this.entry.copyFrom(templateEntry.entry);
this.entry.fields.Title = '';
this._fillByEntry();
}
});

View File

@ -377,6 +377,17 @@ const FileModel = Backbone.Model.extend({
return hash ? kdbxweb.ByteUtils.bytesToBase64(hash.getBinary()) : null;
},
forEachEntryTemplate: function(callback) {
if (!this.db.meta.entryTemplatesGroup) {
return;
}
const group = this.getGroup(this.subId(this.db.meta.entryTemplatesGroup.id));
if (!group) {
return;
}
group.forEachOwnEntry({}, callback);
},
setSyncProgress: function() {
this.set({ syncing: true });
},

View File

@ -29,7 +29,7 @@ const GroupModel = MenuItemModel.extend({
},
setGroup: function(group, file, parentGroup) {
const isRecycleBin = file.db.meta.recycleBinUuid && file.db.meta.recycleBinUuid.id === group.uuid.id;
const isRecycleBin = group.uuid.equals(file.db.meta.recycleBinUuid);
const id = file.subId(group.uuid.id);
this.set({
id: id,
@ -125,7 +125,10 @@ const GroupModel = MenuItemModel.extend({
},
matches: function(filter) {
return (filter && filter.includeDisabled || this.group.enableSearching !== false) &&
return (filter && filter.includeDisabled ||
this.group.enableSearching !== false &&
!this.group.uuid.equals(this.file.db.meta.entryTemplatesGroup)
) &&
(!filter || !filter.autoType || this.group.enableAutoType !== false);
},

View File

@ -5,6 +5,7 @@ const DropdownView = require('./dropdown-view');
const FeatureDetector = require('../util/feature-detector');
const Format = require('../util/format');
const Locale = require('../util/locale');
const Comparators = require('../util/comparators');
const ListSearchView = Backbone.View.extend({
template: require('templates/list-search.hbs'),
@ -278,6 +279,7 @@ const ListSearchView = Backbone.View.extend({
this.hideSearchOptions();
return;
}
this.hideSearchOptions();
this.$el.find('.list__search-btn-new').addClass('sel--active');
const view = new DropdownView();
@ -288,11 +290,30 @@ const ListSearchView = Backbone.View.extend({
top: this.$el.find('.list__search-btn-new')[0].getBoundingClientRect().bottom,
right: this.$el[0].getBoundingClientRect().right + 1
},
options: this.createOptions
options: this.createOptions.concat(this.getCreateEntryTemplateOptions())
});
this.views.searchDropdown = view;
},
getCreateEntryTemplateOptions: function() {
const entryTemplates = this.model.getEntryTemplates();
const hasMultipleFiles = this.model.files.length > 1;
this.entryTemplates = {};
const options = [];
entryTemplates.forEach(tmpl => {
const id = 'tmpl:' + tmpl.entry.id;
options.push({
value: id,
icon: tmpl.entry.icon,
text: hasMultipleFiles ? tmpl.file.get('name') + ' / ' + tmpl.entry.title : tmpl.entry.title
});
this.entryTemplates[id] = tmpl;
});
options.sort(Comparators.stringComparator('text', true));
options.push({ value: 'tmpl', icon: 'sticky-note-o', text: Format.capFirst(Locale.template) });
return options;
},
sortDropdownSelect: function(e) {
this.hideSearchOptions();
Backbone.trigger('set-sort', e.item);
@ -307,6 +328,13 @@ const ListSearchView = Backbone.View.extend({
case 'group':
this.trigger('create-group');
break;
case 'tmpl':
this.trigger('create-template');
break;
default:
if (this.entryTemplates[e.item]) {
this.trigger('create-entry', { template: this.entryTemplates[e.item] });
}
}
},

View File

@ -8,6 +8,7 @@ const DragDropInfo = require('../comp/drag-drop-info');
const AppSettingsModel = require('../models/app-settings-model');
const Locale = require('../util/locale');
const Format = require('../util/format');
const Alerts = require('../comp/alerts');
const ListView = Backbone.View.extend({
template: require('templates/list.hbs'),
@ -47,6 +48,7 @@ const ListView = Backbone.View.extend({
this.listenTo(this.views.search, 'select-next', this.selectNext);
this.listenTo(this.views.search, 'create-entry', this.createEntry);
this.listenTo(this.views.search, 'create-group', this.createGroup);
this.listenTo(this.views.search, 'create-template', this.createTemplate);
this.listenTo(this, 'show', this.viewShown);
this.listenTo(this, 'hide', this.viewHidden);
this.listenTo(this, 'view-resize', this.viewResized);
@ -147,8 +149,8 @@ const ListView = Backbone.View.extend({
}
},
createEntry: function() {
const newEntry = this.model.createNewEntry();
createEntry: function(arg) {
const newEntry = this.model.createNewEntry(arg);
this.items.unshift(newEntry);
this.render();
this.selectItem(newEntry);
@ -159,6 +161,10 @@ const ListView = Backbone.View.extend({
Backbone.trigger('edit-group', newGroup);
},
createTemplate: function() {
Alerts.notImplemented();
},
selectItem: function(item) {
this.model.activeEntryId = item.id;
Backbone.trigger('entry-selected', item);

View File

@ -4,6 +4,7 @@ Release notes
`+` plugins
`*` translations are available only as plugins
`*` Dropbox API V2
`+` entry templates
`+` support cloud providers in iOS homescreen apps
`+` mobile field editing improvements
`+` file path hint in recent files list