mirror of
https://github.com/typemill/typemill.git
synced 2025-01-17 21:38:25 +01:00
Version 1.3.3: Posts and Pages
This commit is contained in:
commit
3069d0dc05
@ -683,6 +683,9 @@ form .large, form .medium, form .small{
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
form .hidden{
|
||||
display: none;
|
||||
}
|
||||
.large img{
|
||||
width: 100%;
|
||||
}
|
||||
@ -932,7 +935,7 @@ ul.cardInfo{
|
||||
border: 0px;
|
||||
}
|
||||
.cardFields.open{
|
||||
max-height: 2800px;
|
||||
max-height: 5000px;
|
||||
transition: max-height 0.5s ease-in;
|
||||
overflow: hidden;
|
||||
border: 1px;
|
||||
@ -957,6 +960,19 @@ ul.cardInfo{
|
||||
display: inline-block;
|
||||
margin: 10px 0;
|
||||
}
|
||||
.cardField.full{
|
||||
width: 100%;
|
||||
}
|
||||
.cardField.half{
|
||||
width: 49.5%;
|
||||
float: left;
|
||||
margin-right:0.5%;
|
||||
}
|
||||
.cardField.third{
|
||||
width: 32%;
|
||||
float:left;
|
||||
margin-right: 1%;
|
||||
}
|
||||
.cardField label{
|
||||
width: 100%;
|
||||
margin-top: 0px;
|
||||
@ -1650,6 +1666,65 @@ button.hdown:hover,button.hdown:focus,button.hdown:active{
|
||||
}
|
||||
|
||||
|
||||
.blog-post{
|
||||
|
||||
}
|
||||
.blog-post svg{
|
||||
color: #ccc;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.blog-post a,
|
||||
.blog-post a:link,
|
||||
.blog-post a:visited{
|
||||
color: #444;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
padding: 0px 15px;
|
||||
margin: 5px 0;
|
||||
border-left: 3px solid;
|
||||
box-sizing: border-box;
|
||||
background-color: #f9f8f6;
|
||||
}
|
||||
.blog-post a:focus,
|
||||
.blog-post a:hover,
|
||||
.blog-post a:active{
|
||||
background-color: #f6f5f3;
|
||||
}
|
||||
.blog-post a.unpublished{
|
||||
border-color: #cc4146;
|
||||
}
|
||||
.blog-post a.published{
|
||||
border-color: #66b0a3;
|
||||
}
|
||||
.blog-post a.modified{
|
||||
border-color: #FFA500;
|
||||
}
|
||||
.blog-post .post-date{
|
||||
float: right;
|
||||
font-size: 0.8em;
|
||||
font-weight: 300;
|
||||
color: #444;
|
||||
}
|
||||
.posts.formWrapper{
|
||||
margin: 20px 0;
|
||||
}
|
||||
.posts input{
|
||||
width: 80%;
|
||||
float: left;
|
||||
}
|
||||
button.post-button{
|
||||
color: #f9f8f6;
|
||||
background: #66b0a3;
|
||||
border: 0px;
|
||||
width: 20%;
|
||||
text-align: center;
|
||||
}
|
||||
button.post-button:hover{
|
||||
background: #4D978A;
|
||||
}
|
||||
|
||||
|
||||
/* .format-bar at the bottom of the page */
|
||||
|
||||
/********************
|
||||
|
@ -75,6 +75,24 @@
|
||||
|
||||
</section>
|
||||
|
||||
{% if item.elementType == "folder" %}
|
||||
|
||||
<section id="posts" v-if="posts">
|
||||
<div class="posts formWrapper">
|
||||
<input v-model="posttitle" type="text" maxlength="60" name="title" placeholder="add a short title">
|
||||
<button type="button" @click.prevent="createPost()" class="post-button">create new post</button>
|
||||
</div>
|
||||
<div>
|
||||
<single-post
|
||||
v-for="post in posts"
|
||||
v-bind:key="post.keyPath"
|
||||
v-bind:post="post"
|
||||
></single-post>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% include 'editor/publish-controller.twig' %}
|
||||
|
||||
<input id="path" type="hidden" value="{{ item.urlRel }}" required readonly />
|
||||
|
@ -18,7 +18,6 @@ let typemillUtilities = {
|
||||
|
||||
addYoutubePlayButton: function(element)
|
||||
{
|
||||
console.info(element.parentNode);
|
||||
element.parentNode.classList.add("video-container");
|
||||
|
||||
var youtubePlaybutton = document.createElement("button");
|
||||
@ -28,12 +27,6 @@ let typemillUtilities = {
|
||||
element.parentNode.appendChild(youtubePlaybutton);
|
||||
},
|
||||
|
||||
start: function(){
|
||||
this.setYoutubeItems();
|
||||
this.addYoutubePlayButtons();
|
||||
this.listenToYoutube();
|
||||
},
|
||||
|
||||
listenToYoutube: function(){
|
||||
document.addEventListener('click', function (event) {
|
||||
|
||||
@ -58,4 +51,10 @@ let typemillUtilities = {
|
||||
}
|
||||
}, true);
|
||||
},
|
||||
|
||||
start: function(){
|
||||
this.setYoutubeItems();
|
||||
this.addYoutubePlayButtons();
|
||||
this.listenToYoutube();
|
||||
},
|
||||
};
|
@ -1,13 +1,14 @@
|
||||
const FormBus = new Vue();
|
||||
|
||||
Vue.component('component-text', {
|
||||
props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
|
||||
props: ['class', 'id', 'description', 'maxlength', 'hidden', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
|
||||
template: '<div class="large">' +
|
||||
'<label>{{ $t(label) }}</label>' +
|
||||
'<input type="text"' +
|
||||
' :id="id"' +
|
||||
' :maxlength="maxlength"' +
|
||||
' :readonly="readonly"' +
|
||||
' :hidden="hidden"' +
|
||||
' :required="required"' +
|
||||
' :disabled="disabled"' +
|
||||
' :name="name"' +
|
||||
@ -357,11 +358,10 @@ Vue.component('tab-meta', {
|
||||
|
||||
let meta = new Vue({
|
||||
|
||||
i18n: new VueI18n({
|
||||
locale: language,
|
||||
messages: vuejsLabels
|
||||
}),
|
||||
|
||||
i18n: new VueI18n({
|
||||
locale: language,
|
||||
messages: vuejsLabels
|
||||
}),
|
||||
delimiters: ['${', '}'],
|
||||
el: '#metanav',
|
||||
data: function () {
|
||||
@ -416,6 +416,16 @@ let meta = new Vue({
|
||||
|
||||
self.formData = response.data.metadata;
|
||||
|
||||
var item = response.data.item;
|
||||
if(item.elementType == "folder" && item.contains == "posts")
|
||||
{
|
||||
posts.posts = item.folderContent;
|
||||
posts.folderid = item.keyPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
posts.posts = false;
|
||||
}
|
||||
})
|
||||
.catch(function (error)
|
||||
{
|
||||
@ -449,6 +459,17 @@ let meta = new Vue({
|
||||
{
|
||||
navi.items = response.data.structure;
|
||||
}
|
||||
|
||||
var item = response.data.item;
|
||||
if(item.elementType == "folder" && item.contains == "posts")
|
||||
{
|
||||
posts.posts = item.folderContent;
|
||||
posts.folderid = item.keyPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
posts.posts = false;
|
||||
}
|
||||
})
|
||||
.catch(function (error)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
const navcomponent = Vue.component('navigation', {
|
||||
template: '#navigation-template',
|
||||
props: ['homepage', 'showForm', 'name', 'hide', 'newItem', 'parent', 'active', 'filetype', 'status', 'elementtype', 'element', 'folder', 'level', 'url', 'root', 'freeze'],
|
||||
props: ['homepage', 'showForm', 'name', 'hide', 'newItem', 'parent', 'active', 'filetype', 'status', 'elementtype', 'contains', 'element', 'folder', 'level', 'url', 'root', 'freeze'],
|
||||
data: function () {
|
||||
return {
|
||||
showForm: false,
|
||||
@ -134,9 +134,9 @@ const navcomponent = Vue.component('navigation', {
|
||||
{
|
||||
publishController.errors.message = false;
|
||||
|
||||
if(this.$root.$data.format.test(this.newItem) || !this.newItem || this.newItem.length > 40)
|
||||
if(this.$root.$data.format.test(this.newItem) || !this.newItem || this.newItem.length > 60)
|
||||
{
|
||||
publishController.errors.message = 'Special Characters are not allowed. Length between 1 and 40.';
|
||||
publishController.errors.message = 'Special Characters are not allowed. Length between 1 and 60.';
|
||||
return;
|
||||
}
|
||||
|
||||
@ -194,13 +194,13 @@ let navi = new Vue({
|
||||
data: function () {
|
||||
return {
|
||||
title: "Navigation",
|
||||
items: JSON.parse(document.getElementById("data-navi").dataset.navi),
|
||||
items: navigation,
|
||||
homepage: JSON.parse(document.getElementById("data-navi").dataset.homepage),
|
||||
editormode: document.getElementById("data-navi").dataset.editormode,
|
||||
root: document.getElementById("main").dataset.url,
|
||||
freeze: false,
|
||||
modalWindow: false,
|
||||
format: /[!@#$%^&*()_+=\[\]{};':"\\|,.<>\/?]/,
|
||||
format: /[@#*()=\[\]{};:"\\|,.<>\/]/,
|
||||
folderName: '',
|
||||
showForm: false,
|
||||
newItem: '',
|
||||
|
68
system/author/js/vue-posts.js
Normal file
68
system/author/js/vue-posts.js
Normal file
@ -0,0 +1,68 @@
|
||||
Vue.component('single-post', {
|
||||
props: ['post'],
|
||||
template: '<div class="blog-post">' +
|
||||
'<a :class="post.status" :href="getUrl(post.urlRelWoF)">' +
|
||||
'<h4><svg class="icon baseline icon-file-text-o"><use xlink:href="#icon-file-text-o"></use></svg> {{ post.name }} <span class="post-date">{{ getDate(post.order) }}</span></h4>' +
|
||||
'</a>' +
|
||||
'</div>',
|
||||
methods: {
|
||||
getUrl: function(posturl){
|
||||
return this.$root.$data.root + '/tm/content/' + this.$root.$data.editormode + posturl;
|
||||
},
|
||||
getDate: function(str){
|
||||
var cleandate = [str.slice(0,4), str.slice(4,6), str.slice(6,8)];
|
||||
return cleandate.join("-");
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let posts = new Vue({
|
||||
el: "#posts",
|
||||
data: function () {
|
||||
return {
|
||||
posts: false,
|
||||
posttitle: '',
|
||||
folderid: false,
|
||||
format: /[@#*()=\[\]{};:"\\|,.<>\/]/,
|
||||
root: document.getElementById("main").dataset.url,
|
||||
editormode: document.getElementById("data-navi").dataset.editormode
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
createPost: function(evt){
|
||||
|
||||
publishController.errors.message = false;
|
||||
|
||||
if(this.format.test(this.posttitle) || this.posttitle == '' || this.posttitle.length > 60)
|
||||
{
|
||||
publishController.errors.message = 'Special Characters are not allowed. Length between 1 and 60.';
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
myaxios.post('/api/v1/post',{
|
||||
'folder_id': this.folderid,
|
||||
'item_name': this.posttitle,
|
||||
'type': 'file',
|
||||
'url': document.getElementById("path").value,
|
||||
'csrf_name': document.getElementById("csrf_name").value,
|
||||
'csrf_value': document.getElementById("csrf_value").value,
|
||||
})
|
||||
.then(function (response) {
|
||||
if(response.data.posts)
|
||||
{
|
||||
self.posts = response.data.posts.folderContent;
|
||||
self.posttitle = '';
|
||||
}
|
||||
})
|
||||
.catch(function (error)
|
||||
{
|
||||
if(error.response)
|
||||
{
|
||||
publishController.errors.message = error.response.data.errors;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
@ -163,33 +163,35 @@
|
||||
<article>
|
||||
{% block content %}{% endblock %}
|
||||
</article>
|
||||
<footer></footer>
|
||||
<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?20200226"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-i18n.min.js?20200226"></script>
|
||||
<script src="{{ base_url }}/system/author/js/autosize.min.js?20200226"></script>
|
||||
<script src="{{ base_url }}/system/author/js/sortable.min.js?20200226"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vuedraggable.umd.min.js?20200226"></script>
|
||||
<script src="{{ base_url }}/system/author/js/author.js?20200226"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-publishcontroller.js?20200226"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-blox-config.js?20200226"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue.min.js?20200120"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-i18n.min.js?20200120"></script>
|
||||
<script src="{{ base_url }}/system/author/js/autosize.min.js?20200120"></script>
|
||||
<script src="{{ base_url }}/system/author/js/author.js?20200120"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-publishcontroller.js?20200120"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-blox-config.js?20200120"></script>
|
||||
<script>
|
||||
let formatConfig = {{ settings.formats|json_encode() }};
|
||||
let language = {{ settings.language|json_encode() }};
|
||||
let vuejsLabels = {{ settings.vuejsLabels|json_encode() }};
|
||||
let navigation = {{ navigation|json_encode() }};
|
||||
</script>
|
||||
|
||||
{{ assets.renderEditorJS() }}
|
||||
|
||||
<script src="{{ base_url }}/system/author/js/vue-blox.js?20200226"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-meta.js?20200226"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-navi.js?20200226"></script>
|
||||
<script src="{{ base_url }}/system/author/js/lazy-video.js?20200226"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-blox.js?20200120"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-posts.js?20200120"></script>
|
||||
<script src="{{ base_url }}/system/author/js/sortable.min.js?20200120"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vuedraggable.umd.min.js?20200120"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-navi.js?20200120"></script>
|
||||
<script src="{{ base_url }}/system/author/js/vue-meta.js?20200120"></script>
|
||||
<script src="{{ base_url }}/system/author/js/lazy-video.js?20200120"></script>
|
||||
|
||||
{{ assets.renderJS() }}
|
||||
|
||||
|
@ -27,9 +27,15 @@ meta:
|
||||
description: Used as fallback when no manual date is set.
|
||||
created:
|
||||
type: date
|
||||
label: Created at (readonly)
|
||||
label: Created at (read only)
|
||||
readonly: readonly
|
||||
class: medium
|
||||
time:
|
||||
type: text
|
||||
readonly: readonly
|
||||
hidden: true
|
||||
class: hidden
|
||||
pattern: '[0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
|
||||
navtitle:
|
||||
type: text
|
||||
label: Navigation Title
|
||||
@ -45,17 +51,6 @@ meta:
|
||||
# label: Show page to
|
||||
# class: medium
|
||||
# options:
|
||||
# null: null
|
||||
# public: Public (standard)
|
||||
# members: Members only (logged in)
|
||||
# customers: Customers only (paying)
|
||||
# list:
|
||||
# type: select
|
||||
# label: List sub-pages
|
||||
# class: medium
|
||||
# options:
|
||||
# null: null
|
||||
# standard: Standard order
|
||||
# revert: Reverse order
|
||||
# asc: Date ascending
|
||||
# desc: Date descending
|
||||
# customers: Customers only (paying)
|
@ -1,5 +1,5 @@
|
||||
<nav id="sidebar-menu" class="sidebar-menu--content">
|
||||
<div id="data-navi" data-navi='{{ navigation|json_encode() }}' data-homepage='{{ homepage|json_encode() }}' data-editormode="{{settings.editor}}"></div>
|
||||
<div id="data-navi" data-homepage='{{ homepage|json_encode() }}' data-editormode="{{settings.editor}}"></div>
|
||||
<div id="mobile-menu" class="menu-action">{{ __('Menu') }} <span class="button-arrow"></span></div>
|
||||
<div id="navi" class="content-navi" v-model="freeze" v-cloak>
|
||||
<div class="navi-list">
|
||||
@ -17,7 +17,7 @@
|
||||
animation="150"
|
||||
:disabled="freeze">
|
||||
<navigation
|
||||
v-for="item in items"
|
||||
v-for="item in items"
|
||||
ref="draggit"
|
||||
:freeze="freeze"
|
||||
:name="item.name"
|
||||
@ -30,8 +30,9 @@
|
||||
:id="item.keyPath"
|
||||
:key="item.keyPath"
|
||||
:elementtype="item.elementType"
|
||||
:contains="item.contains"
|
||||
:filetype="item.fileType"
|
||||
:status="item.status"
|
||||
:status="item.status"
|
||||
:folder="item.folderContent"
|
||||
></navigation>
|
||||
</draggable>
|
||||
@ -61,7 +62,7 @@
|
||||
<a v-bind:href="getUrl(root, url)" :class="checkActive(active,parent)"><span class="iconwrapper"><svg class="icon" :class="getIconClass(elementtype, filetype, hide)"><use :xlink:href="getIcon(elementtype, filetype, hide)"></use></svg></span><span :class="getLevel(level)">{{ name }}</span><span class="movewrapper"><span class="movewrapper"><svg class="icon icon-arrows-v"><use xlink:href="#icon-arrows-v"></use></svg></span></a>
|
||||
<draggable v-if="folder" class="navi-list" tag="ul"
|
||||
@start="onStart"
|
||||
@end="onEnd"
|
||||
@end="onEnd"
|
||||
:list="folder"
|
||||
:move="checkMove"
|
||||
group="file"
|
||||
@ -69,6 +70,7 @@
|
||||
:disabled="freeze">
|
||||
<navigation
|
||||
v-for="item in folder"
|
||||
v-if="contains == 'pages'"
|
||||
ref="draggit"
|
||||
:freeze="freeze"
|
||||
:name="item.name"
|
||||
@ -82,11 +84,12 @@
|
||||
:key="item.keyPath"
|
||||
:filetype="item.fileType"
|
||||
:status="item.status"
|
||||
:elementtype="item.elementType"
|
||||
:elementtype="item.elementType"
|
||||
:contains="item.contains"
|
||||
:folder="item.folderContent"
|
||||
></navigation>
|
||||
</draggable>
|
||||
<ul v-if="folder" class="navi-list">
|
||||
<ul v-if="folder && contains == 'pages'" class="navi-list">
|
||||
<li class="navi-item file">
|
||||
<span class="iconwrapper">
|
||||
<svg class="icon icon-plus"><use xlink:href="#icon-plus"></use></svg>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="cardField{{ errors[itemName][field.name] ? ' error' : '' }}">
|
||||
<div class="cardField{{ errors[itemName][field.name] ? ' error' : '' }}{{field.fieldsize ? ' ' ~ field.fieldsize : ''}}">
|
||||
|
||||
<label for="{{ itemName }}[{{ field.name }}]">{{ __( field.getLabel() ) }}
|
||||
{% if field.getAttribute('required') %}<strong><abbr title="{{ __('required') }}">*</abbr></strong>{% endif %}
|
||||
|
@ -22,7 +22,7 @@
|
||||
<div class="cardInner cardHead">
|
||||
|
||||
{% if theme.img %}
|
||||
<img src="{{ base_url() }}/themes/{{themeName}}/{{themeName}}.jpg" />
|
||||
<img src="{{ base_url() }}/themes/{{themeName}}/{{ theme.img }}" />
|
||||
{% else %}
|
||||
<div class="no-preview">{{ __('No Preview') }}</div>
|
||||
{% endif %}
|
||||
@ -32,7 +32,7 @@
|
||||
|
||||
<div class="cardDescription">
|
||||
<h2>{{ themeName }}</h2>
|
||||
<p>{{ __('TYPEMILL_DESCRIPTION') }}</p>
|
||||
<p>{{ theme.description }}</p>
|
||||
<ul class="cardInfo">
|
||||
<li>{{ theme.version ? theme.version : __('Unknown') }}</li><li>
|
||||
{{ theme.licence ? theme.licence : __('Unkown') }}</li><li>
|
||||
|
Loading…
x
Reference in New Issue
Block a user