96 lines
2.9 KiB
TypeScript
96 lines
2.9 KiB
TypeScript
import React from 'react';
|
|
import ReactDOM from 'react-dom/client';
|
|
|
|
import { ILlmActionRequest, ILlmInitAction, ModalDisplayStyle } from './common/interfaces';
|
|
import { App } from './App';
|
|
import { getTargetText, isTargetCkeditor, setTargetText } from './common/textUtil';
|
|
import { getPromptStreamResponse } from './common/adminApiUtil';
|
|
|
|
// Store the React root globally to avoid remounting
|
|
let modalRoot: ReactDOM.Root | null = null;
|
|
|
|
export const initModal = (action: ILlmInitAction) => {
|
|
// Find the modal container
|
|
const modalContainer: Element | null = document.querySelector('[data-wpj-modal-mount]');
|
|
|
|
if (!modalContainer) {
|
|
console.error('Modal container with [data-wpj-modal-mount] not found.');
|
|
return;
|
|
}
|
|
|
|
// Create a root if it doesn't exist
|
|
if (!modalRoot) {
|
|
modalRoot = ReactDOM.createRoot(modalContainer);
|
|
}
|
|
|
|
const dataAttr = modalContainer.getAttribute('data-wpj-modal-mount');
|
|
const displayStyle = (dataAttr ? dataAttr : 'modal') as ModalDisplayStyle;
|
|
// Render modal with updated data
|
|
modalRoot.render(
|
|
// <React.StrictMode>
|
|
<App close={closeModal} llmAction={action} displayStyle={displayStyle} />,
|
|
// </React.StrictMode>,
|
|
);
|
|
};
|
|
|
|
let applyGlobalAbort: ((reason?: string) => void) | null = null;
|
|
|
|
export const applyAction = (action: ILlmInitAction, buttonId?: string) => {
|
|
const body: ILlmActionRequest = {
|
|
...action,
|
|
text: getTargetText(action.target),
|
|
};
|
|
|
|
const buttonEl = document.getElementById(buttonId ?? '');
|
|
buttonEl?.classList.add('is-submitting');
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
applyGlobalAbort && applyGlobalAbort('applyUser');
|
|
applyGlobalAbort = null;
|
|
|
|
let result = '';
|
|
|
|
// throttle update interval, because ckeditor behaves weirdly when update interval is too fast
|
|
let updateInterval: any = null;
|
|
|
|
updateInterval =
|
|
isTargetCkeditor(action.target) &&
|
|
setInterval(() => {
|
|
setTargetText(action.target, result);
|
|
}, 700);
|
|
const request = getPromptStreamResponse(body, (partialResponse) => {
|
|
result = partialResponse;
|
|
!isTargetCkeditor(action.target) && setTargetText(action.target, result);
|
|
});
|
|
applyGlobalAbort = request.abort;
|
|
request.promise
|
|
.then(() => {
|
|
setTargetText(action.target, result);
|
|
buttonEl?.classList.remove('is-submitting');
|
|
})
|
|
.catch((reason) => {
|
|
if (reason !== 'applyUser') {
|
|
buttonEl?.classList.remove('is-submitting');
|
|
}
|
|
})
|
|
.finally(() => {
|
|
updateInterval && clearInterval(updateInterval);
|
|
});
|
|
};
|
|
|
|
export const cancelAction = () => {
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
applyGlobalAbort && applyGlobalAbort();
|
|
applyGlobalAbort = null;
|
|
};
|
|
|
|
export function closeModal() {
|
|
if (modalRoot) {
|
|
modalRoot.unmount();
|
|
modalRoot = null;
|
|
window.parent.postMessage({
|
|
event: 'llm-modal-closed',
|
|
});
|
|
}
|
|
}
|