Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
14e45e9
Move action-list from icingadb-web as is
sukhwinder33445 Jun 26, 2024
1dd04ff
ActionList: Make it stand alone widget
sukhwinder33445 Jun 26, 2024
ab0fcf2
ActionList: Define const `listIdentifier` and `listItemIdentifier` va…
sukhwinder33445 Jun 26, 2024
5220cc7
ActionList: First search for the action-list in the focussed container
sukhwinder33445 Jun 27, 2024
c50c2a6
ActionList: remove click selector `not(.page-selector)`
sukhwinder33445 Jun 27, 2024
92caf69
ActionList: OnKeyDown: find next selectable list item based on data-attr
sukhwinder33445 Jun 27, 2024
c507070
ActionList: dont select lastActivated as fallback
sukhwinder33445 Jun 27, 2024
b99a738
ActionList: Remove load-more functionality
sukhwinder33445 Jun 27, 2024
911c055
ActionList: getDirectionalNext: return only selectable next item or n…
sukhwinder33445 Jun 27, 2024
84f63e2
ActionList: Simplify code
sukhwinder33445 Jun 27, 2024
5788d63
ActionList: Load items properly after auto/manual page refresh
sukhwinder33445 Jul 1, 2024
44889d9
ActionList: Unbind the keydown event listner properly
sukhwinder33445 Jul 4, 2024
ea11f58
ActionList: Introduce event `selection-start` and `selection-end`
sukhwinder33445 Jul 4, 2024
ee64395
ActionList: load(): Clear known selection if no detail url given
sukhwinder33445 Jul 16, 2024
d4d94ad
ActionList: Rename `notJquery` to `$`
sukhwinder33445 Jul 16, 2024
21273f3
ActionList: Introduce the `processing` property with getter/setter
sukhwinder33445 Jul 18, 2024
2fd0de1
Introduce `ActionListBehavior`
sukhwinder33445 Jul 18, 2024
976c70b
Add `LoadMore` and `LoadMoreBehavior`
sukhwinder33445 Jul 18, 2024
d93babd
ActionList: Remove special handeling for `.dashboard`
sukhwinder33445 Jul 18, 2024
d0c5c4f
ActionList: Let the ActionList know if it is the primary list
sukhwinder33445 Jul 18, 2024
6a55958
ActionListBehavior: Don't return before creating actionLists on #col2
sukhwinder33445 Jul 19, 2024
b6b4ec0
ActionListBehavior: getActionLists(): Return #col1 lists if no param …
sukhwinder33445 Jul 19, 2024
f61332a
ActionList: Add class ptoperty `isMultiSelectable`
sukhwinder33445 Jul 19, 2024
47675ed
ActionList: Add footer count only to primary lists
sukhwinder33445 Jul 19, 2024
d753e6f
ActionListBehavior: Set processing to false when the req is cancelled
sukhwinder33445 Jul 19, 2024
4a0d7fe
ActionList: Don't navigate if only `a` is pressed
sukhwinder33445 Jul 19, 2024
2e57d74
ActionList: getDirectionNext(): Return list's first/last elem if null…
sukhwinder33445 Jul 29, 2024
4975053
ActionList: Simplify code
sukhwinder33445 Jul 29, 2024
11df169
ActionList: Use bool `isArrowUp` param instead event.key
sukhwinder33445 Jul 30, 2024
0fdf274
ActionList: Take items with css propery `display:contents` into account
sukhwinder33445 Jul 30, 2024
4d29138
ActionList: load(): Scroll active item into view
sukhwinder33445 Jul 30, 2024
b60b125
(ActionList|LoadMore)Behavior: Require `EventListener` instead of `Ic…
sukhwinder33445 Nov 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 208 additions & 0 deletions asset/js/compat/ActionListBehavior.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
define(["../widget/ActionList", "icinga/legacy-app/EventListener"],function (ActionList, EventListener) {

"use strict";

class ActionListBehavior extends EventListener {
constructor(icinga) {
super(icinga);

this.on('beforerender', '#main > .container', this.onBeforeRender, this);
this.on('rendered', '#main > .container', this.onRendered, this);
this.on('close-column', '#main > #col2', this.onColumnClose, this);
this.on('column-moved', this.onColumnMoved, this);
this.on('selection-start', this.onSelectionStart, this);
this.on('selection-end', this.onSelectionEnd, this);
this.on('all-deselected', this.allDeselected, this);

/**
* Action lists
*
* @type {WeakMap<object, ActionList>}
* @private
*/
this._actionLists = new WeakMap();

/**
* Cached action lists
*
* Holds values only during the time between `beforerender` and `rendered`
*
* @type {{}}
* @private
*/
this._cachedActionLists = {};
}

/**
* @param event
* @param content
* @param action
* @param autorefresh
* @param scripted
*/
onBeforeRender(event, content, action, autorefresh, scripted) {
if (! autorefresh) {
return;
}

let _this = event.data.self;
let lists = _this.getActionLists(event.target)

// Remember current instances
lists.forEach((list) => {
let actionList = _this._actionLists.get(list);
if (actionList) {
_this._cachedActionLists[_this.icinga.utils.getDomPath(list).join(' > ')] = actionList;
}
});
}

/**
* @param event
* @param autorefresh
* @param scripted
*/
onRendered(event, autorefresh, scripted) {
let _this = event.data.self;
let container = event.target;
let detailUrl = _this.getDetailUrl();

if (autorefresh) {
// Apply remembered instances
for (let listPath in _this._cachedActionLists) {
let actionList = _this._cachedActionLists[listPath];
let list = container.querySelector(listPath);
if (list !== null) {
actionList.refresh(list, detailUrl);
_this._actionLists.set(list, actionList);
} else {
actionList.destroy();
}

delete _this._cachedActionLists[listPath];
}
}

let lists = _this.getActionLists(event.currentTarget);
lists.forEach(list => {
let actionList = _this._actionLists.get(list);
if (! actionList) {
let isPrimary = list.parentElement.matches('#main > #col1 > .content');
actionList = (new ActionList(list, isPrimary)).bind();
actionList.load(detailUrl);

_this._actionLists.set(list, actionList);
} else {
actionList.load(detailUrl); // navigated back to the same page
}
});

if (event.target.id === 'col2') { // navigated back/forward and the detail url is changed
let lists = _this.getActionLists();
lists.forEach(list => {
let actionList = _this._actionLists.get(list);

if (actionList) {
actionList.load(detailUrl);
}
});
}
}

onColumnClose(event)
{
let _this = event.data.self;
let lists = _this.getActionLists();
lists.forEach((list) => {
let actionList = _this._actionLists.get(list);
if (actionList) {
actionList.load();
}
});
}

/**
* Triggers when column is moved to left or right
*
* @param event
* @param sourceId The content is moved from
*/
onColumnMoved(event, sourceId) {
if (event.target.id === 'col2' && sourceId === 'col1') { // only for browser-back (col1 shifted to col2)
let _this = event.data.self;
let lists = _this.getActionLists(event.target);
lists.forEach((list) => {
let actionList = _this._actionLists.get(list);
if (actionList) {
actionList.load();
}
});
}
}

/**
* Selection started and in process
*
* @param event
*/
onSelectionStart(event) {
const container = event.target.closest('.container');
container.dataset.suspendAutorefresh = '';
}

/**
* Triggers when selection ends, the url can be loaded now
* @param event
*/
onSelectionEnd(event) {
let _this = event.data.self;

let req = _this.icinga.loader.loadUrl(
event.detail.url,
_this.icinga.loader.getLinkTargetFor($(event.target.firstChild))
);

req.always((_, __, errorThrown) => {

if (errorThrown !== 'abort') {
delete event.target.closest('.container').dataset.suspendAutorefresh;
event.detail.actionList.setProcessing(false);
}
});
}

allDeselected(event) {
let _this = event.data.self;
if (_this.icinga.loader.getLinkTargetFor($(event.target), false).attr('id') === 'col2') {
_this.icinga.ui.layout1col();
_this.icinga.history.pushCurrentState();
delete event.target.closest('.container').dataset.suspendAutorefresh;
}
}

getDetailUrl() {
return this.icinga.utils.parseUrl(
this.icinga.history.getCol2State().replace(/^#!/, '')
);
}

/**
* Get action lists from the given element
*
* If element is not provided, all action lists from col1 will be returned
*
* @param element
*
* @return NodeList
*/
getActionLists(element = null) {
if (element === null) {
return document.querySelectorAll('#col1 [data-interactable-action-list]');
}

return element.querySelectorAll('[data-interactable-action-list]');
}
}

return ActionListBehavior;
});
84 changes: 84 additions & 0 deletions asset/js/compat/LoadMoreBehavior.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
define(["../widget/LoadMore", "icinga/legacy-app/EventListener"],function (LoadMore, EventListener) {

"use strict";

class LoadMoreBehavior extends EventListener {
constructor(icinga) {
super(icinga);

this.on('rendered', '#main > .container', this.onRendered, this);
this.on('load', this.onLoad, this);

/**
* Load More elements
*
* @type {WeakMap<object, LoadMore>}
* @private
*/
this._loadMoreElements = new WeakMap();
}

/**
* @param event
*/
onRendered(event)
{
let _this = event.data.self;

event.currentTarget.querySelectorAll('.load-more').forEach(element => {
_this._loadMoreElements.set(element, new LoadMore(element));
});
}

onLoad(event) {
let _this = event.data.self;
let anchor = event.target;
let showMore = anchor.parentElement;
var progressTimer = _this.icinga.timer.register(function () {
var label = anchor.innerText;

var dots = label.substr(-3);
if (dots.slice(0, 1) !== '.') {
dots = '. ';
} else {
label = label.slice(0, -3);
if (dots === '...') {
dots = '. ';
} else if (dots === '.. ') {
dots = '...';
} else if (dots === '. ') {
dots = '.. ';
}
}

anchor.innerText = label + dots;
}, null, 250);

let url = anchor.getAttribute('href');

let req = _this.icinga.loader.loadUrl(
// Add showCompact, we don't want controls in paged results
_this.icinga.utils.addUrlFlag(url, 'showCompact'),
$(showMore.parentElement),
undefined,
undefined,
'append',
false,
progressTimer
);
req.addToHistory = false;
req.done(function () {
showMore.remove();

// Set data-icinga-url to make it available for Icinga.History.getCurrentState()
req.$target.closest('.container').data('icingaUrl', url);

_this.icinga.history.replaceCurrentState();
});

return req;
}
}

return LoadMoreBehavior;
});
Loading
Loading