mirror of https://github.com/keeweb/keeweb.git
fix #609: enable/disable plugins
This commit is contained in:
parent
8cf469e55c
commit
4433654686
|
@ -453,8 +453,9 @@
|
|||
"setPlInstallBtn": "Install",
|
||||
"setPlInstallBtnProgress": "Installing",
|
||||
"setPlUninstallBtn": "Uninstall",
|
||||
"setPlDisableBtn": "Disable",
|
||||
"setPlEnableBtn": "Enable",
|
||||
"setPlUpdateBtn": "Update",
|
||||
"setPlUpdating": "Updating",
|
||||
"setPlLocaleBtn": "Switch to this language",
|
||||
"setPlThemeBtn": "Switch to this theme",
|
||||
"setPlJs": "code",
|
||||
|
|
|
@ -6,10 +6,7 @@ const Logger = require('../util/logger');
|
|||
|
||||
const PluginManager = Backbone.Model.extend({
|
||||
defaults: {
|
||||
state: '',
|
||||
installing: null,
|
||||
uninstalling: null,
|
||||
updating: null,
|
||||
lastInstall: null,
|
||||
plugins: new PluginCollection()
|
||||
},
|
||||
|
@ -54,10 +51,36 @@ const PluginManager = Backbone.Model.extend({
|
|||
if (!plugin) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
this.set('uninstalling', id);
|
||||
this.trigger('change');
|
||||
return plugin.uninstall().then(() => {
|
||||
plugins.remove(id);
|
||||
this.set('uninstalling', null);
|
||||
this.trigger('change');
|
||||
this.saveState();
|
||||
});
|
||||
},
|
||||
|
||||
disable(id) {
|
||||
const plugins = this.get('plugins');
|
||||
const plugin = plugins.get(id);
|
||||
if (!plugin || plugin.get('status') !== Plugin.STATUS_ACTIVE) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
this.trigger('change');
|
||||
return plugin.disable().then(() => {
|
||||
this.trigger('change');
|
||||
this.saveState();
|
||||
});
|
||||
},
|
||||
|
||||
activate(id) {
|
||||
const plugins = this.get('plugins');
|
||||
const plugin = plugins.get(id);
|
||||
if (!plugin || plugin.get('status') === Plugin.STATUS_ACTIVE) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
this.trigger('change');
|
||||
return plugin.install(true).then(() => {
|
||||
this.trigger('change');
|
||||
this.saveState();
|
||||
});
|
||||
},
|
||||
|
@ -65,21 +88,21 @@ const PluginManager = Backbone.Model.extend({
|
|||
update(id) {
|
||||
const plugins = this.get('plugins');
|
||||
const oldPlugin = plugins.get(id);
|
||||
if (!oldPlugin) {
|
||||
if (!oldPlugin || [Plugin.STATUS_ACTIVE, Plugin.STATUS_INACTIVE, Plugin.STATUS_NONE].indexOf(oldPlugin.get('status')) < 0) {
|
||||
return Promise.reject();
|
||||
}
|
||||
const url = oldPlugin.get('url');
|
||||
this.set({ updating: id });
|
||||
this.trigger('change');
|
||||
return Plugin.loadFromUrl(url).then(newPlugin => {
|
||||
return oldPlugin.update(newPlugin).then(() => {
|
||||
this.set({ updating: null });
|
||||
this.trigger('change');
|
||||
this.saveState();
|
||||
}).catch(e => {
|
||||
this.set('updating', null);
|
||||
this.trigger('change');
|
||||
throw e;
|
||||
});
|
||||
}).catch(e => {
|
||||
this.set({ updating: null });
|
||||
this.trigger('change');
|
||||
throw e;
|
||||
});
|
||||
},
|
||||
|
@ -90,7 +113,7 @@ const PluginManager = Backbone.Model.extend({
|
|||
url: desc.url,
|
||||
local: true
|
||||
});
|
||||
return plugin.install()
|
||||
return plugin.install(desc.enabled)
|
||||
.then(() => plugin)
|
||||
.catch(() => plugin);
|
||||
},
|
||||
|
@ -99,9 +122,15 @@ const PluginManager = Backbone.Model.extend({
|
|||
SettingsStore.save('plugins', {
|
||||
plugins: this.get('plugins').map(plugin => ({
|
||||
manifest: plugin.get('manifest'),
|
||||
url: plugin.get('url')
|
||||
url: plugin.get('url'),
|
||||
enabled: plugin.get('status') === 'active'
|
||||
}))
|
||||
});
|
||||
},
|
||||
|
||||
getStatus(id) {
|
||||
const plugin = this.get('plugins').get(id);
|
||||
return plugin ? plugin.get('status') : '';
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -13,22 +13,26 @@ const io = new IoCache({
|
|||
logger: new Logger('storage-plugin-files')
|
||||
});
|
||||
|
||||
const Plugin = Backbone.Model.extend({
|
||||
idAttribute: 'name',
|
||||
|
||||
const PluginStatus = {
|
||||
STATUS_NONE: '',
|
||||
STATUS_ACTIVE: 'active',
|
||||
STATUS_INACTIVE: 'inactive',
|
||||
STATUS_INSTALLING: 'installing',
|
||||
STATUS_ACTIVATING: 'activating',
|
||||
STATUS_UNINSTALLING: 'uninstalling',
|
||||
STATUS_UPDATING: 'updating',
|
||||
STATUS_INVALID: 'invalid',
|
||||
STATUS_ERROR: 'error',
|
||||
};
|
||||
|
||||
const Plugin = Backbone.Model.extend(_.extend({}, PluginStatus, {
|
||||
idAttribute: 'name',
|
||||
|
||||
defaults: {
|
||||
name: '',
|
||||
manifest: '',
|
||||
url: '',
|
||||
status: 'inactive',
|
||||
status: '',
|
||||
installTime: null,
|
||||
installError: null,
|
||||
updateError: null
|
||||
|
@ -43,7 +47,7 @@ const Plugin = Backbone.Model.extend({
|
|||
this.logger = new Logger(`plugin:${name}`);
|
||||
},
|
||||
|
||||
install() {
|
||||
install(activate) {
|
||||
const ts = this.logger.ts();
|
||||
this.set('status', this.STATUS_INSTALLING);
|
||||
return Promise.resolve().then(() => {
|
||||
|
@ -53,6 +57,11 @@ const Plugin = Backbone.Model.extend({
|
|||
this.set('status', this.STATUS_INVALID);
|
||||
throw 'Plugin validation error: ' + error;
|
||||
}
|
||||
this.set('status', this.STATUS_INACTIVE);
|
||||
if (!activate) {
|
||||
this.logger.info('Loaded inactive plugin');
|
||||
return;
|
||||
}
|
||||
return this.installWithManifest()
|
||||
.then(() => this.set('installTime', this.logger.ts() - ts))
|
||||
.catch(err => {
|
||||
|
@ -358,8 +367,17 @@ const Plugin = Backbone.Model.extend({
|
|||
},
|
||||
|
||||
uninstall() {
|
||||
return this.disable.then(() => {
|
||||
return this.deleteResources().then(() => {
|
||||
this.set('status', '');
|
||||
this.logger.info('Uninstall complete', this.logger.ts(ts));
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
disable() {
|
||||
const manifest = this.get('manifest');
|
||||
this.logger.info('Uninstalling plugin with resources', Object.keys(manifest.resources).join(', '));
|
||||
this.logger.info('Disabling plugin with resources', Object.keys(manifest.resources).join(', '));
|
||||
this.set('status', this.STATUS_UNINSTALLING);
|
||||
const ts = this.logger.ts();
|
||||
return Promise.resolve().then(() => {
|
||||
|
@ -376,10 +394,8 @@ const Plugin = Backbone.Model.extend({
|
|||
if (manifest.theme) {
|
||||
this.removeTheme(manifest.theme);
|
||||
}
|
||||
return this.deleteResources().then(() => {
|
||||
this.set('status', this.STATUS_INACTIVE);
|
||||
this.logger.info('Uninstall complete', this.logger.ts(ts));
|
||||
});
|
||||
this.set('status', this.STATUS_INACTIVE);
|
||||
this.logger.info('Disable complete', this.logger.ts(ts));
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -432,7 +448,9 @@ const Plugin = Backbone.Model.extend({
|
|||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
_.extend(Plugin, PluginStatus);
|
||||
|
||||
Plugin.loadFromUrl = function(url) {
|
||||
if (url[url.length - 1] !== '/') {
|
||||
|
|
|
@ -9,13 +9,15 @@ const SettingsPluginsView = Backbone.View.extend({
|
|||
events: {
|
||||
'click .settings_plugins-install-btn': 'installClick',
|
||||
'click .settings_plugins-uninstall-btn': 'uninstallClick',
|
||||
'click .settings_plugins-disable-btn': 'disableClick',
|
||||
'click .settings_plugins-enable-btn': 'enableClick',
|
||||
'click .settings_plugins-update-btn': 'updateClick',
|
||||
'click .settings_plugins-use-locale-btn': 'useLocaleClick',
|
||||
'click .settings_plugins-use-theme-btn': 'useThemeClick'
|
||||
},
|
||||
|
||||
initialize() {
|
||||
this.listenTo(PluginManager, 'change:installing change:uninstalling change:updating', this.render.bind(this));
|
||||
this.listenTo(PluginManager, 'change', this.render.bind(this));
|
||||
},
|
||||
|
||||
render() {
|
||||
|
@ -29,8 +31,7 @@ const SettingsPluginsView = Backbone.View.extend({
|
|||
updateError: plugin.get('updateError')
|
||||
})),
|
||||
lastInstallUrl: PluginManager.get('installing') || (lastInstall.error ? lastInstall.url : ''),
|
||||
lastInstallError: lastInstall.error,
|
||||
updating: PluginManager.get('updating')
|
||||
lastInstallError: lastInstall.error
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
@ -66,17 +67,21 @@ const SettingsPluginsView = Backbone.View.extend({
|
|||
|
||||
uninstallClick(e) {
|
||||
const pluginId = $(e.target).data('plugin');
|
||||
if (PluginManager.get('updating') === pluginId || PluginManager.get('uninstalling') === pluginId) {
|
||||
return;
|
||||
}
|
||||
PluginManager.uninstall(pluginId);
|
||||
},
|
||||
|
||||
disableClick(e) {
|
||||
const pluginId = $(e.target).data('plugin');
|
||||
PluginManager.disable(pluginId);
|
||||
},
|
||||
|
||||
enableClick(e) {
|
||||
const pluginId = $(e.target).data('plugin');
|
||||
PluginManager.activate(pluginId);
|
||||
},
|
||||
|
||||
updateClick(e) {
|
||||
const pluginId = $(e.target).data('plugin');
|
||||
if (PluginManager.get('updating') === pluginId || PluginManager.get('uninstalling') === pluginId) {
|
||||
return;
|
||||
}
|
||||
PluginManager.update(pluginId);
|
||||
},
|
||||
|
||||
|
|
|
@ -15,21 +15,17 @@
|
|||
<div class="settings__plugins-plugin-desc">
|
||||
<a href="{{plugin.manifest.url}}" target="_blank">{{plugin.manifest.url}}</a>, v{{plugin.manifest.version}},
|
||||
{{#res 'setPlCreatedBy'}}<a href="{{plugin.manifest.author.url}}" target="_blank">{{plugin.manifest.author.name}}</a> ({{plugin.manifest.author.email}}){{/res}},
|
||||
{{#res 'setPlLoadTime'}}{{plugin.installTime}}ms{{/res}}
|
||||
{{#ifeq plugin.status 'active'}}{{#res 'setPlLoadTime'}}{{plugin.installTime}}ms{{/res}}{{else}}{{plugin.status}}{{/ifeq}}
|
||||
{{#ifeq plugin.status 'error'}}<span class="error-color"> ({{res 'setPlLoadError'}}){{/ifeq}}
|
||||
{{#if plugin.updateError}}<div class="error-color settings__plugins-upd-error">{{res 'setPlUpdateError'}}: <pre>{{plugin.updateError}}</pre></div>{{/if}}
|
||||
</div>
|
||||
<div class="settings__plugins-plugin-buttons">
|
||||
<button class="settings_plugins-uninstall-btn btn-error" data-plugin="{{plugin.id}}">{{res 'setPlUninstallBtn'}}</button>
|
||||
<button class="settings_plugins-update-btn btn-silent" data-plugin="{{plugin.id}}">
|
||||
{{~#ifeq plugin.id ../updating}}{{res 'setPlUpdating'}}…{{else}}{{res 'setPlUpdateBtn'}}{{/ifeq~}}
|
||||
</button>
|
||||
{{#if plugin.manifest.locale}}
|
||||
<button class="settings_plugins-use-locale-btn btn-silent" data-locale="{{plugin.manifest.locale.name}}">{{res 'setPlLocaleBtn'}}</button>
|
||||
{{/if}}
|
||||
{{#if plugin.manifest.theme}}
|
||||
<button class="settings_plugins-use-theme-btn btn-silent" data-theme="{{plugin.manifest.theme.name}}">{{res 'setPlThemeBtn'}}</button>
|
||||
{{/if}}
|
||||
{{#ifeq plugin.status 'active'}}<button class="settings_plugins-disable-btn btn-silent" data-plugin="{{plugin.id}}">{{res 'setPlDisableBtn'}}</button>{{/ifeq}}
|
||||
{{#ifeq plugin.status 'inactive'}}<button class="settings_plugins-enable-btn btn-silent" data-plugin="{{plugin.id}}">{{res 'setPlEnableBtn'}}</button>{{/ifeq}}
|
||||
<button class="settings_plugins-update-btn btn-silent" data-plugin="{{plugin.id}}">{{res 'setPlUpdateBtn'}}</button>
|
||||
{{#if plugin.manifest.locale}}<button class="settings_plugins-use-locale-btn btn-silent" data-locale="{{plugin.manifest.locale.name}}">{{res 'setPlLocaleBtn'}}</button>{{/if}}
|
||||
{{#if plugin.manifest.theme}}<button class="settings_plugins-use-theme-btn btn-silent" data-theme="{{plugin.manifest.theme.name}}">{{res 'setPlThemeBtn'}}</button>{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
|
|
Loading…
Reference in New Issue