mirror of
https://github.com/ONLYOFFICE/onlyoffice.github.io.git
synced 2026-04-07 14:04:30 +08:00
select type in custom assistant
This commit is contained in:
@ -37,7 +37,10 @@
|
|||||||
<script type="text/javascript" src="https://onlyoffice.github.io/sdkjs-plugins/v1/plugins.js"></script>
|
<script type="text/javascript" src="https://onlyoffice.github.io/sdkjs-plugins/v1/plugins.js"></script>
|
||||||
<script type="text/javascript" src="https://onlyoffice.github.io/sdkjs-plugins/v1/plugins-ui.js"></script>
|
<script type="text/javascript" src="https://onlyoffice.github.io/sdkjs-plugins/v1/plugins-ui.js"></script>
|
||||||
<link rel="stylesheet" href="https://onlyoffice.github.io/sdkjs-plugins/v1/plugins.css">
|
<link rel="stylesheet" href="https://onlyoffice.github.io/sdkjs-plugins/v1/plugins.css">
|
||||||
|
<link rel="stylesheet" href="vendor/select2-4.0.6-rc.1/dist/css/select2.css"/>
|
||||||
<link rel="stylesheet" href="./resources/styles/customAssistant.css">
|
<link rel="stylesheet" href="./resources/styles/customAssistant.css">
|
||||||
|
<script src="vendor/jquery/jquery-3.7.1.min.js"></script>
|
||||||
|
<script src="vendor/select2-4.0.6-rc.1/dist/js/select2.js"></script>
|
||||||
<script type="text/javascript" src="scripts/utils/theme.js" defer></script>
|
<script type="text/javascript" src="scripts/utils/theme.js" defer></script>
|
||||||
<script type="text/javascript" src="scripts/customAssistant.js" defer></script>
|
<script type="text/javascript" src="scripts/customAssistant.js" defer></script>
|
||||||
</head>
|
</head>
|
||||||
@ -52,6 +55,7 @@
|
|||||||
<input type="hidden" id="input_prompt_id" value="" />
|
<input type="hidden" id="input_prompt_id" value="" />
|
||||||
<input type="text" id="input_prompt_name" class="form-control i18n" maxlength="30"
|
<input type="text" id="input_prompt_name" class="form-control i18n" maxlength="30"
|
||||||
placeholder="Assistant's name" spellcheck="false" required />
|
placeholder="Assistant's name" spellcheck="false" required />
|
||||||
|
<select id="assistantType" class="form-control" title="Type"></select>
|
||||||
<textarea id="input_prompt" rows="1" class="form-control i18n" placeholder="Enter your query here..."
|
<textarea id="input_prompt" rows="1" class="form-control i18n" placeholder="Enter your query here..."
|
||||||
spellcheck="false" required></textarea>
|
spellcheck="false" required></textarea>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -56,7 +56,9 @@
|
|||||||
<script type="text/javascript" src="scripts/text-annotations/text-annotator.js"></script>
|
<script type="text/javascript" src="scripts/text-annotations/text-annotator.js"></script>
|
||||||
<script type="text/javascript" src="scripts/text-annotations/spelling.js"></script>
|
<script type="text/javascript" src="scripts/text-annotations/spelling.js"></script>
|
||||||
<script type="text/javascript" src="scripts/text-annotations/grammar.js"></script>
|
<script type="text/javascript" src="scripts/text-annotations/grammar.js"></script>
|
||||||
<script type="text/javascript" src="scripts/text-annotations/custom-assistant.js"></script>
|
<script type="text/javascript" src="scripts/custom-annotations/annotation-popup.js" defer></script>
|
||||||
|
<script type="text/javascript" src="scripts/custom-annotations/assistant.js" defer></script>
|
||||||
|
<script type="text/javascript" src="scripts/custom-annotations/custom-annotator.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="scripts/generate.js"></script>
|
<script type="text/javascript" src="scripts/generate.js"></script>
|
||||||
<script type="text/javascript" src="scripts/code.js"></script>
|
<script type="text/javascript" src="scripts/code.js"></script>
|
||||||
|
|||||||
@ -0,0 +1,204 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright Ascensio System SIA 2010-2025
|
||||||
|
*
|
||||||
|
* This program is a free software product. You can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||||
|
* version 3 as published by the Free Software Foundation. In accordance with
|
||||||
|
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||||||
|
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||||||
|
* of any third-party rights.
|
||||||
|
*
|
||||||
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||||||
|
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
*
|
||||||
|
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||||||
|
* street, Riga, Latvia, EU, LV-1050.
|
||||||
|
*
|
||||||
|
* The interactive user interfaces in modified source and object code versions
|
||||||
|
* of the Program must display Appropriate Legal Notices, as required under
|
||||||
|
* Section 5 of the GNU AGPL version 3.
|
||||||
|
*
|
||||||
|
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||||||
|
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||||||
|
* grant you any rights under trademark law for use of our trademarks.
|
||||||
|
*
|
||||||
|
* All the Product's GUI elements, including illustrations and icon sets, as
|
||||||
|
* well as technical writing content are licensed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||||||
|
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
function CustomAnnotationPopup()
|
||||||
|
{
|
||||||
|
this.popup = null;
|
||||||
|
this.type = 0; // 0 - spelling, 1 - grammar
|
||||||
|
this.paraId = -1;
|
||||||
|
this.rangeId = -1;
|
||||||
|
|
||||||
|
this.content = "";
|
||||||
|
this.width = 318;
|
||||||
|
this.height = 500;
|
||||||
|
|
||||||
|
this.open = function(type, paraId, rangeId, data)
|
||||||
|
{
|
||||||
|
if (this.popup && 0 === this.type && 1 === type)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
this._calculateWindowSize(data);
|
||||||
|
return this._open(type, paraId, rangeId);
|
||||||
|
};
|
||||||
|
|
||||||
|
this._open = function(type, paraId, rangeId)
|
||||||
|
{
|
||||||
|
if (this.type === type
|
||||||
|
&& rangeId === this.rangeId
|
||||||
|
&& paraId === this.paraId)
|
||||||
|
return this.popup;
|
||||||
|
|
||||||
|
this.type = type;
|
||||||
|
this.paraId = paraId;
|
||||||
|
this.rangeId = rangeId;
|
||||||
|
|
||||||
|
if (this.popup)
|
||||||
|
this.popup.close();
|
||||||
|
|
||||||
|
let variation = {
|
||||||
|
url : 'annotationPopup.html',
|
||||||
|
isVisual : true,
|
||||||
|
buttons : this._getButtons(),
|
||||||
|
isModal : false,
|
||||||
|
description: this._getTitle(),
|
||||||
|
EditorsSupport : ["word", "slide", "cell", "pdf"],
|
||||||
|
size : [this.width, this.height],
|
||||||
|
fixedSize : true,
|
||||||
|
isTargeted : true
|
||||||
|
};
|
||||||
|
let popup = new window.Asc.PluginWindow();
|
||||||
|
|
||||||
|
let _t = this;
|
||||||
|
popup.attachEvent("onWindowReady", function() {
|
||||||
|
let name2color = {
|
||||||
|
"theme-light": "#F62211",
|
||||||
|
"theme-classic-light": "#D9534F",
|
||||||
|
|
||||||
|
"theme-dark": "#F62211",
|
||||||
|
"theme-contrast-dark": "#F62211",
|
||||||
|
|
||||||
|
"theme-gray": "#F62211",
|
||||||
|
|
||||||
|
"theme-white": "#F23D3D",
|
||||||
|
"theme-night": "#F23D3D"
|
||||||
|
};
|
||||||
|
let type2color = {
|
||||||
|
"light": "#F62211",
|
||||||
|
"dark": "#F62211"
|
||||||
|
};
|
||||||
|
|
||||||
|
let color = type2color["light"];
|
||||||
|
if (window.Asc.plugin.theme)
|
||||||
|
{
|
||||||
|
if (window.Asc.plugin.theme.Name && name2color[window.Asc.plugin.theme.Name])
|
||||||
|
color = name2color[window.Asc.plugin.theme.Name];
|
||||||
|
else if (window.Asc.plugin.theme.Type && type2color[window.Asc.plugin.theme.Type])
|
||||||
|
color = type2color[window.Asc.plugin.theme.Type];
|
||||||
|
}
|
||||||
|
|
||||||
|
popup.command("onUpdateContent", {
|
||||||
|
content : _t.content,
|
||||||
|
color : color
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
popup.show(variation);
|
||||||
|
this.popup = popup;
|
||||||
|
return popup;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.close = function(type)
|
||||||
|
{
|
||||||
|
if (undefined !== type && this.type !== type)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!this.popup)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.type = -1;
|
||||||
|
this.rangeId = -1;
|
||||||
|
this.paraId = -1;
|
||||||
|
|
||||||
|
this.popup.close();
|
||||||
|
this.popup = null;
|
||||||
|
Asc.Editor.callMethod("FocusEditor");
|
||||||
|
};
|
||||||
|
|
||||||
|
this._getTitle = function()
|
||||||
|
{
|
||||||
|
return window.Asc.plugin.tr(this.type === 0 ? "Spelling suggestion" : "Grammar suggestion");
|
||||||
|
};
|
||||||
|
|
||||||
|
this._getButtons = function()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
{ text: window.Asc.plugin.tr('Accept'), primary: true },
|
||||||
|
{ text: window.Asc.plugin.tr('Reject'), primary: false }
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
this._calculateWindowSize = function(data)
|
||||||
|
{
|
||||||
|
let backColor = window.Asc.plugin.theme ? window.Asc.plugin.theme["background-normal"] : "#FFFFFF";
|
||||||
|
let textColor = window.Asc.plugin.theme ? window.Asc.plugin.theme["text-normal"] : "#3D3D3D";
|
||||||
|
let borderColor = window.Asc.plugin.theme ? window.Asc.plugin.theme["border-divider"] : "#666666";
|
||||||
|
let ballonColor = window.Asc.plugin.theme ? window.Asc.plugin.theme["canvas-background"] : "#F5F5F5";
|
||||||
|
this.content = `<div class="back-color text-color" style="background:${backColor}; overflow:hidden; max-width:320px; min-width:280px;color:${textColor}; user-select:none;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;">
|
||||||
|
<div style="padding:16px 16px 0px 16px;">
|
||||||
|
|
||||||
|
<div style="margin-bottom:12px;">
|
||||||
|
<div class="text-color" style="font-size:11px; font-weight:700; color:${textColor}; margin-bottom:6px;">
|
||||||
|
${window.Asc.plugin.tr("Suggested correction")}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ballon-color text-color border-color" style="font-size:12px; color:${textColor}; line-height:1.5; background:${ballonColor}; border:1px solid ${borderColor}; border-radius:3px; padding:10px;">
|
||||||
|
<div style="display:flex; align-items:center; gap:8px;">
|
||||||
|
<span class="text-color" style="color:${textColor}; font-weight:normal;">${data.original}</span>
|
||||||
|
<span class="text-color" style="color:${textColor}; font-weight:bold;">→</span>
|
||||||
|
<span class="text-color" style="color:${textColor}; font-weight:normal;">${data.suggested}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
if (data.explanation) {
|
||||||
|
this.content += `<div style="margin-bottom:16px;">
|
||||||
|
<div class="text-color" class="text-color" style="font-size:11px; font-weight:700; color:${textColor}; margin-bottom:6px;">
|
||||||
|
${window.Asc.plugin.tr("Explanation")}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ballon-color text-color border-color" style="font-size:12px; color:${textColor}; line-height:1.5; background:${ballonColor}; border:1px solid ${borderColor}; border-radius:3px; padding:10px;">${data.explanation}</div>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.content += "</div></div>";
|
||||||
|
|
||||||
|
let measureDiv = document.createElement("div");
|
||||||
|
measureDiv.style.position = "absolute";
|
||||||
|
measureDiv.style.left = "-9999px";
|
||||||
|
measureDiv.style.top = "-9999px";
|
||||||
|
measureDiv.style.width = this.width + "px";
|
||||||
|
measureDiv.style.visibility = "hidden";
|
||||||
|
measureDiv.style.pointerEvents = "none";
|
||||||
|
measureDiv.style.opacity = "0";
|
||||||
|
measureDiv.style.margin = "0";
|
||||||
|
measureDiv.style.padding = "0";
|
||||||
|
measureDiv.innerHTML = this.content;
|
||||||
|
|
||||||
|
document.body.appendChild(measureDiv);
|
||||||
|
|
||||||
|
this.height = measureDiv.scrollHeight;
|
||||||
|
|
||||||
|
document.body.removeChild(measureDiv);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var customAnnotationPopup = new CustomAnnotationPopup();
|
||||||
@ -32,12 +32,12 @@
|
|||||||
|
|
||||||
function CustomAssistant(assistantData)
|
function CustomAssistant(assistantData)
|
||||||
{
|
{
|
||||||
TextAnnotator.call(this);
|
CustomAnnotator.call(this);
|
||||||
this.type = 1;
|
this.type = 1;
|
||||||
this.assistantData = assistantData;
|
this.assistantData = assistantData;
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomAssistant.prototype = Object.create(TextAnnotator.prototype);
|
CustomAssistant.prototype = Object.create(CustomAnnotator.prototype);
|
||||||
CustomAssistant.prototype.constructor = CustomAssistant;
|
CustomAssistant.prototype.constructor = CustomAssistant;
|
||||||
|
|
||||||
CustomAssistant.prototype.annotateParagraph = async function(paraId, recalcId, text)
|
CustomAssistant.prototype.annotateParagraph = async function(paraId, recalcId, text)
|
||||||
@ -55,28 +55,7 @@ CustomAssistant.prototype.annotateParagraph = async function(paraId, recalcId, t
|
|||||||
isSendedEndLongAction = true;
|
isSendedEndLongAction = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let argPrompt = `You are a grammar correction tool that analyzes text for punctuation and style issues only. You will receive text to analyze and must respond with corrections in a specific JSON format.
|
let argPrompt = `${this.assistantData.query}
|
||||||
|
|
||||||
CRITICAL REQUIREMENT - READ CAREFULLY:
|
|
||||||
The "sentence" field in your JSON response MUST contain the EXACT text from the original input with NO changes whatsoever - not even fixing capitalization, punctuation, or anything else. Copy it character-by-character exactly as it appears in the original. Only the "suggestion" field should contain corrections.
|
|
||||||
|
|
||||||
Your task is to:
|
|
||||||
- Check ONLY for punctuation errors (commas, periods, semicolons, colons, apostrophes, quotation marks, etc.) and style issues (sentence structure, word order, grammar, capitalization)
|
|
||||||
- Completely ignore spelling errors and typos. Do not mention them, do not flag them, do not include sentences just because they contain spelling errors. Pretend all words are spelled correctly.
|
|
||||||
- Return corrections in JSON format only
|
|
||||||
|
|
||||||
What counts as an error:
|
|
||||||
- Missing or incorrect punctuation (periods, commas, semicolons, etc.)
|
|
||||||
- Run-on sentences needing punctuation
|
|
||||||
- Incorrect sentence structure or word order
|
|
||||||
- Grammar issues (subject-verb agreement, tense consistency, etc.)
|
|
||||||
- Capitalization errors
|
|
||||||
|
|
||||||
What does NOT count as an error:
|
|
||||||
- Misspelled words or typos
|
|
||||||
- Missing letters in words
|
|
||||||
- Wrong letters in words
|
|
||||||
|
|
||||||
Response format - return ONLY this JSON array with no additional text:
|
Response format - return ONLY this JSON array with no additional text:
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright Ascensio System SIA 2010-2025
|
||||||
|
*
|
||||||
|
* This program is a free software product. You can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||||
|
* version 3 as published by the Free Software Foundation. In accordance with
|
||||||
|
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||||||
|
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||||||
|
* of any third-party rights.
|
||||||
|
*
|
||||||
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||||||
|
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
*
|
||||||
|
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||||||
|
* street, Riga, Latvia, EU, LV-1050.
|
||||||
|
*
|
||||||
|
* The interactive user interfaces in modified source and object code versions
|
||||||
|
* of the Program must display Appropriate Legal Notices, as required under
|
||||||
|
* Section 5 of the GNU AGPL version 3.
|
||||||
|
*
|
||||||
|
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||||||
|
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||||||
|
* grant you any rights under trademark law for use of our trademarks.
|
||||||
|
*
|
||||||
|
* All the Product's GUI elements, including illustrations and icon sets, as
|
||||||
|
* well as technical writing content are licensed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||||||
|
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
function CustomAnnotator()
|
||||||
|
{
|
||||||
|
this.paraId = null;
|
||||||
|
this.rangeId = null;
|
||||||
|
|
||||||
|
this.paragraphs = {};
|
||||||
|
this.waitParagraphs = {};
|
||||||
|
this.paraToCheck = new Set();
|
||||||
|
this.checked = new Set(); // was checked on the previous request
|
||||||
|
|
||||||
|
this.type = -1;
|
||||||
|
}
|
||||||
|
CustomAnnotator.prototype.onChangeParagraph = async function(paraId, recalcId, text, ranges)
|
||||||
|
{
|
||||||
|
this._handleNewRanges(ranges, paraId, text);
|
||||||
|
this.waitParagraphs[paraId] = {
|
||||||
|
recalcId : recalcId,
|
||||||
|
text : text
|
||||||
|
};
|
||||||
|
|
||||||
|
this._checkParagraph(paraId);
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.checkParagraphs = async function(paraIds)
|
||||||
|
{
|
||||||
|
this.paraToCheck.clear()
|
||||||
|
let _t = this;
|
||||||
|
paraIds.forEach(function(paraId) {
|
||||||
|
if (!_t.checked.has(paraId) || _t.waitParagraphs[paraId])
|
||||||
|
_t.paraToCheck.add(paraId);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.paraToCheck.forEach(paraId => this._checkParagraph(paraId));
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype._checkParagraph = async function(paraId)
|
||||||
|
{
|
||||||
|
if (!this.paraToCheck.has(paraId) || !this.waitParagraphs[paraId])
|
||||||
|
return;
|
||||||
|
|
||||||
|
let recalcId = this.waitParagraphs[paraId].recalcId;
|
||||||
|
let text = this.waitParagraphs[paraId].text;
|
||||||
|
|
||||||
|
// TODO: Temporarily for simplicity
|
||||||
|
let range = this.getAnnotationRangeObj(paraId);
|
||||||
|
range["rangeId"] = undefined;
|
||||||
|
range["all"] = true;
|
||||||
|
await Asc.Editor.callMethod("RemoveAnnotationRange", [range]);
|
||||||
|
await this.annotateParagraph(paraId, recalcId, text);
|
||||||
|
|
||||||
|
delete this.waitParagraphs[paraId];
|
||||||
|
this.paraToCheck.delete(paraId);
|
||||||
|
|
||||||
|
this.checked.add(paraId);
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.annotateParagraph = async function(paraId, recalcId, text)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.openPopup = async function(paraId, rangeId)
|
||||||
|
{
|
||||||
|
if (!customAnnotationPopup)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let popup = customAnnotationPopup.open(this.type, paraId, rangeId, this.getInfoForPopup(paraId, rangeId));
|
||||||
|
if (!popup)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let _t = this;
|
||||||
|
popup.onAccept = async function() {
|
||||||
|
await _t.onAccept(paraId, rangeId);
|
||||||
|
_t.closePopup();
|
||||||
|
};
|
||||||
|
popup.onReject = async function() {
|
||||||
|
await _t.onReject(paraId, rangeId);
|
||||||
|
_t.closePopup();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.closePopup = function()
|
||||||
|
{
|
||||||
|
if (!customAnnotationPopup)
|
||||||
|
return;
|
||||||
|
|
||||||
|
customAnnotationPopup.close(this.type);
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.getInfoForPopup = function(paraId, rangeId)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.onAccept = async function(paraId, rangeId)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.onReject = async function(paraId, rangeId)
|
||||||
|
{
|
||||||
|
let range = this.getAnnotationRangeObj(paraId, rangeId);
|
||||||
|
await Asc.Editor.callMethod("RemoveAnnotationRange", [range]);
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.getAnnotation = function(paraId, rangeId)
|
||||||
|
{
|
||||||
|
if (!paraId || !rangeId || !this.paragraphs[paraId] || !this.paragraphs[paraId][rangeId])
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return this.paragraphs[paraId][rangeId];
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.getAnnotationRangeObj = function(paraId, rangeId)
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"paragraphId" : paraId,
|
||||||
|
"rangeId" : rangeId
|
||||||
|
};
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.onClick = function(paraId, ranges)
|
||||||
|
{
|
||||||
|
if (!ranges || !ranges.length)
|
||||||
|
this.closePopup();
|
||||||
|
else
|
||||||
|
this.openPopup(paraId, ranges[0]);
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.onBlur = function()
|
||||||
|
{
|
||||||
|
this.closePopup();
|
||||||
|
this.resetCurrentRange();
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.onFocus = function(paraId, rangeId)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype.resetCurrentRange = function()
|
||||||
|
{
|
||||||
|
this.paraId = null;
|
||||||
|
this.rangeId = null;
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype._handleNewRanges = function(ranges, paraId, text)
|
||||||
|
{
|
||||||
|
if (!ranges || !Array.isArray(ranges))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ranges.forEach(range => this._handleNewRangePositions(range, paraId, text));
|
||||||
|
// ↓↓↓ TODO: the cycle seems to make no sense ↓↓↓
|
||||||
|
for (let i = 0; i < ranges.length; ++i)
|
||||||
|
{
|
||||||
|
this._handleNewRangePositions(ranges[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
CustomAnnotator.prototype._handleNewRangePositions = function(range, paraId, text)
|
||||||
|
{
|
||||||
|
};
|
||||||
@ -33,16 +33,19 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
/// <reference path="./utils/theme.js" />
|
/// <reference path="./utils/theme.js" />
|
||||||
|
/// <reference path="../vendor/select2-4.0.6-rc.1/dist/js/select2.js" />
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} localStorageCustomAssistantItem
|
* @typedef {Object} localStorageCustomAssistantItem
|
||||||
* @property {string} id
|
* @property {string} id
|
||||||
* @property {string} name
|
* @property {string} name
|
||||||
|
* @property {number} type
|
||||||
* @property {string} query
|
* @property {string} query
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function (window) {
|
(function (window) {
|
||||||
const LOCAL_STORAGE_KEY = "onlyoffice_ai_saved_assistants";
|
const LOCAL_STORAGE_KEY = "onlyoffice_ai_saved_assistants";
|
||||||
const { form, textarea, inputId, inputName } = getFormElements();
|
let selectType = null;
|
||||||
|
const { form, textarea, inputId, inputName } = initFormElements();
|
||||||
const mainContainer = document.getElementById("custom_assistant_window");
|
const mainContainer = document.getElementById("custom_assistant_window");
|
||||||
if (!mainContainer) {
|
if (!mainContainer) {
|
||||||
console.error("Custom Assistant: required elements are missing");
|
console.error("Custom Assistant: required elements are missing");
|
||||||
@ -92,6 +95,7 @@
|
|||||||
if (assistant) {
|
if (assistant) {
|
||||||
inputId.value = assistant.id;
|
inputId.value = assistant.id;
|
||||||
inputName.value = assistant.name;
|
inputName.value = assistant.name;
|
||||||
|
selectType.val(assistant.type).trigger('change');
|
||||||
textarea.value = assistant.query;
|
textarea.value = assistant.query;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,8 +126,9 @@
|
|||||||
|
|
||||||
/** @returns {localStorageCustomAssistantItem} */
|
/** @returns {localStorageCustomAssistantItem} */
|
||||||
function saveCustomAssistantToLocalStorage() {
|
function saveCustomAssistantToLocalStorage() {
|
||||||
const id = inputId.value.trim();
|
const id = inputId.value;
|
||||||
const name = inputName.value.trim();
|
const name = inputName.value.trim();
|
||||||
|
const type = Number(selectType.val());
|
||||||
const query = textarea.value.trim();
|
const query = textarea.value.trim();
|
||||||
|
|
||||||
/** @type {localStorageCustomAssistantItem[]} */
|
/** @type {localStorageCustomAssistantItem[]} */
|
||||||
@ -134,9 +139,9 @@
|
|||||||
(item) => item.id === id
|
(item) => item.id === id
|
||||||
);
|
);
|
||||||
if (existingAssistantIndex !== -1) {
|
if (existingAssistantIndex !== -1) {
|
||||||
savedAssistants[existingAssistantIndex] = { id, name, query };
|
savedAssistants[existingAssistantIndex] = { id, name, type, query };
|
||||||
} else {
|
} else {
|
||||||
savedAssistants.push({ id, name, query });
|
savedAssistants.push({ id, name, type, query });
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -144,11 +149,11 @@
|
|||||||
JSON.stringify(savedAssistants)
|
JSON.stringify(savedAssistants)
|
||||||
);
|
);
|
||||||
|
|
||||||
return { id, name, query };
|
return { id, name, type, query };
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {{textarea: HTMLTextAreaElement, inputId: HTMLInputElement, inputName: HTMLInputElement, form: HTMLFormElement}} */
|
/** @returns {{textarea: HTMLTextAreaElement, inputId: HTMLInputElement, inputName: HTMLInputElement, form: HTMLFormElement}} */
|
||||||
function getFormElements() {
|
function initFormElements() {
|
||||||
const form = document.getElementById("input_prompt_wrapper");
|
const form = document.getElementById("input_prompt_wrapper");
|
||||||
const inputId = document.getElementById("input_prompt_id");
|
const inputId = document.getElementById("input_prompt_id");
|
||||||
const inputName = document.getElementById("input_prompt_name");
|
const inputName = document.getElementById("input_prompt_name");
|
||||||
@ -172,6 +177,28 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectType = $('#assistantType');
|
||||||
|
selectType.select2({
|
||||||
|
data : [{
|
||||||
|
id: 0,
|
||||||
|
text: "Hint"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
text: "Replace"
|
||||||
|
}],
|
||||||
|
tags: true,
|
||||||
|
minimumResultsForSearch: Infinity,
|
||||||
|
dropdownAutoWidth: true
|
||||||
|
});
|
||||||
|
selectType.on('select2:select', (e) => {
|
||||||
|
|
||||||
|
});
|
||||||
|
selectType.val(1);
|
||||||
|
|
||||||
|
selectType.trigger('select2:select');
|
||||||
|
selectType.trigger('change');
|
||||||
|
|
||||||
return { form, textarea, inputId, inputName };
|
return { form, textarea, inputId, inputName };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user