Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
300 changes: 280 additions & 20 deletions dist/doboard-widget-bundle.js

Large diffs are not rendered by default.

32 changes: 27 additions & 5 deletions dist/doboard-widget-bundle.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/doboard-widget-bundle.min.js.map

Large diffs are not rendered by default.

131 changes: 131 additions & 0 deletions js/src/handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -470,3 +470,134 @@ function getSafeUrl(url) {
return '#';
}

function initSpotfixWidget({horizontalPosition}) {
const spotfixWrapedWidget = document.querySelector('.doboard_task_widget-wrap');
if (!spotfixWrapedWidget) return () => {};

const state = {
isDragging: false,
hasDragged: false,
startY: 0,
startBottom: 0,
};

const controller = new AbortController();
const signal = controller.signal;

setupBaseWidgetStyles(spotfixWrapedWidget, signal);
restoreWidgetPosition(spotfixWrapedWidget, 'doboardWidgetPosBottom');

const dragHandle = createDragHandle({widget: spotfixWrapedWidget, horizontalPosition});

setupHoverEffects(spotfixWrapedWidget, dragHandle, state, signal);
setupDragAndDropEvents(spotfixWrapedWidget, dragHandle, state, 'doboardWidgetPosBottom', signal);

return function destroy() {
controller.abort();
dragHandle.remove();
};
}

function setupBaseWidgetStyles(widget, signal) {
widget.style.position = 'fixed';
widget.style.top = 'auto';
widget.style.cursor = 'pointer';
widget.style.userSelect = 'none';

widget.addEventListener('dragstart', (e) => e.preventDefault(), { signal });
}

function restoreWidgetPosition(widget, storageKey) {
const savedBottom = localStorage.getItem(storageKey);
if (savedBottom && savedBottom !== 'NaNpx') {
widget.style.bottom = savedBottom;
}
}

function createDragHandle({widget, horizontalPosition}) {
const dragHandle = document.createElement('div');
dragHandle.classList.add(horizontalPosition === 'left' ? 'spotfix-draganddrop-trigger-left' : 'spotfix-draganddrop-trigger');
dragHandle.innerHTML = `<img src='${SpotFixSVGLoader.getAsDataURI('iconDragAndDrop')}'/>`;

widget.appendChild(dragHandle);
return dragHandle;
}

function setupHoverEffects(widget, dragHandle, state, signal) {
widget.addEventListener('mouseenter', () => {
dragHandle.style.opacity = '1';
}, { signal });

widget.addEventListener('mouseleave', () => {
if (!state.isDragging) {
dragHandle.style.opacity = '0';
}
}, { signal });
}

