[REM] base,web: delete menu Apps Store, Updates
Those menus are supposed to be integrations with apps.odoo.com, but it doens't work and not maintained. Existing menus that open apps store links should be enough: * Apps >> Apps >> Theme Store --> https://apps.odoo.com/apps/themes * Apps >> Apps >> Third-Part Apps --> https://apps.odoo.com/apps/modules --- close #72902 close #74602 closes odoo/odoo#106379 Related: odoo/enterprise#34324 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
@@ -276,7 +276,6 @@ This module provides the core of the Odoo Web Client.
|
||||
'web/static/src/legacy/js/widgets/week_days.js',
|
||||
'web/static/src/legacy/js/widgets/signature.js',
|
||||
'web/static/src/legacy/js/widgets/attach_document.js',
|
||||
'web/static/src/legacy/js/apps.js',
|
||||
'web/static/src/legacy/js/env.js',
|
||||
'web/static/src/legacy/js/model.js',
|
||||
'web/static/src/legacy/js/owl_compatibility.js',
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
odoo.define('web.Apps', function (require) {
|
||||
"use strict";
|
||||
|
||||
var AbstractAction = require('web.AbstractAction');
|
||||
var config = require('web.config');
|
||||
var core = require('web.core');
|
||||
var framework = require('web.framework');
|
||||
var session = require('web.session');
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
var apps_client = null;
|
||||
|
||||
var Apps = AbstractAction.extend({
|
||||
contentTemplate: 'EmptyComponent',
|
||||
remote_action_tag: 'loempia.embed',
|
||||
failback_action_id: 'base.open_module_tree',
|
||||
|
||||
init: function(parent, action) {
|
||||
this._super(parent, action);
|
||||
var options = action.params || {};
|
||||
this.params = options; // NOTE forwarded to embedded client action
|
||||
},
|
||||
|
||||
get_client: function() {
|
||||
// return the client via a promise, resolved or rejected depending if
|
||||
// the remote host is available or not.
|
||||
var check_client_available = function(client) {
|
||||
var i = new Image();
|
||||
var def = new Promise(function (resolve, reject) {
|
||||
i.onerror = function() {
|
||||
reject(client);
|
||||
};
|
||||
i.onload = function() {
|
||||
resolve(client);
|
||||
};
|
||||
});
|
||||
var ts = new Date().getTime();
|
||||
i.src = _.str.sprintf('%s/web/static/src/img/sep-a.gif?%s', client.origin, ts);
|
||||
return def;
|
||||
};
|
||||
if (apps_client) {
|
||||
return check_client_available(apps_client);
|
||||
} else {
|
||||
return this._rpc({model: 'ir.module.module', method: 'get_apps_server'})
|
||||
.then(function(u) {
|
||||
var link = $(_.str.sprintf('<a href="%s"></a>', u))[0];
|
||||
var host = _.str.sprintf('%s//%s', link.protocol, link.host);
|
||||
var dbname = link.pathname;
|
||||
if (dbname[0] === '/') {
|
||||
dbname = dbname.substr(1);
|
||||
}
|
||||
var client = {
|
||||
origin: host,
|
||||
dbname: dbname
|
||||
};
|
||||
apps_client = client;
|
||||
return check_client_available(client);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
$(window).off("message." + this.uniq);
|
||||
if (this.$ifr) {
|
||||
this.$ifr.remove();
|
||||
this.$ifr = null;
|
||||
}
|
||||
return this._super();
|
||||
},
|
||||
|
||||
_on_message: function($e) {
|
||||
var self = this, client = this.client, e = $e.originalEvent;
|
||||
|
||||
if (e.origin !== client.origin) {
|
||||
return;
|
||||
}
|
||||
|
||||
var dispatcher = {
|
||||
'event': function(m) { self.trigger('message:' + m.event, m); },
|
||||
'action': function(m) {
|
||||
self.do_action(m.action).then(function(r) {
|
||||
var w = self.$ifr[0].contentWindow;
|
||||
w.postMessage({id: m.id, result: r}, client.origin);
|
||||
});
|
||||
},
|
||||
'rpc': function(m) {
|
||||
return self._rpc({route: m.args[0], params: m.args[1]}).then(function(r) {
|
||||
var w = self.$ifr[0].contentWindow;
|
||||
w.postMessage({id: m.id, result: r}, client.origin);
|
||||
});
|
||||
},
|
||||
'Model': function(m) {
|
||||
return self._rpc({model: m.model, method: m.args[0], args: m.args[1]})
|
||||
.then(function(r) {
|
||||
var w = self.$ifr[0].contentWindow;
|
||||
w.postMessage({id: m.id, result: r}, client.origin);
|
||||
});
|
||||
},
|
||||
};
|
||||
// console.log(e.data);
|
||||
if (!_.isObject(e.data)) { return; }
|
||||
if (dispatcher[e.data.type]) {
|
||||
dispatcher[e.data.type](e.data);
|
||||
}
|
||||
},
|
||||
|
||||
start: function() {
|
||||
var self = this;
|
||||
return new Promise(function (resolve, reject) {
|
||||
self.get_client().then(function (client) {
|
||||
self.client = client;
|
||||
|
||||
var qs = {db: client.dbname};
|
||||
if (config.isDebug()) {
|
||||
qs.debug = odoo.debug;
|
||||
}
|
||||
var u = $.param.querystring(client.origin + "/apps/embed/client", qs);
|
||||
var css = {width: '100%', height: '750px'};
|
||||
self.$ifr = $('<iframe>').attr('src', u);
|
||||
|
||||
self.uniq = _.uniqueId('apps');
|
||||
$(window).on("message." + self.uniq, self.proxy('_on_message'));
|
||||
|
||||
self.on('message:ready', self, function(m) {
|
||||
var w = this.$ifr[0].contentWindow;
|
||||
var act = {
|
||||
type: 'ir.actions.client',
|
||||
tag: this.remote_action_tag,
|
||||
params: _.extend({}, this.params, {
|
||||
db: session.db,
|
||||
origin: session.origin,
|
||||
})
|
||||
};
|
||||
w.postMessage({type:'action', action: act}, client.origin);
|
||||
});
|
||||
|
||||
self.on('message:set_height', self, function(m) {
|
||||
this.$ifr.height(m.height);
|
||||
});
|
||||
|
||||
self.on('message:blockUI', self, function() { framework.blockUI(); });
|
||||
self.on('message:unblockUI', self, function() { framework.unblockUI(); });
|
||||
self.on('message:warn', self, function(m) {self.displayNotification({ title: m.title, message: m.message, sticky: m.sticky, type: 'danger' }); });
|
||||
|
||||
self.$ifr.appendTo(self.$('.o_content')).css(css).addClass('apps-client');
|
||||
|
||||
resolve();
|
||||
}, function() {
|
||||
self.displayNotification({ title: _t('Odoo Apps will be available soon'), message: _t('Showing locally available modules'), sticky: true, type: 'danger' });
|
||||
return self._rpc({
|
||||
route: '/web/action/load',
|
||||
params: {action_id: self.failback_action_id},
|
||||
}).then(function(action) {
|
||||
return self.do_action(action, {clear_breadcrumbs: true});
|
||||
}).then(resolve, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var AppsUpdates = Apps.extend({
|
||||
remote_action_tag: 'loempia.embed.updates',
|
||||
});
|
||||
|
||||
core.action_registry.add("apps", Apps);
|
||||
core.action_registry.add("apps.updates", AppsUpdates);
|
||||
|
||||
return Apps;
|
||||
|
||||
});
|
||||
@@ -803,110 +803,6 @@ class Module(models.Model):
|
||||
|
||||
return res
|
||||
|
||||
@assert_log_admin_access
|
||||
def download(self, download=True):
|
||||
return []
|
||||
|
||||
@assert_log_admin_access
|
||||
@api.model
|
||||
def install_from_urls(self, urls):
|
||||
if not self.env.user.has_group('base.group_system'):
|
||||
raise AccessDenied()
|
||||
|
||||
# One-click install is opt-in - cfr Issue #15225
|
||||
ad_dir = tools.config.addons_data_dir
|
||||
if not os.access(ad_dir, os.W_OK):
|
||||
msg = (_("Automatic install of downloaded Apps is currently disabled.") + "\n\n" +
|
||||
_("To enable it, make sure this directory exists and is writable on the server:") +
|
||||
"\n%s" % ad_dir)
|
||||
_logger.warning(msg)
|
||||
raise UserError(msg)
|
||||
|
||||
apps_server = werkzeug.urls.url_parse(self.get_apps_server())
|
||||
|
||||
OPENERP = odoo.release.product_name.lower()
|
||||
tmp = tempfile.mkdtemp()
|
||||
_logger.debug('Install from url: %r', urls)
|
||||
try:
|
||||
# 1. Download & unzip missing modules
|
||||
for module_name, url in urls.items():
|
||||
if not url:
|
||||
continue # nothing to download, local version is already the last one
|
||||
|
||||
up = werkzeug.urls.url_parse(url)
|
||||
if up.scheme != apps_server.scheme or up.netloc != apps_server.netloc:
|
||||
raise AccessDenied()
|
||||
|
||||
try:
|
||||
_logger.info('Downloading module `%s` from OpenERP Apps', module_name)
|
||||
response = requests.get(url)
|
||||
response.raise_for_status()
|
||||
content = response.content
|
||||
except Exception:
|
||||
_logger.exception('Failed to fetch module %s', module_name)
|
||||
raise UserError(_('The `%s` module appears to be unavailable at the moment, please try again later.', module_name))
|
||||
else:
|
||||
zipfile.ZipFile(io.BytesIO(content)).extractall(tmp)
|
||||
assert os.path.isdir(os.path.join(tmp, module_name))
|
||||
|
||||
# 2a. Copy/Replace module source in addons path
|
||||
for module_name, url in urls.items():
|
||||
if module_name == OPENERP or not url:
|
||||
continue # OPENERP is special case, handled below, and no URL means local module
|
||||
module_path = modules.get_module_path(module_name, downloaded=True, display_warning=False)
|
||||
bck = backup(module_path, False)
|
||||
_logger.info('Copy downloaded module `%s` to `%s`', module_name, module_path)
|
||||
shutil.move(os.path.join(tmp, module_name), module_path)
|
||||
if bck:
|
||||
shutil.rmtree(bck)
|
||||
|
||||
# 2b. Copy/Replace server+base module source if downloaded
|
||||
if urls.get(OPENERP):
|
||||
# special case. it contains the server and the base module.
|
||||
# extract path is not the same
|
||||
base_path = os.path.dirname(modules.get_module_path('base'))
|
||||
|
||||
# copy all modules in the SERVER/odoo/addons directory to the new "odoo" module (except base itself)
|
||||
for d in os.listdir(base_path):
|
||||
if d != 'base' and os.path.isdir(os.path.join(base_path, d)):
|
||||
destdir = os.path.join(tmp, OPENERP, 'addons', d) # XXX 'odoo' subdirectory ?
|
||||
shutil.copytree(os.path.join(base_path, d), destdir)
|
||||
|
||||
# then replace the server by the new "base" module
|
||||
server_dir = tools.config['root_path'] # XXX or dirname()
|
||||
bck = backup(server_dir)
|
||||
_logger.info('Copy downloaded module `odoo` to `%s`', server_dir)
|
||||
shutil.move(os.path.join(tmp, OPENERP), server_dir)
|
||||
#if bck:
|
||||
# shutil.rmtree(bck)
|
||||
|
||||
self.update_list()
|
||||
|
||||
with_urls = [module_name for module_name, url in urls.items() if url]
|
||||
downloaded = self.search([('name', 'in', with_urls)])
|
||||
installed = self.search([('id', 'in', downloaded.ids), ('state', '=', 'installed')])
|
||||
|
||||
to_install = self.search([('name', 'in', list(urls)), ('state', '=', 'uninstalled')])
|
||||
post_install_action = to_install.button_immediate_install()
|
||||
|
||||
if installed or to_install:
|
||||
# in this case, force server restart to reload python code...
|
||||
self._cr.commit()
|
||||
odoo.service.server.restart()
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'home',
|
||||
'params': {'wait': True},
|
||||
}
|
||||
return post_install_action
|
||||
|
||||
finally:
|
||||
shutil.rmtree(tmp)
|
||||
|
||||
@api.model
|
||||
def get_apps_server(self):
|
||||
return tools.config.get('apps_server', 'https://apps.odoo.com/apps')
|
||||
|
||||
def _update_dependencies(self, depends=None, auto_install_requirements=()):
|
||||
self.env['ir.module.module.dependency'].flush_model()
|
||||
existing = set(dep.name for dep in self.dependencies_id)
|
||||
|
||||
@@ -249,20 +249,5 @@
|
||||
</record>
|
||||
<menuitem id="menu_theme_store" parent="menu_apps" name="Theme Store" sequence="10" action="action_theme_store"/>
|
||||
|
||||
|
||||
<!-- Apps modules -->
|
||||
<record model="ir.actions.client" id="modules_act_cl">
|
||||
<field name="name">App Store</field>
|
||||
<field name="tag">apps</field>
|
||||
</record>
|
||||
<menuitem id="module_mi" parent="base.menu_management" sequence="10" action="modules_act_cl" groups="base.group_no_one"/>
|
||||
|
||||
<record model="ir.actions.client" id="modules_updates_act_cl">
|
||||
<field name="name">Updates</field>
|
||||
<field name="tag">apps.updates</field>
|
||||
<field name="params">{}</field>
|
||||
</record>
|
||||
<menuitem id="menu_module_updates" parent="base.menu_management" sequence="20" action="modules_updates_act_cl" groups="base.group_no_one"/>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user