Add frontend assets and plugin bundles

Add the legacy frontend themes, scripts, and plugin assets required by the main SPOTA interfaces.
This commit is contained in:
Power BI Dev
2026-05-02 10:09:32 +07:00
parent efdb11db3f
commit a52c2a8462
2061 changed files with 513282 additions and 0 deletions

768
js/calendar.js Normal file
View File

@@ -0,0 +1,768 @@
/**
* Bootstrap based calendar full view.
*
* https://github.com/Serhioromano/bootstrap-calendar
*
* User: Sergey Romanov <serg4172@mail.ru>
* Version 0.1
*/
"use strict";
Date.prototype.getWeek = function() {
var onejan = new Date(this.getFullYear(), 0, 1);
return Math.ceil((((this.getTime() - onejan.getTime()) / 86400000) + onejan.getDay() + 1) / 7);
}
Date.prototype.getMonthFormatted = function() {
var month = this.getMonth() + 1;
return month < 10 ? '0' + month : month;
}
Date.prototype.getDateFormatted = function() {
var date = this.getDate();
return date < 10 ? '0' + date : date;
}
if(!String.prototype.format) {
String.prototype.format = function() {
var args = arguments;
return this.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined' ? args[number] : match;
});
};
}
;
(function($) {
var defaults = {
width: '100%', // maximum width of all calendar
view: 'month', // month, week, day
day: 'now', // what day to start with. No matter month, week or day this will be a starting point
// format yyyy-mm-dd or now
first_day: 1, // Which day is first 2 - sunday or 1 - monday
events_url: '', // URL to return JSON list of events in special format.
// {success:1, result: [....]} or for error {success:0, error:'Something terrible happened'}
// events: [...] as described in events property description
// The start and end variables will be sent to this url
/**
* path to templates should end with slash /. It can be as relative
*
* /component/bootstrap-calendar/tmpls/
*
* or absolute
*
* http://localhost/component/bootstrap-calendar/tmpls/
*/
tmpl_path: 'tmpls/',
classes: {
months: {
inmonth: 'cal-day-inmonth',
outmonth: 'cal-day-outmonth',
saturday: 'cal-day-weekend',
sunday: 'cal-day-weekend',
holidays: 'cal-day-holiday',
today: 'cal-day-today'
},
week: {
workday: 'cal-day-workday',
saturday: 'cal-day-weekend',
sunday: 'cal-day-weekend',
holidays: 'cal-day-holiday',
today: 'cal-day-today'
}
},
enable_easter_holidays: false, // Set to true if you want to enable Easter and Easter Monday as holidays
views: {
year: {
slide_events: 1,
enable: 1
},
month: {
slide_events: 1,
enable: 1
},
week: {
enable: 1
},
day: {
enable: 1
}
},
// ------------------------------------------------------------
// CALLBACKS. Events triggered by calendar class. You can use
// those to affect you UI
// ------------------------------------------------------------
onAfterEventsLoad: function(events) {
// Inside this function 'this' is the calendar instance
},
onBeforeEventsLoad: function(next) {
// Inside this function 'this' is the calendar instance
next();
},
onAfterViewLoad: function(view) {
// Inside this function 'this' is the calendar instance
},
// -------------------------------------------------------------
// INTERNAL USE ONLY. DO NOT ASSIGN IT WILL BE OVERRIDDEN ANYWAY
// -------------------------------------------------------------
events: [],
position: {
start: new Date(),
end: new Date()
},
templates: {
year: '',
month: '',
week: '',
day: ''
},
stop_cycling: false
};
var strings = {
error_noview: 'Calendar: View {0} not found',
error_dateformat: 'Calendar: Wrong date format {0}. Should be either "now" or "yyyy-mm-dd"',
error_loadurl: 'Calendar: Events load URL is not set',
error_where: 'Calendar: Wrong navigation direction {0}. Can be only "next" or "prev" or "today"',
title_year: 'Year {0}',
title_month: '{0} year {1}',
title_week: '{0} week of year {1}',
title_day: '{0} {1} {2} year {3}',
week:'Week',
m0: 'January',
m1: 'February',
m2: 'March',
m3: 'April',
m4: 'May',
m5: 'June',
m6: 'July',
m7: 'August',
m8: 'September',
m9: 'October',
m10: 'November',
m11: 'December',
ms0: 'Jan',
ms1: 'Feb',
ms2: 'Mar',
ms3: 'Apr',
ms4: 'May',
ms5: 'Jun',
ms6: 'Jul',
ms7: 'Aug',
ms8: 'Sep',
ms9: 'Oct',
ms10: 'Nov',
ms11: 'Dec',
d0: 'Sunday',
d1: 'Monday',
d2: 'Tuesday',
d3: 'Wednesday',
d4: 'Thursday',
d5: 'Friday',
d6: 'Saturday',
easter: 'Easter',
easterMonday: 'Easter Monday'
};
function buildEventsUrl(events_url, data) {
var separator, key, url;
url = events_url;
separator = (events_url.indexOf('?') < 0) ? '?' : '&';
for(key in data) {
url += separator + key + '=' + encodeURIComponent(data[key]);
separator = '&';
}
return url;
}
function Calendar(params, context) {
this.options = $.extend(true, {}, defaults, params);
this.setLanguage(this.options.language);
this.context = context;
context.css('width', this.options.width);
this.view();
return this;
}
Calendar.prototype.setOptions = function(object) {
$.extend(this.options, object);
if('language' in object) {
this.setLanguage(object.language);
}
}
Calendar.prototype.setLanguage = function(lang) {
if(window.calendar_languages && (lang in window.calendar_languages)) {
this.strings = $.extend(true, {}, strings, calendar_languages[lang]);
this.options.language = lang;
} else {
this.strings = strings;
delete this.options.language;
}
}
Calendar.prototype._render = function() {
this.context.html('');
this._loadTemplate(this.options.view);
this.stop_cycling = false;
var data = {};
data.events = [];
data.cal = this;
data.day = 1;
// Getting list of days in a week in correct order. Works for month and week views
if(this.options.first_day == 1) {
data.months = [this.strings.d1, this.strings.d2, this.strings.d3, this.strings.d4, this.strings.d5, this.strings.d6, this.strings.d0]
} else {
data.months = [this.strings.d0, this.strings.d1, this.strings.d2, this.strings.d3, this.strings.d4, this.strings.d5, this.strings.d6]
}
// Get all events between start and end
var start = parseInt(this.options.position.start.getTime());
var end = parseInt(this.options.position.end.getTime());
$.each(this.options.events, function(k, event) {
if((parseInt(event.start) <= end) && (parseInt(event.end) >= start)) {
data.events.push(event);
}
});
switch(this.options.view) {
case 'month':
break;
case 'week':
break;
case 'day':
break;
}
data.start = new Date(this.options.position.start.getTime());
data.lang = this.strings;
this.context.append(this.options.templates[this.options.view](data));
this._update();
};
Calendar.prototype._week = function(event) {
this._loadTemplate('week-days');
var t = {};
var start = parseInt(this.options.position.start.getTime());
var end = parseInt(this.options.position.end.getTime());
var events = [];
var self = this;
$.each(this.options.events, function(k, event) {
if((parseInt(event.start) <= end) && (parseInt(event.end) >= start)) {
event.start_day = new Date(parseInt(event.start)).getDay();
if(self.options.first_day == 1) {
event.start_day = (event.start_day + 6) % 7;
}
if((event.end - event.start) <= 86400000) {
event.days = 1;
} else {
event.days = ((event.end - event.start) / 86400000);
}
if(event.start < start) {
event.days = event.days - ((start - event.start) / 86400000);
event.start_day = 0;
}
event.days = Math.ceil(event.days);
if(event.start_day + event.days > 7) {
event.days = 7 - (event.start_day);
}
if(self.options.first_day == 1) {
}
events.push(event);
}
});
t.events = events;
t.cal = this;
return self.options.templates['week-days'](t);
}
Calendar.prototype._month = function(month) {
this._loadTemplate('year-month');
var t = {};
var newmonth = month + 1;
t.data_day = this.options.position.start.getFullYear() + '-' + (newmonth < 10 ? '0' + newmonth : newmonth) + '-' + '01';
t.month_name = this.strings['m' + month];
var curdate = new Date(this.options.position.start.getFullYear(), month, 1, 0, 0, 0);
var start = parseInt(curdate.getTime());
var end = parseInt(new Date(this.options.position.start.getFullYear(), month + 1, 0, 0, 0, 0).getTime());
var events = [];
$.each(this.options.events, function(k, event) {
if((parseInt(event.start) <= end) && (parseInt(event.end) >= start)) {
events.push(event);
}
});
t.events = events;
return this.options.templates['year-month'](t);
}
Calendar.prototype._day = function(week, day) {
this._loadTemplate('month-day');
var t = {tooltip: ''};
var cls = this.options.classes.months.outmonth;
var firstday = this.options.position.start.getDay();
if(this.options.first_day == 2) {
firstday++;
} else {
firstday = (firstday == 0 ? 7 : firstday);
}
day = (day - firstday) + 1;
var curdate = new Date(this.options.position.start.getFullYear(), this.options.position.start.getMonth(), day, 0, 0, 0);
// if day of the current month
if(day > 0) {
cls = this.options.classes.months.inmonth;
}
// stop cycling table rows;
if((day + 1) > this.options.position.end.getDate()) {
this.stop_cycling = true;
}
// if day of the next month
if(day > this.options.position.end.getDate()) {
day = day - this.options.position.end.getDate();
cls = this.options.classes.months.outmonth;
}
cls = $.trim(cls + " " + this._getDayClass("months", curdate));
if(day <= 0) {
var daysinprevmonth = (new Date(this.options.position.start.getFullYear(), this.options.position.start.getMonth(), 0)).getDate();
day = daysinprevmonth - Math.abs(day);
cls += ' cal-month-first-row';
}
var holiday = this._getHoliday(curdate);
if(holiday !== false) {
t.tooltip = holiday;
}
t.data_day = curdate.getFullYear() + '-' + curdate.getMonthFormatted() + '-' + (day < 10 ? '0' + day : day);
t.cls = cls;
t.day = day;
var start = parseInt(curdate.getTime());
var end = parseInt(start + 86400000);
var events = [];
$.each(this.options.events, function(k, event) {
if((parseInt(event.start) < end) && (parseInt(event.end) > start)) {
events.push(event);
}
});
t.events = events;
return this.options.templates['month-day'](t);
}
Calendar.prototype._getHoliday = function(date) {
if(this.options.enable_easter_holidays) {
var easter = getEasterDate(date.getFullYear());
if(easter.toDateString() == date.toDateString()) {
return this.strings.easter;
}
var easterMonday = new Date();
easterMonday.setTime(easter.getTime());
easterMonday.setDate(easter.getDate() + 1);
if(easterMonday.toDateString() == date.toDateString()) {
return this.strings.easterMonday;
}
}
if(this.options.holidays) {
var date_str = date.getDateFormatted() + '-' + date.getMonthFormatted();
if(date_str in this.options.holidays) {
return this.options.holidays[date_str];
}
date_str += '-' + date.getFullYear();
if(date_str in this.options.holidays) {
return this.options.holidays[date_str];
}
}
return false;
};
Calendar.prototype._getHolidayName = function(date) {
var holiday = this._getHoliday(date);
return (holiday === false) ? "" : holiday;
};
Calendar.prototype._getDayClass = function(class_group, date) {
var self = this;
var addClass = function(which, to) {
var cls;
cls = (self.options.classes && (class_group in self.options.classes) && (which in self.options.classes[class_group])) ? self.options.classes[class_group][which] : "";
if((typeof(cls) == "string") && cls.length) {
to.push(cls);
}
};
var classes = [];
if(date.toDateString() == (new Date()).toDateString()) {
addClass("today", classes);
}
var holiday = this._getHoliday(date);
if(holiday !== false) {
addClass("holidays", classes);
}
switch(date.getDay()) {
case 0:
addClass("sunday", classes);
break;
case 6:
addClass("saturday", classes);
break;
}
return classes.join(" ");
};
Calendar.prototype.view = function(view) {
if(view) this.options.view = view;
this._init_position();
this._loadEvents();
this._render();
this.options.onAfterViewLoad.call(this, this.options.view);
};
Calendar.prototype.navigate = function(where, next) {
var to = $.extend({}, this.options.position);
if(where == 'next') {
switch(this.options.view) {
case 'year':
to.start.setFullYear(this.options.position.start.getFullYear() + 1);
break;
case 'month':
to.start.setMonth(this.options.position.start.getMonth() + 1);
break;
case 'week':
to.start.setDate(this.options.position.start.getDate() + 7);
break;
case 'day':
to.start.setDate(this.options.position.start.getDate() + 1);
break;
}
} else if(where == 'prev') {
switch(this.options.view) {
case 'year':
to.start.setFullYear(this.options.position.start.getFullYear() - 1);
break;
case 'month':
to.start.setMonth(this.options.position.start.getMonth() - 1);
break;
case 'week':
to.start.setDate(this.options.position.start.getDate() - 7);
break;
case 'day':
to.start.setDate(this.options.position.start.getDate() - 1);
break;
}
} else if(where == 'today') {
to.start.setTime(new Date().getTime());
}
else {
$.error(this.strings.error_where.format(where))
}
this.options.day = to.start.getFullYear() + '-' + to.start.getMonthFormatted() + '-' + to.start.getDateFormatted();
this.view();
if(_.isFunction(next)) {
next();
}
};
Calendar.prototype._init_position = function() {
var year, month, day;
if(this.options.day == 'now') {
var date = new Date();
year = date.getFullYear();
month = date.getMonth();
day = date.getDate();
} else if(this.options.day.match(/^\d{4}-\d{2}-\d{2}$/g)) {
var list = this.options.day.split('-');
year = list[0];
month = list[1] - 1;
day = list[2];
}
else {
$.error(this.strings.error_dateformat.format(this.options.day));
}
switch(this.options.view) {
case 'year':
this.options.position.start.setTime(new Date(year, 0, 1).getTime());
this.options.position.end.setTime(new Date(year, 12, 0, 23, 59, 59).getTime());
break;
case 'month':
this.options.position.start.setTime(new Date(year, month, 1).getTime());
this.options.position.end.setTime(new Date(year, month + 1, 0, 23, 59, 59).getTime());
break;
case 'day':
this.options.position.start.setTime(new Date(year, month, day).getTime());
this.options.position.end.setTime(new Date(year, month, day, 23, 59, 59).getTime());
break;
case 'week':
var curr = new Date(year, month, day);
var first = curr.getDate() - curr.getDay();
if(this.options.first_day == 1) first += 1;
var last = first + 6;
this.options.position.start.setTime(new Date(year, month, first).getTime());
this.options.position.end.setTime(new Date(year, month, last, 23, 59, 59).getTime());
break;
default:
$.error(this.strings.error_noview.format(this.options.view))
}
return this;
};
Calendar.prototype.getTitle = function() {
var p = this.options.position.start;
switch(this.options.view) {
case 'year':
return this.strings.title_year.format(p.getFullYear());
break;
case 'month':
return this.strings.title_month.format(this.strings['m' + p.getMonth()], p.getFullYear());
break;
case 'week':
return this.strings.title_week.format(p.getWeek(), p.getFullYear());
break;
case 'day':
return this.strings.title_day.format(this.strings['d' + p.getDay()], p.getDate(), this.strings['m' + p.getMonth()], p.getFullYear());
break;
}
return;
};
Calendar.prototype.isToday = function() {
var now = new Date().getTime();
return ((now > this.options.position.start) && (now < this.options.position.end));
}
Calendar.prototype.getStartDate = function() {
return this.options.position.start;
}
Calendar.prototype.getEndDate = function() {
return this.options.position.end;
}
Calendar.prototype._loadEvents = function() {
if(!this.options.events_url) {
$.error(this.strings.error_loadurl);
}
var self = this;
this.options.onBeforeEventsLoad.call(this, function() {
$.ajax({
url: buildEventsUrl(self.options.events_url, {from: self.options.position.start.getTime(), to: self.options.position.end.getTime()}),
dataType: 'json',
type: 'GET',
async: false
}).done(function(json) {
if(!json.success) {
$.error(json.error);
}
self.options.events = json.result || [];
self.options.onAfterEventsLoad.call(self, json.result);
});
});
};
Calendar.prototype._loadTemplate = function(name) {
if(this.options.templates[name]) {
return;
}
var self = this;
$.ajax({
url: this.options.tmpl_path + name + '.html',
dataType: 'html',
type: 'GET',
async: false
}).done(function(html) {
self.options.templates[name] = _.template(html);
});
};
Calendar.prototype._update = function() {
var self = this;
$('*[rel="tooltip"]').tooltip();
$('*[data-cal-date]').click(function() {
var view = $(this).data('cal-view');
if(!self.options.views[view].enable) {
return;
}
self.options.day = $(this).data('cal-date');
self.view(view);
});
$('.cal-cell').dblclick(function() {
var view = $('[data-cal-date]', this).data('cal-view');
if(!self.options.views[view].enable) {
return;
}
self.options.day = $('[data-cal-date]', this).data('cal-date');
self.view(view);
});
this['_update_' + this.options.view]();
};
Calendar.prototype._update_day = function() {
};
Calendar.prototype._update_week = function() {
};
Calendar.prototype._update_year = function() {
this._update_month_year();
};
Calendar.prototype._update_month = function() {
this._update_month_year();
var week = $(document.createElement('div')).attr('id', 'cal-week-box');
week.html(this.strings.week);
var start = this.options.position.start.getFullYear() + '-' + this.options.position.start.getMonthFormatted() + '-';
$('.cal-month-box .cal-row-fluid').each(function(k, v) {
var row = $(v);
row.bind('mouseenter',function() {
var child = $('.cal-cell1:first-child .cal-month-day', row);
var day = (child.hasClass('cal-month-first-row') ? 1 : $('[data-cal-date]', child).text());
day = (day < 10 ? '0' + day : day);
week.attr('data-cal-week', start + day).show().appendTo(child);
}).bind('mouseleave', function() {
week.hide();
});
});
var self = this;
week.click(function() {
self.options.day = $(this).data('cal-week');
self.view('week');
});
$('a.event').mouseenter(function() {
$('a.event' + $(this).data('event-id')).parents('.cal-cell1').addClass('day-highlight dh-' + $(this).data('event-class'));
});
$('a.event').mouseleave(function() {
$('div.cal-cell1').removeClass('day-highlight dh-' + $(this).data('event-class'));
});
};
Calendar.prototype._update_month_year = function() {
if(!this.options.views[this.options.view].slide_events) {
return;
}
var activecell = 0;
var self = this;
var downbox = $(document.createElement('div')).attr('id', 'cal-day-box').html('<i class="icon-chevron-down"></i>');
$('.cal-month-day, .cal-year-box .span3').each(function(k, v) {
$(v).bind('mouseenter', function() {
if($('.events-list', v).length == 0) return;
if($(v).children('[data-cal-date]').text() == activecell) return;
downbox.show().appendTo(v);
});
$(v).bind('mouseleave', function() {
downbox.hide();
});
});
var slider = $(document.createElement('div')).attr('id', 'cal-slide-box');
slider.hide().click(function(event) {
event.stopPropagation();
});
this._loadTemplate('events-list');
downbox.click(function(event) {
event.stopPropagation();
var $this = $(this);
var cell = $this.parents('.cal-cell');
var row = $this.parents('.cal-row-fluid');
var tick_position = cell.data('cal-row');
$this.fadeOut('fast');
slider.html(self.options.templates['events-list']({events: $('.events-list a.event', cell)}))
.slideUp('fast', function() {
row.after(slider);
activecell = $('[data-cal-date]', cell).text();
$('#cal-slide-tick').addClass('tick' + tick_position).show();
slider.slideDown('fast', function() {
$('body').one('click', function() {
slider.slideUp('fast');
activecell = 0;
});
});
});
$('a.event-item').mouseenter(function() {
$('a.event' + $(this).data('event-id')).parents('.cal-cell1').addClass('day-highlight dh-' + $(this).data('event-class'));
});
$('a.event-item').mouseleave(function() {
$('div.cal-cell1').removeClass('day-highlight dh-' + $(this).data('event-class'));
});
});
};
function getEasterDate(year) {
var a = year % 19;
var b = Math.floor(year / 100);
var c = year % 100;
var d = Math.floor(b / 4);
var e = b % 4;
var f = Math.floor((b + 8) / 25);
var g = Math.floor((b - f + 1) / 3);
var h = (19 * a + b - d - g + 15) % 30;
var i = Math.floor(c / 4);
var k = c % 4;
var l = (32 + 2 * e + 2 * i - h - k) % 7;
var m = Math.floor((a + 11 * h + 22 * l) / 451);
var n0 = (h + l + 7 * m + 114)
var n = Math.floor(n0 / 31) - 1;
var p = n0 % 31 + 1;
return new Date(year, n, p, 0, 0, 0);
}
$.fn.calendar = function(params) {
return new Calendar(params, this);
}
}(jQuery));