Elastic: Mobile mode for tasks

This commit is contained in:
Aleksander Machniak 2018-03-25 13:15:30 +00:00
parent c4a62b6658
commit 3b6c5b7bfd
9 changed files with 246 additions and 112 deletions

View file

@ -1113,34 +1113,55 @@ function tag_draggable_helper()
function tag_draggable_start(event, ui)
{
// register notes list to receive drop events
if (rcmail.gui_objects.noteslist) {
// register notes list to receive drop events
$('tr', rcmail.gui_objects.noteslist).droppable({
addClasses: false,
hoverClass: 'droptarget',
accept: tag_droppable_accept,
drop: tag_draggable_dropped
});
}
// allow to drop tags onto edit form title
$('body.task-notes .content.formcontainer,#notedetailstitle.boxtitle').droppable({
addClasses: false,
accept: function() { return $(this).is('.formcontainer,.boxtitle'); },
drop: function(event, ui) {
var tag = tag_find(ui.draggable.data('tag'));
$('#tagedit-input').val(tag.name).trigger('transformToTag');
$('.tagline .placeholder', rcmail.gui_objects.noteviewtitle).hide();
}
}).addClass('tag-droppable');
// allow to drop tags onto note edit form
$('body.task-notes .content.formcontainer,#notedetailstitle.boxtitle').droppable({
addClasses: false,
accept: function() { return $(this).is('.formcontainer,.boxtitle'); },
drop: function(event, ui) {
var tag = tag_find(ui.draggable.data('tag'));
$('#tagedit-input').val(tag.name).trigger('transformToTag');
$('.tagline .placeholder', rcmail.gui_objects.noteviewtitle).hide();
}
}).addClass('tag-droppable');
}
else if (rcmail.task == 'tasks' && rcmail.gui_objects.resultlist) {
$('div.taskhead', rcmail.gui_objects.resultlist).droppable({
addClasses: false,
hoverClass: 'droptarget',
accept: tag_droppable_accept,
drop: tag_draggable_dropped
});
// allow to drop tags onto task edit form
$('body.task-tasks .content.formcontainer').droppable({
addClasses: false,
accept: function() { return $(this).is('.formcontainer') && $('#taskedit').is(':visible'); },
drop: function(event, ui) {
var tag = tag_find(ui.draggable.data('tag'));
$('#tagedit-input').val(tag.name).trigger('transformToTag');
}
}).addClass('tag-droppable');
}
}
function tag_draggable_dropped(event, ui)
{
var drop_id = $(this).attr('id').replace(/^rcmrow/, ''),
tag = tag_find(ui.draggable.data('tag'));
var drop_id = tag_draggable_target_id(this),
tag = tag_find(ui.draggable.data('tag')),
list = $(this).parent();
rcmail.triggerEvent('kolab-tags-drop', {id: drop_id, tag: tag.name, list: $(this).parent()});
rcmail.triggerEvent('kolab-tags-drop', {id: drop_id, tag: tag.name, list: list});
}
function tag_droppable_accept(draggable)
@ -1149,18 +1170,32 @@ function tag_droppable_accept(draggable)
return false;
}
var tag = tag_find(draggable.data('tag')),
drop_id = $(this).attr('id').replace(/^rcmrow/, ''),
var drop_id = tag_draggable_target_id(this),
tag = tag_find(draggable.data('tag')),
data = rcmail.triggerEvent('kolab-tags-drop-data', {id: drop_id});
// target already has this tag assigned
if (!data || (data.tags && $.inArray(tag.name, data.tags) >= 0)) {
if (!data || !tag || (data.tags && $.inArray(tag.name, data.tags) >= 0)) {
return false;
}
return true;
}
function tag_draggable_target_id(elem)
{
var id = $(elem).attr('id');
if (id) {
id = id.replace(/^rcmrow/, ''); // Notes
}
else {
id = $(elem).parent().attr('rel'); // Tasks
}
return id;
}
// Convert list of tag names into "blocks" and add to the specified element
function kolab_tags_text_block(tags, element, del_btn)
{

View file

@ -941,7 +941,7 @@ class libcalendaring extends rcube_plugin
case 'until':
$radio = new html_radiobutton(array('name' => 'repeat', 'class' => 'edit-recurrence-until'));
$select = $this->interval_selector(array('name' => 'times', 'id' => 'edit-recurrence-repeat-times', 'class' => 'form-control'));
$input = new html_inputfield(array('name' => 'untildate', 'id' => 'edit-recurrence-enddate', 'size' => "10", 'class' => 'form-control'));
$input = new html_inputfield(array('name' => 'untildate', 'id' => 'edit-recurrence-enddate', 'size' => '10', 'class' => 'form-control datepicker'));
$html = html::div('line first',
$radio->show('', array('value' => '', 'id' => 'edit-recurrence-repeat-forever'))
@ -978,7 +978,7 @@ class libcalendaring extends rcube_plugin
case 'rdate':
$ul = html::tag('ul', array('id' => 'edit-recurrence-rdates', 'class' => 'recurrence-rdates'), '');
$input = new html_inputfield(array('name' => 'rdate', 'id' => 'edit-recurrence-rdate-input', 'size' => "10", 'class' => 'form-control'));
$input = new html_inputfield(array('name' => 'rdate', 'id' => 'edit-recurrence-rdate-input', 'size' => "10", 'class' => 'form-control datepicker'));
$button = new html_inputfield(array('type' => 'button', 'class' => 'button add', 'value' => $this->gettext('addrdate')));
$html = html::div($attrib, html::label(array('class' => 'col-form-label col-sm-2', 'for' => 'edit-recurrence-rdate-input'), $this->gettext('bydates'))

View file

@ -158,7 +158,8 @@
display: inline;
float: none;
font-size: 1em;
margin-left: .2rem;
margin-left: .3rem;
color: @color-black-shade-text;
}
&.req-participant:after {
@ -362,13 +363,9 @@
}
.edit-alarm-buttons {
width: 5em;
a {
line-height: 1.2;
display: block;
line-height: 1;
padding: .375em .25em;
float: left;
margin: 0 .25rem;
&:before {
@ -386,6 +383,10 @@
display: none;
}
.edit-alarm-item:not(.first) .add-alarm {
display: none;
}
.edit-alarm-type {
flex: 1;
}

View file

@ -170,13 +170,17 @@
}
span.date {
font-size: 90%;
line-height: 1.8em;
color: @color-list-secondary;
position: absolute;
padding-left: .2em;
font-size: 90%;
line-height: 2.5;
color: @color-list-secondary;
cursor: pointer;
input {
// TODO
line-height: 1;
padding: 0;
margin-top: -2px;
}
}
@ -239,6 +243,26 @@
}
}
html.touch #tasklist {
li {
font-size: 1rem;
}
span.flagged,
input[type=checkbox],
.icon-checkbox + label {
display: none;
}
span.title {
margin-right: .5rem;
}
span.tags {
right: .5rem;
}
}
#taskshow {
& + .formbuttons {
button.disabled {
@ -272,10 +296,6 @@
font-size: .9em;
}
&.status-cancelled {
// TODO
}
.attachmentslist li {
margin-right: 1em;
}
@ -302,18 +322,6 @@
}
}
.taskitem-draghelper {
.overflow-ellipsis;
}
.quickview-active {
// TODO
}
#rootdroppable {
// TODO ?
}
#print-layout {
#tasklist {
padding: 0;
@ -339,3 +347,16 @@
}
}
}
.taskitem-draghelper {
.overflow-ellipsis;
}
.quickview-active {
// TODO ?
}
#rootdroppable {
// TODO ?
}

View file

@ -91,14 +91,16 @@
}
}
a.quickview:before {
content: @fa-var-eye;
opacity: .2;
color: @color-link;
}
a.quickview {
&:before {
content: @fa-var-eye;
opacity: .2;
color: @color-link;
}
a.quickview:after {
display: none !important;
&:after {
display: none !important;
}
}
&.focusview {
@ -211,6 +213,7 @@
position: relative !important;
margin: 0 .3em 0 -1em !important;
right: 0 !important;
font-size: 1.15em;
}
}
@ -246,6 +249,13 @@ html.touch .listing {
height: @listing-touch-line-height !important;
}
}
.actions {
margin-left: .2rem;
a {
margin-right: .5rem;
}
}
}
}

View file

@ -75,7 +75,7 @@ $labels['removetag'] = 'Remove';
$labels['removelink'] = 'Remove email reference';
$labels['auto'] = 'Auto';
$labels['taskdetails'] = 'Details';
$labels['taskdetails'] = 'Task details';
$labels['newtask'] = 'New Task';
$labels['edittask'] = 'Edit Task';
$labels['save'] = 'Save';

View file

@ -119,64 +119,64 @@
<h2 id="task-title" class="task-title"></h2>
<div id="task-description" class="task-description"></div>
<div id="task-attendees" class="form-group row task-attendees">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.assignedto" /></label>
<span class="task-text col-sm-10 form-control-plaintext"></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.assignedto" /></label>
<span class="task-text col-sm-8 form-control-plaintext"></span>
</div>
<div id="task-tags" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.tags" /></label>
<span class="task-text tagedit col-sm-10 form-control-plaintext"></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.tags" /></label>
<span class="task-text tagedit col-sm-8 form-control-plaintext"></span>
</div>
<div id="task-start" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.start" /></label>
<span class="col-sm-10 form-control-plaintext"><span class="task-text"></span> <span id="task-starttime"></span></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.start" /></label>
<span class="col-sm-8 form-control-plaintext"><span class="task-text"></span> <span id="task-starttime"></span></span>
</div>
<div id="task-date" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.datetime" /></label>
<span class="col-sm-10 form-control-plaintext"><span class="task-text"></span> <span id="task-time"></span></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.datetime" /></label>
<span class="col-sm-8 form-control-plaintext"><span class="task-text"></span> <span id="task-time"></span></span>
</div>
<div id="task-recurrence" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.repeat" /></label>
<span class="task-text col-sm-10 form-control-plaintext"></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.repeat" /></label>
<span class="task-text col-sm-8 form-control-plaintext"></span>
</div>
<div id="task-alarm" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.alarms" /></label>
<span class="task-text col-sm-10 form-control-plaintext"></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.alarms" /></label>
<span class="task-text col-sm-8 form-control-plaintext"></span>
</div>
<div id="task-organizer" class="form-group row task-attendees">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.roleorganizer" /></label>
<span class="task-text col-sm-10 form-control-plaintext"></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.roleorganizer" /></label>
<span class="task-text col-sm-8 form-control-plaintext"></span>
</div>
<div id="task-list" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.list" /></label>
<span class="task-text col-sm-10 form-control-plaintext"></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.list" /></label>
<span class="task-text col-sm-8 form-control-plaintext"></span>
</div>
<div id="task-completeness" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.complete" /></label>
<span class="task-text col-sm-10 form-control-plaintext"></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.complete" /></label>
<span class="task-text col-sm-8 form-control-plaintext"></span>
</div>
<div id="task-status" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.status" /></label>
<span class="task-text col-sm-10 form-control-plaintext"></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.status" /></label>
<span class="task-text col-sm-8 form-control-plaintext"></span>
</div>
<div id="task-links" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.links" /></label>
<span class="task-text col-sm-10"></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.links" /></label>
<span class="task-text col-sm-8"></span>
</div>
<div id="task-attachments" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="attachments" /></label>
<div class="task-text col-sm-10"></div>
<label class="col-sm-4 col-form-label"><roundcube:label name="attachments" /></label>
<div class="task-text col-sm-8"></div>
</div>
<div id="task-created" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.created" /></label>
<span class="task-text task-created col-sm-10 form-control-plaintext"></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.created" /></label>
<span class="task-text task-created col-sm-8 form-control-plaintext"></span>
</div>
<div id="task-changed" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.changed" /></label>
<span class="task-text task-changed col-sm-10 form-control-plaintext"></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.changed" /></label>
<span class="task-text task-changed col-sm-8 form-control-plaintext"></span>
</div>
<div id="task-rsvp-comment" class="form-group row">
<label class="col-sm-2 col-form-label"><roundcube:label name="tasklist.rsvpcomment" /></label>
<span class="task-text col-sm-10 form-control-plaintext"></span>
<label class="col-sm-4 col-form-label"><roundcube:label name="tasklist.rsvpcomment" /></label>
<span class="task-text col-sm-8 form-control-plaintext"></span>
</div>
<roundcube:object name="plugin.task_rsvp_buttons" id="task-rsvp" class="tasklist-invitebox invitebox boxinformation" style="display:none" />
</div>

View file

@ -18,7 +18,7 @@
<div class="form-group row">
<label for="taskedit-startdate" class="col-sm-2 col-form-label"><roundcube:label name="tasklist.start" /></label>
<div class="col-sm-10 datetime">
<input type="text" name="startdate" size="10" id="taskedit-startdate" class="form-control" /> &nbsp;
<input type="text" name="startdate" size="10" id="taskedit-startdate" class="form-control datepicker" /> &nbsp;
<input type="text" name="starttime" size="6" id="taskedit-starttime" class="form-control" aria-label="<roundcube:label name='tasklist.starttime' />" />
<a href="#nodate" class="edit-nodate" rel="#taskedit-startdate,#taskedit-starttime"><roundcube:label name="tasklist.nodate" /></a>
</div>
@ -26,7 +26,7 @@
<div class="form-group row">
<label for="taskedit-date" class="col-sm-2 col-form-label"><roundcube:label name="tasklist.datetime" /></label>
<div class="col-sm-10 datetime">
<input type="text" name="date" size="10" id="taskedit-date" class="form-control" /> &nbsp;
<input type="text" name="date" size="10" id="taskedit-date" class="form-control datepicker" /> &nbsp;
<input type="text" name="time" size="6" id="taskedit-time" class="form-control" aria-label="<roundcube:label name='tasklist.duetime' />" />
<a href="#nodate" class="edit-nodate" rel="#taskedit-date,#taskedit-time"><roundcube:label name="tasklist.nodate" /></a>
</div>

View file

@ -641,32 +641,67 @@ function rcube_tasklist_ui(settings)
}, datepicker_settings);
rcmail.addEventListener('kolab-tags-search', filter_tasks)
/*
// TODO
.addEventListener('kolab-tags-drop-data', function(e) { return notesdata[e.id]; })
.addEventListener('kolab-tags-drop-data', function(e) { return listdata[e.id]; })
.addEventListener('kolab-tags-drop', function(e) {
if ($(e.list).is('#kolabnoteslist')) {
return;
}
var rec = notesdata[e.id];
var rec = listdata[e.id];
if (rec && rec.id && e.tag) {
savedata = me.selected_note && rec.uid == me.selected_note.uid ? get_save_data() : $.extend({}, rec);
if (savedata.id) delete savedata.id;
if (savedata.html) delete savedata.html;
if (!savedata.tags)
savedata.tags = [];
savedata.tags.push(e.tag);
rcmail.lock_form(rcmail.gui_objects.noteseditform, true);
saving_lock = rcmail.set_busy(true, 'kolab_notes.savingdata');
rcmail.http_post('action', { _data: savedata, _do: 'edit' }, true);
if (!rec.tags)
rec.tags = [];
rec.tags.push(e.tag);
save_task(rec, 'edit');
}
});
*/
// Create simple list widget replacement for Elastic skin,
// as we do not use list nor treelist widget for tasks list
rcmail.tasklist = {
_find_sibling: function(dir) {
if (me.selected_task && me.selected_task.id) {
var n = false,
target = $('li[rel="' + me.selected_task.id + '"] > .taskhead', rcmail.gui_objects.resultlist)[0],
items = $(rcmail.gui_objects.resultlist).find('.taskhead');
items.each(function(i, item) {
if (item === target) {
n = i;
return false;
}
});
if (n !== false) {
return items[n + dir];
}
}
},
get_single_selection: function() {
if (me.selected_task) {
return me.selected_task.id;
}
},
get_node: function(uid) {
if (me.selected_task && me.selected_task.id) {
return {collapsed: true};
}
},
expand: function() {
if (me.selected_task && me.selected_task.id) {
var parent = $('li[rel="' + me.selected_task.id + '"]', rcmail.gui_objects.resultlist).parent('.childtasks')[0];
if (parent) {
$(parent).parent().children('.childtoggle.collapsed').click();
}
}
},
get_next: function() {
return rcmail.tasklist._find_sibling(1);
},
get_prev: function() {
return rcmail.tasklist._find_sibling(-1);
},
select: function(node) {
$(node).click();
}
};
rcmail.triggerEvent('tasklist-init');
}
@ -1087,7 +1122,7 @@ function rcube_tasklist_ui(settings)
return;
fix_tree_toggles();
update_taglist();//activetags);
update_taglist();
if (!count) {
msgbox.html(rcmail.gettext('notasksfound','tasklist')).show();
@ -1950,6 +1985,17 @@ function rcube_tasklist_ui(settings)
me.selected_task = rec;
list = rec.list && me.tasklists[rec.list] ? me.tasklists[rec.list] : {};
// hide nav buttons on mobile (elastic)
$('.content-frame-navigation > .buttons > .disabled').hide();
// for Elastic
rcmail.triggerEvent('show-content', {
mode: 'info',
title: rcmail.gettext('taskdetails', 'tasklist'),
obj: $('#taskshow').parent(),
scrollElement: $('#taskshow')
});
var status = rcmail.gettext('status-' + String(rec.status).toLowerCase(),'tasklist');
// fill dialog data
@ -2154,7 +2200,10 @@ function rcube_tasklist_ui(settings)
// Elastic
$dialog.removeClass('hidden').parents('.watermark').addClass('formcontainer');
//$('#notedetailsbox').parent().trigger('loaded');
$('#taskshow').parent().trigger('loaded');
// hide nav buttons on mobile (elastic)
$('.content-frame-navigation > .buttons > :not(.disabled)').show();
}
/**
@ -2366,6 +2415,21 @@ function rcube_tasklist_ui(settings)
if (rcmail.busy || !me.has_permission(list, 'i') || (action == 'edit' && (!rec || rec.readonly)))
return false;
// hide nav buttons on mobile (elastic)
$('.content-frame-navigation > .buttons > .disabled').hide();
if (action == 'new') {
$(rcmail.gui_objects.resultlist).find('.selected').removeClass('selected');
}
// for Elastic
rcmail.triggerEvent('show-content', {
mode: rec.uid ? 'edit' : 'add',
title: rcmail.gettext(rec.uid ? 'edittask' : 'newtask', 'tasklist'),
obj: $('#taskedit').parent(),
scrollElement: $('#taskedit')
});
me.selected_task = $.extend({ valarms:[] }, rec); // clone task object
rec = me.selected_task;
@ -2649,7 +2713,10 @@ function rcube_tasklist_ui(settings)
// Elastic
editform.removeClass('hidden').parents('.watermark').addClass('formcontainer');
//$('#notedetailsbox').parent().trigger('loaded');
$('#taskedit').parent().trigger('loaded');
// show nav buttons on mobile (elastic)
$('.content-frame-navigation > .buttons > :not(.disabled)').show();
}
/**
@ -3114,7 +3181,7 @@ function rcube_tasklist_ui(settings)
if (list && list.caldavurl) {
var dialog = $('<div>').addClass('showurldialog').append('<p>'+rcmail.gettext('caldavurldescription', 'tasklist')+'</p>'),
textbox = $('<textarea>').addClass('urlbox form-control').css('width', '100%')
.attr({rows: 2, readonly: true}).appendTo(dialog);
.attr({rows: 3, readonly: true}).appendTo(dialog);
rcmail.simple_dialog(dialog, 'tasklist.showcaldavurl', null, {
open: function() { textbox.val(list.caldavurl).select(); },