mirror of
https://github.com/typemill/typemill.git
synced 2025-01-17 21:38:25 +01:00
Version 1.3.1: Improved Meta-Tabs and Translations
This commit is contained in:
parent
e09487e668
commit
0d09fe60b1
2
cache/lastCache.txt
vendored
2
cache/lastCache.txt
vendored
@ -1 +1 @@
|
||||
1577899842
|
||||
1578262565
|
@ -30,10 +30,13 @@ class MetaApiController extends ContentController
|
||||
# loop through all plugins
|
||||
foreach($this->settings['plugins'] as $name => $plugin)
|
||||
{
|
||||
$pluginSettings = \Typemill\Settings::getObjectSettings('plugins', $name);
|
||||
if($pluginSettings && isset($pluginSettings['metatabs']))
|
||||
if($plugin['active'])
|
||||
{
|
||||
$metatabs = array_merge_recursive($metatabs, $pluginSettings['metatabs']);
|
||||
$pluginSettings = \Typemill\Settings::getObjectSettings('plugins', $name);
|
||||
if($pluginSettings && isset($pluginSettings['metatabs']))
|
||||
{
|
||||
$metatabs = array_merge_recursive($metatabs, $pluginSettings['metatabs']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,4 +158,6 @@ class MetaApiController extends ContentController
|
||||
# return with the new metadata
|
||||
return $response->withJson(array('metadata' => $metaData, 'errors' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# check models -> writeYaml for getPageMeta and getPageMetaDefaults.
|
@ -463,7 +463,7 @@ class SettingsController extends Controller
|
||||
|
||||
if($validate->newUser($params, $userroles))
|
||||
{
|
||||
$userdata = array('username' => $params['username'], 'email' => $params['email'], 'userrole' => $params['userrole'], 'password' => $params['password']);
|
||||
$userdata = array('username' => $params['username'], 'firstname' => $params['firstname'], 'lastname' => $params['lastname'], 'email' => $params['email'], 'userrole' => $params['userrole'], 'password' => $params['password']);
|
||||
|
||||
$user->createUser($userdata);
|
||||
|
||||
@ -511,7 +511,7 @@ class SettingsController extends Controller
|
||||
|
||||
if($validate->existingUser($params, $userroles))
|
||||
{
|
||||
$userdata = array('username' => $params['username'], 'email' => $params['email'], 'userrole' => $params['userrole']);
|
||||
$userdata = array('username' => $params['username'], 'firstname' => $params['firstname'], 'lastname' => $params['lastname'], 'email' => $params['email'], 'userrole' => $params['userrole']);
|
||||
|
||||
if(empty($params['password']) AND empty($params['newpassword']))
|
||||
{
|
||||
|
@ -64,6 +64,7 @@ class Field
|
||||
'id',
|
||||
'autocomplete',
|
||||
'placeholder',
|
||||
'maxlength',
|
||||
'size',
|
||||
'rows',
|
||||
'cols',
|
||||
|
@ -38,6 +38,15 @@ class User extends WriteYaml
|
||||
'password' => $this->generatePassword($params['password']),
|
||||
'userrole' => $params['userrole']
|
||||
);
|
||||
|
||||
if(isset($params['firstname']))
|
||||
{
|
||||
$userdata['firstname'] = $params['firstname'];
|
||||
}
|
||||
if(isset($params['lastname']))
|
||||
{
|
||||
$userdata['lastname'] = $params['lastname'];
|
||||
}
|
||||
|
||||
if($this->updateYaml('settings/users', $userdata['username'] . '.yaml', $userdata))
|
||||
{
|
||||
@ -58,8 +67,20 @@ class User extends WriteYaml
|
||||
$update = array_merge($userdata, $params);
|
||||
|
||||
$this->updateYaml('settings/users', $userdata['username'] . '.yaml', $update);
|
||||
|
||||
$_SESSION['user'] = $update['username'];
|
||||
$_SESSION['role'] = $update['userrole'];
|
||||
|
||||
if(isset($update['firstname']))
|
||||
{
|
||||
$_SESSION['firstname'] = $update['firstname'];
|
||||
}
|
||||
if(isset($update['lastname']))
|
||||
{
|
||||
$_SESSION['lastname'] = $update['lastname'];
|
||||
}
|
||||
|
||||
return $userdata['username'];
|
||||
return $userdata['username'];
|
||||
}
|
||||
|
||||
public function deleteUser($username)
|
||||
@ -88,6 +109,15 @@ class User extends WriteYaml
|
||||
$_SESSION['user'] = $user['username'];
|
||||
$_SESSION['role'] = $user['userrole'];
|
||||
$_SESSION['login'] = $user['lastlogin'];
|
||||
|
||||
if(isset($user['firstname']))
|
||||
{
|
||||
$_SESSION['firstname'] = $user['firstname'];
|
||||
}
|
||||
if(isset($user['lastname']))
|
||||
{
|
||||
$_SESSION['lastname'] = $user['lastname'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,6 +124,10 @@ class Validation
|
||||
$v->rule('lengthBetween', 'password', 5, 20)->message("Length between 5 - 20");
|
||||
$v->rule('lengthBetween', 'username', 3, 20)->message("Length between 3 - 20");
|
||||
$v->rule('userAvailable', 'username')->message("User already exists");
|
||||
$v->rule('noHTML', 'firstname')->message(" contains HTML");
|
||||
$v->rule('lengthBetween', 'firstname', 2, 40);
|
||||
$v->rule('noHTML', 'lastname')->message(" contains HTML");
|
||||
$v->rule('lengthBetween', 'lastname', 2, 40);
|
||||
$v->rule('email', 'email')->message("e-mail is invalid");
|
||||
$v->rule('in', 'userrole', $userroles);
|
||||
|
||||
@ -137,10 +141,14 @@ class Validation
|
||||
$v->rule('alphaNum', 'username')->message("invalid");
|
||||
$v->rule('lengthBetween', 'username', 3, 20)->message("Length between 3 - 20");
|
||||
$v->rule('userExists', 'username')->message("user does not exist");
|
||||
$v->rule('noHTML', 'firstname')->message(" contains HTML");
|
||||
$v->rule('lengthBetween', 'firstname', 2, 40);
|
||||
$v->rule('noHTML', 'lastname')->message(" contains HTML");
|
||||
$v->rule('lengthBetween', 'lastname', 2, 40);
|
||||
$v->rule('email', 'email')->message("e-mail is invalid");
|
||||
$v->rule('in', 'userrole', $userroles);
|
||||
|
||||
return $this->validationResult($v);
|
||||
return $this->validationResult($v);
|
||||
}
|
||||
|
||||
public function username($username)
|
||||
@ -329,7 +337,23 @@ class Validation
|
||||
{
|
||||
$v->rule('required', $fieldName);
|
||||
}
|
||||
|
||||
if(isset($fieldDefinitions['maxlength']))
|
||||
{
|
||||
$v->rule('lengthMax', $fieldName, $fieldDefinitions['maxlength']);
|
||||
}
|
||||
if(isset($fieldDefinitions['max']))
|
||||
{
|
||||
$v->rule('max', $fieldName, $fieldDefinitions['max']);
|
||||
}
|
||||
if(isset($fieldDefinitions['min']))
|
||||
{
|
||||
$v->rule('min', $fieldName, $fieldDefinitions['min']);
|
||||
}
|
||||
if(isset($fieldDefinitions['pattern']))
|
||||
{
|
||||
$v->rule('regex', $fieldName, '/^' . $fieldDefinitions['pattern'] . '$/');
|
||||
}
|
||||
|
||||
switch($fieldDefinitions['type'])
|
||||
{
|
||||
case "select":
|
||||
@ -350,7 +374,7 @@ class Validation
|
||||
{
|
||||
$v->rule('in', $key, $options);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case "color":
|
||||
$v->rule('regex', $fieldName, '/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/');
|
||||
break;
|
||||
@ -361,33 +385,35 @@ class Validation
|
||||
$v->rule('date', $fieldName);
|
||||
break;
|
||||
case "checkbox":
|
||||
$v->rule('accepted', $fieldName);
|
||||
if(isset($fieldDefinitions['required']))
|
||||
{
|
||||
$v->rule('accepted', $fieldName);
|
||||
}
|
||||
break;
|
||||
case "url":
|
||||
$v->rule('lengthMax', $fieldName, 200);
|
||||
$v->rule('url', $fieldName);
|
||||
$v->rule('lengthMax', $fieldName, 200);
|
||||
break;
|
||||
case "text":
|
||||
$v->rule('lengthMax', $fieldName, 200);
|
||||
$v->rule('noHTML', $fieldName);
|
||||
$v->rule('lengthMax', $fieldName, 500);
|
||||
$v->rule('regex', $fieldName, '/^[\pL0-9_ \-\.\?\!\/\:]*$/u');
|
||||
break;
|
||||
case "textarea":
|
||||
$v->rule('lengthMax', $fieldName, 1000);
|
||||
$v->rule('noHTML', $fieldName);
|
||||
// $v->rule('regex', $fieldName, '/<[^<]+>/');
|
||||
$v->rule('lengthMax', $fieldName, 1000);
|
||||
break;
|
||||
case "paragraph":
|
||||
$v->rule('lengthMax', $fieldName, 1000);
|
||||
$v->rule('noHTML', $fieldName);
|
||||
$v->rule('lengthMax', $fieldName, 1000);
|
||||
break;
|
||||
case "password":
|
||||
$v->rule('lengthMax', $fieldName, 100);
|
||||
break;
|
||||
default:
|
||||
$v->rule('lengthMax', $fieldName, 1000);
|
||||
$v->rule('regex', $fieldName, '/^[\pL0-9_ \-]*$/u');
|
||||
$v->rule('regex', $fieldName, '/^[\pL0-9_ \-]*$/u');
|
||||
}
|
||||
|
||||
return $this->validationResult($v, $objectName);
|
||||
}
|
||||
|
||||
|
@ -86,12 +86,27 @@ class WriteYaml extends Write
|
||||
$description = substr($description, 0, $lastSpace);
|
||||
}
|
||||
|
||||
$author = $settings['author'];
|
||||
|
||||
if(isset($_SESSION))
|
||||
{
|
||||
if(isset($_SESSION['firstname']) && $_SESSION['firstname'] !='' && isset($_SESSION['lastname']) && $_SESSION['lastname'] != '')
|
||||
{
|
||||
$author = $_SESSION['firstname'] . ' ' . $_SESSION['lastname'];
|
||||
}
|
||||
elseif(isset($_SESSION['user']))
|
||||
{
|
||||
$author = $_SESSION['user'];
|
||||
}
|
||||
}
|
||||
|
||||
# create new meta-file
|
||||
$meta = [
|
||||
'meta' => [
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'author' => $settings['author'], # change to session, extend userdata
|
||||
'author' => $author,
|
||||
'created' => date("Y-m-d"),
|
||||
]
|
||||
];
|
||||
|
||||
|
@ -1773,7 +1773,6 @@ button.format-item.close:hover{
|
||||
top: 0;
|
||||
left: 0;
|
||||
transform: translate(-50%, -100%);
|
||||
transition: 0.2s all;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@ -1809,7 +1808,7 @@ button.format-item.close:hover{
|
||||
margin-right: 2px;
|
||||
}
|
||||
.urlinput{
|
||||
width: 80%;
|
||||
width: 75%;
|
||||
min-height: auto;
|
||||
background: #555;
|
||||
color: #fff;
|
||||
|
@ -5,6 +5,27 @@
|
||||
|
||||
<div class="formWrapper">
|
||||
|
||||
<div id="metanav" class="metanav" v-cloak>
|
||||
|
||||
<button
|
||||
v-for="tab in tabs"
|
||||
v-bind:key="tab"
|
||||
v-bind:class="['tab-button', { active: currentTab === tab }]"
|
||||
v-on:click="currentTab = tab"
|
||||
>${tab}</button>
|
||||
|
||||
<component
|
||||
class="tab"
|
||||
v-bind:is="currentTabComponent"
|
||||
:saved="saved"
|
||||
:errors="formErrors[currentTab]"
|
||||
:schema="formDefinitions[currentTab]"
|
||||
:formdata="formData[currentTab]"
|
||||
v-on:saveform="saveForm">
|
||||
</component>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="editor" class="editor">
|
||||
<form action="#" v-cloak>
|
||||
|
||||
|
@ -393,7 +393,7 @@ const contentComponent = Vue.component('content-block', {
|
||||
})
|
||||
|
||||
const inlineFormatsComponent = Vue.component('inline-formats', {
|
||||
template: '<div><div :style="{ left: `${x}px`, top: `${y}px` }" @mousedown.prevent="" v-show="showInlineFormat" id="formatBar" class="inlineFormatBar">' +
|
||||
template: '<div><div :style="{ left: `${x}px`, top: `${y}px`, width: `${z}px` }" @mousedown.prevent="" v-show="showInlineFormat" id="formatBar" class="inlineFormatBar">' +
|
||||
'<div v-if="link">' +
|
||||
'<input v-model="url" @keyup.13="formatLink" ref="urlinput" class="urlinput" type="text" placeholder="insert url">' +
|
||||
'<span class="inlineFormatItem inlineFormatLink" @mousedown.prevent="formatLink"><svg class="icon icon-check"><use xlink:href="#icon-check"></use></svg></span>' +
|
||||
@ -410,10 +410,12 @@ const inlineFormatsComponent = Vue.component('inline-formats', {
|
||||
data: function(){
|
||||
return {
|
||||
formatBar: false,
|
||||
formatElements: 0,
|
||||
startX: 0,
|
||||
startY: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 150,
|
||||
textComponent: '',
|
||||
selectedText: '',
|
||||
startPos: false,
|
||||
@ -500,6 +502,10 @@ const inlineFormatsComponent = Vue.component('inline-formats', {
|
||||
|
||||
this.y = event.offsetY - 15;
|
||||
|
||||
/* calculate the width of the format bar */
|
||||
this.formatElements = document.getElementsByClassName('inlineFormatItem').length;
|
||||
this.z = this.formatElements * 30;
|
||||
|
||||
this.showInlineFormat = true;
|
||||
this.selectedText = selectedText;
|
||||
},
|
||||
@ -508,30 +514,35 @@ const inlineFormatsComponent = Vue.component('inline-formats', {
|
||||
content = this.textComponent.value;
|
||||
content = content.substring(0, this.startPos) + '**' + this.selectedText + '**' + content.substring(this.endPos, content.length);
|
||||
this.$parent.updatemarkdown(content);
|
||||
this.showInlineFormat = false;
|
||||
},
|
||||
formatItalic()
|
||||
{
|
||||
content = this.textComponent.value;
|
||||
content = content.substring(0, this.startPos) + '_' + this.selectedText + '_' + content.substring(this.endPos, content.length);
|
||||
this.$parent.updatemarkdown(content);
|
||||
this.showInlineFormat = false;
|
||||
},
|
||||
formatCode()
|
||||
{
|
||||
content = this.textComponent.value;
|
||||
content = content.substring(0, this.startPos) + '`' + this.selectedText + '`' + content.substring(this.endPos, content.length);
|
||||
this.$parent.updatemarkdown(content);
|
||||
this.$parent.updatemarkdown(content);
|
||||
this.showInlineFormat = false;
|
||||
},
|
||||
formatMath()
|
||||
{
|
||||
content = this.textComponent.value;
|
||||
content = content.substring(0, this.startPos) + '$' + this.selectedText + '$' + content.substring(this.endPos, content.length);
|
||||
this.$parent.updatemarkdown(content);
|
||||
this.showInlineFormat = false;
|
||||
},
|
||||
formatLink()
|
||||
{
|
||||
if(this.url == "")
|
||||
{
|
||||
this.link = false;
|
||||
this.link = false;
|
||||
this.showInlineFormat = false;
|
||||
return;
|
||||
}
|
||||
content = this.textComponent.value;
|
||||
@ -543,11 +554,15 @@ const inlineFormatsComponent = Vue.component('inline-formats', {
|
||||
openLink()
|
||||
{
|
||||
this.link = true;
|
||||
this.url = '';
|
||||
this.z = 200;
|
||||
this.$nextTick(() => this.$refs.urlinput.focus());
|
||||
},
|
||||
closeLink()
|
||||
{
|
||||
this.link = false;
|
||||
this.url = '';
|
||||
this.showInlineFormat = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -1,26 +1,21 @@
|
||||
const FormBus = new Vue();
|
||||
|
||||
Vue.component('component-text', {
|
||||
props: ['class', 'placeholder', 'label', 'name', 'type', 'size', 'value', 'errors'],
|
||||
props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<input type="text" :name="name" :placeholder="placeholder" :value="value" @input="update($event, name)">' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
update: function($event, name)
|
||||
{
|
||||
FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Vue.component('component-date', {
|
||||
props: ['class', 'placeholder', 'readonly', 'label', 'name', 'type', 'size', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<input type="date" :readonly="readonly" :name="name" :placeholder="placeholder" :value="value" @input="update($event, name)">' +
|
||||
'<input type="text"' +
|
||||
' :id="id"' +
|
||||
' :maxlength="maxlength"' +
|
||||
' :readonly="readonly"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' :name="name"' +
|
||||
' :placeholder="placeholder"' +
|
||||
' :value="value"' +
|
||||
'@input="update($event, name)">' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
update: function($event, name)
|
||||
@ -31,11 +26,195 @@ Vue.component('component-date', {
|
||||
})
|
||||
|
||||
Vue.component('component-textarea', {
|
||||
props: ['class', 'placeholder', 'label', 'name', 'type', 'size', 'value', 'errors'],
|
||||
props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{label}}</label>' +
|
||||
'<textarea :name="name" v-model="value" @input="update($event, name)"></textarea>' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<textarea ' +
|
||||
' :id="id"' +
|
||||
' :readonly="readonly"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' :name="name"' +
|
||||
' :placeholder="placeholder"' +
|
||||
' :value="value"' +
|
||||
' @input="update($event, name)"></textarea>' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
update: function($event, name)
|
||||
{
|
||||
FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Vue.component('component-url', {
|
||||
props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<input type="url"' +
|
||||
' :id="id"' +
|
||||
' :maxlength="maxlength"' +
|
||||
' :readonly="readonly"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' :name="name"' +
|
||||
' :placeholder="placeholder"' +
|
||||
' :value="value"' +
|
||||
'@input="update($event, name)">' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
update: function($event, name)
|
||||
{
|
||||
FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Vue.component('component-number', {
|
||||
props: ['class', 'id', 'description', 'min', 'max', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<input type="number"' +
|
||||
' :id="id"' +
|
||||
' :min="min"' +
|
||||
' :min="max"' +
|
||||
' :maxlength="maxlength"' +
|
||||
' :readonly="readonly"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' :name="name"' +
|
||||
' :placeholder="placeholder"' +
|
||||
' :value="value"' +
|
||||
'@input="update($event, name)">' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
update: function($event, name)
|
||||
{
|
||||
FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Vue.component('component-email', {
|
||||
props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<input type="email"' +
|
||||
' :id="id"' +
|
||||
' :maxlength="maxlength"' +
|
||||
' :readonly="readonly"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' :name="name"' +
|
||||
' :placeholder="placeholder"' +
|
||||
' :value="value"' +
|
||||
'@input="update($event, name)">' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
update: function($event, name)
|
||||
{
|
||||
FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Vue.component('component-tel', {
|
||||
props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<input type="tel"' +
|
||||
' :id="id"' +
|
||||
' :maxlength="maxlength"' +
|
||||
' :readonly="readonly"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' :name="name"' +
|
||||
' :placeholder="placeholder"' +
|
||||
' :value="value"' +
|
||||
'@input="update($event, name)">' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
update: function($event, name)
|
||||
{
|
||||
FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Vue.component('component-password', {
|
||||
props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<input type="password"' +
|
||||
' :id="id"' +
|
||||
' :maxlength="maxlength"' +
|
||||
' :readonly="readonly"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' :name="name"' +
|
||||
' :placeholder="placeholder"' +
|
||||
' :value="value"' +
|
||||
'@input="update($event, name)">' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
update: function($event, name)
|
||||
{
|
||||
FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Vue.component('component-date', {
|
||||
props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<input type="date" ' +
|
||||
' :id="id"' +
|
||||
' :readonly="readonly"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' :name="name"' +
|
||||
' :placeholder="placeholder"' +
|
||||
' :value="value"' +
|
||||
' @input="update($event, name)">' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
update: function($event, name)
|
||||
{
|
||||
FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Vue.component('component-color', {
|
||||
props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<input type="color" ' +
|
||||
' :id="id"' +
|
||||
' :readonly="readonly"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' :name="name"' +
|
||||
' :placeholder="placeholder"' +
|
||||
' :value="value"' +
|
||||
' @input="update($event, name)">' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
update: function($event, name)
|
||||
@ -46,13 +225,20 @@ Vue.component('component-textarea', {
|
||||
})
|
||||
|
||||
Vue.component('component-select', {
|
||||
props: ['class', 'placeholder', 'label', 'name', 'type', 'size', 'options', 'value', 'errors'],
|
||||
props: ['class', 'id', 'description', 'readonly', 'required', 'disabled', 'label', 'name', 'type', 'options', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{label}}</label>' +
|
||||
'<select v-model="value" @change="update($event,name)">' +
|
||||
'<option v-for="option,optionkey in options" v-bind:value="optionkey">{{option}}</option>' +
|
||||
'<select' +
|
||||
' :id="id"' +
|
||||
' :name="name"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' v-model="value"' +
|
||||
' @change="update($event,name)">' +
|
||||
'<option v-for="option,optionkey in options" v-bind:value="optionkey">{{option}}</option>' +
|
||||
'</select>' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
update: function($event, name)
|
||||
@ -63,13 +249,21 @@ Vue.component('component-select', {
|
||||
})
|
||||
|
||||
Vue.component('component-checkbox', {
|
||||
props: ['class', 'label', 'checkboxlabel', 'name', 'type', 'value', 'errors'],
|
||||
props: ['class', 'id', 'description', 'readonly', 'required', 'disabled', 'label', 'checkboxlabel', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<label class="control-group">{{ checkboxlabel }}' +
|
||||
'<input type="checkbox" :name="name" v-model="value" @change="update($event, value, name)">' +
|
||||
'<input type="checkbox"' +
|
||||
' :id="id"' +
|
||||
' :readonly="readonly"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' :name="name"' +
|
||||
' v-model="value"' +
|
||||
' @change="update($event, value, name)">' +
|
||||
'<span class="checkmark"></span>' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</label>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
@ -80,14 +274,50 @@ Vue.component('component-checkbox', {
|
||||
},
|
||||
})
|
||||
|
||||
Vue.component('component-checkboxlist', {
|
||||
props: ['class', 'description', 'readonly', 'required', 'disabled', 'label', 'checkboxlabel', 'options', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<label v-for="option, optionvalue in options" class="control-group">{{ option }}' +
|
||||
'<input type="checkbox"' +
|
||||
' :id="optionvalue"' +
|
||||
' :value="optionvalue"' +
|
||||
' v-model="value" ' +
|
||||
' @change="update($event, value, optionvalue, name)">' +
|
||||
'<span class="checkmark"></span>' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
update: function($event, value, optionvalue, name)
|
||||
{
|
||||
/* if value (array) for checkboxlist is not initialized yet */
|
||||
if(value === true || value === false)
|
||||
{
|
||||
value = [optionvalue];
|
||||
}
|
||||
FormBus.$emit('forminput', {'name': name, 'value' : value});
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Vue.component('component-radio', {
|
||||
props: ['label', 'options', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="medium">' +
|
||||
props: ['class', 'id', 'description', 'readonly', 'required', 'disabled', 'options', 'label', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ label }}</label>' +
|
||||
'<label v-for="option,optionvalue in options" class="control-group">{{ option }}' +
|
||||
'<input type="radio" :name="name" :value="optionvalue" v-model="value" @change="update($event, value, name)">' +
|
||||
'<input type="radio"' +
|
||||
' :id="id"' +
|
||||
' :readonly="readonly"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' :name="name"' +
|
||||
' :value="optionvalue"' +
|
||||
' v-model="value" ' +
|
||||
' @change="update($event, value, name)">' +
|
||||
'<span class="radiomark"></span>' +
|
||||
'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
|
||||
'<span v-else class="fielddescription"><small>{{ description }}</small></span>' +
|
||||
'</label>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
@ -167,12 +397,14 @@ let meta = new Vue({
|
||||
.then(function (response) {
|
||||
|
||||
var formdefinitions = response.data.metadefinitions;
|
||||
|
||||
for (var key in formdefinitions) {
|
||||
if (formdefinitions.hasOwnProperty(key)) {
|
||||
self.tabs.push(key);
|
||||
self.formErrors[key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
self.formErrorsReset = self.formErrors;
|
||||
self.formDefinitions = formdefinitions;
|
||||
|
||||
|
@ -20,6 +20,9 @@
|
||||
<link rel="stylesheet" href="{{ base_url }}/system/author/css/normalize.css" />
|
||||
<link rel="stylesheet" href="{{ base_url }}/system/author/css/style.css?20191231" />
|
||||
<link rel="stylesheet" href="{{ base_url }}/system/author/css/color-picker.min.css" />
|
||||
|
||||
{{ assets.renderCSS() }}
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<svg style="position: absolute; width: 0; height: 0; overflow: hidden" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
@ -56,13 +59,25 @@
|
||||
</article>
|
||||
<footer></footer>
|
||||
</div>
|
||||
<script src="{{ base_url }}/system/author/js/axios.min.js?20191124"></script>
|
||||
<script>
|
||||
const myaxios = axios.create();
|
||||
myaxios.defaults.baseURL = "{{ base_url }}";
|
||||
</script>
|
||||
<script src="{{ base_url }}/system/author/js/vue.min.js?20191231"></script>
|
||||
<script src="{{ base_url }}/system/author/js/autosize.min.js?20191231"></script>
|
||||
<script src="{{ base_url }}/system/author/js/sortable.min.js?20191231"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vuedraggable.umd.min.js?20191231"></script>
|
||||
<script src="{{ base_url }}/system/author/js/author.js?20191231"></script>
|
||||
|
||||
{{ assets.renderEditorJS() }}
|
||||
|
||||
<script src="{{ base_url }}/system/author/js/vue-publishcontroller.js?20191231"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-editor.js?20191231"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-meta.js?20191231"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-navi.js?20191231"></script>
|
||||
|
||||
{{ assets.renderJS() }}
|
||||
|
||||
</body>
|
||||
</html>
|
@ -3,19 +3,30 @@ meta:
|
||||
title:
|
||||
type: text
|
||||
label: Meta title
|
||||
size: 60
|
||||
maxlength: 60
|
||||
class: large
|
||||
description:
|
||||
type: textarea
|
||||
label: Meta description
|
||||
size: 160
|
||||
class: large
|
||||
description: If not filled, the description is extracted from content.
|
||||
author:
|
||||
type: text
|
||||
label: author
|
||||
class: large
|
||||
description: Taken from your user account if set.
|
||||
manualdate:
|
||||
type: date
|
||||
label: Manual date
|
||||
modified:
|
||||
type: date
|
||||
label: Last modified at (readonly)
|
||||
label: Last modified live (readonly)
|
||||
readonly: readonly
|
||||
class: large
|
||||
class: medium
|
||||
description: Used as fallback when no manual date is set.
|
||||
created:
|
||||
type: date
|
||||
label: Created at (readonly)
|
||||
readonly: readonly
|
||||
class: medium
|
@ -23,6 +23,22 @@
|
||||
<span class="error">{{ errors.username | first }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="large{{ errors.firstname ? ' errors' : '' }}">
|
||||
<label for="firstname">First Name</label>
|
||||
<input type="text" name="firstname" value="{{ old.firstname ? old.firstname : userdata.firstname }}">
|
||||
{% if errors.firstname %}
|
||||
<span class="error">{{ errors.firstname | first }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="large{{ errors.lastname ? ' errors' : '' }}">
|
||||
<label for="lastname">Last Name</label>
|
||||
<input type="text" name="lastname" value="{{ old.lastname ? old.lastname : userdata.lastname }}">
|
||||
{% if errors.lastname %}
|
||||
<span class="error">{{ errors.lastname | first }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="large{{ errors.email ? ' errors' : '' }}">
|
||||
<label for="email">E-Mail <abbr title="required">*</abbr></label>
|
||||
@ -48,7 +64,7 @@
|
||||
|
||||
<div class="large{{ errors.password ? ' errors' : '' }}">
|
||||
<label for="password">Actual Password</label>
|
||||
<input type="password" name="password">
|
||||
<input type="password" name="password" autocomplete="off">
|
||||
{% if errors.password %}
|
||||
<span class="error">{{ errors.password | first }}</span>
|
||||
{% endif %}
|
||||
@ -56,7 +72,7 @@
|
||||
|
||||
<div class="large{{ errors.newpassword ? ' errors' : '' }}">
|
||||
<label for="newpassword">New Password</label>
|
||||
<input type="password" name="newpassword">
|
||||
<input type="password" name="newpassword" autocomplete="off">
|
||||
{% if errors.newpassword %}
|
||||
<span class="error">{{ errors.newpassword | first }}</span>
|
||||
{% endif %}
|
||||
|
@ -22,7 +22,23 @@
|
||||
<span class="error">{{ errors.username | first }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="large{{ errors.firstname ? ' errors' : '' }}">
|
||||
<label for="firstname">First Name</label>
|
||||
<input type="text" name="firstname" value="{{ old.firstname ? old.firstname : userdata.firstname }}">
|
||||
{% if errors.firstname %}
|
||||
<span class="error">{{ errors.firstname | first }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="large{{ errors.lastname ? ' errors' : '' }}">
|
||||
<label for="lastname">Last Name</label>
|
||||
<input type="text" name="lastname" value="{{ old.lastname ? old.lastname : userdata.lastname }}">
|
||||
{% if errors.lastname %}
|
||||
<span class="error">{{ errors.lastname | first }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="large{{ errors.email ? ' errors' : '' }}">
|
||||
<label for="email">E-Mail <abbr title="required">*</abbr></label>
|
||||
<input type="text" name="email" value="{{ old.email ? old.email : '' }}" required>
|
||||
@ -45,7 +61,7 @@
|
||||
|
||||
<div class="large{{ errors.password ? ' errors' : '' }}">
|
||||
<label for="password">Password <abbr title="required">*</abbr></label>
|
||||
<input type="password" name="password" required>
|
||||
<input type="password" name="password" autocomplete="off" required>
|
||||
{% if errors.password %}
|
||||
<span class="error">{{ errors.password | first }}</span>
|
||||
{% endif %}
|
||||
|
@ -1,3 +1,5 @@
|
||||
{% set published = metatabs.meta.manualdate ? metatabs.meta.manualdate : metatabs.meta.modified %}
|
||||
|
||||
{% if content is empty %}
|
||||
|
||||
<h1>{{ item.name }}</h1>
|
||||
@ -9,10 +11,10 @@
|
||||
{% if (settings.themes.typemill.socialPosition.top or settings.themes.typemill.modifiedPosition.top or settings.themes.typemill.authorPosition.top or settings.themes.typemill.gitPosition.top) %}
|
||||
<div class="meta-info">
|
||||
{% if settings.themes.typemill.authorPosition.top %}
|
||||
<small>{{ settings.themes.typemill.authorIntro }}: {{ settings.author }}</small>
|
||||
<small>{{ settings.themes.typemill.authorIntro }}: {{ metatabs.meta.author|default(settings.author) }}</small>
|
||||
{% endif %}
|
||||
{% if settings.themes.typemill.modifiedPosition.top %}
|
||||
<small>{{ settings.themes.typemill.modifiedText }}: {{ metatabs.meta.modified|date(settings.themes.typemill.modifiedFormat) }}</small>
|
||||
<small>{{ settings.themes.typemill.modifiedText }}: {{ published|date(settings.themes.typemill.modifiedFormat) }}</small>
|
||||
{% endif %}
|
||||
{% if settings.themes.typemill.socialPosition.top %}
|
||||
<div id="share-icons" class="share-icons hide">
|
||||
@ -34,10 +36,10 @@
|
||||
{% if (settings.themes.typemill.socialPosition.bottom or settings.themes.typemill.modifiedPosition.bottom or settings.themes.typemill.authorPosition.bottom or settings.themes.typemill.gitPosition.bottom) %}
|
||||
<div class="meta-info">
|
||||
{% if settings.themes.typemill.authorPosition.bottom %}
|
||||
<small>{{ settings.themes.typemill.authorIntro }}: {{ settings.author }}</small>
|
||||
<small>{{ settings.themes.typemill.authorIntro }}: {{ metatabs.meta.author|default(settings.author) }}</small>
|
||||
{% endif %}
|
||||
{% if settings.themes.typemill.modifiedPosition.bottom %}
|
||||
<small>{{ settings.themes.typemill.modifiedText }}: {{ metatabs.meta.modified|date(settings.themes.typemill.modifiedFormat) }}</small>
|
||||
<small>{{ settings.themes.typemill.modifiedText }}: {{ published|date(settings.themes.typemill.modifiedFormat) }}</small>
|
||||
{% endif %}
|
||||
{% if settings.themes.typemill.socialPosition.bottom %}
|
||||
<div id="share-icons-bottom" class="share-icons hide">
|
||||
|
@ -69,6 +69,7 @@
|
||||
<script src="{{ base_url }}/themes/typemill/js/script.js"></script>
|
||||
<script src="{{ base_url }}/system/author/js/lazy-video.js?20190602"></script>
|
||||
<script>typemillUtilities.start();</script>
|
||||
|
||||
{{ assets.renderJS() }}
|
||||
|
||||
{% endblock %}
|
||||
|
@ -1,5 +1,5 @@
|
||||
name: Typemill Theme
|
||||
version: 1.2.0
|
||||
version: 1.2.1
|
||||
description: The standard theme for Typemill. Responsive, minimal and without any dependencies. It uses the system fonts Calibri and Helvetica. No JavaScript is used.
|
||||
author: Sebastian Schürmanns
|
||||
homepage: https://typemill.net
|
||||
|
Loading…
x
Reference in New Issue
Block a user