summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorSuraj Shukla <suh@odoo.com>2017-04-13 18:28:59 +0530
committerAaron Bohy <aab@odoo.com>2018-02-27 12:18:55 +0100
commitebe58d9267bc979c64c399234120fed7b66cc374 (patch)
tree82533519882c584b44d7d6655212b76523136594 /addons/web/static/src
parentd36695cbc7210147ecb316bc1b7000413aad399a (diff)
[IMP] web: Calendar: mobile UX improvements
The following tweaks have been applied on mobile devices: - remove left and right arrow in control panel - enable swipe navigation (instead of left/right arrows) - replace 'Today' button by a calendar icon - remove static text 'Attendees:' in events - shorten header content in week mode to prevent them from overlapping - ensure that the calendar fits in the screen Also introduce a mobile test suite for the calendar view. Task #31449
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_controller.js42
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_model.js7
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_renderer.js30
-rw-r--r--addons/web/static/src/less/web_calendar.less37
-rw-r--r--addons/web/static/src/xml/web_calendar.xml19
5 files changed, 105 insertions, 30 deletions
diff --git a/addons/web/static/src/js/views/calendar/calendar_controller.js b/addons/web/static/src/js/views/calendar/calendar_controller.js
index e496734ed5d..73a83fd26e2 100644
--- a/addons/web/static/src/js/views/calendar/calendar_controller.js
+++ b/addons/web/static/src/js/views/calendar/calendar_controller.js
@@ -10,6 +10,7 @@ odoo.define('web.CalendarController', function (require) {
*/
var AbstractController = require('web.AbstractController');
+var config = require('web.config');
var core = require('web.core');
var Dialog = require('web.Dialog');
var dialogs = require('web.view_dialogs');
@@ -23,8 +24,10 @@ var CalendarController = AbstractController.extend({
changeDate: '_onChangeDate',
changeFilter: '_onChangeFilter',
dropRecord: '_onDropRecord',
+ next: '_onNext',
openCreate: '_onOpenCreate',
openEvent: '_onOpenEvent',
+ prev: '_onPrev',
quickCreate: '_onQuickCreate',
toggleFullWidth: '_onToggleFullWidth',
updateRecord: '_onUpdateRecord',
@@ -73,15 +76,16 @@ var CalendarController = AbstractController.extend({
*/
renderButtons: function ($node) {
var self = this;
- this.$buttons = $(QWeb.render("CalendarView.buttons", {'widget': this}));
+ this.$buttons = $(QWeb.render('CalendarView.buttons', {
+ isMobile: config.device.isMobile,
+ }));
this.$buttons.on('click', 'button.o_calendar_button_new', function () {
self.trigger_up('switch_view', {view_type: 'form'});
});
_.each(['prev', 'today', 'next'], function (action) {
self.$buttons.on('click', '.o_calendar_button_' + action, function () {
- self.model[action]();
- self.reload();
+ self._move(action);
});
});
_.each(['day', 'week', 'month'], function (scale) {
@@ -105,6 +109,18 @@ var CalendarController = AbstractController.extend({
//--------------------------------------------------------------------------
/**
+ * Move to the requested direction and reload the view
+ *
+ * @private
+ * @param {string} to either 'prev', 'next' or 'today'
+ * @returns {Deferred}
+ */
+ _move: function (to) {
+ this.model[to]();
+ return this.reload();
+ },
+ /**
+ * @private
* @param {Object} record
* @param {integer} record.id
* @returns {Deferred}
@@ -160,6 +176,14 @@ var CalendarController = AbstractController.extend({
* @private
* @param {OdooEvent} event
*/
+ _onNext: function (event) {
+ event.stopPropagation();
+ this._move('next');
+ },
+ /**
+ * @private
+ * @param {OdooEvent} event
+ */
_onOpenCreate: function (event) {
var self = this;
if (this.model.get().scale === "month") {
@@ -306,6 +330,15 @@ var CalendarController = AbstractController.extend({
open_dialog(true);
},
/**
+ * @private
+ * @param {OdooEvent} event
+ */
+ _onPrev: function () {
+ event.stopPropagation();
+ this._move('prev');
+ },
+
+ /**
* Handles saving data coming from quick create box
*
* @private
@@ -364,8 +397,7 @@ var CalendarController = AbstractController.extend({
this.$buttons.find('.active').removeClass('active');
this.$buttons.find('.o_calendar_button_' + this.mode).addClass('active');
}
- var subtitle = (this.mode === 'week' ? _t('Week ') : '') + event.data.title;
- this.set({title: this.displayName + ' (' + subtitle + ')'});
+ this.set({title: this.displayName + ' (' + event.data.title + ')'});
},
});
diff --git a/addons/web/static/src/js/views/calendar/calendar_model.js b/addons/web/static/src/js/views/calendar/calendar_model.js
index 102407e533d..ca28e90713f 100644
--- a/addons/web/static/src/js/views/calendar/calendar_model.js
+++ b/addons/web/static/src/js/views/calendar/calendar_model.js
@@ -6,7 +6,6 @@ var Context = require('web.Context');
var core = require('web.core');
var fieldUtils = require('web.field_utils');
var session = require('web.session');
-var time = require('web.time');
var _t = core._t;
@@ -400,12 +399,6 @@ return AbstractModel.extend({
weekNumbers: true,
weekNumberTitle: _t("W"),
allDayText: _t("All day"),
- views: {
- week: {
- columnFormat: 'ddd ' + time.getLangDateFormat(),
- titleFormat: time.getLangTimeFormat(),
- }
- },
monthNames: moment.months(),
monthNamesShort: moment.monthsShort(),
dayNames: moment.weekdays(),
diff --git a/addons/web/static/src/js/views/calendar/calendar_renderer.js b/addons/web/static/src/js/views/calendar/calendar_renderer.js
index b07ea293619..469130c723a 100644
--- a/addons/web/static/src/js/views/calendar/calendar_renderer.js
+++ b/addons/web/static/src/js/views/calendar/calendar_renderer.js
@@ -2,6 +2,7 @@ odoo.define('web.CalendarRenderer', function (require) {
"use strict";
var AbstractRenderer = require('web.AbstractRenderer');
+var config = require('web.config');
var core = require('web.core');
var Dialog = require('web.Dialog');
var field_utils = require('web.field_utils');
@@ -192,6 +193,9 @@ return AbstractRenderer.extend({
start: function () {
this._initSidebar();
this._initCalendar();
+ if (config.device.isMobile) {
+ this._bindSwipe();
+ }
return this._super();
},
/**
@@ -289,6 +293,27 @@ return AbstractRenderer.extend({
/**
* @private
+ * Bind handlers to enable swipe navigation
+ *
+ * @private
+ */
+ _bindSwipe: function () {
+ var self = this;
+ var touchStartX;
+ var touchEndX;
+ this.$calendar.on('touchstart', function (event) {
+ touchStartX = event.originalEvent.touches[0].pageX;
+ });
+ this.$calendar.on('touchend', function (event) {
+ touchEndX = event.originalEvent.changedTouches[0].pageX;
+ if (touchStartX - touchEndX > 100) {
+ self.trigger_up('next');
+ } else if (touchStartX - touchEndX < -100) {
+ self.trigger_up('prev');
+ }
+ });
+ },
+ /**
* @param {any} event
* @returns {string} the html for the rendered event
*/
@@ -297,6 +322,7 @@ return AbstractRenderer.extend({
event: event,
fields: this.state.fields,
format: this._format.bind(this),
+ isMobile: config.device.isMobile,
read_only_mode: this.read_only_mode,
record: event.record,
user_context: session.user_context,
@@ -376,11 +402,9 @@ return AbstractRenderer.extend({
viewRender: function (view) {
// compute mode from view.name which is either 'month', 'agendaWeek' or 'agendaDay'
var mode = view.name === 'month' ? 'month' : (view.name === 'agendaWeek' ? 'week' : 'day');
- // compute title: in week mode, display the week number
- var title = mode === 'week' ? view.intervalStart.week() : view.title;
self.trigger_up('viewUpdated', {
mode: mode,
- title: title,
+ title: view.title,
});
},
height: 'parent',
diff --git a/addons/web/static/src/less/web_calendar.less b/addons/web/static/src/less/web_calendar.less
index d6aab5e0e38..05c9a5d6b4a 100644
--- a/addons/web/static/src/less/web_calendar.less
+++ b/addons/web/static/src/less/web_calendar.less
@@ -66,9 +66,6 @@
}
.fc-view {
overflow-x: auto;
- > table {
- min-width: 600px;
- }
}
}
@@ -202,12 +199,6 @@
}
}
-@media only screen and (max-width: 768px) {
- .o_calendar_container {
- padding: 0;
- }
-}
-
.modal {
.o_attendee_head {
width: 32px;
@@ -220,3 +211,31 @@
display: none;
}
}
+
+// Mobile rules
+@media only screen and (max-width: 768px) {
+ .o_calendar_container {
+ padding: 0;
+ }
+}
+@media (max-width: @screen-xs-max) {
+ .o_control_panel {
+ .o_cp_left {
+ width: 100%;
+ .o_cp_buttons {
+ width: 100%;
+ .o_calendar_button_today {
+ float: right;
+ > .o_calendar_text {
+ margin-top: 3px;
+ }
+ }
+ }
+ }
+ }
+ .o_calendar_view {
+ .fc-day-header {
+ word-spacing: 1000px; // force line break in week mode
+ }
+ }
+}
diff --git a/addons/web/static/src/xml/web_calendar.xml b/addons/web/static/src/xml/web_calendar.xml
index 6573a51ca4e..ae9250d79e9 100644
--- a/addons/web/static/src/xml/web_calendar.xml
+++ b/addons/web/static/src/xml/web_calendar.xml
@@ -20,9 +20,9 @@
<t t-foreach="widget.displayFields" t-as="name">
<div t-attf-class="o_field_#{name} o_field_type_#{fields[name].type}">
<t t-if="widget.displayFields[name].avatar_field">
- <t t-esc="fields[name].string"/>:
+ <t t-if="!isMobile"><t t-esc="fields[name].string"/>:</t>
<div class="o_calendar_avatars pull-right">
- <t t-foreach="widget.getAvatars(record, name, widget.displayFields[name].avatar_field).slice(0,3)" t-as="image"><t t-raw="image"/></t>
+ <t t-foreach="widget.getAvatars(record, name, widget.displayFields[name].avatar_field).slice(0,3)" t-as="image"><t t-raw="image"/></t>
<span t-if="record[name].length - 3 > 0">+<t t-esc="record[name].length - 3"/></span>
</div>
</t>
@@ -63,10 +63,17 @@
<t t-name="CalendarView.buttons">
<div class="o_calendar_buttons">
- <button class="o_calendar_button_prev btn btn-sm btn-primary"><span class="fa fa-arrow-left"/></button>
- <button class="o_calendar_button_today btn btn-sm btn-primary">Today</button>
- <button class="o_calendar_button_next btn btn-sm btn-primary"><span class="fa fa-arrow-right"/></button>
-
+ <t t-if="isMobile">
+ <span class="fa-stack o_calendar_button_today">
+ <i class="fa fa-calendar-o fa-stack-2x"></i>
+ <strong class="o_calendar_text fa-stack-1x"><t t-esc="moment().date()"/></strong>
+ </span>
+ </t>
+ <t t-else="">
+ <button class="o_calendar_button_prev btn btn-sm btn-primary"><span class="fa fa-arrow-left"/></button>
+ <button class="o_calendar_button_today btn btn-sm btn-primary">Today</button>
+ <button class="o_calendar_button_next btn btn-sm btn-primary"><span class="fa fa-arrow-right"/></button>
+ </t>
<div class="btn-group btn-group-sm">
<button type="button" class="o_calendar_button_day btn btn-sm btn-default">Day</button>
<button type="button" class="o_calendar_button_week btn btn-sm btn-default">Week</button>