Merge branch 'flectra-app-store' into 'master'

[IMP] improvement on app store.

See merge request flectra-hq/flectra!162
This commit is contained in:
Parthiv Patel 2018-10-31 11:53:56 +00:00
commit c3cd4c4867
5 changed files with 94 additions and 70 deletions

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
import tarfile
import uuid
import babel.messages.pofile
import base64
@ -570,7 +571,7 @@ class Home(http.Controller):
@http.route(['/web/app_action'], type='json', auth="user")
def app_action(self, action='', module_name='', **kwargs):
if request.env.user.has_group('base.group_system'):
if request.env.user.has_group('base.group_system') and config.get('app_store') == 'install':
if module_name and action:
module = request.env['ir.module.module'].search([('state', '=', 'installed'), ('name', '=', module_name)], limit=1)
if module:
@ -581,7 +582,7 @@ class Home(http.Controller):
@http.route(['/web/get_modules'], type='json', auth="user")
def get_modules(self, **kwargs):
if request.env.user.has_group('base.group_system'):
if request.env.user.has_group('base.group_system') and config.get('app_store') in ['install', 'download']:
try:
modules = request.env['ir.module.module'].search_read([('state', '=', 'installed')], fields=['name'])
p = requests.post(server_url + '/flectrahq/get_modules', data=kwargs)
@ -595,11 +596,11 @@ class Home(http.Controller):
return False
return False
@http.route(['/web/module_download/<int:id>'], type='http', auth="user", methods=['GET', 'POST'])
def app_download(self, id=None):
if request.env.user.has_group('base.group_system'):
@http.route(['/web/module_download/<string:id>'], type='http', auth="user", methods=['GET', 'POST'])
def app_download(self, id=None, **kwargs):
if request.env.user.has_group('base.group_system') and config.get('app_store') in ['install', 'download']:
dbuuid = request.env['ir.config_parameter'].get_param('database.uuid')
p = requests.get(server_url + '/flectrahq/get_module_zip/' + str(id) + '/1', params={'dbuuid': dbuuid})
p = requests.get(server_url + '/flectrahq/get_module_zip/' + str(id), params={'dbuuid': dbuuid})
try:
data = json.loads(p.content.decode('utf-8'))
if data.get('error', False):
@ -618,17 +619,12 @@ class Home(http.Controller):
return request.not_found()
return request.not_found()
@http.route(['/web/app_download_install/<int:id>'], type='json', auth="user")
def app_download_install(self, id=None):
if request.env.user.has_group('base.group_system'):
@http.route(['/web/app_download_install'], type='json', auth="user")
def app_download_install(self, checksum=None, module_name=None, id=None, **kwargs):
if request.env.user.has_group('base.group_system') and config.get('app_store') == 'install':
IrModule = request.env['ir.module.module']
try:
res_get_details = requests.get(server_url + '/flectrahq/get_module_zip/' + str(id) + '/0')
module_file_details = json.loads(res_get_details.content.decode('utf-8'))
except:
return {"error": "Internal Server Error"}
finally:
res_download = requests.get(server_url + '/flectrahq/get_module_zip/' + str(id) + '/1')
res_download = requests.get(server_url + '/flectrahq/get_module_zip/' + str(id))
downloaded_file_checksum = hashlib.sha1(res_download.content or b'').hexdigest()
if res_download.status_code == 200:
try:
@ -637,9 +633,8 @@ class Home(http.Controller):
return data
except:
pass
if module_file_details['checksum'] == downloaded_file_checksum:
path = os.path.join(tmp_dir_path, module_file_details['name'])
if checksum == downloaded_file_checksum:
path = os.path.join(tmp_dir_path, uuid.uuid4().hex)
try:
with open(path, 'wb') as f:
f.write(res_download.content)
@ -650,14 +645,15 @@ class Home(http.Controller):
finally:
IrModule.update_list()
root.load_addons()
modules = IrModule.search([('name', '=', module_file_details['module_name'])], limit=1)
modules.button_immediate_install()
if module_name:
modules = IrModule.search([('name', '=', module_name)], limit=1)
modules.button_immediate_install()
os.remove(path)
return {"success": "Module is successfully installed."}
else:
return {"error": "File Crash."}
return {"error": "Internal Server Error."}
return {"error": "File crashed when downloading."}
except:
return {"error": "Internal Server Error"}
return False

View File

