Elastic: Various elements of the Tasks UI

This commit is contained in:
Aleksander Machniak 2018-03-23 12:39:39 +01:00
parent 6bba054b0e
commit 8c4e836dea
18 changed files with 201 additions and 145 deletions

View file

@ -2873,7 +2873,6 @@ class calendar extends rcube_plugin
}
else if (in_array($header->ctype, array('multipart/alternative', 'multipart/mixed'))) {
// TODO: fetch bodystructure and search for ical parts. Maybe too expensive?
if (!empty($header->structure) && is_array($header->structure->parts)) {
foreach ($header->structure->parts as $part) {
if (libcalendaring::part_is_vcalendar($part) && !empty($part->ctype_parameters['method'])) {

View file

@ -1830,13 +1830,15 @@ function rcube_calendar_ui(settings)
$.each(event_attendees, function(i, v){ exists |= (v.email == data.email); });
if (exists)
return false;
var calendar = me.selected_event && me.calendars[me.selected_event.calendar] ? me.calendars[me.selected_event.calendar] : me.calendars[me.selected_calendar];
var dispname = Q(data.name || data.email);
if (data.email)
dispname = '<a href="mailto:' + data.email + '" title="' + Q(data.email) + '" class="mailtolink" data-cutype="' + data.cutype + '">' + dispname + '</a>';
else
dispname = '<span>' + dispname + '</span>';
// role selection
var organizer = data.role == 'ORGANIZER';
var opts = {};
@ -1916,12 +1918,16 @@ function rcube_calendar_ui(settings)
// select organizer identity
if (data.identity_id)
$('#edit-identities-list').val(data.identity_id);
// check free-busy status
if (avail == 'loading') {
check_freebusy_status(tr.find('.availability > *:first'), data.email, me.selected_event);
}
// Make Elastic checkboxes pretty
if (window.UI && UI.pretty_checkbox)
$(tr).find('input[type=checkbox]').each(function() { UI.pretty_checkbox(this); });
event_attendees.push(data);
return true;
};
@ -3979,9 +3985,10 @@ function rcube_calendar_ui(settings)
}
rcmail.init_address_input_events($('#edit-attendee-name'), ac_props);
rcmail.addEventListener('autocomplete_insert', function(e) {
var success = false;
var cutype, success = false;
if (e.field.name == 'participant') {
success = add_attendees(e.insert, { role:'REQ-PARTICIPANT', status:'NEEDS-ACTION', cutype:(e.data && e.data.type == 'group' ? 'GROUP' : 'INDIVIDUAL') });
cutype = e.data && e.data.type == 'group' && e.result_type == 'person' ? 'GROUP' : 'INDIVIDUAL';
success = add_attendees(e.insert, { role:'REQ-PARTICIPANT', status:'NEEDS-ACTION', cutype:cutype });
}
else if (e.field.name == 'resource' && e.data && e.data.email) {
success = add_attendee($.extend(e.data, { role:'REQ-PARTICIPANT', status:'NEEDS-ACTION', cutype:'RESOURCE' }));

View file

@ -146,7 +146,7 @@
<div id="event-attachments" class="form-group row">
<div class="event-text"></div>
</div>
<roundcube:object name="plugin.event_rsvp_buttons" id="event-rsvp" class="event-dialog-message" style="display:none" />
<roundcube:object name="plugin.event_rsvp_buttons" id="event-rsvp" class="calendar-invitebox invitebox boxinformation" style="display:none" />
</div>
<roundcube:include file="/templates/eventedit.html" />
@ -283,7 +283,7 @@
<roundcube:if condition="config:kolab_bonnie_api" />
<div id="eventhistory" class="popupmenu" aria-hidden="true">
<roundcube:object name="plugin.object_changelog_table" id="event-changelog-table" class="records-table changelog-table" />
<roundcube:object name="plugin.object_changelog_table" id="event-changelog-table" class="changelog-table" />
<div class="compare-button"><input type="button" class="button" value="↳ <roundcube:label name='libkolab.compare' />" /></div>
</div>

View file

@ -120,7 +120,7 @@
<fieldset id="event-panel-attendees">
<legend><roundcube:label name="calendar.tabattendees" /></legend>
<h3 id="aria-label-attendeestable" class="voice"><roundcube:label name="calendar.arialabeleventattendees" /></h3>
<roundcube:object name="plugin.attendees_list" id="edit-attendees-table" class="records-table edit-attendees-table no-img table-sm"
<roundcube:object name="plugin.attendees_list" id="edit-attendees-table" class="edit-attendees-table no-img table-sm"
coltitle="attendee" aria-labelledby="aria-label-attendeestable" />
<roundcube:object name="plugin.attendees_form" id="edit-attendees-form" />
<roundcube:include file="/templates/freebusylegend.html" />
@ -129,7 +129,7 @@
<fieldset id="event-panel-resources">
<legend><roundcube:label name="calendar.tabresources" /></legend>
<h3 id="aria-label-resourcestable" class="voice"><roundcube:label name="calendar.arialabeleventresources" /></h3>
<roundcube:object name="plugin.attendees_list" id="edit-resources-table" class="records-table edit-attendees-table no-img table-sm"
<roundcube:object name="plugin.attendees_list" id="edit-resources-table" class="edit-attendees-table no-img table-sm"
coltitle="resource" aria-labelledby="aria-label-resourcestable" />
<roundcube:object name="plugin.resources_form" id="edit-resources-form" />
<roundcube:include file="/templates/freebusylegend.html" />

View file

@ -742,52 +742,6 @@ a.miniColors-trigger {
margin: 0 -0.2em;
}
#event-status-badge {
width: 100px;
height: 100px;
position: absolute;
top: 0;
right: 0;
overflow: hidden;
}
#event-status-badge span {
display: none;
text-transform: uppercase;
width: 150px;
height: 20px;
line-height: 20px;
position: absolute;
left: -20px;
top: 35px;
padding-left: 10px;
text-align: center;
font-weight: bold;
font-size: 12px;
color: #fff;
box-shadow: 1px 1px 2px #ccc, -1px -1px 2px #ccc;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.eventdialog.status-cancelled #event-status-badge span {
background: url(images/badge.png) 26px -24px no-repeat #cc0000;
display: block;
}
.eventdialog.sensitivity-private #event-status-badge span {
background: url(images/badge.png) 40px -52px no-repeat #0066ff;
display: block;
}
.eventdialog.sensitivity-confidential #event-status-badge span {
background: url(images/badge.png) 20px 2px no-repeat #cc0000;
display: block;
}
.calendarmain .status-cancelled #event-title,
.calendarmain .sensitivity-private #event-title,
.calendarmain .sensitivity-confidential #event-title {

View file

@ -69,13 +69,12 @@
<roundcube:button command="createnote" type="link"
class="button create disabled" classAct="button create"
label="create" title="kolab_notes.createnote" innerclass="inner" data-fab="true" />
<roundcube:button command="delete" type="link"
class="button delete disabled" classAct="button delete"
title="delete" label="delete" innerClass="inner" />
<span class="spacer"></span>
<roundcube:button command="print" type="link" data-hidden="small"
class="button print disabled" classAct="button print"
label="print" title="print" innerClass="inner" />
<roundcube:button command="delete" type="link"
class="button delete disabled" classAct="button delete"
title="delete" label="delete" innerClass="inner" />
<roundcube:button command="sendnote" type="link"
class="button send disabled" classAct="button send"
label="kolab_notes.send" title="kolab_notes.sendnote" innerClass="inner" />

View file

@ -810,7 +810,7 @@ class libcalendaring_itip
return html::div($attrib,
html::div('label', $this->gettext('acceptinvitation')) .
html::div('rsvp-buttons',
html::div('rsvp-buttons itip-buttons',
$buttons .
html::div('itip-reply-controls', $this->itip_rsvp_options_ui($attrib['id']))
)
@ -830,9 +830,15 @@ class libcalendaring_itip
}
// add checkbox to suppress itip reply message
else if ($itip_sending >= 2) {
$toggle_attrib = array(
'type' => 'checkbox',
'id' => 'noreply-'.$dom_id,
'value' => 1,
'disabled' => $disable,
'checked' => ($itip_sending & 1) == 0,
);
$rsvp_additions = html::label(array('class' => 'noreply-toggle'),
html::tag('input', array('type' => 'checkbox', 'id' => 'noreply-'.$dom_id, 'value' => 1, 'disabled' => $disable, 'checked' => ($itip_sending & 1) == 0))
. ' ' . $this->gettext('itipsuppressreply')
html::tag('input', $toggle_attrib) . ' ' . $this->gettext('itipsuppressreply')
);
}
@ -846,7 +852,7 @@ class libcalendaring_itip
'id' => 'reply-comment-' . $dom_id,
'name' => '_comment',
'cols' => 40,
'rows' => 6,
'rows' => 4,
'class' => 'form-control',
'style' => 'display:none',
'placeholder' => $this->gettext('itipcomment')

View file

Before

Width:  |  Height:  |  Size: 746 B

After

Width:  |  Height:  |  Size: 746 B

View file

@ -172,3 +172,49 @@ label.noreply-toggle + a.reply-comment-toggle {
.ui-widget-content a.button {
color: #52525;
}
#event-status-badge {
width: 100px;
height: 100px;
position: absolute;
top: 0;
right: 0;
overflow: hidden;
}
#event-status-badge span {
display: none;
text-transform: uppercase;
width: 150px;
height: 20px;
line-height: 20px;
position: absolute;
left: -20px;
top: 35px;
padding-left: 10px;
text-align: center;
font-weight: bold;
font-size: 12px;
color: #fff;
box-shadow: 1px 1px 2px #ccc, -1px -1px 2px #ccc;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.status-cancelled #event-status-badge span {
background: url(images/badge.png) 26px -24px no-repeat #cc0000;
display: block;
}
.sensitivity-private #event-status-badge span {
background: url(images/badge.png) 40px -52px no-repeat #0066ff;
display: block;
}
.sensitivity-confidential #event-status-badge span {
background: url(images/badge.png) 20px 2px no-repeat #cc0000;
display: block;
}

