From 585839698573fce314adda4fb05cfa33ee307f84 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 22 Apr 2021 18:33:17 +0200 Subject: [PATCH] Calendar improvements --- .../src/less2/include/colortheme-dark.less | 3 + .../src/less2/include/colortheme.less | 2 + .../src/less2/include/notifications.less | 2 +- www/calendar/app-calendar.less | 63 ++++++++++++- www/calendar/inner.js | 90 ++++++++++++++----- www/common/outer/calendar.js | 28 +++++- 6 files changed, 161 insertions(+), 27 deletions(-) diff --git a/customize.dist/src/less2/include/colortheme-dark.less b/customize.dist/src/less2/include/colortheme-dark.less index 869ff862b..588d1888e 100644 --- a/customize.dist/src/less2/include/colortheme-dark.less +++ b/customize.dist/src/less2/include/colortheme-dark.less @@ -423,3 +423,6 @@ // Calendar @cp_calendar-border: @cryptpad_color_grey_600; +@cp_calendar-now: @cryptpad_color_brand_300; +@cp_calendar-now-fg: @cryptpad_color_grey_800; + diff --git a/customize.dist/src/less2/include/colortheme.less b/customize.dist/src/less2/include/colortheme.less index 6af7fe46a..3ab249f9f 100644 --- a/customize.dist/src/less2/include/colortheme.less +++ b/customize.dist/src/less2/include/colortheme.less @@ -423,3 +423,5 @@ // Calendar @cp_calendar-border: @cryptpad_color_grey_300; +@cp_calendar-now: @cryptpad_color_brand; +@cp_calendar-now-fg: @cryptpad_color_grey_200; diff --git a/customize.dist/src/less2/include/notifications.less b/customize.dist/src/less2/include/notifications.less index 892779a37..f3bc8c0b4 100644 --- a/customize.dist/src/less2/include/notifications.less +++ b/customize.dist/src/less2/include/notifications.less @@ -23,7 +23,7 @@ align-items: center; padding: 0 5px; color: @cp_dropdown-fg; - &.preview { + &.preview:not(.fa-calendar) { color: @cryptpad_color_red; } } diff --git a/www/calendar/app-calendar.less b/www/calendar/app-calendar.less index 407ec8004..fb358e038 100644 --- a/www/calendar/app-calendar.less +++ b/www/calendar/app-calendar.less @@ -41,7 +41,25 @@ } } } + .tui-full-calendar-weekday-filled { + background-color: @cp_dropdown-bg-hover !important; + } + + .tui-full-calendar-timegrid-hourmarker-time { + color: @cp_calendar-now !important; + } + .tui-full-calendar-timegrid-hourmarker-line-left, .tui-full-calendar-timegrid-hourmarker-line-today { + border-color: @cp_calendar-now !important; + } + .tui-full-calendar-timegrid-todaymarker { + background-color: @cp_calendar-now !important; + } + .tui-full-calendar-month { + .tui-full-calendar-today .tui-full-calendar-weekday-grid-date-decorator { + background-color: @cp_calendar-now !important; + color: @cp_calendar-now-fg !important; + } .tui-full-calendar-weekday-schedule-time .tui-full-calendar-weekday-schedule-title { color: @cryptpad_text_col !important; // XXX } @@ -193,12 +211,24 @@ & > div { display: flex; } + .cp-calendar-notif-list-container { + margin-bottom: 10px; + } .cp-calendar-notif-list { display: flex; flex-flow: column; .cp-notif-entry { + margin-bottom: 2px; + .cp-notif-value { + width: 170px; + display: inline-flex; + .cp-before { + flex: 1; + min-width: 0; + } + } span:not(:last-child) { - margin-right: 20px; + margin-right: 5px; } } } @@ -210,6 +240,7 @@ } .cp-calendar-notif-form { align-items: center; + margin-bottom: 20px; input { width: 100px; } @@ -241,6 +272,7 @@ justify-content: space-between; } .cp-calendar-list { + overflow-y: auto; .cp-calendar-team { height: 30px; .avatar_main(30px); @@ -256,13 +288,21 @@ align-items: center; justify-content: center; margin: 5px 0; + &:not(:first-child) { + margin-top: 30px; + } } .cp-calendar-entry { display: flex; align-items: center; justify-content: space-between; padding: 5px; - cursor: pointer; + &:not(.cp-unclickable) { + cursor: pointer; + } + .cp-dropdown-container { + position: initial; + } &.cp-ghost { padding: 0; button { @@ -291,8 +331,27 @@ &.cp-restricted { color: @cp_drive-header-fg; } + .cp-calendar-icon { + width: 36px; + display: inline-flex; + height: 36px; + margin: -5px; + align-items: center; + justify-content: center; + } &.cp-active { background: @cp_sidebar-left-active; + .cp-calendar-inactive { + display: none; + } + } + &:not(.cp-active) { + .cp-calendar-icon { + background: transparent !important; + } + .cp-calendar-active { + display: none; + } } .tools_unselectable(); .cp-calendar-color { diff --git a/www/calendar/inner.js b/www/calendar/inner.js index 55ec3666e..152acde99 100644 --- a/www/calendar/inner.js +++ b/www/calendar/inner.js @@ -71,8 +71,9 @@ Messages.calendar_deleteTeamConfirm = "Are you sure you want to delete this cale Messages.calendar_deleteOwned = " It will still be visible for the users it has been shared with."; Messages.calendar_errorNoCalendar = "No editable calendar selected!"; Messages.calendar_myCalendars = "My calendars"; -Messages.calendar_tempCalendar = "Temp calendar"; +Messages.calendar_tempCalendar = "Viewing"; Messages.calendar_import = "Import to my calendars"; +Messages.calendar_import_temp = "Import this calendar"; Messages.calendar_newEvent = "New event"; Messages.calendar_new = "New calendar"; Messages.calendar_dateRange = "{0} - {1}"; @@ -86,6 +87,7 @@ Messages.calendar_allDay = "All day"; Messages.calendar_minutes = "Minutes"; Messages.calendar_hours = "Hours"; Messages.calendar_days = "Days"; +Messages.calendar_before = "before"; Messages.calendar_notifications = "Reminders"; Messages.calendar_addNotification = "Add reminder"; @@ -148,7 +150,7 @@ Messages.calendar_noNotification = "None"; var brightness = Math.round(((parseInt(rgb[0]) * 299) + (parseInt(rgb[1]) * 587) + (parseInt(rgb[2]) * 114)) / 1000); - return (brightness > 125) ? 'black' : 'white'; + return (brightness > 125) ? '#424242' : '#EEEEEE'; }; var getWeekDays = function () { @@ -181,7 +183,17 @@ Messages.calendar_noNotification = "None"; }; var getSchedules = function () { var s = []; - Object.keys(APP.calendars).forEach(function (id) { + var calendars = Object.keys(APP.calendars); + if (APP.currentCalendar) { + var currentCal = calendars.filter(function (id) { + var c = APP.calendars[id]; + var t = c.teams || []; + if (id !== APP.currentCalendar) { return; } + return t.length === 1 && t[0] === 0; + }); + if (currentCal.length) { calendars = currentCal; } + } + calendars.forEach(function (id) { var c = APP.calendars[id]; if (c.hidden || c.restricted || c.loading) { return; } var data = c.content || {}; @@ -633,18 +645,25 @@ Messages.calendar_noNotification = "None"; if (!md) { return; } var active = data.hidden ? '' : '.cp-active'; var restricted = data.restricted ? '.cp-restricted' : ''; - var calendar = h('div.cp-calendar-entry'+active+restricted, { + var temp = teamId === 0 ? '.cp-unclickable' : ''; + var calendar = h('div.cp-calendar-entry'+active+restricted+temp, { 'data-uid': id }, [ - h('span.cp-calendar-color', { + h('span.cp-calendar-icon', { style: 'background-color: '+md.color+';' - }), + }, [ + h('i.cp-calendar-active.fa.fa-calendar', { + style: 'color: '+getContrast(md.color)+';' + }), + h('i.cp-calendar-inactive.fa.fa-calendar-o') + ]), h('span.cp-calendar-title', md.title), data.restricted ? h('i.fa.fa-ban', {title: Messages.fm_restricted}) : (isReadOnly(id, teamId) ? h('i.fa.fa-eye', {title: Messages.readonly}) : undefined), edit ]); $(calendar).click(function () { + if (teamId === 0) { return; } data.hidden = !data.hidden; if (APP.$calendars) { APP.$calendars.find('[data-uid="'+id+'"]').toggleClass('cp-active', !data.hidden); @@ -672,11 +691,29 @@ Messages.calendar_noNotification = "None"; }); }; var tempCalendars = filter(0); - if (tempCalendars.length) { + if (tempCalendars.length && tempCalendars[0] === APP.currentCalendar) { APP.$calendars.append(h('div.cp-calendar-team', [ h('span', Messages.calendar_tempCalendar) ])); makeCalendarEntry(tempCalendars[0], 0); + var importTemp = h('button', [ + h('i.fa.fa-calendar-plus-o'), + h('span', Messages.calendar_import_temp), + h('span') + ]); + $(importTemp).click(function () { + importCalendar({ + id: tempCalendars[0], + teamId: 0 + }, function (obj) { + if (obj && obj.error) { + console.error(obj.error); + return void UI.warn(obj.error); + } + }); + }); + APP.$calendars.append(h('div.cp-calendar-entry.cp-ghost', importTemp)); + return; } var myCalendars = filter(1); if (myCalendars.length) { @@ -687,6 +724,18 @@ Messages.calendar_noNotification = "None"; myCalendars.forEach(function (id) { makeCalendarEntry(id, 1); }); + + // Add new button + var $newContainer = $(h('div.cp-calendar-entry.cp-ghost')).appendTo($calendars); + var newButton = h('button', [ + h('i.fa.fa-calendar-plus-o'), + h('span', Messages.calendar_new), + h('span') + ]); + $(newButton).click(function () { + editCalendar(); + }).appendTo($newContainer); + Object.keys(privateData.teams).forEach(function (teamId) { var calendars = filter(teamId); if (!calendars.length) { return; } @@ -701,17 +750,6 @@ Messages.calendar_noNotification = "None"; makeCalendarEntry(id, teamId); }); }); - - // Add new button - var $newContainer = $(h('div.cp-calendar-entry.cp-ghost')).appendTo($calendars); - var newButton = h('button', [ - h('i.fa.fa-plus'), - h('span', Messages.calendar_new), - h('span') - ]); - $(newButton).click(function () { - editCalendar(); - }).appendTo($newContainer); }); onCalendarsUpdate.fire(); @@ -978,7 +1016,7 @@ Messages.calendar_noNotification = "None"; $number.attr('max', max); if ($number.val() > max) { $number.val(max); } }); - var addNotif = h('button.btn.btn-primary.fa.fa-plus'); + var addNotif = h('button.btn.btn-primary-outline.fa.fa-plus'); var $list = $(h('div.cp-calendar-notif-list')); var listContainer = h('div.cp-calendar-notif-list-container', [ h('span.cp-notif-label', Messages.calendar_notifications), @@ -987,14 +1025,17 @@ Messages.calendar_noNotification = "None"; ]); var addNotification = function (unit, value) { var unitValue = (unit === "minutes") ? 1 : (unit === "hours" ? 60 : (60*24)); - var del = h('button.btn.btn-danger.small.fa.fa-times'); + var del = h('button.btn.btn-danger-outline.small.fa.fa-times'); var minutes = value * unitValue; if ($list.find('[data-minutes="'+minutes+'"]').length) { return; } var span = h('span.cp-notif-entry', { 'data-minutes': minutes }, [ - h('span', value), - h('span', Messages['calendar_'+unit]), + h('span.cp-notif-value', [ + h('span', value), + h('span', Messages['calendar_'+unit]), + h('span.cp-before', Messages.calendar_before) + ]), del ]); $(del).click(function () { @@ -1211,8 +1252,11 @@ Messages.calendar_noNotification = "None"; return; } if (privateData.calendarHash) { + var hash = privateData.hashes.editHash || privateData.hashes.viewHash; + var secret = Hash.getSecrets('calendar', hash, privateData.password); + APP.currentCalendar = secret.channel; APP.module.execCommand('OPEN', { - hash: privateData.hashes.editHash || privateData.hashes.viewHash, + hash: hash, password: privateData.password }, function (obj) { if (obj && obj.error) { console.error(obj.error); } diff --git a/www/common/outer/calendar.js b/www/common/outer/calendar.js index 5f39004c1..1bb5fd570 100644 --- a/www/common/outer/calendar.js +++ b/www/common/outer/calendar.js @@ -211,6 +211,10 @@ define([ c.lm.setReadOnly(false, upgradeCrypto); c.readOnly = false; } else if (teamId === 0) { + // If we open a second tab with the same temp URL, push to tempId + if (c.stores.length === 1 && c.stores[0] === 0 && c.tempId.length && cfg.cId) { + c.tempId.push(cfg.cId); + } // Existing calendars can't be "temp calendars" (unless they are an upgrade) return void cb(); } @@ -229,7 +233,10 @@ define([ if (c.stores && c.stores.indexOf(teamId) !== -1) { return void cb(); } // If we store a temp calendar to our account or team, remove this "temp calendar" - if (c.stores.indexOf(0) !== -1) { c.stores.splice(c.stores.indexOf(0), 1); } + if (c.stores.indexOf(0) !== -1) { + c.stores.splice(c.stores.indexOf(0), 1); + c.tempId = []; + } c.stores.push(teamId); if (!data.href) { @@ -245,12 +252,17 @@ define([ ready: false, channel: channel, readOnly: !data.href, + tempId: [], stores: [teamId], roStores: data.href ? [] : [teamId], reminders: {}, hashes: {} }; + if (teamId === 0) { + c.tempId.push(cfg.cId); + } + var parsed = Hash.parsePadUrl(data.href || data.roHref); var secret = Hash.getSecrets('calendar', parsed.hash, data.password); @@ -539,6 +551,7 @@ define([ title: '...' }; openChannel(ctx, { + cId: cId, storeId: 0, data: cal }, cb); @@ -815,6 +828,19 @@ define([ var removeClient = function (ctx, cId) { var idx = ctx.clients.indexOf(cId); ctx.clients.splice(idx, 1); + + Object.keys(ctx.calendars).forEach(function (id) { + var cal = ctx.calendars[id]; + if (cal.stores.length !== 1 || cal.stores[0] !== 0 || !cal.tempId.length) { return; } + // This is a temp calendar: check if the closed tab had this calendar opened + var idx = cal.tempId.indexOf(cId); + if (idx !== -1) { cal.tempId.splice(idx, 1); } + if (!cal.tempId.length) { + cal.stores = []; + // Close calendar + closeCalendar(ctx, id); + } + }); }; Calendar.init = function (cfg, waitFor, emit) {