first commit
This commit is contained in:
95
admin/static/llm-modal/index.tsx
Normal file
95
admin/static/llm-modal/index.tsx
Normal file
@@ -0,0 +1,95 @@
|
||||
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',
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user