View file

@ -757,63 +757,6 @@ fieldset.categories .input-group {
}
#event-status-badge {
width: 7rem;
height: 7rem;
position: absolute;
top: 0;
right: 0;
overflow: hidden;
span {
display: none;
text-transform: uppercase;
line-height: 20px;
position: absolute;
left: -2.4rem;
top: 2.4rem;
width: 13.2rem;
text-align: center;
font-weight: bold;
font-size: .85rem;
color: #fff;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
&:before {
&:extend(.font-icon-class);
display: inline;
float: none;
}
.status-cancelled & {
background-color: darken(@color-error, 10%);
display: block;
&:before {
content: @fa-var-times-circle;
}
}
.sensitivity-private & {
background-color: darken(@color-warning, 10%);
display: block;
&:before {
content: @fa-var-lock;
}
}
.sensitivity-confidential & {
background-color: darken(@color-error, 10%);
display: block;
&:before {
content: @fa-var-user-secret;
}
}
}
}
@color-availability-unknown: #ddd;
@color-availability-free: #abd640;

View file

@ -79,9 +79,15 @@
.itip-reply-controls {
margin-top: .25rem;
width: 100%;
& > label {
display: inline;
}
a {
margin-left: 1em;
white-space: nowrap;
}
}
@ -173,6 +179,7 @@
color: @color-warning;
}
&.completed:after,
&.accepted:after {
content: @fa-var-check-circle;
color: @color-success;
@ -196,9 +203,8 @@
content: @fa-var-briefcase; // TODO: better icon
}
&.completed:after,
&.in-process:after {
// TODO ?
content: @fa-var-cog;
}
}
@ -214,6 +220,8 @@
}
.edit-attendees-table {
width: 100%;
th, td {
width: 1%;
text-align: center;
@ -221,7 +229,7 @@
td {
border: 0;
padding-bottom: 0;
padding: 0 .3rem;
}
th {
@ -234,6 +242,14 @@
}
th.invite {
input {
display: none;
}
label {
cursor: pointer;
}
label:before {
&:extend(.font-icon-class);
content: @fa-var-envelope;
@ -244,9 +260,25 @@
}
td.invite {
label:before {
line-height: 1.6;
height: 1.5em;
}
}
td.name {
span {
line-height: 2.5;
display: flex;
& > :first-child {
.overflow-ellipsis;
// width and flex is required to make overflow working
flex: 1;
width: 1px;
white-space: nowrap;
}
}
}
@ -278,11 +310,16 @@
}
}
a.expandlink {
&:before {
content: @fa-var-plus-square;
line-height: 2;
}
}
.inner {
display: none;
}
// TODO: a.expandlink
}
.form-searchbar {
@ -309,8 +346,10 @@
}
}
.messagelist tbody .attachment span.ical {
// TODO
.attachmentslist li.ics:before,
.attachmentslist li.text.calendar:before,
.messagelist tbody .attachment span.ical:before {
.font-icon-regular(@fa-var-calendar-alt);
}
.alarms-input {
@ -456,3 +495,61 @@
display: initial; // fixes buggy height of the element
}
}
#event-status-badge {
width: 7rem;
height: 7rem;
position: absolute;
top: 0;
right: 0;
overflow: hidden;
span {
display: none;
text-transform: uppercase;
line-height: 20px;
position: absolute;
left: -2.4rem;
top: 2.4rem;
width: 13.2rem;
text-align: center;
font-weight: bold;
font-size: .85rem;
color: #fff;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
&:before {
&:extend(.font-icon-class);
display: inline;
float: none;
}
.status-cancelled & {
background-color: darken(@color-error, 10%);
display: block;
&:before {
content: @fa-var-times-circle;
}
}
.sensitivity-private & {
background-color: darken(@color-warning, 10%);
display: block;
&:before {
content: @fa-var-lock;
}
}
.sensitivity-confidential & {
background-color: darken(@color-error, 10%);
display: block;
&:before {
content: @fa-var-user-secret;
}
}
}
}

