diff --git a/static/koboldai.css b/static/koboldai.css index 8230f352..32241fbf 100644 --- a/static/koboldai.css +++ b/static/koboldai.css @@ -1947,12 +1947,62 @@ body { flex-grow: 1; overflow-y: hidden; filter: brightness(70%); + padding: 0px 7px; +} + +.finder-wi-block > textarea { + width: 100%; + border: none; + resize: none; +} + +.finder-wi-title { + /* Cannot use display: block here, it will add a
to the contenteditable. */ + display: inline-block; + width: 100%; + font-size: 32px; + background-color: var(--input_background); + padding: 7px 5px 0px 5px; + margin: 10px 0px; } .finder-wi-content { - width: 100%; height: 30%; - border: none; +} + +.finder-wi-added-keys { + display: inline-block; +} + +.finder-wi-tag-icon { + position: relative; + top: 4px; + right: 2px; + font-size: 18px !important; + cursor: pointer; +} + +.tag-text { cursor: text; } + +[data-placeholder]:empty:before { + content: attr(data-placeholder); + opacity: 0.6; +} + +.finder-wi-activation-header-container { + display: flex; + justify-content: space-between; + margin-top: 10px; +} + +.finder-wi-activation-header-container > h3 { + margin: 0px; +} + +.finder-wi-always-container { + display: flex; + align-items: center; + column-gap: 5px; } /*---------------------------------- Global ------------------------------------------------*/ @@ -1960,6 +2010,15 @@ body { display: none; } +.block { + display: block; +} + +.disabled { + opacity: 0.4; + pointer-events: none; +} + #input_text { grid-area: textarea; background-color: var(--input_background); diff --git a/static/koboldai.js b/static/koboldai.js index 2042ce31..66b2a286 100644 --- a/static/koboldai.js +++ b/static/koboldai.js @@ -3391,6 +3391,17 @@ function $e(tag, parent, attributes) { return element; } +function makeFinderWITag(name, container, isPrimary) { + let wiTag = $e("span", container, {classes: ["tag"]}); + let wiTagIcon = $e("span", wiTag, {classes: ["finder-wi-tag-icon", "material-icons-outlined"], innerText: "close"}); + let wiTagText = $e("span", wiTag, {innerText: name, contenteditable: true}); + + wiTagIcon.addEventListener("click", function(e) { + // TODO: Server + wiTag.remove(); + }); +} + function updateWISearchListings(entry) { const wiCarousel = document.getElementById("finder-wi-carousel"); @@ -3400,6 +3411,8 @@ function updateWISearchListings(entry) { if (entries.length == 1) entries = [null, entries[0], null]; if (entries.length == 2) entries = [null, ...entries]; + console.log(entries); + for (const [i, entry] of entries.entries()) { let wiBlock = $e("div", wiCarousel, {classes: ["finder-wi-block"]}); @@ -3409,20 +3422,85 @@ function updateWISearchListings(entry) { continue; } + // Focus is the center highlighted one. If there is 3 entries (max), + // the important one is at the center. Otherwise, the important one is + // in the front. if ((i == 1 && entries.length == 3) || (i == 0 && entries.length < 3)) { wiBlock.classList.add("finder-wi-focus"); } - let wiTitle = $e("h2", wiBlock, {classes: ["finder-wi-title"], innerText: entry.title}); - let wiAlwaysLabel = $e("span", wiBlock, {innerText: "Always Activate"}); - let wiAlways = $e("input", wiBlock, {type: "checkbox", "data-toggle": "toggle", "data-size": "mini"}); + let wiTitle = $e("span", wiBlock, {classes: ["finder-wi-title"], innerText: entry.title, contenteditable: true, "data-placeholder": "Entry"}); + wiTitle.addEventListener("keydown", function(e) { + if (e.key === "Enter") e.preventDefault(); + }); + + let wiTextLabel = $e("h3", wiBlock, {innerText: "Text", "style.margin": "10px 0px 5px 0px"}); + /* + let wiContentLabel = $e("span", wiBlock, { + classes: ["block"], innerText: "Text: " + }); + */ + let wiContent = $e("textarea", wiBlock, {classes: ["finder-wi-content"], value: entry.content, placeholder: "Write your World Info here!"}); + let wiComment = $e("textarea", wiBlock, {placeholder: "Comment"}); + + let wiActivationHeaderContainer = $e("div", wiBlock, {classes: ["finder-wi-activation-header-container"]}); + let wiActivationLabel = $e("h3", wiActivationHeaderContainer, {innerText: "Activation", "style.display": "inline"}); + let wiAlwaysContainer = $e("div", wiActivationHeaderContainer, {classes: ["finder-wi-always-container"]}); + let wiAlwaysLabel = $e("span", wiAlwaysContainer, {innerText: "Always Activate"}); + + let wiAlways = $e("input", wiAlwaysContainer, {type: "checkbox", "data-toggle": "toggle", "data-size": "mini", "data-onstyle": "success"}); + $(wiAlways).change(function(e) { + console.log("<3!!") + if (this.checked) { + wiTagActivationContainer.classList.add("disabled"); + } else { + wiTagActivationContainer.classList.remove("disabled"); + } + }); $(wiAlways).bootstrapToggle(); - // Tags - //let wiTagContainer = document.createElement("") + let wiActivationHelp = $e("span", wiBlock, {classes: ["help_text"], innerText: "Change when the AI reads this World Info entry"}) + let wiTagActivationContainer = $e("div", wiBlock); - let wiContent = $e("textarea", wiBlock, {classes: ["finder-wi-content"], value: entry.content}); + for (const isPrimary of [true, false]) { + let wiTagLabel = $e("span", wiTagActivationContainer, { + classes: ["block"], + innerText: isPrimary ? "Requires one of:" : "And (if present):" + }); + + let wiTagContainer = $e("div", wiTagActivationContainer, { + id: isPrimary ? "finder-wi-required-keys" : "finder-wi-secondary-keys", + classes: ["finder-wi-keys"] + }); + let wiAddedTagContainer = $e("div", wiTagContainer, {classes: ["finder-wi-added-keys"]}); + + // Existing keys + for (const key of entry.key) { + makeFinderWITag(key, wiAddedTagContainer); + } + + // The "fake key" add button + let wiNewTag = $e("span", wiTagContainer, {classes: ["tag"]}); + let wiNewTagIcon = $e("span", wiNewTag, {classes: ["finder-wi-tag-icon", "material-icons-outlined"], innerText: "add"}); + let wiNewTagText = $e("span", wiNewTag, {classes: ["tag-text"], contenteditable: true, "data-placeholder": "Key"}); + + function newTag() { + // TODO: Server + let tagName = wiNewTagText.innerText; + wiNewTagText.innerText = ""; + if (!tagName.trim()) return; + makeFinderWITag(tagName, wiAddedTagContainer, isPrimary) + } + + wiNewTagText.addEventListener("blur", newTag); + wiNewTagText.addEventListener("keydown", function(e) { + if (e.key === "Enter") { + newTag(); + e.preventDefault(); + } + }); + } } }