1
0
mirror of https://github.com/typemill/typemill.git synced 2025-08-06 14:16:46 +02:00

Activate Plugins and Themes

This commit is contained in:
trendschau
2023-03-02 14:50:02 +01:00
parent 807f490eb5
commit 64fddf7da4
6 changed files with 298 additions and 79 deletions

View File

@@ -51,7 +51,7 @@ class ControllerApiSystemExtensions extends ControllerData
if(!isset($licenseScope[$definitions['license']]))
{
$response->getBody()->write(json_encode([
'message' => 'We can not activate this plugin because you need a valid '. $definitions['license'] .'-license and your website must run under the domain of your license.',
'message' => 'Activation failed because you need a valid '. $definitions['license'] .'-license for this and your website must run under the domain of your license.',
]));
return $response->withHeader('Content-Type', 'application/json')->withStatus(400);
@@ -60,9 +60,15 @@ class ControllerApiSystemExtensions extends ControllerData
}
$objectdata = [];
$objectdata[$params['type']][$params['name']] = $this->settings[$params['type']][$params['name']];
$objectdata[$params['type']][$params['name']]['active'] = $params['checked'];
if($params['type'] == 'plugins')
{
$objectdata[$params['type']][$params['name']] = $this->settings[$params['type']][$params['name']];
$objectdata[$params['type']][$params['name']]['active'] = $params['checked'];
}
elseif($params['type'] == 'themes')
{
$objectdata['theme'] = $params['name'];
}
# store updated settings here
$updatedSettings = Settings::updateSettings($objectdata);

View File