View file

@ -279,10 +279,6 @@
.attachmentslist li {
margin-right: 1em;
}
.itip-buttons {
// TODO
}
}
#taskedit-attachment-form {

View file

@ -93,7 +93,7 @@
<roundcube:button command="newtask" type="link"
class="button create disabled" classAct="button create"
label="create" title="tasklist.newtask" innerClass="inner" data-fab="true" />
<roundcube:button command="print" type="link"
<roundcube:button command="print" type="link" data-hidden="small"
class="button print disabled" classAct="button print"
label="print" title="tasklist.printtitle" innerClass="inner" />
<roundcube:button command="delete-task" type="link"
@ -114,6 +114,7 @@
<div class="content scroller watermark" role="main" aria-labelledby="aria-label-taskform">
<roundcube:include file="/templates/taskedit.html" />
<div id="taskshow" class="hidden formcontent propform text-only" data-nodialog="true">
<div id="event-status-badge"><span></span></div>
<div id="task-parent-title" class="task-parent-title"></div>
<h2 id="task-title" class="task-title"></h2>
<div id="task-description" class="task-description"></div>
@ -177,7 +178,7 @@
<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>
</div>
<roundcube:object name="plugin.task_rsvp_buttons" id="task-rsvp" class="itip-buttons" style="display:none" />
<roundcube:object name="plugin.task_rsvp_buttons" id="task-rsvp" class="tasklist-invitebox invitebox boxinformation" style="display:none" />
</div>
<div class="formbuttons">
<roundcube:button command="save-task" label="save"
@ -196,7 +197,7 @@
<roundcube:if condition="env:tasklist_driver == 'kolab' && config:kolab_bonnie_api" />
<div id="taskhistory" class="popupmenu" aria-hidden="true">
<roundcube:object name="plugin.object_changelog_table" class="records-table changelog-table" />
<roundcube:object name="plugin.object_changelog_table" class="changelog-table" />
<div class="compare-button"><input type="button" class="button" value="↳ <roundcube:label name='libkolab.compare' />" /></div>
</div>

