Merge pull request #637 from micz/new_model_selector_issue603
New model selector
This commit is contained in:
commit
7fe0840296
11 changed files with 4270 additions and 17 deletions
|
|
@ -1,5 +1,8 @@
|
|||
file: pages\_lib\list.js
|
||||
source: https://raw.githubusercontent.com/javve/list.js/v2.3.1/dist/list.js
|
||||
|
||||
file: pages\_lib\tom-select.base.js
|
||||
source: https://cdn.jsdelivr.net/npm/tom-select@2.4.4/dist/js/tom-select.base.js
|
||||
|
||||
file: js\lib\diff.js
|
||||
source: https://cdnjs.cloudflare.com/ajax/libs/jsdiff/7.0.0/diff.js
|
||||
|
|
@ -523,6 +523,14 @@ export async function transformTagsLabels(labels, tags_list) {
|
|||
return output;
|
||||
}
|
||||
|
||||
export function setTomSelectBorder(el){
|
||||
if (el.getValue() === "") {
|
||||
el.control.style.border = '2px solid red';
|
||||
} else {
|
||||
el.control.style.border = '1px solid #d0d0d0';
|
||||
}
|
||||
}
|
||||
|
||||
export function getAPIsInitMessageString(args = {}) {
|
||||
const {
|
||||
api_string = '',
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import {
|
|||
getChatGPTWebModelsList_HTML,
|
||||
isAPIKeyValue,
|
||||
getConnectionType,
|
||||
setTomSelectBorder
|
||||
} from '../js/mzta-utils.js';
|
||||
import {
|
||||
injectConnectionUI,
|
||||
|
|
@ -75,6 +76,7 @@ function saveOptions(e) {
|
|||
async function restoreOptions() {
|
||||
function setCurrentChoice(result) {
|
||||
document.querySelectorAll(".option-input").forEach(element => {
|
||||
if(!element.id) return;
|
||||
taLog.log("Options restoring " + element.id + " = " + (isAPIKeyValue(element.id) ? "****************" : result[element.id]));
|
||||
switch (element.type) {
|
||||
case 'checkbox':
|
||||
|
|
@ -100,6 +102,10 @@ async function restoreOptions() {
|
|||
if (element.value === '') {
|
||||
element.selectedIndex = -1;
|
||||
}
|
||||
if (element.tomselect) {
|
||||
element.tomselect.setValue(element.value, true);
|
||||
setTomSelectBorder(element.tomselect);
|
||||
}
|
||||
break;
|
||||
case 'textarea':
|
||||
element.value = result[element.id];
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@import url("tom-select.default.min.css");
|
||||
|
||||
tr.conntype_chatgpt_api, tr.conntype_chatgpt_api2{
|
||||
background-color: rgb(185, 220, 252) !important;
|
||||
}
|
||||
|
|
@ -91,6 +93,10 @@ span.opt_title{
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ts-control, .ts-dropdown{
|
||||
font-size: 14.4px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
tr.conntype_chatgpt_api, tr.conntype_chatgpt_api2{
|
||||
background-color: rgb(0, 0, 58) !important;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import './tom-select.base.js';
|
||||
import {
|
||||
prefs_default,
|
||||
integration_options_config
|
||||
|
|
@ -29,7 +30,8 @@ import {
|
|||
validateCustomData_ChatGPTWeb,
|
||||
sanitizeChatGPTModelData,
|
||||
sanitizeChatGPTWebCustomData,
|
||||
prepareOriginURL
|
||||
prepareOriginURL,
|
||||
setTomSelectBorder
|
||||
} from '../../js/mzta-utils.js';
|
||||
import { openAICompConfigs } from '../../js/api/openai_comp_configs.js';
|
||||
import {
|
||||
|
|
@ -669,6 +671,7 @@ export async function injectConnectionUI({
|
|||
while (openaiCompModelSelect.options.length > 0) {
|
||||
openaiCompModelSelect.remove(0);
|
||||
}
|
||||
syncTomSelect(openaiCompModelSelect);
|
||||
document.getElementById(getPrefixedId('openai_comp_use_v1')).checked = !!config.use_v1;
|
||||
document.getElementById(getPrefixedId('openai_comp_chat_name')).value = config.chat_name || '';
|
||||
// Trigger change events if needed
|
||||
|
|
@ -697,6 +700,7 @@ export async function injectConnectionUI({
|
|||
chatgpt_option.value = prefs.chatgpt_model;
|
||||
chatgpt_option.text = prefs.chatgpt_model;
|
||||
select_chatgpt_model.appendChild(chatgpt_option);
|
||||
select_chatgpt_model.value = prefs.chatgpt_model;
|
||||
select_chatgpt_model.addEventListener("change", () => warn_ChatGPT_APIKeyEmpty(modelId_prefix));
|
||||
|
||||
document.getElementById(getPrefixedId('btnUpdateChatGPTModels')).addEventListener('click', async () => {
|
||||
|
|
@ -734,6 +738,7 @@ export async function injectConnectionUI({
|
|||
select_chatgpt_model.appendChild(option);
|
||||
}
|
||||
});
|
||||
syncTomSelect(select_chatgpt_model);
|
||||
document.getElementById(getPrefixedId('chatgpt_model_fetch_loading')).style.display = 'none';
|
||||
});
|
||||
|
||||
|
|
@ -746,6 +751,7 @@ export async function injectConnectionUI({
|
|||
google_gemini_option.value = prefs.google_gemini_model;
|
||||
google_gemini_option.text = prefs.google_gemini_model;
|
||||
select_google_gemini_model.appendChild(google_gemini_option);
|
||||
select_google_gemini_model.value = prefs.google_gemini_model;
|
||||
select_google_gemini_model.addEventListener("change", () => warn_GoogleGemini_APIKeyEmpty(modelId_prefix));
|
||||
|
||||
document.getElementById(getPrefixedId('btnUpdateGoogleGeminiModels')).addEventListener('click', async () => {
|
||||
|
|
@ -776,6 +782,7 @@ export async function injectConnectionUI({
|
|||
select_google_gemini_model.appendChild(option);
|
||||
}
|
||||
});
|
||||
syncTomSelect(select_google_gemini_model);
|
||||
document.getElementById(getPrefixedId('google_gemini_model_fetch_loading')).style.display = 'none';
|
||||
});
|
||||
|
||||
|
|
@ -788,6 +795,7 @@ export async function injectConnectionUI({
|
|||
ollama_option.value = prefs.ollama_model;
|
||||
ollama_option.text = prefs.ollama_model;
|
||||
select_ollama_model.appendChild(ollama_option);
|
||||
select_ollama_model.value = prefs.ollama_model;
|
||||
select_ollama_model.addEventListener("change", () => warn_Ollama_HostEmpty(modelId_prefix));
|
||||
|
||||
document.getElementById(getPrefixedId('btnUpdateOllamaModels')).addEventListener('click', async () => {
|
||||
|
|
@ -831,6 +839,7 @@ export async function injectConnectionUI({
|
|||
select_ollama_model.appendChild(option);
|
||||
}
|
||||
});
|
||||
syncTomSelect(select_ollama_model);
|
||||
document.getElementById(getPrefixedId('ollama_model_fetch_loading')).style.display = 'none';
|
||||
} catch (error) {
|
||||
document.getElementById(getPrefixedId('ollama_model_fetch_loading')).style.display = 'none';
|
||||
|
|
@ -847,6 +856,7 @@ export async function injectConnectionUI({
|
|||
openai_comp_option.value = prefs.openai_comp_model;
|
||||
openai_comp_option.text = prefs.openai_comp_model;
|
||||
select_openai_comp_model.appendChild(openai_comp_option);
|
||||
select_openai_comp_model.value = prefs.openai_comp_model;
|
||||
select_openai_comp_model.addEventListener("change", () => warn_OpenAIComp_HostEmpty(modelId_prefix));
|
||||
|
||||
document.getElementById(getPrefixedId('btnUpdateOpenAICompModels')).addEventListener('click', async () => {
|
||||
|
|
@ -879,6 +889,7 @@ export async function injectConnectionUI({
|
|||
select_openai_comp_model.appendChild(option);
|
||||
}
|
||||
});
|
||||
syncTomSelect(select_openai_comp_model);
|
||||
document.getElementById(getPrefixedId('openai_comp_model_fetch_loading')).style.display = 'none';
|
||||
});
|
||||
|
||||
|
|
@ -891,6 +902,7 @@ export async function injectConnectionUI({
|
|||
anthropic_option.value = prefs.anthropic_model;
|
||||
anthropic_option.text = prefs.anthropic_model;
|
||||
select_anthropic_model.appendChild(anthropic_option);
|
||||
select_anthropic_model.value = prefs.anthropic_model;
|
||||
select_anthropic_model.addEventListener("change", () => warn_Anthropic_APIKeyEmpty(modelId_prefix));
|
||||
select_anthropic_model.addEventListener("change", () => warn_Anthropic_VersionEmpty(modelId_prefix));
|
||||
|
||||
|
|
@ -933,6 +945,7 @@ export async function injectConnectionUI({
|
|||
select_anthropic_model.appendChild(option);
|
||||
}
|
||||
});
|
||||
syncTomSelect(select_anthropic_model);
|
||||
document.getElementById(getPrefixedId('anthropic_model_fetch_loading')).style.display = 'none';
|
||||
});
|
||||
|
||||
|
|
@ -948,6 +961,7 @@ export async function injectConnectionUI({
|
|||
option.text = modelName;
|
||||
select_openai_comp_model.appendChild(option);
|
||||
select_openai_comp_model.value = modelName;
|
||||
syncTomSelect(select_openai_comp_model);
|
||||
select_openai_comp_model.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
}
|
||||
});
|
||||
|
|
@ -961,6 +975,7 @@ export async function injectConnectionUI({
|
|||
select_openai_comp_model.remove(0);
|
||||
}
|
||||
select_openai_comp_model.value = '';
|
||||
syncTomSelect(select_openai_comp_model);
|
||||
select_openai_comp_model.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
});
|
||||
|
||||
|
|
@ -1011,6 +1026,29 @@ export async function injectConnectionUI({
|
|||
|
||||
updateCORSWarnings(modelId_prefix);
|
||||
|
||||
['chatgpt_model', 'google_gemini_model', 'ollama_model', 'openai_comp_model', 'anthropic_model'].forEach(id => {
|
||||
const el = document.getElementById(getPrefixedId(id));
|
||||
if (el && !el.tomselect) {
|
||||
let ts = new TomSelect(el, {
|
||||
create: false,
|
||||
maxOptions: null,
|
||||
maxItems: 1,
|
||||
sortField: {
|
||||
field: "text",
|
||||
direction: "asc"
|
||||
}
|
||||
});
|
||||
ts.on('change', function() {
|
||||
setTomSelectBorder(this);
|
||||
});
|
||||
if (el.value) {
|
||||
ts.setValue(el.value);
|
||||
}
|
||||
console.log(">>>>>>>>>>>>>>> el.value: " + el.value);
|
||||
setTomSelectBorder(ts);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
select: conntype_select,
|
||||
onTypeChange: (fn) => { onTypeChange = fn; fn(conntype_select.value, { select: conntype_select }); }
|
||||
|
|
@ -1207,6 +1245,24 @@ export function showConnectionOptions(conntype_select, modelId_prefix = '') {
|
|||
|
||||
// From here there are internal functions
|
||||
|
||||
function syncTomSelect(element) {
|
||||
if (element && element.tomselect) {
|
||||
element.tomselect.sync();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleTomSelectDisabled(element, disabled) {
|
||||
element.disabled = disabled;
|
||||
if (element.tomselect) {
|
||||
if (disabled) {
|
||||
element.tomselect.disable();
|
||||
element.tomselect.clear();
|
||||
} else {
|
||||
element.tomselect.enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getModelEl(model, modelId_prefix) {
|
||||
return document.getElementById((modelId_prefix ? modelId_prefix : '') + model);
|
||||
}
|
||||
|
|
@ -1261,13 +1317,13 @@ function warn_ChatGPT_APIKeyEmpty(modelId_prefix) {
|
|||
if(apiKeyInput.value === ''){
|
||||
apiKeyInput.style.border = '2px solid red';
|
||||
btnFetchChatGPTModels.disabled = true;
|
||||
modelChatGPT.disabled = true;
|
||||
toggleTomSelectDisabled(modelChatGPT, true);
|
||||
modelChatGPT.selectedIndex = -1;
|
||||
modelChatGPT.style.border = '';
|
||||
}else{
|
||||
apiKeyInput.style.border = '';
|
||||
btnFetchChatGPTModels.disabled = false;
|
||||
modelChatGPT.disabled = false;
|
||||
toggleTomSelectDisabled(modelChatGPT, false);
|
||||
if((modelChatGPT.selectedIndex === -1)||(modelChatGPT.value === '')){
|
||||
modelChatGPT.style.border = '2px solid red';
|
||||
}else{
|
||||
|
|
@ -1284,13 +1340,13 @@ function warn_GoogleGemini_APIKeyEmpty(modelId_prefix) {
|
|||
if(apiKeyInput.value === ''){
|
||||
apiKeyInput.style.border = '2px solid red';
|
||||
btnFetchGoogleGeminiModels.disabled = true;
|
||||
modelGoogleGemini.disabled = true;
|
||||
toggleTomSelectDisabled(modelGoogleGemini, true);
|
||||
modelGoogleGemini.selectedIndex = -1;
|
||||
modelGoogleGemini.style.border = '';
|
||||
}else{
|
||||
apiKeyInput.style.border = '';
|
||||
btnFetchGoogleGeminiModels.disabled = false;
|
||||
modelGoogleGemini.disabled = false;
|
||||
toggleTomSelectDisabled(modelGoogleGemini, false);
|
||||
if((modelGoogleGemini.selectedIndex === -1)||(modelGoogleGemini.value === '')){
|
||||
modelGoogleGemini.style.border = '2px solid red';
|
||||
}else{
|
||||
|
|
@ -1308,14 +1364,14 @@ function warn_Ollama_HostEmpty(modelId_prefix) {
|
|||
if(hostInput.value === ''){
|
||||
hostInput.style.border = '2px solid red';
|
||||
btnFetchOllamaModels.disabled = true;
|
||||
modelOllama.disabled = true;
|
||||
toggleTomSelectDisabled(modelOllama, true);
|
||||
modelOllama.selectedIndex = -1;
|
||||
modelOllama.style.border = '';
|
||||
btnGiveAllUrlsPermission_ollama_api.disabled = true;
|
||||
}else{
|
||||
hostInput.style.border = '';
|
||||
btnFetchOllamaModels.disabled = false;
|
||||
modelOllama.disabled = false;
|
||||
toggleTomSelectDisabled(modelOllama, false);
|
||||
if((modelOllama.selectedIndex === -1)||(modelOllama.value === '')){
|
||||
modelOllama.style.border = '2px solid red';
|
||||
}else{
|
||||
|
|
@ -1334,14 +1390,14 @@ function warn_OpenAIComp_HostEmpty(modelId_prefix) {
|
|||
if(hostInput.value === ''){
|
||||
hostInput.style.border = '2px solid red';
|
||||
btnUpdateOpenAICompModels.disabled = true;
|
||||
modelOpenAIComp.disabled = true;
|
||||
toggleTomSelectDisabled(modelOpenAIComp, true);
|
||||
modelOpenAIComp.selectedIndex = -1;
|
||||
modelOpenAIComp.style.border = '';
|
||||
btnGiveAllUrlsPermission_openai_comp_api.disabled = true;
|
||||
}else{
|
||||
hostInput.style.border = '';
|
||||
btnUpdateOpenAICompModels.disabled = false;
|
||||
modelOpenAIComp.disabled = false;
|
||||
toggleTomSelectDisabled(modelOpenAIComp, false);
|
||||
if((modelOpenAIComp.selectedIndex === -1)||(modelOpenAIComp.value === '')){
|
||||
modelOpenAIComp.style.border = '2px solid red';
|
||||
}else{
|
||||
|
|
@ -1359,13 +1415,13 @@ function warn_Anthropic_APIKeyEmpty(modelId_prefix) {
|
|||
if(apiKeyInput.value === ''){
|
||||
apiKeyInput.style.border = '2px solid red';
|
||||
btnFetchAnthropicModels.disabled = true;
|
||||
modelAnthropic.disabled = true;
|
||||
toggleTomSelectDisabled(modelAnthropic, true);
|
||||
modelAnthropic.selectedIndex = -1;
|
||||
modelAnthropic.style.border = '';
|
||||
}else{
|
||||
apiKeyInput.style.border = '';
|
||||
btnFetchAnthropicModels.disabled = false;
|
||||
modelAnthropic.disabled = false;
|
||||
toggleTomSelectDisabled(modelAnthropic, false);
|
||||
if((modelAnthropic.selectedIndex === -1)||(modelAnthropic.value === '')){
|
||||
modelAnthropic.style.border = '2px solid red';
|
||||
}else{
|
||||
|
|
@ -1382,13 +1438,13 @@ function warn_Anthropic_VersionEmpty(modelId_prefix) {
|
|||
if(versionInput.value === ''){
|
||||
versionInput.style.border = '2px solid red';
|
||||
btnFetchAnthropicModels.disabled = true;
|
||||
modelAnthropic.disabled = true;
|
||||
toggleTomSelectDisabled(modelAnthropic, true);
|
||||
modelAnthropic.selectedIndex = -1;
|
||||
modelAnthropic.style.border = '';
|
||||
}else{
|
||||
versionInput.style.border = '';
|
||||
btnFetchAnthropicModels.disabled = false;
|
||||
modelAnthropic.disabled = false;
|
||||
toggleTomSelectDisabled(modelAnthropic, false);
|
||||
if((modelAnthropic.selectedIndex === -1)||(modelAnthropic.value === '')){
|
||||
modelAnthropic.style.border = '2px solid red';
|
||||
}else{
|
||||
|
|
|
|||
4135
pages/_lib/tom-select.base.js
Normal file
4135
pages/_lib/tom-select.base.js
Normal file
File diff suppressed because it is too large
Load diff
2
pages/_lib/tom-select.default.min.css
vendored
Normal file
2
pages/_lib/tom-select.default.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -34,7 +34,8 @@ import {
|
|||
import {
|
||||
getAccountsList,
|
||||
normalizeStringList,
|
||||
isAPIKeyValue
|
||||
isAPIKeyValue,
|
||||
setTomSelectBorder
|
||||
} from "../../js/mzta-utils.js";
|
||||
import {
|
||||
initializeSpecificIntegrationUI
|
||||
|
|
@ -301,6 +302,7 @@ function saveOptions(e) {
|
|||
async function restoreOptions() {
|
||||
function setCurrentChoice(result) {
|
||||
document.querySelectorAll(".option-input").forEach(element => {
|
||||
if(!element.id) return;
|
||||
taLog.log("Options restoring " + element.id + " = " + (isAPIKeyValue(element.id) ? "****************" : result[element.id]));
|
||||
switch (element.type) {
|
||||
case 'checkbox':
|
||||
|
|
@ -338,6 +340,10 @@ async function restoreOptions() {
|
|||
if (element.value === '') {
|
||||
element.selectedIndex = -1;
|
||||
}
|
||||
if (element.tomselect) {
|
||||
element.tomselect.setValue(element.value, true);
|
||||
setTomSelectBorder(element.tomselect);
|
||||
}
|
||||
}else{
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ import {
|
|||
sanitizeHtml,
|
||||
validateCustomData_ChatGPTWeb,
|
||||
getChatGPTWebModelsList_HTML,
|
||||
openTab
|
||||
openTab,
|
||||
setTomSelectBorder
|
||||
} from "../../js/mzta-utils.js";
|
||||
import { taLogger } from "../../js/mzta-logger.js";
|
||||
import {
|
||||
|
|
@ -567,7 +568,24 @@ function populateConnectionUI(tr, id, prefix, selectId) {
|
|||
val = prefs[propName];
|
||||
}
|
||||
}
|
||||
inputEl.type === 'checkbox' ? inputEl.checked = (val === true || val === 'true') : inputEl.value = val || '';
|
||||
if (inputEl.type === 'checkbox') {
|
||||
inputEl.checked = (val === true || val === 'true');
|
||||
} else {
|
||||
if (inputEl.tomselect) {
|
||||
const restoreValue = val || '';
|
||||
let optionExists = Array.from(inputEl.options).some(opt => opt.value === restoreValue);
|
||||
if (!optionExists && restoreValue !== '') {
|
||||
let newOption = new Option(restoreValue, restoreValue);
|
||||
inputEl.add(newOption);
|
||||
}
|
||||
inputEl.value = restoreValue;
|
||||
inputEl.tomselect.sync();
|
||||
inputEl.tomselect.setValue(restoreValue, true);
|
||||
setTomSelectBorder(inputEl.tomselect);
|
||||
} else {
|
||||
inputEl.value = val || '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,11 @@ import {
|
|||
} from "../../js/mzta-placeholders.js";
|
||||
import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js";
|
||||
import { taSpamReport } from '../../js/mzta-spamreport.js';
|
||||
import { getAccountsList, isAPIKeyValue } from "../../js/mzta-utils.js";
|
||||
import {
|
||||
getAccountsList,
|
||||
isAPIKeyValue,
|
||||
setTomSelectBorder
|
||||
} from "../../js/mzta-utils.js";
|
||||
import {
|
||||
initializeSpecificIntegrationUI
|
||||
} from "../_lib/connection-ui.js";
|
||||
|
|
@ -290,6 +294,7 @@ function saveOptions(e) {
|
|||
async function restoreOptions() {
|
||||
function setCurrentChoice(result) {
|
||||
document.querySelectorAll(".option-input").forEach(element => {
|
||||
if(!element.id) return;
|
||||
taLog.log("Options restoring " + element.id + " = " + (isAPIKeyValue(element.id) ? "****************" : result[element.id]));
|
||||
switch (element.type) {
|
||||
case 'checkbox':
|
||||
|
|
@ -325,6 +330,10 @@ async function restoreOptions() {
|
|||
if (element.value === '') {
|
||||
element.selectedIndex = -1;
|
||||
}
|
||||
if (element.tomselect) {
|
||||
element.tomselect.setValue(element.value, true);
|
||||
setTomSelectBorder(element.tomselect);
|
||||
}
|
||||
}else{
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ function saveOptions(e) {
|
|||
async function restoreOptions() {
|
||||
function setCurrentChoice(result) {
|
||||
document.querySelectorAll(".option-input").forEach(element => {
|
||||
if(!element.id) return;
|
||||
taLog.log("Options restoring " + element.id + " = " + (isAPIKeyValue(element.id) ? "****************" : result[element.id]));
|
||||
switch (element.type) {
|
||||
case 'checkbox':
|
||||
|
|
@ -244,6 +245,9 @@ async function restoreOptions() {
|
|||
if (element.value === '') {
|
||||
element.selectedIndex = -1;
|
||||
}
|
||||
if (element.tomselect) {
|
||||
element.tomselect.setValue(element.value, true);
|
||||
}
|
||||
}else{
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue