mirror of https://github.com/keeweb/keeweb.git
plugin management page
This commit is contained in:
parent
624a1c10c7
commit
9c30035381
|
@ -450,6 +450,11 @@
|
|||
"setPlInstallLabel": "Plugin URL",
|
||||
"setPlInstallBtn": "Install",
|
||||
"setPlInstallBtnProgress": "Installing",
|
||||
"setPlUninstallBtn": "Uninstall",
|
||||
"setPlLocaleBtn": "Switch to this language",
|
||||
"setPlJs": "code",
|
||||
"setPlCss": "styles",
|
||||
"setPlLoc": "language",
|
||||
|
||||
"setAboutTitle": "About",
|
||||
"setAboutBuilt": "This app is built with these awesome tools",
|
||||
|
|
|
@ -7,33 +7,40 @@ const PluginCollection = require('./plugin-collection');
|
|||
const PluginManager = Backbone.Model.extend({
|
||||
defaults: {
|
||||
state: '',
|
||||
installing: false,
|
||||
installing: null,
|
||||
uninstalling: null,
|
||||
lastInstall: null,
|
||||
plugins: new PluginCollection()
|
||||
},
|
||||
|
||||
install(url) {
|
||||
this.set('installing', true);
|
||||
return Plugin.load(url).then(plugin => {
|
||||
const plugins = this.get('plugins');
|
||||
return Promise.resolve().then(() => {
|
||||
if (plugins.get(plugin.id)) {
|
||||
return plugins.get(plugin.id).uninstall().then(() => {
|
||||
plugins.remove(plugin.id);
|
||||
});
|
||||
}
|
||||
}).then(() => {
|
||||
const lastInstall = { url, dt: new Date() };
|
||||
this.set({ installing: url, lastInstall: lastInstall });
|
||||
return Plugin.load(url).then(plugin =>
|
||||
this.uninstall(plugin.id).then(() => {
|
||||
const plugins = this.get('plugins');
|
||||
plugins.push(plugin);
|
||||
return plugin.install().then(() => {
|
||||
this.set('installing', false);
|
||||
}).catch(e => {
|
||||
this.set('installing', false);
|
||||
throw e;
|
||||
this.set({ installing: null });
|
||||
});
|
||||
});
|
||||
}).catch(e => {
|
||||
this.set('installing', false);
|
||||
})
|
||||
).catch(e => {
|
||||
this.set({ installing: null, lastInstall: _.extend(lastInstall, { error: e.toString() }) });
|
||||
throw e;
|
||||
});
|
||||
},
|
||||
|
||||
uninstall(id) {
|
||||
const plugins = this.get('plugins');
|
||||
const plugin = plugins.get(id);
|
||||
if (!plugin) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
this.set('uninstalling', id);
|
||||
return plugin.uninstall().then(() => {
|
||||
plugins.remove(id);
|
||||
this.set('uninstalling', null);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -21,9 +21,11 @@ const Plugin = Backbone.Model.extend({
|
|||
resources: null,
|
||||
|
||||
initialize(manifest, url) {
|
||||
this.set('name', manifest.name);
|
||||
this.set('manifest', manifest);
|
||||
this.set('url', url);
|
||||
this.set({
|
||||
name: manifest.name,
|
||||
manifest,
|
||||
url
|
||||
});
|
||||
this.logger = new Logger(`plugin:${manifest.name}`);
|
||||
},
|
||||
|
||||
|
@ -136,8 +138,10 @@ const Plugin = Backbone.Model.extend({
|
|||
if (this.resources.loc) {
|
||||
promises.push(this.applyLoc(manifest.locale, this.resources.loc));
|
||||
}
|
||||
this.set('status', 'active');
|
||||
return Promise.all(promises)
|
||||
.then(() => {
|
||||
this.set('status', 'active');
|
||||
})
|
||||
.catch(e => {
|
||||
this.logger.info('Install error', e);
|
||||
this.uninstall();
|
||||
|
@ -211,11 +215,15 @@ const Plugin = Backbone.Model.extend({
|
|||
removeLoc(locale) {
|
||||
delete SettingsManager.allLocales[locale.name];
|
||||
delete SettingsManager.customLocales[locale.name];
|
||||
if (SettingsManager.activeLocale === locale.name) {
|
||||
SettingsManager.setLocale('en');
|
||||
}
|
||||
},
|
||||
|
||||
uninstall() {
|
||||
const manifest = this.get('manifest');
|
||||
this.logger.info('Uninstalling plugin with resources', Object.keys(manifest.resources).join(', '));
|
||||
this.set('status', 'uninstalling');
|
||||
const ts = this.logger.ts();
|
||||
return Promise.resolve().then(() => {
|
||||
if (manifest.resources.css) {
|
||||
|
@ -232,6 +240,7 @@ const Plugin = Backbone.Model.extend({
|
|||
if (manifest.resources.loc) {
|
||||
this.removeLoc(this.get('manifest').locale);
|
||||
}
|
||||
this.set('status', 'inactive');
|
||||
this.logger.info('Uninstall complete', this.logger.ts(ts));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,18 +3,33 @@
|
|||
const Backbone = require('backbone');
|
||||
const Locale = require('../../util/locale');
|
||||
const PluginManager = require('../../plugins/plugin-manager');
|
||||
const AppSettingsModel = require('../../models/app-settings-model');
|
||||
|
||||
const SettingsPluginsView = Backbone.View.extend({
|
||||
template: require('templates/settings/settings-plugins.hbs'),
|
||||
|
||||
events: {
|
||||
'click .settings_plugins-install-btn': 'installClick'
|
||||
'click .settings_plugins-install-btn': 'installClick',
|
||||
'click .settings_plugins-uninstall-btn': 'uninstallClick',
|
||||
'click .settings_plugins-use-locale-btn': 'useLocaleClick'
|
||||
},
|
||||
|
||||
initialize() {
|
||||
this.listenTo(PluginManager, 'change:installing change:uninstalling', this.render.bind(this));
|
||||
},
|
||||
|
||||
render() {
|
||||
const lastInstall = PluginManager.get('lastInstall') || {};
|
||||
this.renderTemplate({
|
||||
plugins: []
|
||||
plugins: PluginManager.get('plugins').map(plugin => ({
|
||||
id: plugin.id,
|
||||
manifest: plugin.get('manifest'),
|
||||
status: plugin.get('status')
|
||||
})),
|
||||
lastInstallUrl: PluginManager.get('installing') || (lastInstall.error ? lastInstall.url : ''),
|
||||
lastInstallError: lastInstall.error
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
installClick() {
|
||||
|
@ -44,6 +59,16 @@ const SettingsPluginsView = Backbone.View.extend({
|
|||
const urlTextBox = this.$el.find('#settings__plugins-install-url');
|
||||
urlTextBox.prop('disabled', false);
|
||||
installBtn.text(Locale.setPlInstallBtn).prop('disabled', false);
|
||||
},
|
||||
|
||||
uninstallClick(e) {
|
||||
const pluginId = $(e.target).data('plugin');
|
||||
PluginManager.uninstall(pluginId);
|
||||
},
|
||||
|
||||
useLocaleClick(e) {
|
||||
const locale = $(e.target).data('locale');
|
||||
AppSettingsModel.instance.set('locale', locale);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -148,7 +148,17 @@
|
|||
}
|
||||
&__plugins {
|
||||
&-install-error {
|
||||
margin-top: $base-padding-h;
|
||||
margin-top: $base-padding-v;
|
||||
}
|
||||
&-plugin-files {
|
||||
margin-top: $base-padding-v;
|
||||
margin-bottom: $base-padding-v;
|
||||
}
|
||||
&-plugin-file {
|
||||
padding-left: $base-padding-h;
|
||||
}
|
||||
&-plugin-desc {
|
||||
margin-bottom: $base-padding-v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
<h3>Core components</h3>
|
||||
<ul>
|
||||
<li><a href="https://github.com/keeweb/kdbxweb" target="_blank">kdbxweb</a><span class="muted-color">, web kdbx library</span></li>
|
||||
<li><a href="https://github.com/vibornoff/asmcrypto.js/" target="_blank">asmcrypto</a><span class="muted-color">, JavaScript cryptographic library
|
||||
with performance in mind</span></li>
|
||||
<li><a href="http://nodeca.github.io/pako/" target="_blank">pako</a><span class="muted-color">, zlib port to JavaScript, very fast</span></li>
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -1,12 +1,40 @@
|
|||
<div>
|
||||
<h1><i class="fa fa-puzzle-piece"></i> {{res 'plugins'}}</h1>
|
||||
<div class="settings__plugins-list">
|
||||
{{#each plugins as |plugin|}}
|
||||
<div class="settings__plugins-plugin">
|
||||
<h2>{{plugin.id}}</h2>
|
||||
<div>{{plugin.manifest.description}}</div>
|
||||
<div>
|
||||
<ul class="settings__plugins-plugin-files">
|
||||
{{#if plugin.manifest.resources.js}}<li class="settings__plugins-plugin-file"><i class="fa fa-code"></i> {{res 'setPlJs'}}</li>{{/if}}
|
||||
{{#if plugin.manifest.resources.css}}<li class="settings__plugins-plugin-file"><i class="fa fa-paint-brush"></i> {{res 'setPlCss'}}</li>{{/if}}
|
||||
{{#if plugin.manifest.resources.loc}}<li class="settings__plugins-plugin-file"><i class="fa fa-language"></i> {{res 'setPlLoc'}}: {{plugin.manifest.locale.title}}</li>{{/if}}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="settings__plugins-plugin-desc">
|
||||
<a href="{{plugin.manifest.url}}" target="_blank">{{plugin.manifest.url}}</a>, v{{plugin.manifest.version}}, created by
|
||||
<a href="{{plugin.manifest.author.url}}" target="_blank">{{plugin.manifest.author.name}}</a> ({{plugin.manifest.author.email}})
|
||||
</div>
|
||||
<div class="settings__plugins-plugin-buttons">
|
||||
<button class="settings_plugins-uninstall-btn btn-silent" data-plugin="{{plugin.id}}">{{res 'setPlUninstallBtn'}}</button>
|
||||
{{#if plugin.manifest.resources.loc}}
|
||||
<button class="settings_plugins-use-locale-btn btn-silent" data-locale="{{plugin.manifest.locale.name}}">{{res 'setPlLocaleBtn'}}</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<h2>{{res 'setPlInstallTitle'}}</h2>
|
||||
<div class="settings__plugins-list"></div>
|
||||
<div class="settings__plugins-install">
|
||||
<div>{{res 'setPlInstallDesc'}}</div>
|
||||
<label for="settings__plugins-install-url">{{res 'setPlInstallLabel'}}</label>
|
||||
<input type="text" class="settings__input input-base" id="settings__plugins-install-url" value="http://localhost:8085/plugins/examples/psychodelic/" />
|
||||
<button class="settings_plugins-install-btn">{{res 'setPlInstallBtn'}}</button>
|
||||
<div class="error-color settings__plugins-install-error"></div>
|
||||
<input type="text" class="settings__input input-base" id="settings__plugins-install-url" value="{{lastInstallUrl}}" />
|
||||
<button class="settings_plugins-install-btn" {{#if installing}}disabled{{/if}}>
|
||||
{{#if installing}}{{res 'setPlInstallBtnProgress'}}{{else}}{{res 'setPlInstallBtn'}}{{/if}}
|
||||
</button>
|
||||
{{#if lastInstallError}}
|
||||
<div class="error-color settings__plugins-install-error">{{lastInstallError}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue