mirror of
https://github.com/typemill/typemill.git
synced 2025-07-25 00:02:28 +02:00
Fixed kixote settings stoarage, fixed customfield storage, large version of customfields, separate theme tabs
This commit is contained in:
2
cache/timer.yaml
vendored
2
cache/timer.yaml
vendored
@@ -1 +1 @@
|
||||
licenseupdate: 1743303388
|
||||
licenseupdate: 1743349357
|
||||
|
@@ -10,6 +10,4 @@ meta:
|
||||
hide: false
|
||||
noindex: false
|
||||
contains: pages
|
||||
template: ''
|
||||
cyanine:
|
||||
template: standard
|
||||
template: ''
|
41
settings/kixote.yaml
Normal file
41
settings/kixote.yaml
Normal file
@@ -0,0 +1,41 @@
|
||||
promptlist:
|
||||
brainstorm:
|
||||
title: brainstorm
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
mermaid:
|
||||
title: mermaid
|
||||
content: 'Return pure mermaid syntax for a [pie, x, y] diagram.'
|
||||
active: true
|
||||
system: true
|
@@ -43,6 +43,7 @@ class ControllerApiKixote extends Controller
|
||||
$params = $request->getParsedBody();
|
||||
$kixoteSettings = $params['kixotesettings'] ?? false;
|
||||
$validate = new Validation();
|
||||
$cleanSettings = [];
|
||||
|
||||
if(isset($kixoteSettings['promptlist']))
|
||||
{
|
||||
@@ -57,6 +58,7 @@ class ControllerApiKixote extends Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
$cleanSettings['promptlist'][$name] = $values;
|
||||
unset($kixoteSettings['promptlist'][$name]['errors']);
|
||||
}
|
||||
}
|
||||
@@ -74,7 +76,7 @@ class ControllerApiKixote extends Controller
|
||||
}
|
||||
|
||||
$settingsModel = new Settings();
|
||||
$result = $settingsModel->updateKixoteSettings($kixoteSettings);
|
||||
$result = $settingsModel->updateKixoteSettings($cleanSettings);
|
||||
|
||||
if(!$result)
|
||||
{
|
||||
|
@@ -20,7 +20,7 @@ class ControllerApiSystemThemes extends Controller
|
||||
|
||||
$extension = new Extension();
|
||||
$formdefinitions = $extension->getThemeDefinition($themename);
|
||||
$formdefinitions = $this->addDatasets($formdefinitions['forms']['fields']);
|
||||
$formdefinitions = $this->addDatasets($formdefinitions['forms']['fields']);
|
||||
$themedata = [];
|
||||
|
||||
# validate input
|
||||
|
@@ -198,11 +198,11 @@ class Settings
|
||||
}
|
||||
else
|
||||
{
|
||||
$settings[$key] = array_merge($userSettings[$key], $newSettings[$key]);
|
||||
# changed from array_merge to array_replace to preserve the index, otherwise numeric values get re-indexed. Alternative is
|
||||
$settings[$key] = array_replace($userSettings[$key], $newSettings[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if($this->storage->updateYaml('settingsFolder', '', 'settings.yaml', $settings))
|
||||
@@ -214,6 +214,16 @@ class Settings
|
||||
return false;
|
||||
}
|
||||
|
||||
private function array_is_list(array $arr)
|
||||
{
|
||||
if ($arr === [])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return array_keys($arr) === range(0, count($arr) - 1);
|
||||
}
|
||||
|
||||
|
||||
public function updateThemeCss(string $name, string $css)
|
||||
{
|
||||
if($css == '')
|
||||
@@ -234,15 +244,6 @@ class Settings
|
||||
return false;
|
||||
}
|
||||
|
||||
private function array_is_list(array $arr)
|
||||
{
|
||||
if ($arr === [])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return array_keys($arr) === range(0, count($arr) - 1);
|
||||
}
|
||||
|
||||
public function getSettingsDefinitions()
|
||||
{
|
||||
$settingsDefinitions = $this->storage->getYaml('systemSettings', '', 'system.yaml');
|
||||
|
@@ -606,18 +606,54 @@ app.component('component-customfields', {
|
||||
},
|
||||
template: `<div :class="css ? css : ''" class="w-full mt-5 mb-5">
|
||||
<label :for="name" class="block mb-1 font-medium">{{ $filters.translate(label) }}</label>
|
||||
<p v-if="fielderrors" class="text-xs text-red-500">{{ fielderrors }}</p>
|
||||
<p v-else class="text-xs">{{ $filters.translate(description) }}</p>
|
||||
<p v-if="fielderrors" class="text-xs text-red-500 mb-2">{{ fielderrors }}</p>
|
||||
<p v-else class="text-xs mb-2">{{ $filters.translate(description) }}</p>
|
||||
<transition-group name="fade" tag="div">
|
||||
<div class="relative flex mb-3" v-for="(pairobject, pairindex) in cfvalue" :key="pairindex">
|
||||
<div
|
||||
v-show = "isLarge(css)"
|
||||
class = "relative mb-2 border-b border-stone-200 dark:border-stone-600"
|
||||
v-for = "(pairobject, pairindex) in cfvalue"
|
||||
:key = "pairindex"
|
||||
>
|
||||
<div class=" mb-3 w-100 flex justify-between">
|
||||
<input
|
||||
type = "text"
|
||||
placeholder = "key"
|
||||
class = "h-12 w-half border px-2 py-3 border-stone-300 bg-stone-200 text-stone-900"
|
||||
:class = "pairobject.keyerror"
|
||||
:value = "pairobject.key"
|
||||
@input = "updatePairKey(pairindex,$event)">
|
||||
<button class="text-white bg-stone-700 w-6 h-6 text-xs hover:bg-rose-500 ml-1" @click.prevent="deleteField(pairindex)">
|
||||
<svg class="icon icon-minus">
|
||||
<use xlink:href="#icon-minus"></use>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="w-full mb-2">
|
||||
<textarea
|
||||
placeholder = "value"
|
||||
class = "w-full border px-2 py-3 border-stone-300 bg-stone-200 text-stone-900"
|
||||
:class = "pairobject.valueerror"
|
||||
rows = "5"
|
||||
:value = "pairobject.value"
|
||||
@input = "updatePairValue(pairindex,$event)">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-show = "!isLarge(css)"
|
||||
v-for = "(pairobject, pairindex) in cfvalue"
|
||||
class = "relative flex mb-3"
|
||||
:key = "pairindex"
|
||||
>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="key"
|
||||
class="h-12 w-full border px-2 py-3 border-stone-300 bg-stone-200 text-stone-900"
|
||||
:class="pairobject.keyerror"
|
||||
:value="pairobject.key"
|
||||
@input="updatePairKey(pairindex,$event)">
|
||||
type = "text"
|
||||
placeholder = "key"
|
||||
class = "h-12 w-full border px-2 py-3 border-stone-300 bg-stone-200 text-stone-900"
|
||||
:class = "pairobject.keyerror"
|
||||
:value = "pairobject.key"
|
||||
@input = "updatePairKey(pairindex,$event)">
|
||||
</div>
|
||||
<div class="flex-grow">
|
||||
<div class="flex">
|
||||
@@ -625,11 +661,11 @@ app.component('component-customfields', {
|
||||
<use xlink:href="#icon-dots-two-vertical"></use>
|
||||
</svg>
|
||||
<textarea
|
||||
placeholder="value"
|
||||
class="w-full border px-2 py-3 border-stone-300 bg-stone-200 text-stone-900"
|
||||
:class="pairobject.valueerror"
|
||||
v-html="pairobject.value"
|
||||
@input="updatePairValue(pairindex,$event)"></textarea>
|
||||
placeholder = "value"
|
||||
class = "w-full border px-2 py-3 border-stone-300 bg-stone-200 text-stone-900"
|
||||
:class = "pairobject.valueerror"
|
||||
:value = "pairobject.value"
|
||||
@input = "updatePairValue(pairindex,$event)"></textarea>
|
||||
<button class="text-white bg-stone-700 w-6 h-6 text-xs hover:bg-rose-500 ml-1" @click.prevent="deleteField(pairindex)">
|
||||
<svg class="icon icon-minus">
|
||||
<use xlink:href="#icon-minus"></use>
|
||||
@@ -662,6 +698,14 @@ app.component('component-customfields', {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isLarge: function(css)
|
||||
{
|
||||
if(css && css.indexOf('cf-large') >= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
update: function(value, name)
|
||||
{
|
||||
this.fielderrors = false;
|
||||
|
@@ -340,4 +340,8 @@ fieldsetai:
|
||||
autocomplete: new-password
|
||||
generator: false
|
||||
label: 'ChatGPT Api Key'
|
||||
description: "Enter your ChatGPT API key here. You can generate a new key on [OpenAI's platform](https://platform.openai.com/docs/pricing). For security reasons, your API key is secret and will not be visible again after you leave this page."
|
||||
description: "Enter your ChatGPT API key here. You can generate a new key on [OpenAI's platform](https://platform.openai.com/docs/pricing). For security reasons, your API key is secret and will not be visible again after you leave this page."
|
||||
customsmall:
|
||||
type: customfields
|
||||
label: 'Customfield Small'
|
||||
description: "This is a small standard customfield."
|
||||
|
@@ -900,8 +900,6 @@ metatabs:
|
||||
type: checkbox
|
||||
label: 'Glossary List (cyanine theme)'
|
||||
checkboxlabel: 'List pages or posts of this folder as glossary (only for folders)'
|
||||
cyanine:
|
||||
fields:
|
||||
fieldsetTemplates:
|
||||
type: fieldset
|
||||
legend: 'Templates'
|
||||
@@ -918,4 +916,4 @@ metatabs:
|
||||
checkboxlabel: List other pages of the folder below content
|
||||
shorttitle:
|
||||
type: text
|
||||
label: Enter a shorttitle for the landingpageInfo section
|
||||
label: Enter a shorttitle for the landingpageInfo section
|
Reference in New Issue
Block a user