Move recent activities to modal (#3864)

* automatically remove deleted timesheets from bookmarks
This commit is contained in:
Kevin Papst
2023-02-22 01:45:40 +01:00
committed by GitHub
parent e7eb89dfd9
commit 1bc1fadc56
16 changed files with 212 additions and 193 deletions

View File

@@ -22,7 +22,6 @@ import KimaiAPI from "./plugins/KimaiAPI";
import KimaiAlternativeLinks from "./plugins/KimaiAlternativeLinks";
import KimaiAjaxModalForm from "./plugins/KimaiAjaxModalForm";
import KimaiActiveRecords from "./plugins/KimaiActiveRecords";
import KimaiRecentActivities from "./plugins/KimaiRecentActivities";
import KimaiEvent from "./plugins/KimaiEvent";
import KimaiAPILink from "./plugins/KimaiAPILink";
import KimaiAlert from "./plugins/KimaiAlert";
@@ -41,6 +40,7 @@ import KimaiCopyDataForm from "./forms/KimaiCopyDataForm";
import KimaiDateNowForm from "./forms/KimaiDateNowForm";
import KimaiNotification from "./plugins/KimaiNotification";
import KimaiHotkeys from "./plugins/KimaiHotkeys";
import KimaiRemoteModal from "./plugins/KimaiRemoteModal";
export default class KimaiLoader {
@@ -82,7 +82,7 @@ export default class KimaiLoader {
kimai.registerPlugin(new KimaiToolbar('form.searchform', 'toolbar-action'));
kimai.registerPlugin(new KimaiAlternativeLinks('.alternative-link'));
kimai.registerPlugin(new KimaiAjaxModalForm('.modal-ajax-form'));
kimai.registerPlugin(new KimaiRecentActivities());
kimai.registerPlugin(new KimaiRemoteModal());
kimai.registerPlugin(new KimaiActiveRecords());
kimai.registerPlugin(new KimaiAPILink('api-link'));
kimai.registerPlugin(new KimaiMultiUpdateTable());

View File

@@ -1,104 +0,0 @@
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/*!
* [KIMAI] KimaiRecentActivities: responsible to reload the users recent activities
*/
import KimaiPlugin from '../KimaiPlugin';
export default class KimaiRecentActivities extends KimaiPlugin {
constructor()
{
super();
this._selector = '.notifications-menu';
}
/**
* @returns {string}
*/
getId()
{
return 'recent-activities';
}
init()
{
const menus = document.querySelectorAll(this._selector);
// the menu can be hidden if user has no permissions to see it
// or no timesheet was recorded yet
if (menus.length === 0 || menus[0].dataset['reload'] === undefined) {
return;
}
const handle = () => {
// TODO this works but using the first menu is not ideal, pass in the reload URL?
this._reloadMenu(menus[0].dataset['reload']);
};
document.addEventListener('kimai.recentActivities', handle);
document.addEventListener('kimai.timesheetUpdate', handle);
document.addEventListener('kimai.timesheetDelete', handle);
document.addEventListener('kimai.activityUpdate', handle);
document.addEventListener('kimai.activityDelete', handle);
document.addEventListener('kimai.projectUpdate', handle);
document.addEventListener('kimai.projectDelete', handle);
document.addEventListener('kimai.customerUpdate', handle);
document.addEventListener('kimai.customerDelete', handle);
this._attachAddRemoveFavorite();
}
/**
* @private
*/
_attachAddRemoveFavorite()
{
[].slice.call(document.querySelectorAll(this._selector + ' a.list-group-item-actions')).map((element) => {
element.addEventListener('click', (event) => {
this._reloadMenu(event.currentTarget.href);
event.preventDefault();
event.stopPropagation();
return false;
});
});
}
/**
* Reload all ercent activities and update the existing menus.
*
* @param {string} url
* @private
*/
_reloadMenu(url)
{
this.fetch(url, {method: 'GET'})
.then(response => {
if (!response.ok) {
return;
}
return response.text().then(html => {
const newFormHtml = document.createElement('div');
newFormHtml.innerHTML = html;
for (let menu of document.querySelectorAll(this._selector)) {
menu.replaceWith(newFormHtml.firstElementChild.cloneNode(true));
}
this._attachAddRemoveFavorite();
});
})
.catch((reason) => {
console.log('Failed to log recent activities', reason);
});
}
}

View File

@@ -0,0 +1,109 @@
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/*!
* [KIMAI] KimaiRecentActivities: responsible to reload the users recent activities
*/
import KimaiPlugin from '../KimaiPlugin';
import { Modal } from 'bootstrap';
export default class KimaiRemoteModal extends KimaiPlugin {
constructor()
{
super();
this._selector = 'a.remote-modal-load';
}
/**
* @returns {string}
*/
getId()
{
return 'remote-modal';
}
init()
{
this.handle = (event) => {
this._showModal(event.currentTarget);
event.stopPropagation();
event.preventDefault();
}
for (let link of document.querySelectorAll(this._selector)) {
link.addEventListener('click', this.handle);
}
document.addEventListener('kimai.closeRemoteModal', () => { this._hide(); });
}
/**
* @param {HTMLElement} element
* @private
*/
_initElement(element)
{
for (let link of element.querySelectorAll('a.remote-modal-reload')) {
link.addEventListener('click', this.handle);
}
}
_hide()
{
this._getModal().hide();
}
_getModalElement()
{
return document.getElementById('remote_modal');
}
/**
* @returns {Modal}
* @private
*/
_getModal()
{
return Modal.getOrCreateInstance(this._getModalElement());
}
/**
* @param {HTMLLinkElement} element
* @private
*/
_showModal(element)
{
this.fetch(element.href, {method: 'GET'})
.then(response => {
if (!response.ok) {
return;
}
return response.text().then(html => {
const newFormHtml = document.createElement('div');
newFormHtml.classList.add('modal-body');
newFormHtml.classList.add('p-0');
newFormHtml.innerHTML = html;
this._initElement(newFormHtml);
const modal = this._getModalElement();
modal.querySelector('.modal-body').replaceWith(newFormHtml);
if (element.dataset['modalTitle'] !== undefined) {
modal.querySelector('.modal-title').textContent = element.dataset['modalTitle'];
}
this._getModal().show();
});
})
.catch((reason) => {
console.log('Failed to load remote modal', reason);
});
}
}

View File

@@ -6,15 +6,6 @@
}
}
@include media-breakpoint-down(sm) {
.notifications-menu .dropdown-menu-card {
width: 100vw;
right: 0;
position: fixed;
top: 56px;
}
}
@media (min-width: 360px) {
.inline-search {
max-width: 235px;