mirror of
https://gitlab.com/signalytic/client-external/streamline/streamline-emr.git
synced 2026-09-13 19:51:30 +00:00
Build modified streamline images
The official image from streamline does not currently work for the arm64 platform. As a temporary measure, the source code and docker build scripts have been lifted from the official images and are used to build locally. Some additional modifications are made to reduce overall image size, these are documented in docker/README.md
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2019 Adam Shaw
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
# FullCalendar List View Plugin
|
||||
|
||||
View your events as a bulleted list
|
||||
|
||||
[View the docs »](https://fullcalendar.io/docs/list-view)
|
||||
|
||||
This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar)
|
||||
@@ -0,0 +1,118 @@
|
||||
/* List View
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
/* possibly reusable */
|
||||
.fc-event-dot {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* view wrapper */
|
||||
.fc-rtl .fc-list-view {
|
||||
direction: rtl;
|
||||
/* unlike core views, leverage browser RTL */
|
||||
}
|
||||
|
||||
.fc-list-view {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
/* table resets */
|
||||
.fc .fc-list-table {
|
||||
table-layout: auto;
|
||||
/* for shrinkwrapping cell content */
|
||||
}
|
||||
|
||||
.fc-list-table td {
|
||||
border-width: 1px 0 0;
|
||||
padding: 8px 14px;
|
||||
}
|
||||
|
||||
.fc-list-table tr:first-child td {
|
||||
border-top-width: 0;
|
||||
}
|
||||
|
||||
/* day headings with the list */
|
||||
.fc-list-heading {
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.fc-list-heading td {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.fc-ltr .fc-list-heading-main {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.fc-ltr .fc-list-heading-alt {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.fc-rtl .fc-list-heading-main {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.fc-rtl .fc-list-heading-alt {
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* event list items */
|
||||
.fc-list-item.fc-has-url {
|
||||
cursor: pointer;
|
||||
/* whole row will be clickable */
|
||||
}
|
||||
|
||||
.fc-list-item-marker,
|
||||
.fc-list-item-time {
|
||||
white-space: nowrap;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
/* make the dot closer to the event title */
|
||||
.fc-ltr .fc-list-item-marker {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.fc-rtl .fc-list-item-marker {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.fc-list-item-title a {
|
||||
/* every event title cell has an <a> tag */
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.fc-list-item-title a[href]:hover {
|
||||
/* hover effect only on titles with hrefs */
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* message when no events */
|
||||
.fc-list-empty-wrap2 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.fc-list-empty-wrap1 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: table;
|
||||
}
|
||||
|
||||
.fc-list-empty {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fc-unthemed .fc-list-empty {
|
||||
/* theme will provide own background */
|
||||
background-color: #eee;
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// Generated by dts-bundle v0.7.3-fork.1
|
||||
// Dependencies for this module:
|
||||
// ../../../../../@fullcalendar/core
|
||||
|
||||
declare module '@fullcalendar/list' {
|
||||
import ListView from '@fullcalendar/list/ListView';
|
||||
export { ListView };
|
||||
const _default: import("@fullcalendar/core").PluginDef;
|
||||
export default _default;
|
||||
}
|
||||
|
||||
declare module '@fullcalendar/list/ListView' {
|
||||
import { View, ViewProps, ScrollComponent, DateMarker, DateRange, DateProfileGenerator, ComponentContext, ViewSpec, EventUiHash, EventRenderRange, EventStore, Seg } from '@fullcalendar/core';
|
||||
export { ListView as default, ListView };
|
||||
class ListView extends View {
|
||||
scroller: ScrollComponent;
|
||||
contentEl: HTMLElement;
|
||||
dayDates: DateMarker[];
|
||||
constructor(context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement);
|
||||
render(props: ViewProps): void;
|
||||
destroy(): void;
|
||||
updateSize(isResize: any, viewHeight: any, isAuto: any): void;
|
||||
computeScrollerHeight(viewHeight: any): number;
|
||||
_eventStoreToSegs(eventStore: EventStore, eventUiBases: EventUiHash, dayRanges: DateRange[]): Seg[];
|
||||
eventRangesToSegs(eventRanges: EventRenderRange[], dayRanges: DateRange[]): any[];
|
||||
eventRangeToSegs(eventRange: EventRenderRange, dayRanges: DateRange[]): any[];
|
||||
renderEmptyMessage(): void;
|
||||
renderSegList(allSegs: any): void;
|
||||
groupSegsByDay(segs: any): any[];
|
||||
buildDayHeaderRow(dayDate: any): HTMLTableRowElement;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
/*!
|
||||
FullCalendar List View Plugin v4.3.0
|
||||
Docs & License: https://fullcalendar.io/
|
||||
(c) 2019 Adam Shaw
|
||||
*/
|
||||
|
||||
import { getAllDayHtml, isMultiDayRange, htmlEscape, FgEventRenderer, memoize, memoizeRendering, ScrollComponent, subtractInnerElHeight, sliceEventStore, intersectRanges, htmlToElement, createFormatter, createElement, buildGotoAnchorHtml, View, startOfDay, addDays, createPlugin } from '@fullcalendar/core';
|
||||
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
/* global Reflect, Promise */
|
||||
|
||||
var extendStatics = function(d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
|
||||
function __extends(d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
}
|
||||
|
||||
var ListEventRenderer = /** @class */ (function (_super) {
|
||||
__extends(ListEventRenderer, _super);
|
||||
function ListEventRenderer(listView) {
|
||||
var _this = _super.call(this, listView.context) || this;
|
||||
_this.listView = listView;
|
||||
return _this;
|
||||
}
|
||||
ListEventRenderer.prototype.attachSegs = function (segs) {
|
||||
if (!segs.length) {
|
||||
this.listView.renderEmptyMessage();
|
||||
}
|
||||
else {
|
||||
this.listView.renderSegList(segs);
|
||||
}
|
||||
};
|
||||
ListEventRenderer.prototype.detachSegs = function () {
|
||||
};
|
||||
// generates the HTML for a single event row
|
||||
ListEventRenderer.prototype.renderSegHtml = function (seg) {
|
||||
var _a = this.context, view = _a.view, theme = _a.theme;
|
||||
var eventRange = seg.eventRange;
|
||||
var eventDef = eventRange.def;
|
||||
var eventInstance = eventRange.instance;
|
||||
var eventUi = eventRange.ui;
|
||||
var url = eventDef.url;
|
||||
var classes = ['fc-list-item'].concat(eventUi.classNames);
|
||||
var bgColor = eventUi.backgroundColor;
|
||||
var timeHtml;
|
||||
if (eventDef.allDay) {
|
||||
timeHtml = getAllDayHtml(view);
|
||||
}
|
||||
else if (isMultiDayRange(eventRange.range)) {
|
||||
if (seg.isStart) {
|
||||
timeHtml = htmlEscape(this._getTimeText(eventInstance.range.start, seg.end, false // allDay
|
||||
));
|
||||
}
|
||||
else if (seg.isEnd) {
|
||||
timeHtml = htmlEscape(this._getTimeText(seg.start, eventInstance.range.end, false // allDay
|
||||
));
|
||||
}
|
||||
else { // inner segment that lasts the whole day
|
||||
timeHtml = getAllDayHtml(view);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Display the normal time text for the *event's* times
|
||||
timeHtml = htmlEscape(this.getTimeText(eventRange));
|
||||
}
|
||||
if (url) {
|
||||
classes.push('fc-has-url');
|
||||
}
|
||||
return '<tr class="' + classes.join(' ') + '">' +
|
||||
(this.displayEventTime ?
|
||||
'<td class="fc-list-item-time ' + theme.getClass('widgetContent') + '">' +
|
||||
(timeHtml || '') +
|
||||
'</td>' :
|
||||
'') +
|
||||
'<td class="fc-list-item-marker ' + theme.getClass('widgetContent') + '">' +
|
||||
'<span class="fc-event-dot"' +
|
||||
(bgColor ?
|
||||
' style="background-color:' + bgColor + '"' :
|
||||
'') +
|
||||
'></span>' +
|
||||
'</td>' +
|
||||
'<td class="fc-list-item-title ' + theme.getClass('widgetContent') + '">' +
|
||||
'<a' + (url ? ' href="' + htmlEscape(url) + '"' : '') + '>' +
|
||||
htmlEscape(eventDef.title || '') +
|
||||
'</a>' +
|
||||
'</td>' +
|
||||
'</tr>';
|
||||
};
|
||||
// like "4:00am"
|
||||
ListEventRenderer.prototype.computeEventTimeFormat = function () {
|
||||
return {
|
||||
hour: 'numeric',
|
||||
minute: '2-digit',
|
||||
meridiem: 'short'
|
||||
};
|
||||
};
|
||||
return ListEventRenderer;
|
||||
}(FgEventRenderer));
|
||||
|
||||
/*
|
||||
Responsible for the scroller, and forwarding event-related actions into the "grid".
|
||||
*/
|
||||
var ListView = /** @class */ (function (_super) {
|
||||
__extends(ListView, _super);
|
||||
function ListView(context, viewSpec, dateProfileGenerator, parentEl) {
|
||||
var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
|
||||
_this.computeDateVars = memoize(computeDateVars);
|
||||
_this.eventStoreToSegs = memoize(_this._eventStoreToSegs);
|
||||
var eventRenderer = _this.eventRenderer = new ListEventRenderer(_this);
|
||||
_this.renderContent = memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer));
|
||||
_this.el.classList.add('fc-list-view');
|
||||
var listViewClassNames = (_this.theme.getClass('listView') || '').split(' '); // wish we didn't have to do this
|
||||
for (var _i = 0, listViewClassNames_1 = listViewClassNames; _i < listViewClassNames_1.length; _i++) {
|
||||
var listViewClassName = listViewClassNames_1[_i];
|
||||
if (listViewClassName) { // in case input was empty string
|
||||
_this.el.classList.add(listViewClassName);
|
||||
}
|
||||
}
|
||||
_this.scroller = new ScrollComponent('hidden', // overflow x
|
||||
'auto' // overflow y
|
||||
);
|
||||
_this.el.appendChild(_this.scroller.el);
|
||||
_this.contentEl = _this.scroller.el; // shortcut
|
||||
context.calendar.registerInteractiveComponent(_this, {
|
||||
el: _this.el
|
||||
// TODO: make aware that it doesn't do Hits
|
||||
});
|
||||
return _this;
|
||||
}
|
||||
ListView.prototype.render = function (props) {
|
||||
var _a = this.computeDateVars(props.dateProfile), dayDates = _a.dayDates, dayRanges = _a.dayRanges;
|
||||
this.dayDates = dayDates;
|
||||
this.renderContent(this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges));
|
||||
};
|
||||
ListView.prototype.destroy = function () {
|
||||
_super.prototype.destroy.call(this);
|
||||
this.renderContent.unrender();
|
||||
this.scroller.destroy(); // will remove the Grid too
|
||||
this.calendar.unregisterInteractiveComponent(this);
|
||||
};
|
||||
ListView.prototype.updateSize = function (isResize, viewHeight, isAuto) {
|
||||
_super.prototype.updateSize.call(this, isResize, viewHeight, isAuto);
|
||||
this.eventRenderer.computeSizes(isResize);
|
||||
this.eventRenderer.assignSizes(isResize);
|
||||
this.scroller.clear(); // sets height to 'auto' and clears overflow
|
||||
if (!isAuto) {
|
||||
this.scroller.setHeight(this.computeScrollerHeight(viewHeight));
|
||||
}
|
||||
};
|
||||
ListView.prototype.computeScrollerHeight = function (viewHeight) {
|
||||
return viewHeight -
|
||||
subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
|
||||
};
|
||||
ListView.prototype._eventStoreToSegs = function (eventStore, eventUiBases, dayRanges) {
|
||||
return this.eventRangesToSegs(sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.nextDayThreshold).fg, dayRanges);
|
||||
};
|
||||
ListView.prototype.eventRangesToSegs = function (eventRanges, dayRanges) {
|
||||
var segs = [];
|
||||
for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) {
|
||||
var eventRange = eventRanges_1[_i];
|
||||
segs.push.apply(segs, this.eventRangeToSegs(eventRange, dayRanges));
|
||||
}
|
||||
return segs;
|
||||
};
|
||||
ListView.prototype.eventRangeToSegs = function (eventRange, dayRanges) {
|
||||
var _a = this, dateEnv = _a.dateEnv, nextDayThreshold = _a.nextDayThreshold;
|
||||
var range = eventRange.range;
|
||||
var allDay = eventRange.def.allDay;
|
||||
var dayIndex;
|
||||
var segRange;
|
||||
var seg;
|
||||
var segs = [];
|
||||
for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex++) {
|
||||
segRange = intersectRanges(range, dayRanges[dayIndex]);
|
||||
if (segRange) {
|
||||
seg = {
|
||||
component: this,
|
||||
eventRange: eventRange,
|
||||
start: segRange.start,
|
||||
end: segRange.end,
|
||||
isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(),
|
||||
isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(),
|
||||
dayIndex: dayIndex
|
||||
};
|
||||
segs.push(seg);
|
||||
// detect when range won't go fully into the next day,
|
||||
// and mutate the latest seg to the be the end.
|
||||
if (!seg.isEnd && !allDay &&
|
||||
dayIndex + 1 < dayRanges.length &&
|
||||
range.end <
|
||||
dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) {
|
||||
seg.end = range.end;
|
||||
seg.isEnd = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return segs;
|
||||
};
|
||||
ListView.prototype.renderEmptyMessage = function () {
|
||||
this.contentEl.innerHTML =
|
||||
'<div class="fc-list-empty-wrap2">' + // TODO: try less wraps
|
||||
'<div class="fc-list-empty-wrap1">' +
|
||||
'<div class="fc-list-empty">' +
|
||||
htmlEscape(this.opt('noEventsMessage')) +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
};
|
||||
// called by ListEventRenderer
|
||||
ListView.prototype.renderSegList = function (allSegs) {
|
||||
var segsByDay = this.groupSegsByDay(allSegs); // sparse array
|
||||
var dayIndex;
|
||||
var daySegs;
|
||||
var i;
|
||||
var tableEl = htmlToElement('<table class="fc-list-table ' + this.calendar.theme.getClass('tableList') + '"><tbody></tbody></table>');
|
||||
var tbodyEl = tableEl.querySelector('tbody');
|
||||
for (dayIndex = 0; dayIndex < segsByDay.length; dayIndex++) {
|
||||
daySegs = segsByDay[dayIndex];
|
||||
if (daySegs) { // sparse array, so might be undefined
|
||||
// append a day header
|
||||
tbodyEl.appendChild(this.buildDayHeaderRow(this.dayDates[dayIndex]));
|
||||
daySegs = this.eventRenderer.sortEventSegs(daySegs);
|
||||
for (i = 0; i < daySegs.length; i++) {
|
||||
tbodyEl.appendChild(daySegs[i].el); // append event row
|
||||
}
|
||||
}
|
||||
}
|
||||
this.contentEl.innerHTML = '';
|
||||
this.contentEl.appendChild(tableEl);
|
||||
};
|
||||
// Returns a sparse array of arrays, segs grouped by their dayIndex
|
||||
ListView.prototype.groupSegsByDay = function (segs) {
|
||||
var segsByDay = []; // sparse array
|
||||
var i;
|
||||
var seg;
|
||||
for (i = 0; i < segs.length; i++) {
|
||||
seg = segs[i];
|
||||
(segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))
|
||||
.push(seg);
|
||||
}
|
||||
return segsByDay;
|
||||
};
|
||||
// generates the HTML for the day headers that live amongst the event rows
|
||||
ListView.prototype.buildDayHeaderRow = function (dayDate) {
|
||||
var dateEnv = this.dateEnv;
|
||||
var mainFormat = createFormatter(this.opt('listDayFormat')); // TODO: cache
|
||||
var altFormat = createFormatter(this.opt('listDayAltFormat')); // TODO: cache
|
||||
return createElement('tr', {
|
||||
className: 'fc-list-heading',
|
||||
'data-date': dateEnv.formatIso(dayDate, { omitTime: true })
|
||||
}, '<td class="' + (this.calendar.theme.getClass('tableListHeading') ||
|
||||
this.calendar.theme.getClass('widgetHeader')) + '" colspan="3">' +
|
||||
(mainFormat ?
|
||||
buildGotoAnchorHtml(this, dayDate, { 'class': 'fc-list-heading-main' }, htmlEscape(dateEnv.format(dayDate, mainFormat)) // inner HTML
|
||||
) :
|
||||
'') +
|
||||
(altFormat ?
|
||||
buildGotoAnchorHtml(this, dayDate, { 'class': 'fc-list-heading-alt' }, htmlEscape(dateEnv.format(dayDate, altFormat)) // inner HTML
|
||||
) :
|
||||
'') +
|
||||
'</td>');
|
||||
};
|
||||
return ListView;
|
||||
}(View));
|
||||
ListView.prototype.fgSegSelector = '.fc-list-item'; // which elements accept event actions
|
||||
function computeDateVars(dateProfile) {
|
||||
var dayStart = startOfDay(dateProfile.renderRange.start);
|
||||
var viewEnd = dateProfile.renderRange.end;
|
||||
var dayDates = [];
|
||||
var dayRanges = [];
|
||||
while (dayStart < viewEnd) {
|
||||
dayDates.push(dayStart);
|
||||
dayRanges.push({
|
||||
start: dayStart,
|
||||
end: addDays(dayStart, 1)
|
||||
});
|
||||
dayStart = addDays(dayStart, 1);
|
||||
}
|
||||
return { dayDates: dayDates, dayRanges: dayRanges };
|
||||
}
|
||||
|
||||
var main = createPlugin({
|
||||
views: {
|
||||
list: {
|
||||
class: ListView,
|
||||
buttonTextKey: 'list',
|
||||
listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' } // like "January 1, 2016"
|
||||
},
|
||||
listDay: {
|
||||
type: 'list',
|
||||
duration: { days: 1 },
|
||||
listDayFormat: { weekday: 'long' } // day-of-week is all we need. full date is probably in header
|
||||
},
|
||||
listWeek: {
|
||||
type: 'list',
|
||||
duration: { weeks: 1 },
|
||||
listDayFormat: { weekday: 'long' },
|
||||
listDayAltFormat: { month: 'long', day: 'numeric', year: 'numeric' }
|
||||
},
|
||||
listMonth: {
|
||||
type: 'list',
|
||||
duration: { month: 1 },
|
||||
listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have
|
||||
},
|
||||
listYear: {
|
||||
type: 'list',
|
||||
duration: { year: 1 },
|
||||
listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default main;
|
||||
export { ListView };
|
||||
@@ -0,0 +1,343 @@
|
||||
/*!
|
||||
FullCalendar List View Plugin v4.3.0
|
||||
Docs & License: https://fullcalendar.io/
|
||||
(c) 2019 Adam Shaw
|
||||
*/
|
||||
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) :
|
||||
typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) :
|
||||
(global = global || self, factory(global.FullCalendarList = {}, global.FullCalendar));
|
||||
}(this, function (exports, core) { 'use strict';
|
||||
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
/* global Reflect, Promise */
|
||||
|
||||
var extendStatics = function(d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
|
||||
function __extends(d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
}
|
||||
|
||||
var ListEventRenderer = /** @class */ (function (_super) {
|
||||
__extends(ListEventRenderer, _super);
|
||||
function ListEventRenderer(listView) {
|
||||
var _this = _super.call(this, listView.context) || this;
|
||||
_this.listView = listView;
|
||||
return _this;
|
||||
}
|
||||
ListEventRenderer.prototype.attachSegs = function (segs) {
|
||||
if (!segs.length) {
|
||||
this.listView.renderEmptyMessage();
|
||||
}
|
||||
else {
|
||||
this.listView.renderSegList(segs);
|
||||
}
|
||||
};
|
||||
ListEventRenderer.prototype.detachSegs = function () {
|
||||
};
|
||||
// generates the HTML for a single event row
|
||||
ListEventRenderer.prototype.renderSegHtml = function (seg) {
|
||||
var _a = this.context, view = _a.view, theme = _a.theme;
|
||||
var eventRange = seg.eventRange;
|
||||
var eventDef = eventRange.def;
|
||||
var eventInstance = eventRange.instance;
|
||||
var eventUi = eventRange.ui;
|
||||
var url = eventDef.url;
|
||||
var classes = ['fc-list-item'].concat(eventUi.classNames);
|
||||
var bgColor = eventUi.backgroundColor;
|
||||
var timeHtml;
|
||||
if (eventDef.allDay) {
|
||||
timeHtml = core.getAllDayHtml(view);
|
||||
}
|
||||
else if (core.isMultiDayRange(eventRange.range)) {
|
||||
if (seg.isStart) {
|
||||
timeHtml = core.htmlEscape(this._getTimeText(eventInstance.range.start, seg.end, false // allDay
|
||||
));
|
||||
}
|
||||
else if (seg.isEnd) {
|
||||
timeHtml = core.htmlEscape(this._getTimeText(seg.start, eventInstance.range.end, false // allDay
|
||||
));
|
||||
}
|
||||
else { // inner segment that lasts the whole day
|
||||
timeHtml = core.getAllDayHtml(view);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Display the normal time text for the *event's* times
|
||||
timeHtml = core.htmlEscape(this.getTimeText(eventRange));
|
||||
}
|
||||
if (url) {
|
||||
classes.push('fc-has-url');
|
||||
}
|
||||
return '<tr class="' + classes.join(' ') + '">' +
|
||||
(this.displayEventTime ?
|
||||
'<td class="fc-list-item-time ' + theme.getClass('widgetContent') + '">' +
|
||||
(timeHtml || '') +
|
||||
'</td>' :
|
||||
'') +
|
||||
'<td class="fc-list-item-marker ' + theme.getClass('widgetContent') + '">' +
|
||||
'<span class="fc-event-dot"' +
|
||||
(bgColor ?
|
||||
' style="background-color:' + bgColor + '"' :
|
||||
'') +
|
||||
'></span>' +
|
||||
'</td>' +
|
||||
'<td class="fc-list-item-title ' + theme.getClass('widgetContent') + '">' +
|
||||
'<a' + (url ? ' href="' + core.htmlEscape(url) + '"' : '') + '>' +
|
||||
core.htmlEscape(eventDef.title || '') +
|
||||
'</a>' +
|
||||
'</td>' +
|
||||
'</tr>';
|
||||
};
|
||||
// like "4:00am"
|
||||
ListEventRenderer.prototype.computeEventTimeFormat = function () {
|
||||
return {
|
||||
hour: 'numeric',
|
||||
minute: '2-digit',
|
||||
meridiem: 'short'
|
||||
};
|
||||
};
|
||||
return ListEventRenderer;
|
||||
}(core.FgEventRenderer));
|
||||
|
||||
/*
|
||||
Responsible for the scroller, and forwarding event-related actions into the "grid".
|
||||
*/
|
||||
var ListView = /** @class */ (function (_super) {
|
||||
__extends(ListView, _super);
|
||||
function ListView(context, viewSpec, dateProfileGenerator, parentEl) {
|
||||
var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
|
||||
_this.computeDateVars = core.memoize(computeDateVars);
|
||||
_this.eventStoreToSegs = core.memoize(_this._eventStoreToSegs);
|
||||
var eventRenderer = _this.eventRenderer = new ListEventRenderer(_this);
|
||||
_this.renderContent = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer));
|
||||
_this.el.classList.add('fc-list-view');
|
||||
var listViewClassNames = (_this.theme.getClass('listView') || '').split(' '); // wish we didn't have to do this
|
||||
for (var _i = 0, listViewClassNames_1 = listViewClassNames; _i < listViewClassNames_1.length; _i++) {
|
||||
var listViewClassName = listViewClassNames_1[_i];
|
||||
if (listViewClassName) { // in case input was empty string
|
||||
_this.el.classList.add(listViewClassName);
|
||||
}
|
||||
}
|
||||
_this.scroller = new core.ScrollComponent('hidden', // overflow x
|
||||
'auto' // overflow y
|
||||
);
|
||||
_this.el.appendChild(_this.scroller.el);
|
||||
_this.contentEl = _this.scroller.el; // shortcut
|
||||
context.calendar.registerInteractiveComponent(_this, {
|
||||
el: _this.el
|
||||
// TODO: make aware that it doesn't do Hits
|
||||
});
|
||||
return _this;
|
||||
}
|
||||
ListView.prototype.render = function (props) {
|
||||
var _a = this.computeDateVars(props.dateProfile), dayDates = _a.dayDates, dayRanges = _a.dayRanges;
|
||||
this.dayDates = dayDates;
|
||||
this.renderContent(this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges));
|
||||
};
|
||||
ListView.prototype.destroy = function () {
|
||||
_super.prototype.destroy.call(this);
|
||||
this.renderContent.unrender();
|
||||
this.scroller.destroy(); // will remove the Grid too
|
||||
this.calendar.unregisterInteractiveComponent(this);
|
||||
};
|
||||
ListView.prototype.updateSize = function (isResize, viewHeight, isAuto) {
|
||||
_super.prototype.updateSize.call(this, isResize, viewHeight, isAuto);
|
||||
this.eventRenderer.computeSizes(isResize);
|
||||
this.eventRenderer.assignSizes(isResize);
|
||||
this.scroller.clear(); // sets height to 'auto' and clears overflow
|
||||
if (!isAuto) {
|
||||
this.scroller.setHeight(this.computeScrollerHeight(viewHeight));
|
||||
}
|
||||
};
|
||||
ListView.prototype.computeScrollerHeight = function (viewHeight) {
|
||||
return viewHeight -
|
||||
core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
|
||||
};
|
||||
ListView.prototype._eventStoreToSegs = function (eventStore, eventUiBases, dayRanges) {
|
||||
return this.eventRangesToSegs(core.sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.nextDayThreshold).fg, dayRanges);
|
||||
};
|
||||
ListView.prototype.eventRangesToSegs = function (eventRanges, dayRanges) {
|
||||
var segs = [];
|
||||
for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) {
|
||||
var eventRange = eventRanges_1[_i];
|
||||
segs.push.apply(segs, this.eventRangeToSegs(eventRange, dayRanges));
|
||||
}
|
||||
return segs;
|
||||
};
|
||||
ListView.prototype.eventRangeToSegs = function (eventRange, dayRanges) {
|
||||
var _a = this, dateEnv = _a.dateEnv, nextDayThreshold = _a.nextDayThreshold;
|
||||
var range = eventRange.range;
|
||||
var allDay = eventRange.def.allDay;
|
||||
var dayIndex;
|
||||
var segRange;
|
||||
var seg;
|
||||
var segs = [];
|
||||
for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex++) {
|
||||
segRange = core.intersectRanges(range, dayRanges[dayIndex]);
|
||||
if (segRange) {
|
||||
seg = {
|
||||
component: this,
|
||||
eventRange: eventRange,
|
||||
start: segRange.start,
|
||||
end: segRange.end,
|
||||
isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(),
|
||||
isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(),
|
||||
dayIndex: dayIndex
|
||||
};
|
||||
segs.push(seg);
|
||||
// detect when range won't go fully into the next day,
|
||||
// and mutate the latest seg to the be the end.
|
||||
if (!seg.isEnd && !allDay &&
|
||||
dayIndex + 1 < dayRanges.length &&
|
||||
range.end <
|
||||
dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) {
|
||||
seg.end = range.end;
|
||||
seg.isEnd = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return segs;
|
||||
};
|
||||
ListView.prototype.renderEmptyMessage = function () {
|
||||
this.contentEl.innerHTML =
|
||||
'<div class="fc-list-empty-wrap2">' + // TODO: try less wraps
|
||||
'<div class="fc-list-empty-wrap1">' +
|
||||
'<div class="fc-list-empty">' +
|
||||
core.htmlEscape(this.opt('noEventsMessage')) +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
};
|
||||
// called by ListEventRenderer
|
||||
ListView.prototype.renderSegList = function (allSegs) {
|
||||
var segsByDay = this.groupSegsByDay(allSegs); // sparse array
|
||||
var dayIndex;
|
||||
var daySegs;
|
||||
var i;
|
||||
var tableEl = core.htmlToElement('<table class="fc-list-table ' + this.calendar.theme.getClass('tableList') + '"><tbody></tbody></table>');
|
||||
var tbodyEl = tableEl.querySelector('tbody');
|
||||
for (dayIndex = 0; dayIndex < segsByDay.length; dayIndex++) {
|
||||
daySegs = segsByDay[dayIndex];
|
||||
if (daySegs) { // sparse array, so might be undefined
|
||||
// append a day header
|
||||
tbodyEl.appendChild(this.buildDayHeaderRow(this.dayDates[dayIndex]));
|
||||
daySegs = this.eventRenderer.sortEventSegs(daySegs);
|
||||
for (i = 0; i < daySegs.length; i++) {
|
||||
tbodyEl.appendChild(daySegs[i].el); // append event row
|
||||
}
|
||||
}
|
||||
}
|
||||
this.contentEl.innerHTML = '';
|
||||
this.contentEl.appendChild(tableEl);
|
||||
};
|
||||
// Returns a sparse array of arrays, segs grouped by their dayIndex
|
||||
ListView.prototype.groupSegsByDay = function (segs) {
|
||||
var segsByDay = []; // sparse array
|
||||
var i;
|
||||
var seg;
|
||||
for (i = 0; i < segs.length; i++) {
|
||||
seg = segs[i];
|
||||
(segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))
|
||||
.push(seg);
|
||||
}
|
||||
return segsByDay;
|
||||
};
|
||||
// generates the HTML for the day headers that live amongst the event rows
|
||||
ListView.prototype.buildDayHeaderRow = function (dayDate) {
|
||||
var dateEnv = this.dateEnv;
|
||||
var mainFormat = core.createFormatter(this.opt('listDayFormat')); // TODO: cache
|
||||
var altFormat = core.createFormatter(this.opt('listDayAltFormat')); // TODO: cache
|
||||
return core.createElement('tr', {
|
||||
className: 'fc-list-heading',
|
||||
'data-date': dateEnv.formatIso(dayDate, { omitTime: true })
|
||||
}, '<td class="' + (this.calendar.theme.getClass('tableListHeading') ||
|
||||
this.calendar.theme.getClass('widgetHeader')) + '" colspan="3">' +
|
||||
(mainFormat ?
|
||||
core.buildGotoAnchorHtml(this, dayDate, { 'class': 'fc-list-heading-main' }, core.htmlEscape(dateEnv.format(dayDate, mainFormat)) // inner HTML
|
||||
) :
|
||||
'') +
|
||||
(altFormat ?
|
||||
core.buildGotoAnchorHtml(this, dayDate, { 'class': 'fc-list-heading-alt' }, core.htmlEscape(dateEnv.format(dayDate, altFormat)) // inner HTML
|
||||
) :
|
||||
'') +
|
||||
'</td>');
|
||||
};
|
||||
return ListView;
|
||||
}(core.View));
|
||||
ListView.prototype.fgSegSelector = '.fc-list-item'; // which elements accept event actions
|
||||
function computeDateVars(dateProfile) {
|
||||
var dayStart = core.startOfDay(dateProfile.renderRange.start);
|
||||
var viewEnd = dateProfile.renderRange.end;
|
||||
var dayDates = [];
|
||||
var dayRanges = [];
|
||||
while (dayStart < viewEnd) {
|
||||
dayDates.push(dayStart);
|
||||
dayRanges.push({
|
||||
start: dayStart,
|
||||
end: core.addDays(dayStart, 1)
|
||||
});
|
||||
dayStart = core.addDays(dayStart, 1);
|
||||
}
|
||||
return { dayDates: dayDates, dayRanges: dayRanges };
|
||||
}
|
||||
|
||||
var main = core.createPlugin({
|
||||
views: {
|
||||
list: {
|
||||
class: ListView,
|
||||
buttonTextKey: 'list',
|
||||
listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' } // like "January 1, 2016"
|
||||
},
|
||||
listDay: {
|
||||
type: 'list',
|
||||
duration: { days: 1 },
|
||||
listDayFormat: { weekday: 'long' } // day-of-week is all we need. full date is probably in header
|
||||
},
|
||||
listWeek: {
|
||||
type: 'list',
|
||||
duration: { weeks: 1 },
|
||||
listDayFormat: { weekday: 'long' },
|
||||
listDayAltFormat: { month: 'long', day: 'numeric', year: 'numeric' }
|
||||
},
|
||||
listMonth: {
|
||||
type: 'list',
|
||||
duration: { month: 1 },
|
||||
listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have
|
||||
},
|
||||
listYear: {
|
||||
type: 'list',
|
||||
duration: { year: 1 },
|
||||
listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
exports.ListView = ListView;
|
||||
exports.default = main;
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
}));
|
||||
+1
@@ -0,0 +1 @@
|
||||
.fc-event-dot{display:inline-block;width:10px;height:10px;border-radius:5px}.fc-rtl .fc-list-view{direction:rtl}.fc-list-view{border-width:1px;border-style:solid}.fc .fc-list-table{table-layout:auto}.fc-list-table td{border-width:1px 0 0;padding:8px 14px}.fc-list-table tr:first-child td{border-top-width:0}.fc-list-heading{border-bottom-width:1px}.fc-list-heading td{font-weight:700}.fc-ltr .fc-list-heading-main{float:left}.fc-ltr .fc-list-heading-alt,.fc-rtl .fc-list-heading-main{float:right}.fc-rtl .fc-list-heading-alt{float:left}.fc-list-item.fc-has-url{cursor:pointer}.fc-list-item-marker,.fc-list-item-time{white-space:nowrap;width:1px}.fc-ltr .fc-list-item-marker{padding-right:0}.fc-rtl .fc-list-item-marker{padding-left:0}.fc-list-item-title a{text-decoration:none;color:inherit}.fc-list-item-title a[href]:hover{text-decoration:underline}.fc-list-empty-wrap2{position:absolute;top:0;left:0;right:0;bottom:0}.fc-list-empty-wrap1{width:100%;height:100%;display:table}.fc-list-empty{display:table-cell;vertical-align:middle;text-align:center}.fc-unthemed .fc-list-empty{background-color:#eee}
|
||||
+6
File diff suppressed because one or more lines are too long
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "@fullcalendar/list",
|
||||
"version": "4.3.0",
|
||||
"title": "FullCalendar List View Plugin",
|
||||
"description": "View your events as a bulleted list",
|
||||
"keywords": [
|
||||
"calendar",
|
||||
"event",
|
||||
"full-sized"
|
||||
],
|
||||
"homepage": "https://fullcalendar.io/",
|
||||
"docs": "https://fullcalendar.io/docs/list-view",
|
||||
"bugs": "https://fullcalendar.io/reporting-bugs",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fullcalendar/fullcalendar.git",
|
||||
"homepage": "https://github.com/fullcalendar/fullcalendar"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "Adam Shaw",
|
||||
"email": "arshaw@arshaw.com",
|
||||
"url": "http://arshaw.com/"
|
||||
},
|
||||
"copyright": "2019 Adam Shaw",
|
||||
"peerDependencies": {
|
||||
"@fullcalendar/core": "~4.3.0"
|
||||
},
|
||||
"main": "main.js",
|
||||
"module": "main.esm.js",
|
||||
"unpkg": "main.min.js",
|
||||
"types": "main.d.ts"
|
||||
}
|
||||
Reference in New Issue
Block a user