@ -99,27 +99,20 @@ var Apps = Widget.extend({
},
_openDialogAfterAction: function (data) {
if (!_.isEmpty(data)) {
var buttons = [];
if (data.success) {
buttons.push({
text: _t("Refresh"),
classes: 'btn-success',
click: function (e) {
window.location.reload();
},
close: true
});
window.location.reload();
return;
}
buttons.push({
text: _t("Cancel"),
classes: 'btn-warning',
var buttons = [{
text: _t("OK"),
classes: 'btn-success',
close: true,
});
}];
var dialog = new Dialog(this, {
size: 'medium',
buttons: buttons,
$content: $("<h4>" + (data.error || data.success) + "</h4>"),
title: _t(data.error ? "Error" : "Message"),
$content: $("<h4>" + data.error + "</h4>"),
title: _t("Error"),
});
dialog.open();
}
@ -152,8 +145,14 @@ var Apps = Widget.extend({
e.preventDefault();
var self = this;
var id = $(e.target).data("module-id");
var data = _.findWhere(this.all_app, {id: id});
self._rpc({
route: '/web/app_download_install/' + id,
route: '/web/app_download_install',
params: {
id: data['md5_val'],
checksum: data['checksum'],
module_name: data['technical_name']
}
}).then(function (data) {
self._openDialogAfterAction(data);
});
@ -172,10 +171,11 @@ var Apps = Widget.extend({
params: {
offset: this.context.categ[this.active_categ]['offset'],
categ: this.active_categ,
search: this.context.categ[self.active_categ]['search']
search: this.context.categ[this.active_categ]['search']
}
}).done(function (data) {
if (data) {
self.all_app = self.all_app.concat(data.modules[self.active_categ]);
self.$el.find('#' + self.active_categ + " .module-kanban:last")
.after(QWeb.render('AppStore.ModuleBoxContainer', {
modules: data.modules[self.active_categ],
@ -183,10 +183,15 @@ var Apps = Widget.extend({
mode: self.mode,
store_url: data.store_url
}));
if (!_.isEmpty(data.modules[self.active_categ])) {
if (!_.isEmpty(data.modules[self.active_categ]) && data.modules[self.active_categ].length == data.limit) {
self.$el.find('#' + self.active_categ + " .load-more").show();
} else {
self.$el.find('#' + self.active_categ + " .load-more").hide();
var $rec = self.$el.find('#' + self.active_categ + " .module-kanban ");
var $load_more = self.$el.find('#' + self.active_categ + " .load-more");
$load_more.hide().next('h3').remove();
if (!$rec.length) {
$load_more.after('<h3>No such module(s) found.</h3>');
}
}
} else {
self.$el.html(QWeb.render('AppStore.TryError', {}));
@ -227,18 +232,25 @@ var Apps = Widget.extend({
}
}).done(function (data) {
if (data) {
self.all_app = self.all_app.concat(data.modules[self.active_categ]);
self.$el.find('#' + self.active_categ).find('.module-kanban').remove();
self.context.categ[self.active_categ]['search'] = search;
self.context.categ[self.active_categ]['offset'] = 0;
$(QWeb.render('AppStore.ModuleBoxContainer', {
modules: data.modules[self.active_categ],
installed_modules: data.installed_modules,
mode: self.mode,
store_url: data.store_url
})).prependTo(self.$el.find('#' + self.active_categ + " .o_kanban_view"));
if (!_.isEmpty(data.modules[self.active_categ])) {
if (!_.isEmpty(data.modules[self.active_categ]) && data.modules[self.active_categ].length == data.limit) {
self.$el.find('#' + self.active_categ + " .load-more").show().next('h3').remove();
} else {
self.$el.find('#' + self.active_categ + " .load-more").hide().after('<h3>No such module(s) found.</h3>');
var $rec = self.$el.find('#' + self.active_categ + " .module-kanban ");
var $load_more = self.$el.find('#' + self.active_categ + " .load-more");
$load_more.hide().next('h3').remove();
if (!$rec.length) {
$load_more.after('<h3>No such module(s) found.</h3>');
}
}
} else {
self.$el.html(QWeb.render('AppStore.TryError', {}));

View File

@ -32,10 +32,13 @@
}
li {
float: none;
> a:hover, > a:focus {
border-color: transparent;
border-radius: 0;
background-color: mix(@brand-primary, #ffffff, 50%);
> a {
white-space: nowrap;
&:hover, &:focus {
border-color: transparent;
border-radius: 0;
background-color: mix(@brand-primary, #ffffff, 50%);
}
}
}
@media (max-width: @screen-sm-max) {
@ -70,13 +73,13 @@
visibility: visible;
}
.oe_module_desc {
min-height: 130px;
.oe_module_action {
white-space: nowrap;
overflow: hidden !important;
text-overflow: ellipsis;
.o_module_tech_name {
display: inline-block;
width: 140px;
white-space: nowrap;
overflow: hidden !important;
text-overflow: ellipsis;
}
}
}

View File

@ -1495,7 +1495,7 @@
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<t t-set="is_install" t-value="installed_modules.includes(m.technical_name)"/>
<li><a t-if="is_install and mode == 'install'" app-action="uninstall" t-att-data-module-id="m.id" href="#" class=" oe_kanban_action oe_kanban_action_a">Uninstall</a></li>
<li><a app-action="download" t-att-data-module-id="m.id" t-att-href="m.price ? 'javascript:void(0);' : '/web/module_download/' + m.id" class=" oe_kanban_action oe_kanban_action_a">Download</a></li>
<li><a app-action="download" t-att-data-module-id="m.id" t-att-href="m.price ? 'javascript:void(0);' : '/web/module_download/' + m.md5_val" class=" oe_kanban_action oe_kanban_action_a">Download</a></li>
<li><a app-action="view-info" t-att-data-module-id="m.id" href="#" class="oe_kanban_action oe_kanban_action_a">View Info</a></li>
<li><a t-attf-href="{{ store_url }}/apps/{{ m.version }}/{{ m.technical_name }}" target="_blank" class=" oe_kanban_action oe_kanban_action_a">View More on Store</a></li>
</ul>
@ -1507,9 +1507,13 @@
<span><t t-esc="m.description or ''"/></span>
</p>
<div class="oe_module_action">
<span class="pull-left"><t t-esc="m.price ? m.price + ' ' + m.currency[1] : 'Free'"/></span><br/>
<code class="pull-left o_module_tech_name"><small><span><t t-esc="m.technical_name"/></span></small></code>
<div class="text-right">
<span t-if="m.price">
<t t-esc="m.currency[2] == 'after' ? m.price + ' ' + m.currency[1] : m.currency[1] + ' ' + m.price"/>
</span>
<span t-else="m.price">Free</span>
<br/>
<code class="o_module_tech_name" t-att-title="m.technical_name"><small><span><t t-esc="m.technical_name"/></span></small></code>
<div class="text-right mt8">
<t t-if="is_install">
<span>Installed</span>
</t>
@ -1521,7 +1525,7 @@
</t>
<t t-else="">
<button t-if="mode == 'install'" app-action="install" t-att-data-module-id="m.id" class="btn btn-primary btn-sm oe_kanban_action oe_kanban_action_button">Install</button>
<a t-if="mode == 'download'" app-action="download" t-att-href="m.price ? 'javascript:void(0);' : '/web/module_download/' + m.id " t-att-data-module-id="m.id" class="btn btn-primary btn-sm oe_kanban_action oe_kanban_action_button">
<a t-if="mode == 'download'" app-action="download" t-att-href="m.price ? 'javascript:void(0);' : '/web/module_download/' + m.md5_val " t-att-data-module-id="m.id" class="btn btn-primary btn-sm oe_kanban_action oe_kanban_action_button">
<span><i class="fa fa-download"/></span>
</a>
</t>
@ -1607,7 +1611,11 @@
<span><t t-esc="m.description or ''"/></span>
</p>
<div class="oe_module_action">
<span><t t-esc="m.price ? m.price + ' ' + m.currency[1] : 'Free'"/></span><br/>
<span t-if="m.price">
<t t-esc="m.currency[2] == 'after' ? m.price + ' ' + m.currency[1] : m.currency[1] + ' ' + m.price"/>
</span>
<span t-else="m.price">Free</span>
<br/>
<code><small><span><t t-esc="m.technical_name"/></span></small></code>
</div>
</div>

View File

@ -636,18 +636,23 @@ class configmanager(object):
except OSError:
logging.getLogger(__name__).debug('Failed to create addons data dir %s', d)
try:
if self.get('db_name') and not os.listdir(os.path.join(d)):
from flectra.sql_db import db_connect
with closing(db_connect(self.get('db_name')).cursor()) as cr:
if flectra.tools.table_exists(cr, 'ir_module_module'):
cr.execute("SELECT latest_version FROM ir_module_module WHERE name=%s", ('base',))
base_version = cr.fetchone()
if base_version and base_version[0]:
tmp = base_version[0].split('.')[:2]
last_version = '.'.join(str(v) for v in tmp)
s = os.path.join(add_dir, last_version)
if float(last_version) < float(release.series) and os.listdir(os.path.join(s)):
self.copytree(s, d)
try:
from flectra.http import request, root
if request.session.db and not os.listdir(os.path.join(d)):
from flectra.sql_db import db_connect
with closing(db_connect(request.session.db).cursor()) as cr:
if flectra.tools.table_exists(cr, 'ir_module_module'):
cr.execute("SELECT latest_version FROM ir_module_module WHERE name=%s", ('base',))
base_version = cr.fetchone()
if base_version and base_version[0]:
tmp = base_version[0].split('.')[:2]
last_version = '.'.join(str(v) for v in tmp)
s = os.path.join(add_dir, last_version)
if float(last_version) < float(release.series) and os.listdir(os.path.join(s)):
self.copytree(s, d)
root.load_addons()
except:
pass
if self.get('app_store') == 'install':
if not os.access(d, os.W_OK):