@@ -34,16 +34,21 @@ class ControllerWebSystem extends ControllerData
public function showThemes($request, $response, $args)
{
$storage = new StorageWrapper('\Typemill\Models\Storage');
$translations = $this->c->get('translations');
$themeSettings = $this->getThemeDetails();
$themedata = [];
$storage = new StorageWrapper('\Typemill\Models\Storage');
$translations = $this->c->get('translations');
$themeDefinitions = $this->getThemeDetails();
$themeSettings = [];
foreach($this->settings['themes'] as $themename => $themeinputs)
{
$themedata[$themename] = $themeinputs;
$themedata[$themename]['customcss'] = $storage->getFile('cache', $themename . '-custom.css');
$themeSettings[$themename] = $themeinputs;
$themeSettings[$themename]['customcss'] = $storage->getFile('cache', $themename . '-custom.css');
}
$license = [];
if(is_array($this->settings['license']))
{
$license = array_keys($this->settings['license']);
}
return $this->c->get('view')->render($response, 'system/themes.twig', [
@@ -51,8 +56,10 @@ class ControllerWebSystem extends ControllerData
'mainnavi' => $this->getMainNavigation($request->getAttribute('c_userrole')),
'systemnavi' => $this->getSystemNavigation($request->getAttribute('c_userrole')),
'jsdata' => [
'settings' => $themedata,
'themes' => $themeSettings,
'settings' => $themeSettings,
'definitions' => $themeDefinitions,
'theme' => $this->settings['theme'],
'license' => $license,
'labels' => $translations,
'urlinfo' => $this->c->get('urlinfo')
]

View File

@@ -743,6 +743,10 @@ video {
margin-bottom: 0.75rem;
}
.mr-3 {
margin-right: 0.75rem;
}
.mt-5 {
margin-top: 1.25rem;
}
@@ -763,10 +767,6 @@ video {
margin-top: 0.5rem;
}
.mr-3 {
margin-right: 0.75rem;
}
.mt-4 {
margin-top: 1rem;
}
@@ -791,6 +791,10 @@ video {
margin-right: 0.5rem;
}
.ml-3 {
margin-left: 0.75rem;
}
.block {
display: block;
}
@@ -831,14 +835,14 @@ video {
height: 2rem;
}
.h-12 {
height: 3rem;
}
.h-6 {
height: 1.5rem;
}
.h-12 {
height: 3rem;
}
.h-5 {
height: 1.25rem;
}
@@ -851,6 +855,14 @@ video {
height: 16rem;
}
.h-0 {
height: 0px;
}
.h-48 {
height: 12rem;
}
.max-h-80 {
max-height: 20rem;
}
@@ -923,6 +935,10 @@ video {
width: 25%;
}
.w-0 {
width: 0px;
}
.max-w-md {
max-width: 28rem;
}
@@ -935,6 +951,10 @@ video {
max-width: 72rem;
}
.flex-1 {
flex: 1 1 0%;
}
.flex-shrink {
flex-shrink: 1;
}
@@ -963,6 +983,12 @@ video {
resize: both;
}
.appearance-none {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
.flex-col {
flex-direction: column;
}
@@ -999,6 +1025,18 @@ video {
justify-content: space-around;
}
.space-x-8 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(2rem * var(--tw-space-x-reverse));
margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse)));
}
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(1rem * var(--tw-space-x-reverse));
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
}
.overflow-auto {
overflow: auto;
}
@@ -1033,6 +1071,11 @@ video {
border-width: 2px;
}
.border-x-8 {
border-left-width: 8px;
border-right-width: 8px;
}
.border-b {
border-bottom-width: 1px;
}
@@ -1057,6 +1100,14 @@ video {
border-left-width: 4px;
}
.border-b-8 {
border-bottom-width: 8px;
}
.border-t-8 {
border-top-width: 8px;
}
.border-solid {
border-style: solid;
}
@@ -1121,6 +1172,26 @@ video {
border-color: rgb(226 232 240 / var(--tw-border-opacity));
}
.border-x-transparent {
border-left-color: transparent;
border-right-color: transparent;
}
.border-b-blue-600 {
--tw-border-opacity: 1;
border-bottom-color: rgb(37 99 235 / var(--tw-border-opacity));
}
.border-b-white {
--tw-border-opacity: 1;
border-bottom-color: rgb(255 255 255 / var(--tw-border-opacity));
}
.border-t-white {
--tw-border-opacity: 1;
border-top-color: rgb(255 255 255 / var(--tw-border-opacity));
}
.bg-teal-600 {
--tw-bg-opacity: 1;
background-color: rgb(13 148 136 / var(--tw-bg-opacity));
@@ -1232,6 +1303,26 @@ video {
padding-bottom: 0.75rem;
}
.px-8 {
padding-left: 2rem;
padding-right: 2rem;
}
.py-2 {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.py-4 {
padding-top: 1rem;
padding-bottom: 1rem;
}
.px-4 {
padding-left: 1rem;
padding-right: 1rem;
}
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
@@ -1242,26 +1333,6 @@ video {
padding-right: 0.25rem;
}
.px-4 {
padding-left: 1rem;
padding-right: 1rem;
}
.py-2 {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.px-8 {
padding-left: 2rem;
padding-right: 2rem;
}
.py-4 {
padding-top: 1rem;
padding-bottom: 1rem;
}
.pl-3 {
padding-left: 0.75rem;
}
@@ -1302,6 +1373,14 @@ video {
padding-bottom: 0.75rem;
}
.pr-8 {
padding-right: 2rem;
}
.pb-4 {
padding-bottom: 1rem;
}
.text-left {
text-align: left;
}
@@ -1445,6 +1524,18 @@ video {
text-decoration-line: underline;
}
.accent-pink-300 {
accent-color: #f9a8d4;
}
.accent-white {
accent-color: #fff;
}
.accent-teal-500 {
accent-color: #14b8a6;
}
.opacity-0 {
opacity: 0;
}
@@ -1507,6 +1598,26 @@ video {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.checked\:bg-white:checked {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
.checked\:bg-blue-500:checked {
--tw-bg-opacity: 1;
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
}
.checked\:bg-teal-500:checked {
--tw-bg-opacity: 1;
background-color: rgb(20 184 166 / var(--tw-bg-opacity));
}
.checked\:text-white:checked {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.hover\:border-b-4:hover {
border-bottom-width: 4px;
}
@@ -1541,6 +1652,11 @@ video {
background-color: rgb(13 148 136 / var(--tw-bg-opacity));
}
.hover\:bg-teal-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(15 118 110 / var(--tw-bg-opacity));
}
.hover\:bg-rose-500:hover {
--tw-bg-opacity: 1;
background-color: rgb(244 63 94 / var(--tw-bg-opacity));

View File

@@ -7,7 +7,7 @@ const app = Vue.createApp({
<p class="py-2">License: {{ plugin.license }}</p>
<div class="flex">
<label :for="pluginname" class="p-2">{{ $filters.translate('active') }}</label>
<input type="checkbox" class="w-6 h-6 my-2"
<input type="checkbox" class="w-6 h-6 my-2 accent-white"
:name="pluginname"
v-model="formData[pluginname]['active']"
@change="activate(pluginname)">
@@ -20,9 +20,12 @@ const app = Vue.createApp({
<p>{{plugin.description}}</p>
</div>
<div class="w-full mt-6 flex justify-between">
<button @click="setCurrent(pluginname)" class="w-half p-3 bg-stone-700 hover:bg-stone-900 text-white cursor-pointer transition duration-100">Configure</button>
<a v-if="!checkLicense(license, plugin.license)" href="https://typemill.net/buy" target="_blank" class="w-half p-3 py-4 text-center bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Buy a license</a>
<a v-else-if="plugin.donate" :href="plugin.donate" target="_blank" class="w-full p-3 my-1 bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Donate</a>
<button @click="setCurrent(pluginname)" class="flex-1 flex items-center justify-center space-x-4 p-3 bg-stone-700 hover:bg-stone-900 text-white cursor-pointer transition duration-100">
<span>Configure</span>
<span :class="(current == pluginname) ? 'border-b-8 border-b-white' : 'border-t-8 border-t-white'" class="h-0 w-0 border-x-8 border-x-transparent"></span>
</button>
<a v-if="!checkLicense(license, plugin.license)" href="https://typemill.net/buy" target="_blank" class="flex-1 ml-3 p-3 py-4 text-center bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Buy a license</a>
<a v-else-if="plugin.paypal" :href="plugin.paypal" target="_blank" class="flex-1 ml-3 p-3 py-4 text-center bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Donate {{plugin.amount}},-</a>
</div>
</div>
<form class="w-full p-8" v-if="current == pluginname">
@@ -51,10 +54,10 @@ const app = Vue.createApp({
</div>
<div class="my-5">
<div :class="messageClass" class="block w-full h-8 px-3 py-1 my-1 text-white transition duration-100">{{ message }}</div>
<div class="w-full">
<button type="submit" @click.prevent="save()" class="w-full p-3 my-1 bg-stone-700 hover:bg-stone-900 text-white cursor-pointer transition duration-100">Save</button>
<a v-if="checkLicense(license, plugin.license)" href="https://typemill.net/buy" target="_blank" class="w-full p-3 my-1 bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Get a license</a>
<a v-else-if="plugin.donate" :href="plugin.donate" target="_blank" class="w-full p-3 my-1 bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Donate</a>
<div class="w-full mt-6 flex justify-between">
<button type="submit" @click.prevent="save()" class="flex-1 p-3 bg-stone-700 hover:bg-stone-900 text-white cursor-pointer transition duration-100">Save</button>
<a v-if="!checkLicense(license, plugin.license)" href="https://typemill.net/buy" target="_blank" class="flex-1 ml-3 p-3 py-4 text-center bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Buy a license</a>
<a v-else-if="plugin.paypal" :href="plugin.paypal" target="_blank" class="flex-1 ml-3 p-3 py-4 text-center bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Donate {{plugin.amount}},-</a>
</div>
</div>
</form>
@@ -93,13 +96,15 @@ const app = Vue.createApp({
eventBus.$on('forminput', formdata => {
this.formData[this.current][formdata.name] = formdata.value;
});
console.info(this.formData);
},
methods: {
getActiveClass: function(pluginname)
{
if(this.formData[pluginname]['active'])
{
return 'bg-teal-500 text-white';
return 'bg-stone-200';
}
},
getLinkToLicense: function()

View File

@@ -3,75 +3,160 @@ const app = Vue.createApp({
<div class="w-full">
<ul>
<li v-for="(theme,themename) in formDefinitions" class="w-full my-4 bg-stone-100">
<div class="w-full flex p-8">
<div class="w-1/2 h-64 overflow-hidden">
<img :src="theme.preview" class="w-full">
<div class="flex justify-between w-full px-8 py-3 border-b border-white" :class="getActiveClass(themename)">
<p class="py-2">License: {{ theme.license }}</p>
<div class="flex">
<label :for="themename" class="p-2">{{ $filters.translate('active') }}</label>
<input type="checkbox" class="w-6 h-6 my-2 accent-white"
:name="themename"
v-model="formData[themename]['active']"
@change="activate(themename)">
</div>
<div class="w-1/2 pl-8 flex flex-col">
<div class="w-full">
</div>
<div class="w-full p-8">
<div class="flex pb-4">
<div class="w-1/2">
<h2 class="text-xl font-bold mb-3">{{theme.name}}</h2>
<div class="text-xs my-3">author: <a :href="theme.homepage" class="hover:underline text-teal-500">{{theme.author}}</a> | version: {{theme.version}} | {{theme.licence}}</div>
<div class="text-xs my-3">author: <a :href="theme.homepage" class="hover:underline text-teal-500">{{theme.author}}</a> | version: {{theme.version}}</div>
<p>{{theme.description}}</p>
</div>
<div class="w-full mt-auto flex justify-between">
<button @click="setCurrent(themename)" class="w-half p-3 bg-stone-700 hover:bg-stone-900 text-white cursor-pointer transition duration-100">Configure</button>
<button class="w-half p-3 bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Donate/Buy</button>
<div class="w-1/2 h-48 overflow-hidden">
<img :src="theme.preview" class="w-full">
</div>
</div>
<div class="w-full mt-6 flex justify-between">
<button @click="setCurrent(themename)" class="flex-1 flex items-center justify-center space-x-4 p-3 bg-stone-700 hover:bg-stone-900 text-white cursor-pointer transition duration-100">
<span>Configure</span>
<span :class="(current == themename) ? 'border-b-8 border-b-white' : 'border-t-8 border-t-white'" class="h-0 w-0 border-x-8 border-x-transparent"></span>
</button>
<a v-if="!checkLicense(license, theme.license)" href="https://typemill.net/buy" target="_blank" class="flex-1 ml-3 p-3 py-4 text-center bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Buy a license</a>
<a v-else-if="theme.paypal" :href="theme.paypal" target="_blank" class="flex-1 ml-3 p-3 py-4 text-center bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Donate {{theme.amount}},-</a>
</div>
</div>
<form class="w-full p-8" v-if="current == themename">
<div v-for="(fieldDefinition, fieldname) in theme.forms.fields">
<fieldset class="flex flex-wrap justify-between border-2 border-stone-200 p-4 my-8" v-if="fieldDefinition.type == 'fieldset'">
<legend class="text-lg font-medium">{{ fieldDefinition.legend }}</legend>
<component v-for="(subfieldDefinition, subfieldname) in fieldDefinition.fields"
:key="subfieldname"
:is="selectComponent(subfieldDefinition.type)"
:errors="errors"
:name="subfieldname"
:userroles="userroles"
:value="formData[themename][subfieldname]"
v-bind="subfieldDefinition">
:key="subfieldname"
:is="selectComponent(subfieldDefinition.type)"
:errors="errors"
:name="subfieldname"
:userroles="userroles"
:value="formData[themename][subfieldname]"
v-bind="subfieldDefinition">
</component>
</fieldset>
<component v-else
:key="fieldname"
:is="selectComponent(fieldDefinition.type)"
:errors="errors"
:name="fieldname"
:userroles="userroles"
:value="formData[themename][fieldname]"
v-bind="fieldDefinition">
:key="fieldname"
:is="selectComponent(fieldDefinition.type)"
:errors="errors"
:name="fieldname"
:userroles="userroles"
:value="formData[themename][fieldname]"
v-bind="fieldDefinition">
</component>
</div>
<div class="my-5">
<div :class="messageClass" class="block w-full h-8 px-3 py-1 my-1 text-white transition duration-100">{{ message }}</div>
<div class="w-full">
<button type="submit" @click.prevent="save()" class="w-full p-3 my-1 bg-stone-700 hover:bg-stone-900 text-white cursor-pointer transition duration-100">Save</button>
<button @click.prevent="" class="w-full p-3 my-1 bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Donate/Buy</button>
<div class="w-full mt-6 flex justify-between">
<button type="submit" @click.prevent="save()" class="flex-1 p-3 bg-stone-700 hover:bg-stone-900 text-white cursor-pointer transition duration-100">Save</button>
<a v-if="!checkLicense(license, theme.license)" href="https://typemill.net/buy" target="_blank" class="flex-1 ml-3 p-3 py-4 text-center bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Buy a license</a>
<a v-else-if="theme.paypal" :href="theme.paypal" target="_blank" class="flex-1 ml-3 p-3 py-4 text-center bg-teal-500 hover:bg-teal-600 text-white cursor-pointer transition duration-100">Donate {{theme.amount}},-</a>
</div>
</div>
</form>
</li>
</ul>
<div class="my-5 text-center">
<modal v-if="showModal" @close="showModal = false">
<template #header>
<h3>License required</h3>
</template>
<template #body>
<p>{{ modalMessage }}</p>
</template>
<template #button>
<a :href="getLinkToLicense()" class="focus:outline-none px-4 p-3 mr-3 text-white bg-teal-500 hover:bg-teal-700 transition duration-100">Check your license</a>
</template>
</modal>
</div>
</div>
</Transition>`,
data() {
return {
current: '',
formDefinitions: data.themes,
formDefinitions: data.definitions,
formData: data.settings,
theme: data.theme,
license: data.license,
message: '',
messageClass: '',
errors: {},
userroles: false
userroles: false,
showModal: false,
modalMessage: 'default',
}
},
mounted() {
eventBus.$on('forminput', formdata => {
this.formData[this.current][formdata.name] = formdata.value;
});
this.deactivateThemes();
this.formData[this.theme].active = true;
},
methods: {
deactivateThemes: function()
{
for (const theme in this.formData) {
delete this.formData[theme].active;
}
},
getActiveClass: function(themename)
{
if(this.formData[themename]['active'])
{
return 'bg-stone-200';
}
},
getLinkToLicense: function()
{
return tmaxios.defaults.baseURL + "/tm/license";
},
checkLicense: function(haystack, needle)
{
if(needle == 'MAKER' || needle == 'BUSINESS')
{
if(haystack.indexOf(needle) == -1)
{
return false;
}
}
return true;
},
activate: function(themename)
{
var self = this;
tmaxios.post('/api/v1/extensions',{
'csrf_name': document.getElementById("csrf_name").value,
'csrf_value': document.getElementById("csrf_value").value,
'type': 'themes',
'name': themename,
'checked': this.formData[themename]['active']
})
.then(function (response)
{
var status = self.formData[themename]['active'];
self.deactivateThemes();
self.formData[themename]['active'] = status;
})
.catch(function (error)
{
self.modalMessage = error.response.data.message;
self.showModal = true;
});
},
setCurrent: function(name)
{
if(this.current == name)

View File

@@ -3,7 +3,7 @@ version: 1.1.12
description: Cyanine is a modern and flexible multi-purpose theme and the standard theme for typemill.
author: Trendschau
homepage: https://trendschau.net
licence: MIT
license: MIT
paypal: https://paypal.me/typemill
amount: 25