OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)
This commit is contained in:
625
app/Domain/Projects/Js/projectsController.js
Normal file
625
app/Domain/Projects/Js/projectsController.js
Normal file
@@ -0,0 +1,625 @@
|
||||
leantime.projectsController = (function () {
|
||||
|
||||
|
||||
function countTickets()
|
||||
{
|
||||
|
||||
jQuery("#sortableTicketKanban .column").each(function () {
|
||||
var counting = jQuery(this).find('.moveable').length;
|
||||
jQuery(this).find(' .count').text(counting);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//Functions
|
||||
|
||||
var initDates = function () {
|
||||
|
||||
jQuery(".projectDateFrom, .projectDateTo").datepicker(
|
||||
{
|
||||
dateFormat: leantime.dateHelper.getFormatFromSettings("dateformat", "jquery"),
|
||||
dayNames: leantime.i18n.__("language.dayNames").split(","),
|
||||
dayNamesMin: leantime.i18n.__("language.dayNamesMin").split(","),
|
||||
dayNamesShort: leantime.i18n.__("language.dayNamesShort").split(","),
|
||||
monthNames: leantime.i18n.__("language.monthNames").split(","),
|
||||
currentText: leantime.i18n.__("language.currentText"),
|
||||
closeText: leantime.i18n.__("language.closeText"),
|
||||
buttonText: leantime.i18n.__("language.buttonText"),
|
||||
isRTL: leantime.i18n.__("language.isRTL") === "true" ? 1 : 0,
|
||||
nextText: leantime.i18n.__("language.nextText"),
|
||||
prevText: leantime.i18n.__("language.prevText"),
|
||||
weekHeader: leantime.i18n.__("language.weekHeader"),
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var initProjectTabs = function () {
|
||||
jQuery('.projectTabs').tabs();
|
||||
};
|
||||
|
||||
var initDuplicateProjectModal = function () {
|
||||
|
||||
var regularModelConfig = {
|
||||
sizes: {
|
||||
minW: 450,
|
||||
minH: 350
|
||||
},
|
||||
resizable: true,
|
||||
autoSizable: true,
|
||||
callbacks: {
|
||||
afterShowCont: function () {
|
||||
jQuery(".showDialogOnLoad").show();
|
||||
initDates();
|
||||
jQuery(".duplicateProjectModal, .formModal").nyroModal(regularModelConfig);
|
||||
},
|
||||
beforeClose: function () {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
jQuery(".duplicateProjectModal").nyroModal(regularModelConfig);
|
||||
|
||||
};
|
||||
|
||||
var initProgressBar = function (percentage) {
|
||||
|
||||
jQuery("#progressbar").progressbar({
|
||||
value: percentage
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
||||
var initProjectTable = function () {
|
||||
|
||||
jQuery(document).ready(function () {
|
||||
|
||||
var size = 100;
|
||||
|
||||
var allProjects = jQuery("#allProjectsTable").DataTable({
|
||||
"language": {
|
||||
"decimal": leantime.i18n.__("datatables.decimal"),
|
||||
"emptyTable": leantime.i18n.__("datatables.emptyTable"),
|
||||
"info": leantime.i18n.__("datatables.info"),
|
||||
"infoEmpty": leantime.i18n.__("datatables.infoEmpty"),
|
||||
"infoFiltered": leantime.i18n.__("datatables.infoFiltered"),
|
||||
"infoPostFix": leantime.i18n.__("datatables.infoPostFix"),
|
||||
"thousands": leantime.i18n.__("datatables.thousands"),
|
||||
"lengthMenu": leantime.i18n.__("datatables.lengthMenu"),
|
||||
"loadingRecords": leantime.i18n.__("datatables.loadingRecords"),
|
||||
"processing": leantime.i18n.__("datatables.processing"),
|
||||
"search": leantime.i18n.__("datatables.search"),
|
||||
"zeroRecords": leantime.i18n.__("datatables.zeroRecords"),
|
||||
"paginate": {
|
||||
"first": leantime.i18n.__("datatables.first"),
|
||||
"last": leantime.i18n.__("datatables.last"),
|
||||
"next": leantime.i18n.__("datatables.next"),
|
||||
"previous": leantime.i18n.__("datatables.previous"),
|
||||
},
|
||||
"aria": {
|
||||
"sortAscending": leantime.i18n.__("datatables.sortAscending"),
|
||||
"sortDescending":leantime.i18n.__("datatables.sortDescending"),
|
||||
}
|
||||
|
||||
},
|
||||
"dom": '<"top">rt<"bottom"ilp><"clear">',
|
||||
"searching": false,
|
||||
"displayLength":100
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var initTodoStatusSortable = function (element) {
|
||||
var sortCounter = 1;
|
||||
|
||||
jQuery(element).find("input.sorter").each(function (index) {
|
||||
|
||||
jQuery(this).val(sortCounter);
|
||||
sortCounter++;
|
||||
});
|
||||
|
||||
jQuery(element).sortable({
|
||||
stop: function ( event, ui ) {
|
||||
|
||||
sortCounter = 1;
|
||||
jQuery(element).find("input.sorter").each(function (index) {
|
||||
jQuery(this).val(sortCounter);
|
||||
sortCounter++;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var initSelectFields = function () {
|
||||
|
||||
jQuery(document).ready(function () {
|
||||
|
||||
jQuery("#todosettings select.colorChosen").on('chosen:ready', function (e, params) {
|
||||
|
||||
var id = jQuery(this).attr('id').replace("-", "_");
|
||||
|
||||
jQuery("#" + id + "_chosen a span").removeClass();
|
||||
jQuery("#" + id + "_chosen a span").addClass(params.selected);
|
||||
|
||||
}).chosen({
|
||||
disable_search_threshold: 10
|
||||
});
|
||||
|
||||
jQuery("#todosettings select.colorChosen").on('change', function (evt, params) {
|
||||
|
||||
var id = jQuery(this).attr('id').replace("-", "_");
|
||||
|
||||
jQuery("#" + id + "_chosen a span").removeClass();
|
||||
jQuery("#" + id + "_chosen a span").addClass(params.selected);
|
||||
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var removeStatus = function (id) {
|
||||
|
||||
jQuery("#todostatus-" + id).parent().remove();
|
||||
|
||||
};
|
||||
|
||||
var addToDoStatus = function (id) {
|
||||
|
||||
var highestKey = -1;
|
||||
|
||||
jQuery("#todosettings ul .statusList").each(function () {
|
||||
|
||||
var keyInt = jQuery(this).find('.labelKey').val();
|
||||
|
||||
if (parseInt(keyInt) >= parseInt(highestKey)) {
|
||||
highestKey = keyInt;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var newKey = parseInt(highestKey) + 1;
|
||||
|
||||
var statusCopy = jQuery(".newStatusTpl").clone();
|
||||
|
||||
statusCopy.html(function (i, oldHTML) {
|
||||
return updatedContent = oldHTML.replaceAll('XXNEWKEYXX', newKey);
|
||||
});
|
||||
|
||||
jQuery('#todoStatusList').append("<li>" + statusCopy.html() + "</li>");
|
||||
|
||||
jQuery("#todosettings select.colorChosen").chosen("destroy");
|
||||
leantime.projectsController.initSelectFields();
|
||||
jQuery("#todoStatusList").sortable("destroy");
|
||||
leantime.projectsController.initTodoStatusSortable("#todoStatusList");
|
||||
|
||||
};
|
||||
|
||||
var readURL = function (input) {
|
||||
|
||||
clearCroppie();
|
||||
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
|
||||
var profileImg = jQuery('#projectAvatar');
|
||||
reader.onload = function (e) {
|
||||
//profileImg.attr('src', e.currentTarget.result);
|
||||
|
||||
_uploadResult = profileImg
|
||||
.croppie(
|
||||
{
|
||||
enableExif: true,
|
||||
viewport: {
|
||||
width: 200,
|
||||
height: 200,
|
||||
type: 'rectangle'
|
||||
},
|
||||
boundary: {
|
||||
width: 250,
|
||||
height: 250
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
_uploadResult.croppie(
|
||||
'bind',
|
||||
{
|
||||
url: e.currentTarget.result
|
||||
}
|
||||
);
|
||||
|
||||
jQuery("#previousImage").hide();
|
||||
};
|
||||
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
}
|
||||
};
|
||||
|
||||
var clearCroppie = function () {
|
||||
jQuery('#profileImg').croppie('destroy');
|
||||
jQuery("#previousImage").show();
|
||||
};
|
||||
|
||||
var saveCroppie = function () {
|
||||
|
||||
jQuery('#save-picture').addClass('running');
|
||||
|
||||
jQuery('#profileImg').attr('src', leantime.appUrl + '/images/loaders/loader28.gif');
|
||||
_uploadResult.croppie(
|
||||
'result',
|
||||
{
|
||||
type: "blob",
|
||||
circle: false
|
||||
}
|
||||
).then(
|
||||
function (result) {
|
||||
var formData = new FormData();
|
||||
formData.append('file', result);
|
||||
jQuery.ajax(
|
||||
{
|
||||
type: 'POST',
|
||||
url: leantime.appUrl + '/projects/projectImage',
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function (resp) {
|
||||
|
||||
jQuery('#save-picture').removeClass('running');
|
||||
|
||||
location.reload();
|
||||
},
|
||||
error: function (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
var initGanttChart = function (projects, viewMode, readonly) {
|
||||
|
||||
function htmlEntities(str)
|
||||
{
|
||||
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
}
|
||||
|
||||
jQuery(document).ready(
|
||||
function () {
|
||||
|
||||
// The Gantt constructor fires on_view_change once while building. Persisting that
|
||||
// event would overwrite the user's saved scale with the default, so ignore any
|
||||
// view change until construction is finished; only user-driven changes save.
|
||||
var ganttInitializing = true;
|
||||
|
||||
if (readonly === false) {
|
||||
var gantt_chart = new Gantt(
|
||||
"#gantt",
|
||||
projects,
|
||||
{
|
||||
header_height: 55,
|
||||
column_width: 20,
|
||||
step: 24,
|
||||
view_modes: ['Day', 'Week', 'Month'],
|
||||
bar_height: 40,
|
||||
static_progress_indicator: true,
|
||||
bar_corner_radius: 10,
|
||||
arrow_curve: 10,
|
||||
padding:20,
|
||||
view_mode: viewMode,
|
||||
date_format: leantime.i18n.__("language.momentJSDate"),
|
||||
language: 'en', // or 'es', 'it', 'ru', 'ptBr', 'fr', 'tr', 'zh'
|
||||
additional_rows: 5,
|
||||
custom_popup_html: function (project) {
|
||||
|
||||
// the task object will contain the updated
|
||||
// dates and progress value
|
||||
var end_date = project._end;
|
||||
|
||||
var popUpHTML = '<div class="details-container" style="min-width:600px;"> ';
|
||||
|
||||
if (project.projectName !== undefined) {
|
||||
popUpHTML += '<h3><b>' + project.name + '</b></h3>';
|
||||
}
|
||||
|
||||
popUpHTML += '<h4>' + htmlEntities(project.name) + '</a></h4><br /> ';
|
||||
|
||||
popUpHTML += '</div>';
|
||||
|
||||
return popUpHTML;
|
||||
},
|
||||
on_click: function (project) {
|
||||
//_initModals();
|
||||
},
|
||||
on_date_change: function (project, start, end) {
|
||||
|
||||
var idParts = project.id.split("-");
|
||||
|
||||
let entityId = 0;
|
||||
let entityType = "";
|
||||
|
||||
if (idParts.length > 1) {
|
||||
if (idParts[0] == "ticket") {
|
||||
entityId = idParts[1];
|
||||
entityType = "ticket"
|
||||
} else if (idParts[0] == "pgm") {
|
||||
entityId = idParts[1];
|
||||
entityType = "project"
|
||||
}
|
||||
} else {
|
||||
entityId = idParts;
|
||||
}
|
||||
|
||||
|
||||
if (entityType == "ticket") {
|
||||
leantime.ticketsRepository.updateMilestoneDates(entityId, start, end, project._index+1);
|
||||
} else {
|
||||
leantime.rpc('Projects.Projects.patchProject', {
|
||||
id: entityId,
|
||||
values: {
|
||||
start: start,
|
||||
end: end,
|
||||
sortIndex: project._index + 1,
|
||||
}
|
||||
}).catch(function (e) {
|
||||
jQuery.growl({ message: (e && e.message) ? e.message : leantime.i18n.__("short_notifications.not_saved"), style: "error" });
|
||||
console.error('Could not update project dates', e);
|
||||
});
|
||||
}
|
||||
|
||||
//leantime.ticketsRepository.updateMilestoneDates(task.id, start, end, task._index);
|
||||
//_initModals();
|
||||
|
||||
},
|
||||
on_sort_change: function (projects) {
|
||||
|
||||
var sortPayload = {};
|
||||
|
||||
for (var i = 0; i < projects.length; i++) {
|
||||
sortPayload[projects[i].id] = projects[i]._index+1;
|
||||
}
|
||||
|
||||
leantime.rpc('Projects.Projects.sortProjects', { params: sortPayload })
|
||||
.catch(function (e) {
|
||||
jQuery.growl({ message: (e && e.message) ? e.message : leantime.i18n.__("short_notifications.not_saved"), style: "error" });
|
||||
console.error('Could not sort projects', e);
|
||||
});
|
||||
|
||||
},
|
||||
on_progress_change: function (project, progress) {
|
||||
|
||||
//_initModals();
|
||||
},
|
||||
on_view_change: function (mode) {
|
||||
|
||||
if (ganttInitializing) { return; }
|
||||
leantime.usersRepository.updateUserViewSettings("projectGantt", mode);
|
||||
|
||||
},
|
||||
on_popup_show: function (project) {
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
var gantt_chart = new Gantt(
|
||||
"#gantt",
|
||||
projects,
|
||||
{
|
||||
readonlyGantt: true,
|
||||
resizing: false,
|
||||
progress: false,
|
||||
is_draggable: false,
|
||||
view_modes: ['Day', 'Week', 'Month'],
|
||||
view_mode: viewMode,
|
||||
custom_popup_html: function (project) {
|
||||
|
||||
var popUpHTML = '<div class="details-container" style="min-width:600px;"> ';
|
||||
|
||||
if (project.projectName !== undefined) {
|
||||
popUpHTML += '<h3><b>' + project.name + '</b></h3>';
|
||||
}
|
||||
|
||||
popUpHTML += '<h4>' + htmlEntities(project.name) + '</a></h4><br /> ';
|
||||
|
||||
popUpHTML += '</div>';
|
||||
|
||||
return popUpHTML;
|
||||
},
|
||||
on_click: function (project) {
|
||||
|
||||
},
|
||||
on_date_change: function (project, start, end) {
|
||||
|
||||
|
||||
},
|
||||
on_progress_change: function (project, progress) {
|
||||
|
||||
//_initModals();
|
||||
},
|
||||
on_view_change: function (mode) {
|
||||
|
||||
if (ganttInitializing) { return; }
|
||||
leantime.usersRepository.updateUserViewSettings("projectGantt", mode);
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
jQuery("#ganttTimeControl").on(
|
||||
"click",
|
||||
"a",
|
||||
function () {
|
||||
|
||||
var $btn = jQuery(this);
|
||||
var mode = $btn.attr("data-value");
|
||||
gantt_chart.change_view_mode(mode);
|
||||
$btn.parent().parent().find('a').removeClass('active');
|
||||
$btn.addClass('active');
|
||||
var label = $btn.text();
|
||||
jQuery(".viewText").text(label);
|
||||
}
|
||||
);
|
||||
|
||||
// Constructor already built the chart at the saved viewMode; construction is done,
|
||||
// so from here on real user-driven view changes are allowed to persist.
|
||||
ganttInitializing = false;
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
var setUpKanbanColumns = function () {
|
||||
|
||||
jQuery(document).ready(function () {
|
||||
|
||||
countTickets();
|
||||
jQuery(".filterBar .row-fluid").css("opacity", "1");
|
||||
|
||||
var height = jQuery("html").height() - 250;
|
||||
|
||||
jQuery("#sortableProjectKanban .column .contentInner").each(function () {
|
||||
if (jQuery(this).height() > height) {
|
||||
height = jQuery(this).height();
|
||||
}
|
||||
});
|
||||
height = height + 50;
|
||||
jQuery("#sortableProjectKanban .column .contentInner").css("min-height", height);
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var initProjectsKanban = function (statusList) {
|
||||
|
||||
jQuery("#sortableProjectKanban .projectBox").hover(function () {
|
||||
jQuery(this).css("background", "var(--kanban-card-hover)");
|
||||
},function () {
|
||||
jQuery(this).css("background", "var(--kanban-card-bg)");
|
||||
});
|
||||
|
||||
var position_updated = false;
|
||||
|
||||
jQuery("#sortableProjectKanban .contentInner").sortable({
|
||||
connectWith: ".contentInner",
|
||||
items: "> .moveable",
|
||||
tolerance: 'intersect',
|
||||
placeholder: "ui-state-highlight",
|
||||
forcePlaceholderSize: true,
|
||||
cancel: ".portlet-toggle,:input,a,input",
|
||||
distance: 25,
|
||||
|
||||
start: function (event, ui) {
|
||||
ui.item.addClass('tilt');
|
||||
tilt_direction(ui.item);
|
||||
},
|
||||
stop: function (event, ui) {
|
||||
ui.item.removeClass("tilt");
|
||||
jQuery("html").unbind('mousemove', ui.item.data("move_handler"));
|
||||
ui.item.removeData("move_handler");
|
||||
|
||||
countTickets();
|
||||
|
||||
var sortPayload = {};
|
||||
var handler = ui.item[0].id;
|
||||
|
||||
for (var i = 0; i < statusList.length; i++) {
|
||||
if (jQuery(".contentInner.status_" + statusList[i]).length) {
|
||||
sortPayload[statusList[i]] = jQuery(".contentInner.status_" + statusList[i]).sortable('serialize');
|
||||
}
|
||||
}
|
||||
|
||||
leantime.rpc('Projects.Projects.patchProjectStatusAndSorting', { params: sortPayload, handler: handler })
|
||||
.catch(function (e) {
|
||||
jQuery.growl({ message: (e && e.message) ? e.message : leantime.i18n.__("short_notifications.not_saved"), style: "error" });
|
||||
console.error('Could not update project sorting', e);
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
function tilt_direction(item)
|
||||
{
|
||||
var left_pos = item.position().left,
|
||||
move_handler = function (e) {
|
||||
if (e.pageX >= left_pos) {
|
||||
item.addClass("right");
|
||||
item.removeClass("left");
|
||||
} else {
|
||||
item.addClass("left");
|
||||
item.removeClass("right");
|
||||
}
|
||||
left_pos = e.pageX;
|
||||
};
|
||||
jQuery("html").bind("mousemove", move_handler);
|
||||
item.data("move_handler", move_handler);
|
||||
}
|
||||
|
||||
jQuery(".portlet")
|
||||
.addClass("ui-widget ui-widget-content ui-helper-clearfix ui-corner-all")
|
||||
.find(".portlet-header")
|
||||
.addClass("ui-widget-header ui-corner-all")
|
||||
.prepend("<span class='ui-icon ui-icon-minusthick portlet-toggle'></span>");
|
||||
|
||||
jQuery(".portlet-toggle").click(function () {
|
||||
var icon = jQuery(this);
|
||||
icon.toggleClass("ui-icon-minusthick ui-icon-plusthick");
|
||||
icon.closest(".portlet").find(".portlet-content").toggle();
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var favoriteProject = function(id, element) {
|
||||
|
||||
jQuery(element).addClass("go");
|
||||
if (jQuery(element).hasClass("isFavorite")) {
|
||||
leantime.reactionsController.removeReaction(
|
||||
'project',
|
||||
id,
|
||||
'favorite',
|
||||
function() {
|
||||
jQuery(element).find("i").removeClass("fa-solid").addClass("fa-regular");
|
||||
jQuery(element).removeClass("isFavorite");
|
||||
}
|
||||
);
|
||||
} else {
|
||||
leantime.reactionsController.addReactions(
|
||||
'project',
|
||||
id,
|
||||
'favorite',
|
||||
function() {
|
||||
jQuery(element).find("i").removeClass("fa-regular").addClass("fa-solid");
|
||||
jQuery(element).addClass("isFavorite");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Make public what you want to have public, everything else is private
|
||||
return {
|
||||
initDates:initDates,
|
||||
initProjectTabs:initProjectTabs,
|
||||
initProgressBar:initProgressBar,
|
||||
initProjectTable:initProjectTable,
|
||||
initDuplicateProjectModal:initDuplicateProjectModal,
|
||||
initTodoStatusSortable:initTodoStatusSortable,
|
||||
initSelectFields:initSelectFields,
|
||||
removeStatus:removeStatus,
|
||||
addToDoStatus:addToDoStatus,
|
||||
saveCroppie:saveCroppie,
|
||||
clearCroppie:clearCroppie,
|
||||
readURL:readURL,
|
||||
initGanttChart:initGanttChart,
|
||||
setUpKanbanColumns:setUpKanbanColumns,
|
||||
initProjectsKanban:initProjectsKanban,
|
||||
favoriteProject:favoriteProject
|
||||
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user