@atlaskit/editor-plugin-tasks-and-decisions
Version:
Tasks and decisions plugin for @atlaskit/editor-core
170 lines (165 loc) • 6.83 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import { bindAll } from 'bind-event-listener';
import { SetAttrsStep } from '@atlaskit/adf-schema/steps';
import { tasksAndDecisionsMessages } from '@atlaskit/editor-common/messages';
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { openRequestEditPopupAt } from '../pm-plugins/helpers';
import { taskItemToDom } from './taskItemNodeSpec';
import { isContentEmpty } from './utils';
export class TaskItemNodeView {
constructor(node, view, getPos, {
api,
placeholder,
intl
}) {
_defineProperty(this, "handleOnClick", event => {
var _this$api, _this$api$taskDecisio, _this$api$taskDecisio2;
if (!((_this$api = this.api) !== null && _this$api !== void 0 && (_this$api$taskDecisio = _this$api.taskDecision) !== null && _this$api$taskDecisio !== void 0 && (_this$api$taskDecisio2 = _this$api$taskDecisio.sharedState.currentState()) !== null && _this$api$taskDecisio2 !== void 0 && _this$api$taskDecisio2.hasEditPermission)) {
event.stopImmediatePropagation();
event.preventDefault();
const pos = this.getPos();
if (typeof pos === 'number') {
openRequestEditPopupAt(this.view, pos);
}
return;
}
});
_defineProperty(this, "handleOnChange", () => {
var _this$api2;
const {
tr
} = this.view.state;
const nodePos = this.getPos();
if (typeof nodePos !== 'number') {
return;
}
const {
localId,
state
} = this.node.attrs;
const isDone = state === 'DONE';
const nextState = isDone ? 'TODO' : 'DONE';
const currentTaskDecisionState = (_this$api2 = this.api) === null || _this$api2 === void 0 ? void 0 : _this$api2.taskDecision.sharedState.currentState();
// logic is inspired from packages/elements/task-decision/src/components/ResourcedTaskItem.tsx
const objectAri = this.getObjectAri();
if (currentTaskDecisionState !== null && currentTaskDecisionState !== void 0 && currentTaskDecisionState.taskDecisionProvider && objectAri) {
currentTaskDecisionState.taskDecisionProvider.toggleTask({
localId,
objectAri
}, nextState);
}
// SetAttrsStep should be used to prevent task updates from being dropped when mapping task ticks
// from a previous version of the document, such as a published page.
tr.step(new SetAttrsStep(nodePos, {
state: nextState,
localId: localId
}));
tr.setMeta('scrollIntoView', false);
const taskItemInfoMeta = {
checkState: nextState,
from: nodePos,
to: nodePos + this.node.nodeSize
};
tr.setMeta('taskItemInfo', taskItemInfoMeta);
this.view.dispatch(tr);
});
this.node = node;
this.view = view;
this.getPos = getPos;
this.intl = intl;
this.api = api;
this.view = view;
const domPlaceholder = placeholder !== null && placeholder !== void 0 ? placeholder : this.intl.formatMessage(tasksAndDecisionsMessages.taskPlaceholder);
const {
dom,
contentDOM
} = DOMSerializer.renderSpec(document, taskItemToDom(node, domPlaceholder, intl));
this.dom = dom;
this.contentDOM = contentDOM;
this.domElement = this.dom instanceof HTMLElement ? this.dom : undefined;
if (this.domElement) {
this.input = this.domElement.querySelector('input[type="checkbox"]');
this.unbindInputDom = bindAll(this.input, [{
type: 'click',
listener: this.handleOnClick
}, {
type: 'change',
listener: this.handleOnChange
}]);
}
}
getContextIdentifierProvider() {
var _this$api3, _this$api3$contextIde, _this$api3$contextIde2;
return (_this$api3 = this.api) === null || _this$api3 === void 0 ? void 0 : (_this$api3$contextIde = _this$api3.contextIdentifier) === null || _this$api3$contextIde === void 0 ? void 0 : (_this$api3$contextIde2 = _this$api3$contextIde.sharedState.currentState()) === null || _this$api3$contextIde2 === void 0 ? void 0 : _this$api3$contextIde2.contextIdentifierProvider;
}
getObjectAri() {
const provider = this.getContextIdentifierProvider();
if (provider) {
return provider.objectId;
}
return undefined;
}
isContentEmpty(node) {
return node.content.childCount === 0;
}
// Update the placeholder visibility based on content
updatePlaceholder(node) {
let currentIsContentEmpty = this.isContentEmpty(node);
if (expValEquals('platform_editor_blocktaskitem_node_tenantid', 'isEnabled', true)) {
currentIsContentEmpty = isContentEmpty(node);
}
if (currentIsContentEmpty !== this.emptyContent) {
var _this$contentDOM;
this.emptyContent = currentIsContentEmpty;
(_this$contentDOM = this.contentDOM) === null || _this$contentDOM === void 0 ? void 0 : _this$contentDOM.toggleAttribute('data-empty', currentIsContentEmpty);
}
}
update(node) {
if (!expValEquals('platform_editor_prevent_taskitem_remount', 'isEnabled', true)) {
const isValidUpdate = node.type === this.node.type && !!(node.attrs.state === this.node.attrs.state);
if (!isValidUpdate) {
return false;
}
}
// Only return false if this is a completely different task
if (this.node.attrs.localId !== node.attrs.localId) {
return false;
}
if (expValEquals('platform_editor_prevent_taskitem_remount', 'isEnabled', true)) {
if (node.type !== this.node.type) {
return false;
}
const stateChanged = node.type === this.node.type && !!(node.attrs.state !== this.node.attrs.state);
// Update task checkbox state to match document state.
// It's possible the state may have changed from a collab edit and not from a checkbox click
// so we need to update the checkbox to match.
if (stateChanged && this.input) {
this.input.checked = node.attrs.state === 'DONE';
}
}
this.updatePlaceholder(node);
if (this.domElement && !node.sameMarkup(this.node)) {
this.domElement.setAttribute('data-task-state', node.attrs.state);
this.domElement.setAttribute('data-task-local-id', node.attrs.localId);
this.domElement.setAttribute('state', node.attrs.state);
}
this.node = node;
return true;
}
ignoreMutation(mutation) {
if (!this.contentDOM) {
return true;
}
return !this.contentDOM.contains(mutation.target) && mutation.type !== 'selection';
}
destroy() {
if (this.unbindInputDom) {
this.unbindInputDom();
}
this.contentDOM = undefined;
this.input = undefined;
this.emptyContent = undefined;
this.api = undefined;
}
}