View file

@ -102,7 +102,7 @@
<roundcube:object name="plugin.identity_select" id="edit-identities-list" class="col-sm-10 form-control" />
</div>
<h3 id="aria-label-attendeestable" class="voice"><roundcube:label name="tasklist.arialabeleventassignments" /></h3>
<roundcube:object name="plugin.attendees_list" id="edit-attendees-table" class="records-table edit-attendees-table no-img table-sm" coltitle="attendee" aria-labelledby="aria-label-attendeestable" />
<roundcube:object name="plugin.attendees_list" id="edit-attendees-table" class="edit-attendees-table no-img table-sm" coltitle="attendee" aria-labelledby="aria-label-attendeestable" />
<roundcube:object name="plugin.attendees_form" id="edit-attendees-form" />
</fieldset>
<!-- attachments list (with upload form) -->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 924 B

View file

@ -811,10 +811,6 @@ body.taskdialog #taskedit {
color: #999;
}
.taskshow.status-cancelled {
background: url(images/badge_cancelled.png) top right no-repeat;
}
.task-parent-title {
position: relative;
top: -0.6em;

View file

@ -159,6 +159,7 @@
<div id="taskshow" class="taskshow">
<div id="task-parent-title" class="form-section task-parent-title"></div>
<div id="event-status-badge"><span></span></div>
<div class="form-section">
<h2 id="task-title"></h2>
</div>

View file

@ -728,7 +728,7 @@ function rcube_tasklist_ui(settings)
rcmail.addEventListener('autocomplete_insert', function(e) {
var cutype, success = false;
if (e.field.name == 'participant') {
cutype = e.data && e.data.type == 'group' ? 'GROUP' : 'INDIVIDUAL';
cutype = e.data && e.data.type == 'group' && e.result_type == 'person' ? 'GROUP' : 'INDIVIDUAL';
success = add_attendees(e.insert, { role:'REQ-PARTICIPANT', status:'NEEDS-ACTION', cutype: cutype });
}
if (e.field && success) {
@ -1848,6 +1848,8 @@ function rcube_tasklist_ui(settings)
var dispname = Q(data.name || data.email);
if (data.email)
dispname = '<a href="mailto:' + data.email + '" title="' + Q(data.email) + '" class="mailtolink" data-cutype="' + data.cutype + '">' + dispname + '</a>';
else
dispname = '<span>' + dispname + '</span>';
// delete icon
var icon = rcmail.env.deleteicon ? '<img src="' + rcmail.env.deleteicon + '" alt="" />' : '<span class="inner">' + Q(rcmail.gettext('delete')) + '</span>';
@ -1868,8 +1870,9 @@ function rcube_tasklist_ui(settings)
// add expand button for groups
if (data.cutype == 'GROUP') {
dispname += ' <a href="#expand" data-email="' + Q(data.email) + '" class="iconbutton add expandlink" title="' + rcmail.gettext('expandattendeegroup','libcalendaring') + '">' +
rcmail.gettext('expandattendeegroup','libcalendaring') + '</a>';
dispname += ' <a href="#expand" data-email="' + Q(data.email)
+ '" class="iconbutton add icon button expandlink" title="' + rcmail.gettext('expandattendeegroup','libcalendaring') + '">'
+ '<span class="inner">' + rcmail.gettext('expandattendeegroup','libcalendaring') + '</span></a>';
}
var elastic = $(attendees_list).parents('.no-img').length > 0;
@ -1895,6 +1898,10 @@ function rcube_tasklist_ui(settings)
$('#taskeditform .attendees-commentbox')[enabled ? 'show' : 'hide']();
});
// Make Elastic checkboxes pretty
if (window.UI && UI.pretty_checkbox)
$(tr).find('input[type=checkbox]').each(function() { UI.pretty_checkbox(this); });
task_attendees.push(data);
return true;
};
@ -1943,6 +1950,8 @@ function rcube_tasklist_ui(settings)
me.selected_task = rec;
list = rec.list && me.tasklists[rec.list] ? me.tasklists[rec.list] : {};
var status = rcmail.gettext('status-' + String(rec.status).toLowerCase(),'tasklist');
// fill dialog data
$('#task-parent-title').html(Q(rec.parent_title || '')+' &raquo;').css('display', rec.parent_title ? 'block' : 'none');
$('#task-title').html(text2html(Q(rec.title || '')));
@ -1953,10 +1962,12 @@ function rcube_tasklist_ui(settings)
$('#task-starttime').text(rec.starttime || '');
$('#task-alarm')[(rec.alarms_text ? 'show' : 'hide')]().children('.task-text').html(Q(rec.alarms_text));
$('#task-completeness .task-text').html(((rec.complete || 0) * 100) + '%');
$('#task-status')[(rec.status ? 'show' : 'hide')]().children('.task-text').html(rcmail.gettext('status-'+String(rec.status).toLowerCase(),'tasklist'));
$('#task-status')[(rec.status ? 'show' : 'hide')]().children('.task-text').text(status);
$('#task-list .task-text').html(Q(me.tasklists[rec.list] ? me.tasklists[rec.list].name : ''));
$('#task-attendees, #task-organizer, #task-created-changed, #task-created, #task-changed, #task-rsvp, #task-rsvp-comment').hide();
$('#event-status-badge > span').text(status);
// tags
var taglist = $('#task-tags').hide().children('.task-text').empty();
if (window.kolab_tags_text_block) {