mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
#21 Add world info export, edit popup and deletion
This commit is contained in:
@@ -54,6 +54,7 @@
|
|||||||
var is_mes_reload_avatar = false;
|
var is_mes_reload_avatar = false;
|
||||||
|
|
||||||
var is_advanced_char_open = false;
|
var is_advanced_char_open = false;
|
||||||
|
var is_world_edit_open = false;
|
||||||
|
|
||||||
var menu_type = '';//what is selected in the menu
|
var menu_type = '';//what is selected in the menu
|
||||||
var selected_button = '';//which button pressed
|
var selected_button = '';//which button pressed
|
||||||
@@ -108,6 +109,7 @@
|
|||||||
var kobold_world_synced = false;
|
var kobold_world_synced = false;
|
||||||
var kobold_sync_failed = false;
|
var kobold_sync_failed = false;
|
||||||
var kobold_is_united = false;
|
var kobold_is_united = false;
|
||||||
|
var imported_world_name = '';
|
||||||
var max_context = 2048;//2048;
|
var max_context = 2048;//2048;
|
||||||
var rep_pen = 1;
|
var rep_pen = 1;
|
||||||
var rep_pen_size = 100;
|
var rep_pen_size = 100;
|
||||||
@@ -1524,8 +1526,16 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (popup_type === 'world_imported') {
|
if (popup_type === 'world_imported' && imported_world_name) {
|
||||||
// switch to a new world
|
koboldai_world_names.forEach((item, i) => {
|
||||||
|
if (item === imported_world_name) {
|
||||||
|
$('#world_info').val(i).change();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
imported_world_name = '';
|
||||||
|
}
|
||||||
|
if (popup_type === 'del_world' && kobold_world) {
|
||||||
|
deleteWorldInfo(kobold_world);
|
||||||
}
|
}
|
||||||
if(popup_type == 'new_chat' && this_chid != undefined && menu_type != "create"){//Fix it; New chat doesn't create while open create character menu
|
if(popup_type == 'new_chat' && this_chid != undefined && menu_type != "create"){//Fix it; New chat doesn't create while open create character menu
|
||||||
clearChat();
|
clearChat();
|
||||||
@@ -1558,6 +1568,7 @@
|
|||||||
$("#dialogue_popup_ok").css("background-color", "#191b31CC");
|
$("#dialogue_popup_ok").css("background-color", "#191b31CC");
|
||||||
$("#dialogue_popup_ok").text("Yes");
|
$("#dialogue_popup_ok").text("Yes");
|
||||||
break;
|
break;
|
||||||
|
case 'del_world':
|
||||||
default:
|
default:
|
||||||
$("#dialogue_popup_ok").css("background-color", "#791b31");
|
$("#dialogue_popup_ok").css("background-color", "#791b31");
|
||||||
$("#dialogue_popup_ok").text("Delete");
|
$("#dialogue_popup_ok").text("Delete");
|
||||||
@@ -1963,6 +1974,7 @@
|
|||||||
kobold_world = !isNaN(worldIndex) ? koboldai_world_names[worldIndex] : null;
|
kobold_world = !isNaN(worldIndex) ? koboldai_world_names[worldIndex] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hideWorldEditor();
|
||||||
syncKoboldWorldInfo(true);
|
syncKoboldWorldInfo(true);
|
||||||
saveSettings();
|
saveSettings();
|
||||||
updateWorldStatus();
|
updateWorldStatus();
|
||||||
@@ -2085,6 +2097,7 @@
|
|||||||
|
|
||||||
function updateWorldStatus() {
|
function updateWorldStatus() {
|
||||||
if($('#world_info_block').is(':visible') && kobold_world) {
|
if($('#world_info_block').is(':visible') && kobold_world) {
|
||||||
|
$('#world_info_edit_button').show();
|
||||||
$('#world_status').show();
|
$('#world_status').show();
|
||||||
|
|
||||||
if (kobold_world_synced) {
|
if (kobold_world_synced) {
|
||||||
@@ -2109,6 +2122,7 @@
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$('#world_status').hide();
|
$('#world_status').hide();
|
||||||
|
$('#world_info_edit_button').hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2140,7 +2154,7 @@
|
|||||||
body: JSON.stringify({ "name": kobold_world })
|
body: JSON.stringify({ "name": kobold_world })
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok === true) {
|
if (response.ok) {
|
||||||
const syncData = await response.json();
|
const syncData = await response.json();
|
||||||
|
|
||||||
if (syncData.ok) {
|
if (syncData.ok) {
|
||||||
@@ -2327,7 +2341,7 @@
|
|||||||
$('#world_info').append(`<option value='${i}'>${item}</option>`);
|
$('#world_info').append(`<option value='${i}'>${item}</option>`);
|
||||||
// preselect world if saved
|
// preselect world if saved
|
||||||
if (item == kobold_world){
|
if (item == kobold_world){
|
||||||
$(`#world_info option[value=${i}]`).attr('selected', 'true');
|
$('#world_info').val(i).change();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// end world info settings
|
// end world info settings
|
||||||
@@ -2921,9 +2935,8 @@
|
|||||||
processData: false,
|
processData: false,
|
||||||
success: function(data){
|
success: function(data){
|
||||||
if (data.name) {
|
if (data.name) {
|
||||||
// TODO reload list of custom worlds to allow selection then offer a popup
|
imported_world_name = data.name;
|
||||||
// popup_type = 'world_imported';
|
updateWorldInfoList(imported_world_name);
|
||||||
// callPopup('<h3>World imported successfully! Select it now?</h3>');
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (jqXHR, exception) => {},
|
error: (jqXHR, exception) => {},
|
||||||
@@ -2933,6 +2946,104 @@
|
|||||||
$('#form_world_import').trigger("reset");
|
$('#form_world_import').trigger("reset");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function updateWorldInfoList(importedWorldName) {
|
||||||
|
var result = await fetch('/getsettings', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({})
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.ok) {
|
||||||
|
var data = await result.json();
|
||||||
|
koboldai_world_names = data.koboldai_world_names?.length ? data.koboldai_world_names : [];
|
||||||
|
$('#world_info').find('option[value!="None"]').remove();
|
||||||
|
|
||||||
|
koboldai_world_names.forEach((item, i) => {
|
||||||
|
$('#world_info').append(`<option value='${i}'>${item}</option>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (importedWorldName) {
|
||||||
|
const indexOf = koboldai_world_names.indexOf(kobold_world);
|
||||||
|
$(`#world_info`).val(indexOf);
|
||||||
|
|
||||||
|
popup_type = 'world_imported';
|
||||||
|
callPopup('<h3>World imported successfully! Select it now?</h3>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function download(content, fileName, contentType) {
|
||||||
|
var a = document.createElement("a");
|
||||||
|
var file = new Blob([content], {type: contentType});
|
||||||
|
a.href = URL.createObjectURL(file);
|
||||||
|
a.download = fileName;
|
||||||
|
a.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// World Info Editor
|
||||||
|
async function showWorldEditor() {
|
||||||
|
is_world_edit_open = true;
|
||||||
|
$('#world_text_content').val('');
|
||||||
|
$('#world_popup').css('display', 'flex');
|
||||||
|
|
||||||
|
if (kobold_world) {
|
||||||
|
const response = await fetch("/getworldinfo", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ name: kobold_world })
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const worldInfoData = await response.text();
|
||||||
|
$('#world_text_content').val(worldInfoData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideWorldEditor() {
|
||||||
|
is_world_edit_open = false;
|
||||||
|
$('#world_popup').css('display', 'none');
|
||||||
|
$('#world_text_content').val('');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteWorldInfo(worldInfoName) {
|
||||||
|
if (!koboldai_world_names.includes(worldInfoName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch("/deleteworldinfo", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ name: worldInfoName })
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
await updateWorldInfoList();
|
||||||
|
$('#world_info').val('None').change();
|
||||||
|
hideWorldEditor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#world_info_edit_button').click(() => {
|
||||||
|
is_world_edit_open ? hideWorldEditor() : showWorldEditor();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#world_popup_export').click(() => {
|
||||||
|
const jsonValue = $('#world_text_content').val();
|
||||||
|
if (kobold_world && jsonValue) {
|
||||||
|
const fileName = `${kobold_world}.json`;
|
||||||
|
download(jsonValue, fileName, 'application/json');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#world_popup_delete').click(() => {
|
||||||
|
popup_type = 'del_world';
|
||||||
|
callPopup('<h3>Delete the World Info?</h3>');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#world_cross').click(() => {
|
||||||
|
hideWorldEditor();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<title>Tavern.AI</title>
|
<title>Tavern.AI</title>
|
||||||
@@ -2990,6 +3101,27 @@
|
|||||||
<div></div>
|
<div></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="world_popup">
|
||||||
|
<div id="world_popup_text">
|
||||||
|
<img id="world_cross" src="img/cross.png">
|
||||||
|
<div>
|
||||||
|
<!-- Probably needs a logo (probably) -->
|
||||||
|
<!-- <img src="img/book2.png" id="world_logo"> -->
|
||||||
|
<h3>World Info creation</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Placeholder until actual editor is implemented -->
|
||||||
|
<h4>File content (read-only)</h4>
|
||||||
|
<textarea id="world_text_content" placeholder="Loading..." form="form_create" disabled></textarea>
|
||||||
|
|
||||||
|
<div id="world_popup_bottom_holder">
|
||||||
|
<div id="world_popup_export" class="menu_button">Export</div>
|
||||||
|
<div id="world_popup_delete" class="menu_button">Delete</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="shadow_select_chat_popup">
|
<div id="shadow_select_chat_popup">
|
||||||
<div id="select_chat_popup">
|
<div id="select_chat_popup">
|
||||||
<div id="select_chat_popup_text">
|
<div id="select_chat_popup_text">
|
||||||
@@ -3141,7 +3273,11 @@
|
|||||||
<input type="range" id="rep_pen_size" name="volume" min="0" max="2048" step="1">
|
<input type="range" id="rep_pen_size" name="volume" min="0" max="2048" step="1">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4 id="world_info_block">World Info</h4><h5>How to use (<a href="/notes/13" target="_blank">?</a>)</h5>
|
<h4 id="world_info_block">
|
||||||
|
World Info
|
||||||
|
<div id="world_import_button" class="right_menu_button"><h2>+Import</h2></div>
|
||||||
|
<h5>How to use (<a href="/notes/13" target="_blank">?</a>)</h5>
|
||||||
|
</h4>
|
||||||
<div id="rm_world_import" class="right_menu" style="display: none;">
|
<div id="rm_world_import" class="right_menu" style="display: none;">
|
||||||
<form id="form_world_import" action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
<form id="form_world_import" action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
||||||
<input type="file" id="world_import_file" accept=".json" name="avatar">
|
<input type="file" id="world_import_file" accept=".json" name="avatar">
|
||||||
@@ -3150,7 +3286,7 @@
|
|||||||
<select id="world_info" class="option_select_right_menu">
|
<select id="world_info" class="option_select_right_menu">
|
||||||
<option value="None">None</option>
|
<option value="None">None</option>
|
||||||
</select>
|
</select>
|
||||||
<div id="world_import_button" class="right_menu_button"><h2>+Import</h2></div>
|
<input id="world_info_edit_button" type="button" value="Details">
|
||||||
<div id="world_status">
|
<div id="world_status">
|
||||||
<div id="world_status_indicator"></div><div id="world_status_text"></div>
|
<div id="world_status_indicator"></div><div id="world_status_text"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -956,12 +956,15 @@ input[type=button] {
|
|||||||
|
|
||||||
#world_info {
|
#world_info {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#world_status{
|
#world_status{
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#world_status_indicator{
|
#world_status_indicator{
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
width: 14px;
|
width: 14px;
|
||||||
@@ -969,21 +972,99 @@ input[type=button] {
|
|||||||
background-color: red;
|
background-color: red;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#world_status_text {
|
#world_status_text {
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#world_import_button {
|
#world_import_button {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#world_import_button h2 {
|
#world_import_button h2 {
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
font-size: 17px;
|
margin-left: 1rem;
|
||||||
|
font-size: 16px;
|
||||||
color: rgb(188, 193, 200, 0.5);
|
color: rgb(188, 193, 200, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#world_info_edit_button {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #ffffffaa;
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#world_popup {
|
||||||
|
display: none;
|
||||||
|
flex-direction: column;
|
||||||
|
max-width: 800px;
|
||||||
|
height: 83vh;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2060;
|
||||||
|
background-color: blue;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin-top: 0px;
|
||||||
|
box-shadow: 0 0 2px rgba(200, 200, 200, 0.1);
|
||||||
|
padding: 4px 36px;
|
||||||
|
background: #191b31F5;
|
||||||
|
border-radius: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#world_text_content {
|
||||||
|
margin: 0;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#world_popup_bottom_holder {
|
||||||
|
padding: 1rem 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
#world_popup_bottom_holder div {
|
||||||
|
margin-left: 1rem;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#world_cross {
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
top: 15px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#world_popup h5 a {
|
||||||
|
color: #936f4a;
|
||||||
|
}
|
||||||
|
|
||||||
|
#world_popup h5 a:hover {
|
||||||
|
color: #998e6b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#world_popup h4 a {
|
||||||
|
color: #936f4a;
|
||||||
|
}
|
||||||
|
|
||||||
|
#world_popup h4 a:hover {
|
||||||
|
color: #998e6b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#world_popup h5 {
|
||||||
|
color: #757575;
|
||||||
|
}
|
||||||
|
|
||||||
.del_checkbox{
|
.del_checkbox{
|
||||||
display: none;
|
display: none;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
|
27
server.js
27
server.js
@@ -709,6 +709,33 @@ app.post('/synckoboldworld', jsonParser, async (request, response) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.post('/getworldinfo', jsonParser, async (request, response) => {
|
||||||
|
if (!request.body?.name) {
|
||||||
|
return response.sendStatus(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
const file = readWorldInfoFile(request.body.name);
|
||||||
|
|
||||||
|
return response.send(file.tavernWorldInfo);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post('/deleteworldinfo', jsonParser, async (request, response) => {
|
||||||
|
if (!request.body?.name) {
|
||||||
|
return response.sendStatus(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
const worldInfoName = request.body.name;
|
||||||
|
const filename = `${worldInfoName}.json`;
|
||||||
|
const pathToWorldInfo = path.join(directories.worlds, filename);
|
||||||
|
|
||||||
|
if (!fs.existsSync(pathToWorldInfo)) {
|
||||||
|
throw new Error(`World info file ${filename} doesn't exist.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.rmSync(pathToWorldInfo);
|
||||||
|
|
||||||
|
return response.sendStatus(200);
|
||||||
|
});
|
||||||
|
|
||||||
function getCharaterFile(directories,response,i){ //old need del
|
function getCharaterFile(directories,response,i){ //old need del
|
||||||
if(directories.length > i){
|
if(directories.length > i){
|
||||||
|
Reference in New Issue
Block a user