mirror of
https://github.com/typemill/typemill.git
synced 2025-08-01 20:00:37 +02:00
V2.17 finish tonality and example articles
This commit is contained in:
2
cache/timer.yaml
vendored
2
cache/timer.yaml
vendored
@@ -1 +1 @@
|
||||
licenseupdate: 1747254971
|
||||
licenseupdate: 1747478031
|
||||
|
@@ -4,46 +4,52 @@ promptlist:
|
||||
content: 'Act as an experienced copywriter and brainstorm 10 compelling article ideas based on the provided topic. The goal is to create content that resonates with the target audience and ranks well on search engines. Identify relevant keywords and trends to align with user interests. Each idea should provide valuable insights, answer common questions, or solve specific problems. Craft engaging headlines that capture attention and match user search intent.'
|
||||
active: true
|
||||
system: true
|
||||
link: null
|
||||
outline:
|
||||
title: outline
|
||||
content: "You are an experienced copywriter skilled in crafting compelling articles tailored to a specific target audience. Conduct in-depth research on the following article idea. Identify the most relevant information, authoritative sources, and key insights. Analyze search intent to determine what readers are looking for when they search for this topic. Define the article’s target audience, ideal length, tone, and structure.\n\nBased on your research, create a detailed structured outline for the article, including:\n\n* A compelling title and meta description.\n* Main headlines (H2, H3) that logically structure the content.\n* Bullet points under each headline, summarizing the key points to be covered.\n\nAfter the outline add a divider list, the headline `Research` and add your research findings."
|
||||
active: true
|
||||
system: true
|
||||
link: null
|
||||
outline2:
|
||||
title: outline2
|
||||
content: "You are an experienced copywriter skilled in crafting compelling, well-structured articles tailored to a specific target audience. Based on the provided article idea, develop a comprehensive content outline that includes:\n\n- Title: A compelling, SEO-optimized headline.\n- User Intent: A one-sentence description of the intent, followed by the category in brackets (Informational, Navigational, Transactional, or Commercial).\n- Keywords: A comma-separated list, with the main keyword first, followed by up to five secondary keywords.\n- Target Audience: One sentence who the article is for and what they expect to gain.\n- Ideal Tone & Style: Concise, authoritative, engaging, personal, etc.\n\nBelow that, provide a detailed article structure:\n- Headings (H2, H3): A logical outline that organizes the content.\n- Bullet points under each heading: Summarizing key points to cover."
|
||||
active: true
|
||||
system: true
|
||||
link: null
|
||||
write:
|
||||
title: write
|
||||
content: "Act as an experienced copywriter tasked with creating a comprehensive and engaging article based on the provided outline or draft. If details such as keywords, user intent, target audience, tone, or style are included, ensure the article aligns with them. If no outline is given, structure the article logically based on best practices for the topic.\n\nCraft a compelling article with:\n- **An eye-catching, SEO-optimized title** featuring the primary keyword.\n- **A strong introduction** that immediately hooks the reader—use a compelling question, statistic, expert quote, or relatable scenario. Clearly state what the article will cover.\n- **A well-structured body** with clear subheadings (H2, H3) incorporating relevant keywords. Ensure smooth transitions between sections and provide thorough, engaging explanations.\n- **Bullet points or lists** where appropriate to enhance readability but prioritize a natural flow of ideas.\n- **A unique perspective** by integrating expert insights, statistics, case studies, or real-life examples.\n- **Natural keyword integration** that enhances SEO without disrupting readability.\n\nMaintain a tone and style that align with the article’s goals and audience, ensuring clarity, engagement, and credibility."
|
||||
active: true
|
||||
system: true
|
||||
link: null
|
||||
proofread:
|
||||
title: proofread
|
||||
content: 'Review the text for grammar, spelling, and correct word usage. Correct any errors and ensure that the appropriate words are used, while maintaining the original tone, style, and phrasing. At the end of the article, provide a list of all corrections made.'
|
||||
active: true
|
||||
system: true
|
||||
link: null
|
||||
refine:
|
||||
title: refine
|
||||
content: 'Refine the text to enhance its wording and style. Ensure that the content is readable, clear, concise, and flows naturally. Feel free to rephrase sentences where necessary, but retain the original tone and unique language usage to avoid making the text sound generic.'
|
||||
active: true
|
||||
system: true
|
||||
link: null
|
||||
review:
|
||||
title: review
|
||||
content: 'Review the article below. Evaluate it based on readability, clarity, SEO best practices, engagement, and search intent. Provide actionable suggestions for improvement, focusing on areas where the text can be refined for better flow, clarity, and alignment with SEO goals.'
|
||||
active: true
|
||||
system: true
|
||||
link: null
|
||||
mermaid:
|
||||
title: mermaid
|
||||
content: 'Return pure mermaid syntax for a [pie, x, y] diagram.'
|
||||
active: true
|
||||
system: true
|
||||
example:
|
||||
title: example
|
||||
content: 'Please use the following and write an article.'
|
||||
link: null
|
||||
tonality:
|
||||
title: tonality
|
||||
content: 'You are an experienced copywriter. Your task is to take the tone from the example and apply them to the article. Tone includes formality or informality, sentence rhythm, word choice, emotional undertone, and stylistic flair. Keep the original structure, content, and key messages of the article intact, but rewrite it in a way that it reads as if written by the same author as the example. The result should preserve the meaning of the article while fully reflecting the tone and writing style of the example.'
|
||||
active: true
|
||||
system: false
|
||||
errors:
|
||||
title: false
|
||||
body: false
|
||||
link: /getting-started/edit-your-page
|
||||
|
@@ -5,8 +5,6 @@ namespace Typemill\Controllers;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Typemill\Models\Validation;
|
||||
use Typemill\Models\Navigation;
|
||||
use Typemill\Models\Content;
|
||||
use Typemill\Models\License;
|
||||
use Typemill\Models\Settings;
|
||||
use Typemill\Models\User;
|
||||
@@ -46,7 +44,7 @@ class ControllerApiKixote extends Controller
|
||||
|
||||
# send to Kixote
|
||||
$response->getBody()->write(json_encode([
|
||||
'settings' => $kixoteSettings
|
||||
'kixotesettings' => $kixoteSettings
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(200);
|
||||
@@ -284,31 +282,35 @@ class ControllerApiKixote extends Controller
|
||||
$promptname = $params['name'] ?? '';
|
||||
$prompt = $params['prompt'] ?? '';
|
||||
$article = $params['article'] ?? '';
|
||||
$example = $params['link'] ?? false;
|
||||
|
||||
if($example)
|
||||
$example = $params['example'] ?? false;
|
||||
|
||||
if($example && $example != "")
|
||||
{
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->articleUrl(['url' => $params['link']]);
|
||||
if($validInput === true)
|
||||
$validation = new Validation();
|
||||
$v = $validation->returnValidator(['content' => $example]);
|
||||
$v->rule('markdownSecure', 'content');
|
||||
if(!$v->validate())
|
||||
{
|
||||
$urlinfo = $this->c->get('urlinfo');
|
||||
$langattr = $this->settings['langattr'];
|
||||
$navigation = new Navigation();
|
||||
$item = $navigation->getItemForUrl($params['url'], $urlinfo, $langattr);
|
||||
if($item)
|
||||
$example = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
# Rough estimate: 1 token ≈ 4 characters
|
||||
$allContent = $prompt . $article . $example;
|
||||
$length = strlen($allContent);
|
||||
$maxlength = 8000 * 4;
|
||||
if ($length > $maxlength)
|
||||
{
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$markdown = $content->getDraftMarkdown($item);
|
||||
if($markdown)
|
||||
{
|
||||
if(is_array($markdown))
|
||||
{
|
||||
$markdown = $content->markdownArrayToText($markdown);
|
||||
}
|
||||
|
||||
$example = $markdown;
|
||||
}
|
||||
$overLimit = $length - $maxlength;
|
||||
$keep = strlen($example) - $overLimit;
|
||||
if($keep > 0)
|
||||
{
|
||||
$example = substr($example, 0, $keep);
|
||||
}
|
||||
else
|
||||
{
|
||||
$example = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -370,12 +372,11 @@ class ControllerApiKixote extends Controller
|
||||
$url = 'https://api.openai.com/v1/chat/completions';
|
||||
$authHeader = "Authorization: Bearer $apikey";
|
||||
|
||||
$content = $prompt;
|
||||
$content = $prompt . "\n<article>" . $article . "<article>";
|
||||
if($example)
|
||||
{
|
||||
$content .= "\n<example>" . $example . "</example>";
|
||||
}
|
||||
$content .= "\n<article>" . $article . "<article>";
|
||||
|
||||
$postdata = [
|
||||
'model' => $model,
|
||||
@@ -446,12 +447,11 @@ class ControllerApiKixote extends Controller
|
||||
"anthropic-version: 2023-06-01"
|
||||
];
|
||||
|
||||
$content = $prompt;
|
||||
$content = $prompt . "\n<article>" . $article . "<article>";
|
||||
if($example)
|
||||
{
|
||||
$content .= "\n<example>" . $example . "</example>";
|
||||
}
|
||||
$content .= "\n<article>" . $article . "<article>";
|
||||
|
||||
$postdata = [
|
||||
'model' => $model,
|
||||
|
@@ -189,6 +189,32 @@ const kixote = Vue.createApp({
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setKixoteSettings(rawSettings)
|
||||
{
|
||||
// Clone to avoid mutating original input
|
||||
const normalizedSettings = rawSettings;
|
||||
|
||||
if (
|
||||
normalizedSettings &&
|
||||
normalizedSettings.promptlist
|
||||
)
|
||||
{
|
||||
const promptlist = normalizedSettings.promptlist;
|
||||
|
||||
for (const key in promptlist)
|
||||
{
|
||||
if (promptlist.hasOwnProperty(key))
|
||||
{
|
||||
if (typeof promptlist[key].link === 'undefined')
|
||||
{
|
||||
promptlist[key].link = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.kixoteSettings = normalizedSettings;
|
||||
},
|
||||
loadKixoteSettings()
|
||||
{
|
||||
self = this;
|
||||
@@ -200,9 +226,9 @@ const kixote = Vue.createApp({
|
||||
})
|
||||
.then(function (response)
|
||||
{
|
||||
if (response.data.settings)
|
||||
if (response.data.kixotesettings)
|
||||
{
|
||||
self.kixoteSettings = response.data.settings;
|
||||
self.setKixoteSettings(response.data.kixotesettings);
|
||||
}
|
||||
})
|
||||
.catch(function (error)
|
||||
@@ -294,7 +320,13 @@ const kixote = Vue.createApp({
|
||||
updateKixoteSettings(newSettings)
|
||||
{
|
||||
this.settingsSaved = false;
|
||||
this.kixoteSettings = { ...this.kixoteSettings, ...newSettings }; // ✅ Merge settings
|
||||
this.kixoteSettings = newSettings;
|
||||
/*
|
||||
this.kixoteSettings = { ...this.kixoteSettings, ...newSettings };
|
||||
|
||||
console.info("this.settings after merge");
|
||||
console.info(this.kixoteSettings);
|
||||
*/
|
||||
},
|
||||
storeKixoteSettings()
|
||||
{
|
||||
@@ -307,13 +339,13 @@ const kixote = Vue.createApp({
|
||||
.then(function (response)
|
||||
{
|
||||
self.settingsSaved = true;
|
||||
self.kixoteSettings = response.data.kixotesettings;
|
||||
self.setKixoteSettings(response.data.kixotesettings);
|
||||
})
|
||||
.catch(function (error)
|
||||
{
|
||||
if(error.response)
|
||||
{
|
||||
self.kixoteSettings = error.response.data.kixotesettings;
|
||||
self.setKixoteSettings(error.response.data.kixotesettings);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -333,7 +365,8 @@ kixote.component('tab-generate', {
|
||||
activeversion: 0,
|
||||
versions: [],
|
||||
prompt: '',
|
||||
promptlink: null,
|
||||
promptlink: false,
|
||||
examplecontent: false,
|
||||
promptError: false,
|
||||
showFocusButton: false,
|
||||
buttonPosition: { top: 0, left: 0 },
|
||||
@@ -349,7 +382,7 @@ kixote.component('tab-generate', {
|
||||
},
|
||||
titleError: false,
|
||||
bodyError: false,
|
||||
currentFilter: 'all',
|
||||
currentFilter: 'user',
|
||||
article: '',
|
||||
index: '',
|
||||
flatnavi: false,
|
||||
@@ -465,14 +498,17 @@ kixote.component('tab-generate', {
|
||||
<div class="w-full bg-stone-600 px-8 py-2">
|
||||
<div class="flex items-start">
|
||||
<span class="text-teal-300 mr-1">Ki></span>
|
||||
<textarea
|
||||
v-model.trim = "prompt"
|
||||
ref = "prompteditor"
|
||||
class = "flex-grow bg-stone-600 focus:outline-none border-0 caret-white"
|
||||
placeholder = "Prompt..."
|
||||
@keydown.enter = "handleKeydown"
|
||||
@input = "resizePromptEditor"
|
||||
></textarea>
|
||||
<div class="flex-grow bg-stone-600">
|
||||
<textarea
|
||||
v-model.trim = "prompt"
|
||||
ref = "prompteditor"
|
||||
class = "w-full bg-stone-600 focus:outline-none border-0 caret-white"
|
||||
placeholder = "Prompt..."
|
||||
@keydown.enter = "handleKeydown"
|
||||
@input = "resizePromptEditor"
|
||||
></textarea>
|
||||
<p class="" v-if="promptlink">Example: {{promptlink}}</p>
|
||||
</div>
|
||||
<button
|
||||
class = "text-teal-300 px-2"
|
||||
@click = "submitPrompt"
|
||||
@@ -516,13 +552,6 @@ kixote.component('tab-generate', {
|
||||
</button>
|
||||
<div class="flex space-x-2">
|
||||
<span class="px-1">Filter:</span>
|
||||
<button
|
||||
@click.prevent="currentFilter = 'system'"
|
||||
:class="{'text-teal-500': currentFilter === 'system', 'text-white': currentFilter !== 'system'}"
|
||||
class="px-1 transition-colors"
|
||||
>
|
||||
system prompts
|
||||
</button>
|
||||
<button
|
||||
@click.prevent="currentFilter = 'user'"
|
||||
:class="{'text-teal-500': currentFilter === 'user', 'text-white': currentFilter !== 'user'}"
|
||||
@@ -530,6 +559,13 @@ kixote.component('tab-generate', {
|
||||
>
|
||||
my prompts
|
||||
</button>
|
||||
<button
|
||||
@click.prevent="currentFilter = 'system'"
|
||||
:class="{'text-teal-500': currentFilter === 'system', 'text-white': currentFilter !== 'system'}"
|
||||
class="px-1 transition-colors"
|
||||
>
|
||||
system prompts
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -540,7 +576,7 @@ kixote.component('tab-generate', {
|
||||
<input
|
||||
type = "text"
|
||||
class = "w-50 p-2 my-1 font-mono bg-stone-600 text-white caret-white focus:outline-none"
|
||||
@input = "validateTitle(newPrompt.title)"
|
||||
@input = "validatePromptTitle(newPrompt.title)"
|
||||
@focus = "editPrompt = newPrompt.title"
|
||||
placeholder = "Enter a title"
|
||||
v-model = "newPrompt.title"
|
||||
@@ -550,7 +586,7 @@ kixote.component('tab-generate', {
|
||||
<textarea
|
||||
class = "w-full p-2 my-1 font-mono bg-stone-600 no-outline text-white caret-white focus:outline-none"
|
||||
rows = "5"
|
||||
@input = "validateBody(newPrompt.content)"
|
||||
@input = "validatePromptBody(newPrompt.content)"
|
||||
@focus = "editPrompt = newPrompt.name"
|
||||
placeholder = "Enter a prompt"
|
||||
v-model = "newPrompt.content"
|
||||
@@ -562,8 +598,8 @@ kixote.component('tab-generate', {
|
||||
<select v-model="newPrompt.link"
|
||||
class="w-full p-2 font-mono bg-stone-600 text-white caret-white focus:outline-none">
|
||||
<option :value="null" class="text-stone-400 italic">Select example article</option>
|
||||
<option v-for="naviitem in flatnavi" :key="naviitem.urlWoF" :value="naviitem.urlRelWoF">
|
||||
{{ naviitem }}
|
||||
<option v-for="navilink in flatnavi" :key="navilink" :value="navilink">
|
||||
{{ navilink }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -577,11 +613,26 @@ kixote.component('tab-generate', {
|
||||
</div>
|
||||
</transition>
|
||||
<div
|
||||
v-for = "(prompttemplate, name) in filteredPrompts"
|
||||
:key="name"
|
||||
v-if = "currentFilter == 'user' && Object.keys(filteredPrompts).length === 0"
|
||||
class = "py-2 px-2"
|
||||
>
|
||||
<div class="border border-stone-700 bg-stone-700 text-stone-100 p-4">
|
||||
<h2 class="text-lg font-semibold mb-2">How to Use</h2>
|
||||
<p class="mb-2">Click the <span class="font-medium">+ Add Prompt</span> button to create your own prompts. A custom prompt can include:</p>
|
||||
<ul class="list-disc list-inside mb-4 space-y-1">
|
||||
<li>A title or name</li>
|
||||
<li>The main prompt text</li>
|
||||
<li>An optional link to an article used as example (e.g. for style or tone)</li>
|
||||
<li>An activation checkbox to show or hide the prompt below the prompt input field</li>
|
||||
</ul>
|
||||
<p>You can also browse the predefined system prompts using the filter above. These cannot be edited, but you can activate or deactivate them as needed.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-for = "(prompttemplate, name) in filteredPrompts"
|
||||
:key = "name"
|
||||
class = "py-2 px-2"
|
||||
>
|
||||
{{ prompttemplate }}
|
||||
<fieldset class="border border-stone-700 p-4">
|
||||
<div class="flex w-full justify-between">
|
||||
<input
|
||||
@@ -590,7 +641,7 @@ kixote.component('tab-generate', {
|
||||
:readonly = "prompttemplate.system"
|
||||
v-model = "prompttemplate.title"
|
||||
@focus = "editPrompt = name"
|
||||
@input = "updatePrompt(kixoteSettings, name)"
|
||||
@input = "updatePrompt(name)"
|
||||
/>
|
||||
<div class="flex space-x-2 items-center">
|
||||
<div v-if="prompttemplate.system == false">
|
||||
@@ -606,7 +657,7 @@ kixote.component('tab-generate', {
|
||||
</span>
|
||||
<button
|
||||
v-else
|
||||
@click.prevent="savePrompts"
|
||||
@click.prevent="saveSettings"
|
||||
class="px-1 text-teal-300 hover:text-teal-500 transition-colors"
|
||||
>update
|
||||
</button>
|
||||
@@ -617,7 +668,7 @@ kixote.component('tab-generate', {
|
||||
type = "checkbox"
|
||||
class = "w-5 h-5 border border-stone-300 bg-stone-600 text-white cursor-pointer"
|
||||
v-model = "prompttemplate.active"
|
||||
@change = "updateSettings(kixoteSettings)"
|
||||
@change = "saveSettings"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
@@ -629,17 +680,17 @@ kixote.component('tab-generate', {
|
||||
v-model = "prompttemplate.content"
|
||||
:readonly = "prompttemplate.system"
|
||||
@focus = "editPrompt = name"
|
||||
@input = "updatePrompt(kixoteSettings, name)"
|
||||
@input = "updatePrompt(name)"
|
||||
>
|
||||
</textarea>
|
||||
<span v-if="prompttemplate.errors?.body" class="text-red-500 text-sm">{{ prompttemplate.errors.body }}</span>
|
||||
|
||||
<div class="space-y-2 my-2">
|
||||
<div class="space-y-2 my-2" v-if="prompttemplate.system !== true">
|
||||
<select v-model="prompttemplate.link"
|
||||
class="w-full p-2 font-mono bg-stone-600 text-white caret-white focus:outline-none">
|
||||
<option :value="null">Select example article</option>
|
||||
<option v-for="naviitem in flatnavi" :key="naviitem.urlWoF" :value="naviitem.urlRelWoF">
|
||||
{{ naviitem }}
|
||||
<option v-for="navilink in flatnavi" :key="navilink" :value="navilink">
|
||||
{{ navilink }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -649,57 +700,6 @@ kixote.component('tab-generate', {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="currentTab === 'tone'">
|
||||
<div class="w-full bg-stone-900 px-8 py-8">
|
||||
<div class="flex justify-between py-2 px-2">
|
||||
<button @click.prevent="addNewTone = !addNewTone">
|
||||
<span v-if="addNewTone">-</span>
|
||||
<span v-else>+</span> add tone
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<transition name="fade">
|
||||
<div v-if="addNewTone" class="py-2 px-2">
|
||||
<fieldset class="border border-stone-700 p-4">
|
||||
<input
|
||||
type="text"
|
||||
class="w-50 p-2 my-1 font-mono bg-stone-600 text-white caret-white focus:outline-none"
|
||||
placeholder="Enter a tone name"
|
||||
v-model="newTone.title"
|
||||
/>
|
||||
|
||||
|
||||
<!-- Tone description result -->
|
||||
<textarea
|
||||
rows="5"
|
||||
class="w-full p-2 my-1 font-mono bg-stone-600 text-white caret-white focus:outline-none"
|
||||
placeholder="Tone description"
|
||||
v-model="newTone.description"
|
||||
></textarea>
|
||||
|
||||
<div class="w-full flex justify-between">
|
||||
|
||||
<!-- Button to analyze tone -->
|
||||
<button
|
||||
@click.prevent="analyzeTone(newTone)"
|
||||
class="px-1 text-teal-300 hover:text-teal-500 transition-colors"
|
||||
>analyze tone</button>
|
||||
|
||||
<!-- Save button -->
|
||||
<button
|
||||
@click.prevent="saveNewTone"
|
||||
class="px-1 text-teal-300 hover:text-teal-500 transition-colors"
|
||||
>save</button>
|
||||
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -755,17 +755,7 @@ kixote.component('tab-generate', {
|
||||
? this.promptlistuser
|
||||
: this.kixoteSettings.promptlist;
|
||||
|
||||
// Normalize `link` to `null` if not present
|
||||
const normalized = {};
|
||||
for (const [key, prompt] of Object.entries(list))
|
||||
{
|
||||
normalized[key] = {
|
||||
...prompt,
|
||||
link: prompt.link ?? null
|
||||
};
|
||||
}
|
||||
|
||||
return normalized;
|
||||
return list;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -820,6 +810,23 @@ kixote.component('tab-generate', {
|
||||
this.versions.push(markdown);
|
||||
this.resizeAiEditor();
|
||||
},
|
||||
setExampleContent(example)
|
||||
{
|
||||
let markdown = '';
|
||||
|
||||
if (Array.isArray(example))
|
||||
{
|
||||
for (const block of example)
|
||||
{
|
||||
if (block && block.markdown)
|
||||
{
|
||||
markdown += block.markdown + '\n\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.examplecontent = markdown.trim();
|
||||
},
|
||||
createFlatNavi() {
|
||||
if (this.navigation && !this.flatnavi) {
|
||||
const nestedNavi = [];
|
||||
@@ -863,6 +870,7 @@ kixote.component('tab-generate', {
|
||||
{
|
||||
this.prompt = this.promptlistactive[index].content;
|
||||
this.promptlink = this.promptlistactive[index].link;
|
||||
this.examplecontent = false;
|
||||
this.resizePromptEditor();
|
||||
},
|
||||
switchVersion(index)
|
||||
@@ -874,13 +882,19 @@ kixote.component('tab-generate', {
|
||||
{
|
||||
this.promptError = false;
|
||||
|
||||
if (this.promptlink && this.examplecontent === false)
|
||||
{
|
||||
this.loadExampleContent();
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
eventBus.$emit('switchLoading');
|
||||
|
||||
tmaxios.post('/api/v1/prompt',{
|
||||
'prompt': this.prompt,
|
||||
'article': this.versions[this.activeversion],
|
||||
'link': this.promptlink
|
||||
'example': this.examplecontent
|
||||
})
|
||||
.then(function (response)
|
||||
{
|
||||
@@ -893,6 +907,7 @@ kixote.component('tab-generate', {
|
||||
self.activeversion = self.versions.length-1;
|
||||
self.prompt = '';
|
||||
self.promptlink = null;
|
||||
self.examplecontent = false;
|
||||
self.resizePromptEditor();
|
||||
self.resizeAiEditor();
|
||||
}
|
||||
@@ -912,6 +927,34 @@ kixote.component('tab-generate', {
|
||||
}
|
||||
});
|
||||
},
|
||||
loadExampleContent()
|
||||
{
|
||||
self = this;
|
||||
|
||||
this.examplecontent = '';
|
||||
|
||||
tmaxios.get('/api/v1/article/content',{
|
||||
params: {
|
||||
'url': this.promptlink,
|
||||
'draft': true
|
||||
}
|
||||
})
|
||||
.then(function (response)
|
||||
{
|
||||
if (response.data.content)
|
||||
{
|
||||
self.setExampleContent(response.data.content);
|
||||
}
|
||||
self.submitPrompt(true);
|
||||
})
|
||||
.catch(function (error)
|
||||
{
|
||||
if(error.response)
|
||||
{
|
||||
}
|
||||
self.submitPrompt(true);
|
||||
});
|
||||
},
|
||||
handleKeydown(event)
|
||||
{
|
||||
if (event.key === 'Enter' && !event.shiftKey)
|
||||
@@ -1015,11 +1058,7 @@ kixote.component('tab-generate', {
|
||||
.replace(/-+/g, '-') // Remove multiple dashes
|
||||
.trim(); // Trim leading/trailing dashes
|
||||
},
|
||||
updateSettings(newSettings)
|
||||
{
|
||||
eventBus.$emit('updateKixoteSettings', newSettings); // Emit event
|
||||
},
|
||||
validateTitle(title)
|
||||
validatePromptTitle(title)
|
||||
{
|
||||
const titleRegex = /^[a-zA-Z0-9 ]{0,20}$/;
|
||||
if (!titleRegex.test(title))
|
||||
@@ -1031,7 +1070,7 @@ kixote.component('tab-generate', {
|
||||
this.titleError = false;
|
||||
}
|
||||
},
|
||||
validateBody(body)
|
||||
validatePromptBody(body)
|
||||
{
|
||||
const bodyRegex = /<\/?[^>]+(>|$)/g;
|
||||
if (bodyRegex.test(body))
|
||||
@@ -1042,36 +1081,36 @@ kixote.component('tab-generate', {
|
||||
{
|
||||
this.bodyError = false;
|
||||
}
|
||||
},
|
||||
savePrompts()
|
||||
},
|
||||
updatePrompt(name)
|
||||
{
|
||||
if (!this.titleError && !this.bodyError)
|
||||
var newSettings = this.kixoteSettings;
|
||||
if(newSettings.promptlist[name] != undefined)
|
||||
{
|
||||
eventBus.$emit('storeKixoteSettings');
|
||||
}
|
||||
},
|
||||
updatePrompt(kixoteSettings, promptname)
|
||||
{
|
||||
if(kixoteSettings.promptlist[promptname] != undefined)
|
||||
{
|
||||
kixoteSettings.promptlist[promptname].errors = {};
|
||||
newSettings.promptlist[name].errors = {};
|
||||
|
||||
this.validateTitle(kixoteSettings.promptlist[promptname].title);
|
||||
kixoteSettings.promptlist[promptname].errors.title = this.titleError;
|
||||
this.validatePromptTitle(newSettings.promptlist[name].title);
|
||||
if(this.titleError)
|
||||
{
|
||||
newSettings.promptlist[name].errors.title = this.titleError;
|
||||
}
|
||||
|
||||
this.validateBody(kixoteSettings.promptlist[promptname].content);
|
||||
kixoteSettings.promptlist[promptname].errors.body = this.bodyError;
|
||||
this.validatePromptBody(newSettings.promptlist[name].content);
|
||||
if(this.bodyError)
|
||||
{
|
||||
newSettings.promptlist[name].errors.body = this.bodyError;
|
||||
}
|
||||
|
||||
this.updateSettings(kixoteSettings);
|
||||
this.updateSettings(newSettings);
|
||||
}
|
||||
},
|
||||
deletePrompt(name)
|
||||
{
|
||||
var promptlist = this.kixoteSettings.promptlist;
|
||||
var newSettings = this.kixoteSettings;
|
||||
|
||||
delete promptlist[name];
|
||||
delete newSettings.promptlist[name];
|
||||
|
||||
this.updateSettings(promptlist);
|
||||
this.updateSettings(newSettings);
|
||||
|
||||
eventBus.$emit('storeKixoteSettings');
|
||||
|
||||
@@ -1083,30 +1122,41 @@ kixote.component('tab-generate', {
|
||||
return false;
|
||||
}
|
||||
|
||||
var promptlist = this.kixoteSettings.promptlist;
|
||||
var newSettings = this.kixoteSettings;
|
||||
|
||||
var promptkey = this.slugify(this.newPrompt.title);
|
||||
promptlist[promptkey] = {
|
||||
newSettings.promptlist[promptkey] = {
|
||||
title: this.newPrompt.title,
|
||||
content: this.newPrompt.content,
|
||||
active: this.newPrompt.active,
|
||||
system: this.newPrompt.system
|
||||
system: this.newPrompt.system,
|
||||
link: this.newPrompt.link
|
||||
};
|
||||
|
||||
this.newPrompt = {
|
||||
title: '',
|
||||
content: '',
|
||||
active: true,
|
||||
system: false
|
||||
system: false,
|
||||
link: null
|
||||
};
|
||||
|
||||
this.addNewPrompt = false;
|
||||
this.updateSettings(promptlist);
|
||||
this.updateSettings(newSettings);
|
||||
eventBus.$emit('storeKixoteSettings');
|
||||
},
|
||||
getArticleMarkdown(url)
|
||||
{
|
||||
|
||||
},
|
||||
updateSettings(newSettings)
|
||||
{
|
||||
eventBus.$emit('updateKixoteSettings', newSettings);
|
||||
},
|
||||
saveSettings()
|
||||
{
|
||||
/* used if activate box for prompts is clicked */
|
||||
if (!this.titleError && !this.bodyError)
|
||||
{
|
||||
eventBus.$emit('storeKixoteSettings');
|
||||
}
|
||||
},
|
||||
exit()
|
||||
{
|
||||
eventBus.$emit('kiExit');
|
||||
|
Reference in New Issue
Block a user