function setupDragAndDropEvents(widget, dragHandle, state, storageKey, signal) {
widget.addEventListener('mousedown', () => {
state.hasDragged = false;
}, { signal });

dragHandle.addEventListener('mousedown', (e) => {
if (e.button !== 0) return;
e.stopPropagation();

state.isDragging = true;
state.hasDragged = false;
state.startY = e.clientY;

const computedStyle = window.getComputedStyle(widget);
state.startBottom = parseFloat(computedStyle.bottom) || 0;

widget.style.top = 'auto';
widget.style.margin = '0';
widget.style.transform = 'none';
dragHandle.style.cursor = 'grabbing';
}, { signal });

document.addEventListener('mousemove', (e) => {
if (!state.isDragging) return;

const deltaY = e.clientY - state.startY;
if (Math.abs(deltaY) > 3) {
state.hasDragged = true;
}

let newBottom = state.startBottom - deltaY;
const maxBottom = window.innerHeight - widget.offsetHeight;

if (newBottom < 0) newBottom = 0;
if (newBottom > maxBottom) newBottom = maxBottom;

widget.style.bottom = newBottom + 'px';
}, { signal });

const stopDrag = () => {
if (state.isDragging) {
state.isDragging = false;
dragHandle.style.cursor = '';

if (!widget.matches(':hover')) {
dragHandle.style.opacity = '0';
}

localStorage.setItem(storageKey, widget.style.bottom);

setTimeout(() => {
state.hasDragged = false;
}, 50);
}
};

document.addEventListener('mouseup', stopDrag, { signal });
document.addEventListener('mouseleave', stopDrag, { signal });

Comment thread
veronika-tseleva-cleantalk marked this conversation as resolved.
widget.addEventListener('click', (e) => {
if (state.hasDragged) {
e.preventDefault();
e.stopPropagation();
}
}, { capture: true, signal });
}
3 changes: 3 additions & 0 deletions js/src/iframe/MessageEditorIframe.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ class MessageEditorIframe {
targetElement.value = data.content;
targetElement.dispatchEvent(new Event('change', {bubbles: true}));
}
if (this.handlers && this.handlers.onChange) {
this.handlers.onChange(data.content);
}
break;
case 'spotfix:tinymce-action':
this.handleEditorAction(data);
Expand Down
16 changes: 16 additions & 0 deletions js/src/loaders/SpotFixSVGLoader.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 15 additions & 1 deletion js/src/loaders/SpotFixTemplatesLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,19 @@ class SpotFixTemplatesLoader {
</label>
</div>
</div>
<div class="doboard_task_widget-user_menu-item" style="padding-right: 12px">
<img src="{{iconTwoSidesArrows}}" alt="" style="margin-right: 12px">
<div style="display: flex; justify-content: space-between; flex-grow: 1; align-items: center">
<span style="display: inline-flex; padding-top: 4px">
<span style="font-weight: 500; font-size: 14px; color: #252A2F; margin-bottom: 4px">
Show widget on screen side</span>
</span>
<div style="padding-right: 16px; display: flex">
<button id="spotfix_widget-task-menu_left" type="button">Left</button>
<button id="spotfix_widget-task-menu_right" style="margin-left: 16px" type="button">Right</button>
</div>
</div>
</div>
<div class="doboard_task_widget-user_menu-item" style="display: none">
<span id="doboard_task_widget-user_menu-logout_button">
<img src="{{iconDoor}}" alt="" style="margin-right: 12px; cursor: pointer">
Expand Down Expand Up @@ -479,7 +492,8 @@ class SpotFixTemplatesLoader {

static wrap_review() {
return `
<button id="doboard_task_widget_button" class="doboard_task_widget-wrap wrap_review" style="bottom: {{position}};">
<button id="doboard_task_widget_button" class="doboard_task_widget-wrap wrap_review"
style="bottom: {{position}}; background-color: rgba(255,255,255,.9) !important;">
<img src="{{iconMarker}}" />
<span id="review_content_button_text">Review content</span>
</button>`;
Expand Down
12 changes: 8 additions & 4 deletions js/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ document.addEventListener('selectionchange', function(e) {

if ( selectedData ) {
// spotFixOpenWidget(selectedData, 'create_issue');
spotFixOpenWidget(selectedData, 'wrap_review');
const timer = setTimeout(() => {
clearTimeout(timer);
spotFixOpenWidget(selectedData, 'wrap');
}, 3000);
spotFixOpenWidget(selectedData, 'wrap_review', timer);
Comment thread
veronika-tseleva-cleantalk marked this conversation as resolved.
}
}
}, SPOTFIX_SHOW_DELAY);
Expand Down Expand Up @@ -120,9 +124,9 @@ function spotFixIsInsideWidget(node) {
* @param {*} selectedData
* @param {*} type
*/
function spotFixOpenWidget(selectedData, type) {
function spotFixOpenWidget(selectedData, type, timerToOpenWrap) {
if (selectedData) {
new CleanTalkWidgetDoboard(selectedData, type);
new CleanTalkWidgetDoboard(selectedData, type, timerToOpenWrap);
}
}

Expand Down Expand Up @@ -266,7 +270,7 @@ function isAnyTaskUpdated(allTasksData) {
if (
currentStateOfTask.taskId &&
currentStateOfTask.taskLastUpdate &&
currentStateOfTask.taskCreatorTaskUser.toString() === issuerId.toString()
currentStateOfTask?.taskCreatorTaskUser?.toString() === issuerId?.toString()
) {
result = storageCheckTaskUpdate(currentStateOfTask.taskId, currentStateOfTask.taskLastUpdate);
if (result) {
Expand Down
Loading
Loading