Skip to content

Instantly share code, notes, and snippets.

@vctls
Last active February 8, 2023 15:48
Show Gist options
  • Save vctls/ee8c77a1ec712984e85b247cbf9f6459 to your computer and use it in GitHub Desktop.
Save vctls/ee8c77a1ec712984e85b247cbf9f6459 to your computer and use it in GitHub Desktop.
OpenProject : replace inline editing on click by a standard edit button.
// ==UserScript==
// @name OpenProject Standard Edit
// @namespace http://tampermonkey.net/
// @version 0.9
// @downloadURL https://gist.github.com/vctls/ee8c77a1ec712984e85b247cbf9f6459/raw
// @updateURL https://gist.github.com/vctls/ee8c77a1ec712984e85b247cbf9f6459/raw
// @description Replace inline editing on click in OpenProject by a standard edit button.
// @author vctls
// @match https://*.openproject.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=openproject.com
// @grant none
// ==/UserScript==
'use strict';
const clickHandler = event => {
const target = event.target;
const parent = target.parentElement;
if (
// If the click event is our custom one,
// or it is triggered on one of the editor buttons
// let it pass.
// Otherwise, prevent it from propagating.
// TODO This must have a cleaner solution.
event.custom !== undefined
|| target.tagName === 'A'
|| target.tagName === 'OP-ICON'
|| parent.tagName === 'OP-ICON'
|| (parent.parent && parent.parent.tagName === 'BUTTON')
|| target.classList.contains('editbutton')
// Allow form controls inside an active editor.
|| target.closest('div.inline-edit--container').classList.contains('-active') && (
(target.attributes.type?.nodeValue === "checkbox" ?? false)
|| target.closest('div.document-editor__toolbar')
)
) {
return;
}
event.preventDefault();
event.stopPropagation();
};
const buttonClickHandler = event => {
if (event.custom !== undefined) return;
const target = event.target;
const clickEvent = new MouseEvent('click', {
bubbles: true
});
clickEvent.custom = true;
target.parentElement.querySelector('.-editable').dispatchEvent(clickEvent);
}
function setupEditorButton(editor) {
const button = document.createElement('button');
button.classList.add('editbutton');
button.classList.add('icon-edit'); // Use existing edit icon.
button.classList.add('inplace-edit--controls') // Style it as existing edit controls.
const s = button.style;
// Absolute position does not work well on the "New Task" view,
// but the script isn't really useful there.
s.position = 'absolute';
s.right = '0';
s.top = '0';
s.height = '40px';
s.width = '40px';
editor.append(button);
button.addEventListener('click', buttonClickHandler);
editor.addEventListener(
'click',
clickHandler,
// This third argument is necessary
// in order to capture all events before
// they trigger other event listeners.
true
);
}
function check(changes, observer) {
// Skip irrelevant pages.
// At the moment, only work pacakage editing views should be handled.
const relevantPagesPattern = new RegExp('(?:/projects/\\w+/)?work_packages/\\d+/.*');
if (!window.location.pathname.match(relevantPagesPattern)){
return;
}
// TODO Get the editors from the changelist instead of querying them.
const editors = document.querySelectorAll('op-editable-attribute-field');
editors.forEach(
editor => {
if (
editor !== null
&& editor.querySelector('.subject, .description')
&& !editor.hasButton) {
setupEditorButton(editor);
editor.hasButton = true;
}
}
);
// Automatically dismiss HTTP response failure errors.
const errorToast = document.querySelector('op-toast')
if (errorToast && errorToast.textContent.includes('Http failure response')) {
errorToast.querySelector('button').dispatchEvent(new MouseEvent('click'));
}
}
(function () {
'use strict';
(new MutationObserver(check)).observe(document, {childList: true, subtree: true});
})();
@vctls
Copy link
Author

vctls commented Dec 22, 2022

I didn't like the way OpenProject enables inline editing on every field by default, which is triggered by a single click on the field.
Dragging does not trigger it, but sometimes you want to be able to select stuff with a double or triple click, or you just click on it by mistake.

This script will disable the default behavior and add an edit button next to each of these fields.
image

@vctls
Copy link
Author

vctls commented Jan 20, 2023

Added automatic dismissal of these useless Http failure response error toasts.

@vctls
Copy link
Author

vctls commented Feb 2, 2023

v0.8: Fixed interference with CKEditor controls.

@vctls
Copy link
Author

vctls commented Feb 8, 2023

v0.9: Fixed interference with anchors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment