Last fixes official release
58
cache/cyanine-custom.css
vendored
@@ -1,30 +1,30 @@
|
||||
.landingpageintro h1{
|
||||
display: inline-block;
|
||||
background: white;
|
||||
padding: 4px 10px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.landingpageintro p{
|
||||
display: inline;
|
||||
background: white;
|
||||
line-height: 2.1rem;
|
||||
padding: 6px 4px 4px;
|
||||
}
|
||||
article a[href^="http"]::after,
|
||||
article a[href^="https://"]::after
|
||||
{
|
||||
content: "";
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
margin-left: 4px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5z'/%3E%3Cpath fill-rule='evenodd' d='M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0v-5z'/%3E%3C/svg%3E");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
display: inline-block;
|
||||
}
|
||||
a[href^="https://www.electrictoolbox.com"] {
|
||||
background: none;
|
||||
padding-right: 0;
|
||||
.landingpageintro h1{
|
||||
display: inline-block;
|
||||
background: white;
|
||||
padding: 4px 10px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.landingpageintro p{
|
||||
display: inline;
|
||||
background: white;
|
||||
line-height: 2.1rem;
|
||||
padding: 6px 4px 4px;
|
||||
}
|
||||
article a[href^="http"]::after,
|
||||
article a[href^="https://"]::after
|
||||
{
|
||||
content: "";
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
margin-left: 4px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5z'/%3E%3Cpath fill-rule='evenodd' d='M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0v-5z'/%3E%3C/svg%3E");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
display: inline-block;
|
||||
}
|
||||
a[href^="https://www.electrictoolbox.com"] {
|
||||
background: none;
|
||||
padding-right: 0;
|
||||
}
|
@@ -3,6 +3,8 @@ meta:
|
||||
owner: Sebastian
|
||||
created: '2023-06-12'
|
||||
time: 22-36-14
|
||||
modified: '2023-03-26'
|
||||
title: 'Typemill provides detailed settings, and you have access to nearly all settings in the author panel. Learn the basics in this short video:'
|
||||
modified: '2023-10-23'
|
||||
title: 'Setup your website'
|
||||
description: ' You will find all configurations and settings under the main navigation point settings with the following sub-navigation:'
|
||||
hide: false
|
||||
noindex: false
|
||||
|
@@ -1,8 +1,16 @@
|
||||
meta:
|
||||
navtitle: 'manage access'
|
||||
title: 'Manage access'
|
||||
description: ' Restrict Access for the Website'
|
||||
heroimage: null
|
||||
heroimagealt: null
|
||||
owner: Sebastian
|
||||
author: null
|
||||
allowedrole: null
|
||||
alloweduser: null
|
||||
manualdate: null
|
||||
modified: '2023-05-06'
|
||||
created: '2023-06-12'
|
||||
time: 22-36-36
|
||||
modified: '2023-05-06'
|
||||
title: 'Typemill has a build-in system to restrict access to pages or to the whole websites. You can activate both features in the system settings under the section "access rights". If you activate one of the features, then Typemill will use session cookies on all frontend pages. Learn all the details in the following video tutorial:'
|
||||
description: ' Restrict Access for the Website'
|
||||
hide: false
|
||||
noindex: false
|
||||
|
@@ -1,8 +1,16 @@
|
||||
meta:
|
||||
navtitle: 'get help'
|
||||
title: 'get help'
|
||||
description: 'If you found a bug or if you have a question, then please open a new issue on GitHub. Do you need professional help, an individual theme or a special plugin?'
|
||||
heroimage: null
|
||||
heroimagealt: null
|
||||
owner: Sebastian
|
||||
author: null
|
||||
allowedrole: null
|
||||
alloweduser: null
|
||||
manualdate: null
|
||||
modified: '2023-05-13'
|
||||
created: '2023-06-12'
|
||||
time: 22-36-34
|
||||
modified: '2023-05-13'
|
||||
title: 'If you need any help, then please read the [documentation on typemill.net](https://typemill.net/typemill) first. You can also check these [video-tutorials](https://www.youtube.com/channel/UCyghKiX2kK9QIqTf1WT1Xxw) about the basics to create a typemill website.'
|
||||
description: 'If you found a bug or if you have a question, then please open a new issue on GitHub. Do you need professional help, an individual theme or a special plugin?'
|
||||
hide: false
|
||||
noindex: false
|
||||
|
@@ -28,6 +28,7 @@ Headlines are simply done with hash chars like this:
|
||||
|
||||
|
||||
|
||||
|
||||
### Third Level Headline
|
||||
|
||||
A third headline is more decent and lower prioritized than a second level headline.
|
||||
@@ -55,6 +56,7 @@ A paragraph is a simple text-block separated with a new line above and below.
|
||||
|
||||
|
||||
|
||||
|
||||
A paragraph is a simple text-block separated with a new line above and below.
|
||||
|
||||
## Soft Linebreak
|
||||
@@ -70,6 +72,7 @@ He said: "again"
|
||||
|
||||
|
||||
|
||||
|
||||
For a soft linebreak (eg. for dialoges in literature), add two spaces at the end of a line and use a simple return.
|
||||
|
||||
She said: "Hello"
|
||||
@@ -87,6 +90,7 @@ For bold text use two **asterix** or two __underscores__.
|
||||
|
||||
|
||||
|
||||
|
||||
For italic text use one *asterix* or one _underscore_.
|
||||
|
||||
For bold text use two **asterix** or two __underscores__.
|
||||
@@ -110,6 +114,7 @@ For an ordered list use whatever number you want and add a dot:
|
||||
|
||||
|
||||
|
||||
|
||||
For an unordered list use a dash
|
||||
|
||||
* like
|
||||
@@ -137,6 +142,7 @@ Easily created for example with three dashes like this:
|
||||
|
||||
|
||||
|
||||
|
||||
Easily created for example with three dashes like this:
|
||||
|
||||
---
|
||||
@@ -156,6 +162,7 @@ You can even use a download-link like []()
|
||||
|
||||
|
||||
|
||||
|
||||
This is an ordinary [Link](http://typemill.net).
|
||||
|
||||
Links can also be [relative](/info).
|
||||
@@ -186,6 +193,7 @@ The same rules as with links, but with a !
|
||||
|
||||
|
||||
|
||||
|
||||
The same rules as with links, but with a !
|
||||
|
||||

|
||||
@@ -207,6 +215,7 @@ You can link an image with a nested syntax like this:
|
||||
|
||||
|
||||
|
||||
|
||||
You can link an image with a nested syntax like this:
|
||||
|
||||
[{.imgClass}](https://typemill.net)
|
||||
@@ -228,6 +237,7 @@ You can controll the image position with the classes .left, .right and .middle l
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
The first image should float on the left side of this paragraph. This might not work with all themes. If you are a theme developer, please ensure that you support the image classes "left", "right" and "center". You can add these classes manually in the raw mode or you can assign them in the visual mode when you edit a picture (double click on it to open the dialog). Images in a separate line are rendered with the html5 elements `figure` and `figcapture`.
|
||||
@@ -254,6 +264,7 @@ There are always some women and men with wise words
|
||||
|
||||
|
||||
|
||||
|
||||
There always some women and men with wise words
|
||||
|
||||
> But I usually don't read them, to be honest.
|
||||
@@ -273,6 +284,7 @@ Add the footnote text at the bottom of the page like this:
|
||||
|
||||
|
||||
|
||||
|
||||
You can write footnotes[^1] with markdown.
|
||||
|
||||
Scroll down to the end of the page[^2] and look for the footnotes.
|
||||
@@ -291,6 +303,7 @@ Footnotes won't work with the visual editor right now, so please use the raw mod
|
||||
|
||||
|
||||
|
||||
|
||||
You won't see the abbreviation directly, but if you write HTML or W3C somewhere, then you can see the tooltip with the explanation.
|
||||
|
||||
*[HTML]: Hyper Text Markup Language
|
||||
@@ -311,6 +324,7 @@ Orange
|
||||
|
||||
|
||||
|
||||
|
||||
Apple
|
||||
: Pomaceous fruit of plants of the genus Malus in
|
||||
the family Rosaceae.
|
||||
@@ -322,18 +336,18 @@ Orange
|
||||
|
||||
You can create different notices if you add a '!', '!!', '!!!', '!!!!' before a line. This will wrap the content into a div-class with the classes `notice1`, `notice2`, `notice3` and `notice4`. You can also span notices over several lines. This logic follows some other CMS like Grav, Lektor or Yellow and it is not compatible with other markdown processors or editors.
|
||||
|
||||
> ! Notice 1
|
||||
> !
|
||||
> ! Please note that you can use **markdown** inside of the notice so you can *format* your text here.
|
||||
|
||||
Notice 2
|
||||
|
||||
Please note that you can use **markdown** inside of the notice so you can *format* your text here.
|
||||
|
||||
! **Notice 3**
|
||||
! Notice 1
|
||||
!
|
||||
! Please note that you can use **markdown** inside of the notice so you can *format* your text here.
|
||||
|
||||
!! **Notice 2**
|
||||
!!
|
||||
!! Please note that you can use **markdown** inside of the notice so you can *format* your text here.
|
||||
|
||||
!!! **Notice 3**
|
||||
!!!
|
||||
!!! Please note that you can use **markdown** inside of the notice so you can *format* your text here.
|
||||
|
||||
## Tables
|
||||
|
||||
````
|
||||
@@ -348,6 +362,7 @@ Please note that you can use **markdown** inside of the notice so you can *forma
|
||||
|
||||
|
||||
|
||||
|
||||
| Name | Usage |
|
||||
|---|---|
|
||||
| My Name | For Me |
|
||||
@@ -364,6 +379,7 @@ Let us create some `<?php inlineCode(); ?>` like this
|
||||
|
||||
|
||||
|
||||
|
||||
Let us create some `<?php inlineCode(); ?>` and now let us check, if a codeblock works:
|
||||
|
||||
````
|
||||
@@ -381,6 +397,7 @@ Use four apostroph like this:
|
||||
|
||||
|
||||
|
||||
|
||||
## Math
|
||||
|
||||
Please activate the math-plugin to use mathematical expressions with LaTeX syntax. You can choose between MathJax or the newer KaTeX library. MathJax is included from a CDN, KaTeX is included in the plugin. So if you don't want to fetch code from a CDN, use KaTeX instead. The markdown syntax in TYPEMILL is the same for both libraries.
|
||||
@@ -396,6 +413,7 @@ inline \(x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a)\) math
|
||||
|
||||
|
||||
|
||||
|
||||
inline $x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a)$ math
|
||||
|
||||
inline \(x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a)\) math
|
||||
@@ -415,6 +433,7 @@ x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a)
|
||||
|
||||
|
||||
|
||||
|
||||
$$
|
||||
x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a)
|
||||
$$
|
@@ -105,18 +105,45 @@
|
||||
* DONE: Captcha integration
|
||||
* DONE: Solution for logo and favicon
|
||||
* FIXED: Raw editor jumps if you edit long text at the end
|
||||
* Reference feature
|
||||
* Typemill Utilities
|
||||
* DONE: Typemill Utilities
|
||||
* DONE: Update CSS for themes
|
||||
* DONE: test with different user rights
|
||||
* Markdown secure rendering
|
||||
* finish youtube component
|
||||
* Handle formdata centrally ???
|
||||
* BUG: Error fields in account form not styled correctly
|
||||
* DONE: Update CSS for themes
|
||||
* BUG: Codefield jumps on editing
|
||||
* False for owner on live?
|
||||
|
||||
## Dark Mode
|
||||
|
||||
* DONE: system
|
||||
* DONE: content-navigation
|
||||
* DONE: visual editor preview
|
||||
* DONE: visual editor edit modes
|
||||
* DONE: raw editor
|
||||
* DONE: meta
|
||||
* DONE: other tabs
|
||||
* DONE: modals
|
||||
* DONE: medialib
|
||||
* DONE: publish-bar.
|
||||
|
||||
## Feedback GitHub
|
||||
|
||||
* FIXED: Website restriction
|
||||
* NO ERROR: Change slug of blog
|
||||
* FIXED: undefined array key "title" in TwigMetaExtension on line 25
|
||||
* FIXED: CSS for navigation
|
||||
* DONE: Test with 8.2.7 (deprecation reports)
|
||||
* NOT REPRODUCED: Meta from home folder?
|
||||
* automatic generated password in firefox
|
||||
* FIXED: upload hero image in landinpage
|
||||
* FIXED: Restriction for custom css to 10000 characters
|
||||
* NOT REPRODUCED: Custom css löschen => false
|
||||
|
||||
## later
|
||||
|
||||
* Handle formdata centrally ???
|
||||
* Reference Feature
|
||||
* Clear cache
|
||||
* Show security Log
|
||||
* User search only for +10 users
|
||||
@@ -161,7 +188,8 @@
|
||||
|
||||
## Upgrade
|
||||
|
||||
* Delete content of system folder
|
||||
* Switch server to php 8.0 at least
|
||||
* Delete content of system folders
|
||||
* Upload new content of system folder with folders typemill and vendor
|
||||
* Backup and delete settings file
|
||||
* upload new index.php file
|
@@ -2,17 +2,13 @@ meta:
|
||||
navtitle: 'To Dos'
|
||||
title: 'A list of open tasks'
|
||||
description: ' Visual Editor with more stuff'
|
||||
heroimage: null
|
||||
heroimagealt: null
|
||||
owner: Sebastian
|
||||
author: null
|
||||
heroimage: media/live/screenshot-2023-08-03-at-15-23-44-setup-3.png
|
||||
heroimagealt: ''
|
||||
owner: 'Sebastian, testauthor'
|
||||
author: ''
|
||||
allowedrole: ''
|
||||
alloweduser: null
|
||||
manualdate: null
|
||||
modified: '2023-06-19'
|
||||
created: '2023-06-19'
|
||||
time: 15-15-01
|
||||
reference: null
|
||||
referencetype: null
|
||||
hide: false
|
||||
noindex: false
|
@@ -32,13 +32,13 @@
|
||||
navtitle: 'markdown test'
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /00-welcome/05-markdown-test.md
|
||||
path: /00-welcome/04-markdown-test.md
|
||||
keyPath: '0.4'
|
||||
/welcome/todos:
|
||||
/welcome/todoss:
|
||||
navtitle: 'To Dos'
|
||||
hide: false
|
||||
noindex: false
|
||||
path: /00-welcome/06-todos.md
|
||||
path: /00-welcome/05-todoss.md
|
||||
keyPath: '0.5'
|
||||
/cyanine-theme:
|
||||
navtitle: 'cyanine theme'
|
||||
|
@@ -11,3 +11,8 @@
|
||||
127.0.0.1;2023-09-15 06:06:46;wrong login
|
||||
127.0.0.1;2023-09-15 22:03:38;wrong login
|
||||
127.0.0.1;2023-09-16 08:49:53;wrong login
|
||||
127.0.0.1;2023-10-23 20:42:13;wrong login
|
||||
127.0.0.1;2023-10-23 21:26:26;wrong login
|
||||
127.0.0.1;2023-10-24 21:52:19;wrong login
|
||||
127.0.0.1;2023-10-26 20:57:09;wrong login
|
||||
127.0.0.1;2023-10-28 12:18:34;wrong login
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 54 KiB |
BIN
media/live/youtube-7yvlwxjl9dc-1.jpg
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
media/live/youtube-7yvlwxjl9dc-2.jpg
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
media/live/youtube-7yvlwxjl9dc.jpg
Normal file
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 105 KiB |
BIN
media/original/youtube-7yvlwxjl9dc-1.jpg
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
media/original/youtube-7yvlwxjl9dc-2.jpg
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
media/original/youtube-7yvlwxjl9dc.jpg
Normal file
After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 708 B |
Before Width: | Height: | Size: 708 B |
Before Width: | Height: | Size: 708 B |
Before Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 9.0 KiB |
BIN
media/thumbs/youtube-7yvlwxjl9dc-1.jpg
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
media/thumbs/youtube-7yvlwxjl9dc-2.jpg
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
media/thumbs/youtube-7yvlwxjl9dc.jpg
Normal file
After Width: | Height: | Size: 3.7 KiB |
@@ -141,8 +141,7 @@ abstract class Controller
|
||||
return $formDefinitions;
|
||||
}
|
||||
|
||||
# used to protect api access, can we do it with middleware?
|
||||
protected function validateRights($userrole, $resource, $action)
|
||||
protected function userroleIsAllowed($userrole, $resource, $action)
|
||||
{
|
||||
$acl = $this->c->get('acl');
|
||||
|
||||
@@ -151,10 +150,45 @@ abstract class Controller
|
||||
return true;
|
||||
}
|
||||
|
||||
die("PLEASE UPDATE THE METHOD validateRights in controller.php");
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function userIsAllowed($username, $pagemeta)
|
||||
{
|
||||
if(
|
||||
isset($pagemeta['meta']['owner']) &&
|
||||
$pagemeta['meta']['owner'] &&
|
||||
$pagemeta['meta']['owner'] !== ''
|
||||
)
|
||||
{
|
||||
$allowedusers = array_map('trim', explode(",", $pagemeta['meta']['owner']));
|
||||
if(
|
||||
in_array($username, $allowedusers)
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
# used to protect api access, can we do it with middleware?
|
||||
protected function validateRights($userrole, $resource, $action)
|
||||
{
|
||||
# check ownership. THIS WILL FAIL ANYWAY!!!
|
||||
# MAYBE WE SHOUD ADD THIS CHECK INTO MIDDLEWARE, TOO ?
|
||||
|
||||
$acl = $this->c->get('acl');
|
||||
|
||||
if($acl->isAllowed($userrole, $resource, $action))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
die("PLEASE UPDATE THE METHOD validateRights in controller.php");
|
||||
|
||||
$writeMeta = new writeMeta();
|
||||
$pagemeta = $writeMeta->getPageMeta($this->settings, $this->item);
|
||||
|
||||
|
@@ -23,16 +23,6 @@ class ControllerApiAuthorArticle extends Controller
|
||||
{
|
||||
public function publishArticle(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'content', 'update');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->articlePublish($params);
|
||||
@@ -59,6 +49,22 @@ class ControllerApiAuthorArticle extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'publish'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
# publish content
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
@@ -106,16 +112,6 @@ class ControllerApiAuthorArticle extends Controller
|
||||
|
||||
public function unpublishArticle(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'content', 'update');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->articlePublish($params);
|
||||
@@ -142,6 +138,22 @@ class ControllerApiAuthorArticle extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'publish'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
# publish content
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
@@ -183,16 +195,6 @@ class ControllerApiAuthorArticle extends Controller
|
||||
|
||||
public function updateDraft(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'mycontent', 'edit');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(401);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->articleUpdate($params);
|
||||
@@ -219,6 +221,22 @@ class ControllerApiAuthorArticle extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'update'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
# save draft content
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$markdown = $params['title'] . PHP_EOL . PHP_EOL . $params['body'];
|
||||
@@ -246,16 +264,6 @@ class ControllerApiAuthorArticle extends Controller
|
||||
|
||||
public function publishDraft(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'mycontent', 'edit');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(401);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->articleUpdate($params);
|
||||
@@ -282,6 +290,22 @@ class ControllerApiAuthorArticle extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'update'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
# save draft content
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$markdown = $params['title'] . PHP_EOL . PHP_EOL . $params['body'];
|
||||
@@ -326,16 +350,6 @@ class ControllerApiAuthorArticle extends Controller
|
||||
|
||||
public function discardArticleChanges(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'mycontent', 'edit');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->articlePublish($params);
|
||||
@@ -362,6 +376,22 @@ class ControllerApiAuthorArticle extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'update'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
# publish content
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$content->deleteDraft($item);
|
||||
@@ -387,16 +417,6 @@ class ControllerApiAuthorArticle extends Controller
|
||||
|
||||
public function createArticle(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'mycontent', 'create');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->navigationItem($params);
|
||||
@@ -495,7 +515,13 @@ class ControllerApiAuthorArticle extends Controller
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(500);
|
||||
}
|
||||
$storage->updateYaml('contentFolder', $folderPath, $namePath . '.yaml', ['meta' => ['navtitle' => $params['item_name']]]);
|
||||
$storage->updateYaml('contentFolder', $folderPath, $namePath . '.yaml',
|
||||
['meta' => [
|
||||
'navtitle' => $params['item_name'],
|
||||
'owner' => $request->getAttribute('c_username'),
|
||||
'created' => date("Y-m-d"),
|
||||
'time' => date("H-i-s")
|
||||
]]);
|
||||
}
|
||||
elseif($params['type'] == 'folder')
|
||||
{
|
||||
@@ -508,7 +534,13 @@ class ControllerApiAuthorArticle extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(500);
|
||||
}
|
||||
$storage->writeFile('contentFolder', $folderPath . DIRECTORY_SEPARATOR . $namePath, 'index.txt', $content);
|
||||
$storage->updateYaml('contentFolder', $folderPath . DIRECTORY_SEPARATOR . $namePath, 'index.yaml', ['meta' => ['navtitle' => $params['item_name']]]);
|
||||
$storage->updateYaml('contentFolder', $folderPath . DIRECTORY_SEPARATOR . $namePath, 'index.yaml',
|
||||
['meta' => [
|
||||
'navtitle' => $params['item_name'],
|
||||
'owner' => $request->getAttribute('c_username'),
|
||||
'created' => date("Y-m-d"),
|
||||
'time' => date("H-i-s")
|
||||
]]);
|
||||
|
||||
# always redirect to a folder
|
||||
# $url = $urlinfo['baseurl'] . '/tm/content/' . $this->settings['editor'] . $folder->urlRelWoF . '/' . $slug;
|
||||
@@ -527,16 +559,6 @@ class ControllerApiAuthorArticle extends Controller
|
||||
|
||||
public function createPost(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'mycontent', 'create');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->navigationItem($params);
|
||||
@@ -619,7 +641,13 @@ class ControllerApiAuthorArticle extends Controller
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(500);
|
||||
}
|
||||
$storage->updateYaml('contentFolder', $folderPath, $namePath . '.yaml', ['meta' => ['navtitle' => $params['item_name']]]);
|
||||
$storage->updateYaml('contentFolder', $folderPath, $namePath . '.yaml',
|
||||
['meta' => [
|
||||
'navtitle' => $params['item_name'],
|
||||
'owner' => $request->getAttribute('c_username'),
|
||||
'created' => date("Y-m-d"),
|
||||
'time' => date("H-i-s")
|
||||
]]);
|
||||
}
|
||||
elseif($params['type'] == 'folder')
|
||||
{
|
||||
@@ -644,16 +672,6 @@ class ControllerApiAuthorArticle extends Controller
|
||||
|
||||
public function renameArticle(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'mycontent', 'edit');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->articleRename($params);
|
||||
@@ -680,6 +698,22 @@ class ControllerApiAuthorArticle extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'update'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
# check if name exists
|
||||
$parentUrl = str_replace($item->slug, '', $item->urlRelWoF);
|
||||
if($parentUrl == '/')
|
||||
@@ -732,16 +766,6 @@ class ControllerApiAuthorArticle extends Controller
|
||||
|
||||
public function sortArticle(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'content', 'update');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->navigationSort($params);
|
||||
@@ -768,6 +792,31 @@ class ControllerApiAuthorArticle extends Controller
|
||||
$navigation = new Navigation();
|
||||
$draftNavigation = $navigation->getDraftNavigation($urlinfo, $langattr);
|
||||
$item = $navigation->getItemWithKeyPath($draftNavigation, $itemKeyPath);
|
||||
if(!$item)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('page not found'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'update'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
$extendedNavigation = $navigation->getExtendedNavigation($urlinfo, $langattr);
|
||||
$pageinfo = $extendedNavigation[$params['url']] ?? false;
|
||||
if(!$pageinfo)
|
||||
@@ -861,16 +910,6 @@ class ControllerApiAuthorArticle extends Controller
|
||||
|
||||
public function deleteArticle(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'content', 'delete');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->articlePublish($params);
|
||||
@@ -897,6 +936,22 @@ class ControllerApiAuthorArticle extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'delete'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
|
||||
# check if it is a folder and if the folder has published pages.
|
||||
|
@@ -8,22 +8,13 @@ use Slim\Routing\RouteContext;
|
||||
use Typemill\Models\Navigation;
|
||||
use Typemill\Models\Validation;
|
||||
use Typemill\Models\Content;
|
||||
use Typemill\Models\Meta;
|
||||
use Typemill\Static\Translations;
|
||||
|
||||
class ControllerApiAuthorBlock extends Controller
|
||||
{
|
||||
public function addBlock(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'content', 'update');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
|
||||
$validate = new Validation();
|
||||
@@ -51,6 +42,22 @@ class ControllerApiAuthorBlock extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'update'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
|
||||
@@ -119,16 +126,6 @@ class ControllerApiAuthorBlock extends Controller
|
||||
|
||||
public function moveBlock(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'content', 'update');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->blockMove($params);
|
||||
@@ -155,6 +152,22 @@ class ControllerApiAuthorBlock extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'update'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
@@ -212,16 +225,6 @@ class ControllerApiAuthorBlock extends Controller
|
||||
|
||||
public function updateBlock(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'content', 'update');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->blockInput($params);
|
||||
@@ -248,6 +251,22 @@ class ControllerApiAuthorBlock extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'update'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
@@ -318,16 +337,6 @@ class ControllerApiAuthorBlock extends Controller
|
||||
|
||||
public function deleteBlock(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'content', 'update');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->blockDelete($params);
|
||||
@@ -354,6 +363,22 @@ class ControllerApiAuthorBlock extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'update'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
|
@@ -15,18 +15,6 @@ class ControllerApiAuthorMeta extends Controller
|
||||
{
|
||||
public function getMeta(Request $request, Response $response, $args)
|
||||
{
|
||||
|
||||
# is it really needed? Check middleware if rights are validated there already
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'content', 'update');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$url = $request->getQueryParams()['url'] ?? false;
|
||||
|
||||
$navigation = new Navigation();
|
||||
@@ -50,6 +38,20 @@ class ControllerApiAuthorMeta extends Controller
|
||||
$metadata = $meta->addMetaDefaults($metadata, $item, $this->settings['author']);
|
||||
}
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'view'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
# if item is a folder
|
||||
if($item->elementType == "folder" && isset($item->contains))
|
||||
{
|
||||
@@ -103,16 +105,6 @@ class ControllerApiAuthorMeta extends Controller
|
||||
|
||||
public function updateMeta(Request $request, Response $response, $args)
|
||||
{
|
||||
$validRights = $this->validateRights($request->getAttribute('c_userrole'), 'content', 'update');
|
||||
if(!$validRights)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
|
||||
$params = $request->getParsedBody();
|
||||
$validate = new Validation();
|
||||
$validInput = $validate->metaInput($params);
|
||||
@@ -140,11 +132,26 @@ class ControllerApiAuthorMeta extends Controller
|
||||
}
|
||||
|
||||
$meta = new Meta();
|
||||
$metadata = $meta->getMetaData($item);
|
||||
|
||||
# if user is not allowed to perform this action (e.g. not admin)
|
||||
if(!$this->userroleIsAllowed($request->getAttribute('c_userrole'), 'content', 'update'))
|
||||
{
|
||||
# then check if user is the owner of this content
|
||||
if(!$this->userIsAllowed($request->getAttribute('c_username'), $metadata))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You do not have enough rights.'),
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
# if item is a folder
|
||||
if($item->elementType == "folder" && isset($item->contains))
|
||||
{
|
||||
$metadata['meta']['contains'] = isset($pagemeta['meta']['contains']) ? $pagemeta['meta']['contains'] : $item->contains;
|
||||
$metadata['meta']['contains'] = isset($metadata['meta']['contains']) ? $metadata['meta']['contains'] : $item->contains;
|
||||
|
||||
# get global metadefinitions
|
||||
$metadefinitions = $meta->getMetaDefinitions($this->settings, $folder = true);
|
||||
@@ -167,7 +174,20 @@ class ControllerApiAuthorMeta extends Controller
|
||||
$tabdefinitions['fields'] = $this->addDatasets($tabdefinitions['fields']);
|
||||
$tabdefinitions = $this->flattenTabFields($tabdefinitions['fields'], []);
|
||||
|
||||
# create validation object
|
||||
$validated['data'] = $validate->recursiveValidation($tabdefinitions, $params['data']);
|
||||
|
||||
if(!empty($validate->errors))
|
||||
{
|
||||
$errors[$params['tab']] = $validate->errors;
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('Please correct the errors in the form.'),
|
||||
'errors' => $errors
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(400);
|
||||
}
|
||||
|
||||
/*
|
||||
$errors = [];
|
||||
|
||||
# take the user input data and iterate over all fields and values
|
||||
@@ -202,8 +222,7 @@ class ControllerApiAuthorMeta extends Controller
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(400);
|
||||
}
|
||||
|
||||
$pageMeta = $meta->getMetaData($item);
|
||||
*/
|
||||
|
||||
# extended
|
||||
$navigation = new Navigation();
|
||||
@@ -213,10 +232,10 @@ class ControllerApiAuthorMeta extends Controller
|
||||
if($params['tab'] == 'meta')
|
||||
{
|
||||
# if manual date has been modified
|
||||
if( $this->hasChanged($params['data'], $pageMeta['meta'], 'manualdate'))
|
||||
if( $this->hasChanged($params['data'], $metadata['meta'], 'manualdate'))
|
||||
{
|
||||
# update the time
|
||||
$params['data']['time'] = date('H-i-s', time());
|
||||
$validated['data']['time'] = date('H-i-s', time());
|
||||
|
||||
# if it is a post, then rename the post
|
||||
if($item->elementType == "file" && strlen($item->order) == 12)
|
||||
@@ -225,7 +244,7 @@ class ControllerApiAuthorMeta extends Controller
|
||||
$metadate = $params['data']['manualdate'];
|
||||
if($metadate == '')
|
||||
{
|
||||
$metadate = $pageMeta['meta']['created'];
|
||||
$metadate = $metadata['meta']['created'];
|
||||
}
|
||||
$datetime = $metadate . '-' . $params['data']['time'];
|
||||
$datetime = implode(explode('-', $datetime));
|
||||
@@ -242,8 +261,8 @@ class ControllerApiAuthorMeta extends Controller
|
||||
}
|
||||
|
||||
# if folder has changed and contains pages instead of posts or posts instead of pages
|
||||
if($item->elementType == "folder" && isset($params['data']['contains']) && isset($pageMeta['meta']['contains']) && $this->hasChanged($params['data'], $pageMeta['meta'], 'contains'))
|
||||
{
|
||||
if($item->elementType == "folder" && isset($params['data']['contains']) && isset($metadata['meta']['contains']) && $this->hasChanged($params['data'], $metadata['meta'], 'contains'))
|
||||
{
|
||||
if($meta->folderContainsFolders($item))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
@@ -275,9 +294,9 @@ class ControllerApiAuthorMeta extends Controller
|
||||
}
|
||||
|
||||
# normalize the meta-input
|
||||
$params['data']['navtitle'] = (isset($params['data']['navtitle']) && $params['data']['navtitle'] !== null )? $params['data']['navtitle'] : '';
|
||||
$params['data']['hide'] = (isset($params['data']['hide']) && $params['data']['hide'] !== null) ? $params['data']['hide'] : false;
|
||||
$params['data']['noindex'] = (isset($params['data']['noindex']) && $params['data']['noindex'] !== null) ? $params['data']['noindex'] : false;
|
||||
$validated['data']['navtitle'] = (isset($params['data']['navtitle']) && $params['data']['navtitle'] !== null )? $params['data']['navtitle'] : '';
|
||||
$validated['data']['hide'] = (isset($params['data']['hide']) && $params['data']['hide'] !== null) ? $params['data']['hide'] : false;
|
||||
$validated['data']['noindex'] = (isset($params['data']['noindex']) && $params['data']['noindex'] !== null) ? $params['data']['noindex'] : false;
|
||||
|
||||
# input values are empty but entry in structure exists
|
||||
if(
|
||||
@@ -290,11 +309,11 @@ class ControllerApiAuthorMeta extends Controller
|
||||
}
|
||||
elseif(
|
||||
# check if navtitle or hide-value has been changed
|
||||
($this->hasChanged($params['data'], $pageMeta['meta'], 'navtitle'))
|
||||
($this->hasChanged($params['data'], $metadata['meta'], 'navtitle'))
|
||||
OR
|
||||
($this->hasChanged($params['data'], $pageMeta['meta'], 'hide'))
|
||||
($this->hasChanged($params['data'], $metadata['meta'], 'hide'))
|
||||
OR
|
||||
($this->hasChanged($params['data'], $pageMeta['meta'], 'noindex'))
|
||||
($this->hasChanged($params['data'], $metadata['meta'], 'noindex'))
|
||||
)
|
||||
{
|
||||
$navigation->clearNavigation();
|
||||
@@ -302,10 +321,10 @@ class ControllerApiAuthorMeta extends Controller
|
||||
}
|
||||
|
||||
# add the new/edited metadata
|
||||
$pageMeta[$params['tab']] = $params['data'];
|
||||
$metadata[$params['tab']] = $validated['data'];
|
||||
|
||||
# store the metadata
|
||||
$store = $meta->updateMeta($pageMeta, $item);
|
||||
$store = $meta->updateMeta($metadata, $item);
|
||||
|
||||
if($store === true)
|
||||
{
|
||||
|
@@ -126,14 +126,21 @@ class ControllerApiSystemUsers extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(400);
|
||||
}
|
||||
|
||||
# if a non-admin-user tries to update another account
|
||||
if(!$isAdmin AND ($username !== $request->getAttribute('username')) )
|
||||
# if it is a non-admin-user
|
||||
if(!$isAdmin)
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You are not allowed to update another user.')
|
||||
]));
|
||||
# do not change userrole
|
||||
unset($userdata['userrole']);
|
||||
|
||||
# if a non-admin-user tries to update another account
|
||||
if(($username !== $request->getAttribute('c_username')))
|
||||
{
|
||||
$response->getBody()->write(json_encode([
|
||||
'message' => Translations::translate('You are not allowed to update another user.')
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
# cleanup password entry
|
||||
|
@@ -71,6 +71,7 @@ class ControllerWebAuthor extends Controller
|
||||
|
||||
return $this->c->get('view')->render($response, 'content/blox-editor.twig', [
|
||||
'settings' => $this->settings,
|
||||
'darkmode' => $request->getAttribute('c_darkmode'),
|
||||
'mainnavi' => $mainNavigation,
|
||||
'content' => $draftMarkdownHtml,
|
||||
'jsdata' => [
|
||||
@@ -139,6 +140,7 @@ class ControllerWebAuthor extends Controller
|
||||
|
||||
return $this->c->get('view')->render($response, 'content/raw-editor.twig', [
|
||||
'settings' => $this->settings,
|
||||
'darkmode' => $request->getAttribute('c_darkmode'),
|
||||
'mainnavi' => $mainNavigation,
|
||||
'content' => $draftMarkdownHtml,
|
||||
'jsdata' => [
|
||||
|
@@ -48,6 +48,7 @@ class ControllerWebFrontend extends Controller
|
||||
{
|
||||
$item = $navigation->getHomepageItem($urlinfo['baseurl']);
|
||||
$item->active = true;
|
||||
$home = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -65,10 +66,8 @@ class ControllerWebFrontend extends Controller
|
||||
|
||||
$keyPathArray = explode(".", $pageinfo['keyPath']);
|
||||
|
||||
#
|
||||
$item = $navigation->getItemWithKeyPath($draftNavigation, $keyPathArray);
|
||||
|
||||
# but what if parent is unpublished ??
|
||||
if(!$item)
|
||||
{
|
||||
return $this->c->get('view')->render($response->withStatus(404), '404.twig', [
|
||||
@@ -257,7 +256,7 @@ class ControllerWebFrontend extends Controller
|
||||
}
|
||||
|
||||
$pagedata = [
|
||||
'home' => false,
|
||||
'home' => $home,
|
||||
'navigation' => $liveNavigation,
|
||||
'title' => $title,
|
||||
'content' => $contentHtml,
|
||||
|
@@ -41,6 +41,7 @@ class ControllerWebSystem extends Controller
|
||||
# 'captcha' => $this->checkIfAddCaptcha(),
|
||||
# 'basicauth' => $user->getBasicAuth(),
|
||||
'settings' => $this->settings,
|
||||
'darkmode' => $request->getAttribute('c_darkmode'),
|
||||
'mainnavi' => $mainNavigation,
|
||||
'jsdata' => [
|
||||
'settings' => $this->settings,
|
||||
@@ -92,6 +93,7 @@ class ControllerWebSystem extends Controller
|
||||
|
||||
return $this->c->get('view')->render($response, 'system/themes.twig', [
|
||||
'settings' => $this->settings,
|
||||
'darkmode' => $request->getAttribute('c_darkmode'),
|
||||
'mainnavi' => $mainNavigation,
|
||||
'jsdata' => [
|
||||
'systemnavi' => $systemNavigation,
|
||||
@@ -145,6 +147,7 @@ class ControllerWebSystem extends Controller
|
||||
|
||||
return $this->c->get('view')->render($response, 'system/plugins.twig', [
|
||||
'settings' => $this->settings,
|
||||
'darkmode' => $request->getAttribute('c_darkmode'),
|
||||
'mainnavi' => $mainNavigation,
|
||||
'jsdata' => [
|
||||
'systemnavi' => $systemNavigation,
|
||||
@@ -188,6 +191,7 @@ class ControllerWebSystem extends Controller
|
||||
|
||||
return $this->c->get('view')->render($response, 'system/license.twig', [
|
||||
'settings' => $this->settings,
|
||||
'darkmode' => $request->getAttribute('c_darkmode'),
|
||||
'mainnavi' => $mainNavigation,
|
||||
'jsdata' => [
|
||||
'systemnavi' => $systemNavigation,
|
||||
@@ -225,6 +229,7 @@ class ControllerWebSystem extends Controller
|
||||
|
||||
return $this->c->get('view')->render($response, 'system/account.twig', [
|
||||
'settings' => $this->settings,
|
||||
'darkmode' => $request->getAttribute('c_darkmode'),
|
||||
'mainnavi' => $mainNavigation,
|
||||
'jsdata' => [
|
||||
'systemnavi' => $systemNavigation,
|
||||
@@ -269,6 +274,7 @@ class ControllerWebSystem extends Controller
|
||||
|
||||
return $this->c->get('view')->render($response, 'system/users.twig', [
|
||||
'settings' => $this->settings,
|
||||
'darkmode' => $request->getAttribute('c_darkmode'),
|
||||
'mainnavi' => $mainNavigation,
|
||||
'jsdata' => [
|
||||
'systemnavi' => $systemNavigation,
|
||||
@@ -313,6 +319,7 @@ class ControllerWebSystem extends Controller
|
||||
|
||||
return $this->c->get('view')->render($response, 'system/user.twig', [
|
||||
'settings' => $this->settings,
|
||||
'darkmode' => $request->getAttribute('c_darkmode'),
|
||||
'mainnavi' => $mainNavigation,
|
||||
'jsdata' => [
|
||||
'systemnavi' => $systemNavigation,
|
||||
@@ -345,6 +352,7 @@ class ControllerWebSystem extends Controller
|
||||
|
||||
return $this->c->get('view')->render($response, 'system/usernew.twig', [
|
||||
'settings' => $this->settings,
|
||||
'darkmode' => $request->getAttribute('c_darkmode'),
|
||||
'mainnavi' => $mainNavigation,
|
||||
'jsdata' => [
|
||||
'systemnavi' => $systemNavigation,
|
||||
@@ -387,6 +395,7 @@ class ControllerWebSystem extends Controller
|
||||
|
||||
return $this->c->get('view')->render($response, 'layouts/layoutSystemBlank.twig', [
|
||||
'settings' => $this->settings,
|
||||
'darkmode' => $request->getAttribute('c_darkmode'),
|
||||
'mainnavi' => $mainNavigation,
|
||||
'jsdata' => [
|
||||
'systemnavi' => $systemNavigation,
|
||||
|
@@ -22,7 +22,13 @@ class TwigMetaExtension extends AbstractExtension
|
||||
|
||||
$metadata = $meta->getMetaData($item);
|
||||
|
||||
if(!$metadata OR $metadata['meta']['title'] == '' OR $metadata['meta']['description'] == '')
|
||||
if(
|
||||
!$metadata
|
||||
OR !isset($metadata['meta']['title'])
|
||||
OR $metadata['meta']['title'] == ''
|
||||
OR !isset($metadata['meta']['description'])
|
||||
OR $metadata['meta']['description'] == ''
|
||||
)
|
||||
{
|
||||
$metadata = $meta->addMetaDefaults($metadata, $item, $settings['author']);
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@ class ApiAuthorization implements MiddlewareInterface
|
||||
{
|
||||
if(!$this->acl->isAllowed($request->getAttribute('c_userrole'), $this->resource, $this->action))
|
||||
{
|
||||
$message = 'userrole: ' . $request->getAttribute('c_userrole') . ' resource: ' . $this->resource . ' action: ' . $this->action;
|
||||
$message = 'Permission denied. Your are an ' . $request->getAttribute('c_userrole') . ' and you cannot ' . $this->action . ' this ' . $this->resource;
|
||||
$response = new Response();
|
||||
|
||||
$response->getBody()->write(json_encode([
|
||||
|
@@ -44,6 +44,10 @@ class SessionMiddleware implements MiddlewareInterface
|
||||
|
||||
$request = $request->withAttribute('c_username', $userdata['username']);
|
||||
$request = $request->withAttribute('c_userrole', $userdata['userrole']);
|
||||
if(isset($userdata['darkmode']))
|
||||
{
|
||||
$request = $request->withAttribute('c_darkmode', $userdata['darkmode']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,7 @@ class WebAuthorization implements MiddlewareInterface
|
||||
|
||||
return $response->withHeader('Location', $this->router->urlFor('user.account'))->withStatus(302);
|
||||
}
|
||||
|
||||
|
||||
$response = $handler->handle($request);
|
||||
|
||||
return $response;
|
||||
|
@@ -34,6 +34,10 @@ class WebRedirectIfUnauthenticated implements MiddlewareInterface
|
||||
|
||||
$request = $request->withAttribute('c_username', $userdata['username']);
|
||||
$request = $request->withAttribute('c_userrole', $userdata['userrole']);
|
||||
if(isset($userdata['darkmode']))
|
||||
{
|
||||
$request = $request->withAttribute('c_darkmode', $userdata['darkmode']);
|
||||
}
|
||||
|
||||
# this executes code from routes first and then executes middleware
|
||||
$response = $handler->handle($request);
|
||||
|
@@ -44,6 +44,7 @@ class Validation
|
||||
# checks if email is available if user is created
|
||||
Validator::addRule('emailAvailable', function($field, $value, array $params, array $fields) use ($user)
|
||||
{
|
||||
if(!$value){ return false; }
|
||||
$email = trim($value);
|
||||
if($email == '' OR $user->findUsersByEmail($email)){ return false; }
|
||||
return true;
|
||||
@@ -255,10 +256,8 @@ class Validation
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -322,10 +321,12 @@ class Validation
|
||||
$v->rule('required', ['username'])->message("required");
|
||||
$v->rule('alphaNum', 'username')->message("invalid");
|
||||
$v->rule('lengthBetween', 'username', 3, 20)->message("Length between 3 - 20");
|
||||
|
||||
if($v->validate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -336,10 +337,12 @@ class Validation
|
||||
$v->rule('required', ['email'])->message("required");
|
||||
$v->rule('noHTML', 'email')->message(" contains HTML");
|
||||
$v->rule('lengthBetween', 'email', 3, 50)->message("Length between 3 - 50");
|
||||
|
||||
if($v->validate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -431,14 +434,12 @@ class Validation
|
||||
$v->rule('lengthBetween', 'item_name', 1, 60);
|
||||
$v->rule('in', 'type', ['file', 'folder']);
|
||||
|
||||
if($v->validate())
|
||||
if($v->validate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
public function blockInput(array $params)
|
||||
@@ -452,11 +453,9 @@ class Validation
|
||||
if($v->validate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
public function blockMove(array $params)
|
||||
@@ -471,10 +470,8 @@ class Validation
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
public function blockDelete(array $params)
|
||||
@@ -488,10 +485,8 @@ class Validation
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
public function articlePublish(array $params)
|
||||
@@ -515,10 +510,8 @@ class Validation
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
public function articleUpdate(array $params)
|
||||
@@ -544,10 +537,8 @@ class Validation
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
public function articleRename(array $params)
|
||||
@@ -562,11 +553,9 @@ class Validation
|
||||
if($v->validate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
public function metaInput(array $params)
|
||||
@@ -578,11 +567,9 @@ class Validation
|
||||
if($v->validate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -599,7 +586,27 @@ class Validation
|
||||
$v->rule('lengthBetween', 'password', 5, 50);
|
||||
$v->rule('equals', 'passwordrepeat', 'password');
|
||||
|
||||
return $this->validationResult($v);
|
||||
if($v->validate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
public function newPassword(array $params)
|
||||
{
|
||||
$v = new Validator($params);
|
||||
$v->rule('required', ['password', 'newpassword']);
|
||||
$v->rule('lengthBetween', 'newpassword', 5, 50);
|
||||
$v->rule('equals', 'passwordrepeat', 'password');
|
||||
|
||||
if($v->validate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -619,14 +626,12 @@ class Validation
|
||||
$v->rule('noHTML', 'title');
|
||||
$v->rule('markdownSecure', 'content');
|
||||
|
||||
if($v->validate())
|
||||
if($v->validate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $v->errors();
|
||||
}
|
||||
}
|
||||
|
||||
return $v->errors();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -687,7 +692,8 @@ class Validation
|
||||
}
|
||||
break;
|
||||
case "codearea":
|
||||
$v->rule('lengthMax', $fieldName, 10000);
|
||||
$v->rule('lengthMax', $fieldName, 50000);
|
||||
# how prevent bad code here?
|
||||
break;
|
||||
case "color":
|
||||
$v->rule('regex', $fieldName, '/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/');
|
||||
@@ -830,65 +836,4 @@ class Validation
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* result for validation
|
||||
*
|
||||
* @param obj $v the validation object.
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function checkArray($arrayvalues, $v)
|
||||
{
|
||||
die('I think checkArray not in use anymore');
|
||||
|
||||
foreach($arrayvalues as $key => $value)
|
||||
{
|
||||
if(is_array($value))
|
||||
{
|
||||
$this->checkArray($value, $v);
|
||||
}
|
||||
$v->rule('noHTML', $value);
|
||||
$v->rule('lengthMax', $value, 1000);
|
||||
}
|
||||
return $v;
|
||||
}
|
||||
|
||||
public function validationResult($v, $name = false)
|
||||
{
|
||||
die("do not use validationResults in validation model anymore");
|
||||
|
||||
if($v->validate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if($name == 'meta')
|
||||
{
|
||||
return $v->errors();
|
||||
}
|
||||
elseif($name)
|
||||
{
|
||||
if(isset($_SESSION['errors'][$name]))
|
||||
{
|
||||
foreach ($v->errors() as $key => $val)
|
||||
{
|
||||
$_SESSION['errors'][$name][$key] = $val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$_SESSION['errors'][$name] = $v->errors();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$_SESSION['errors'] = $v->errors();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -10,7 +10,7 @@
|
||||
<span class="px-4 py-2 border-b-2 border-stone-200">meta</span>
|
||||
</div>
|
||||
|
||||
<div class="px-12 py-8 bg-stone-50">
|
||||
<div class="px-12 py-8 bg-stone-50 dark:bg-stone-700 dark:text-stone-200">
|
||||
{% for block in content %}
|
||||
<div class="blox-preview px-6 py-3 mb-1">{{ block.html|raw }}</div>
|
||||
{% endfor %}
|
||||
|
@@ -177,6 +177,9 @@
|
||||
.sideaction:hover ~ .blox-preview{
|
||||
background: rgb(245 245 244);
|
||||
}
|
||||
.dark .sideaction:hover ~ .blox-preview{
|
||||
background: rgb(28 25 23);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -225,6 +228,14 @@
|
||||
.blox-preview tr:nth-child(even){ background-color:rgb(245 245 244); }
|
||||
.blox-preview td{ padding: 5px;}
|
||||
|
||||
.dark .blox-preview thead{
|
||||
background: rgb(28 25 23);
|
||||
}
|
||||
.dark .blox-preview tr:nth-child(even){ background-color:transparent; }
|
||||
.dark table, .dark th, .dark td {
|
||||
border: 1px solid rgb(87 83 78);
|
||||
}
|
||||
|
||||
.blox-preview dl{
|
||||
border-top: 1px solid rgb(20 184 166);
|
||||
border-bottom: 1px solid rgb(20 184 166);
|
||||
@@ -249,12 +260,16 @@
|
||||
.blox-preview dd{
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.blox-preview pre,.blox-preview code{
|
||||
white-space: pre;
|
||||
color: #333;
|
||||
background: rgb(245 245 244);
|
||||
}
|
||||
.dark .blox-preview pre,.dark .blox-preview code{
|
||||
white-space: pre;
|
||||
color: #fff;
|
||||
background: rgb(87 83 78);
|
||||
}
|
||||
.blox-preview code{
|
||||
display: inline-block;
|
||||
padding: 0 0.5em;
|
||||
@@ -286,6 +301,11 @@
|
||||
padding-top:12px;
|
||||
padding-bottom:12px;
|
||||
}
|
||||
.dark .blox-preview blockquote{
|
||||
color: #fff;
|
||||
background: rgb(87 83 78);
|
||||
}
|
||||
|
||||
.blox-preview blockquote:before {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
@@ -323,6 +343,13 @@
|
||||
background: rgb(245 245 244);
|
||||
padding: 10px;
|
||||
}
|
||||
.dark .blox-preview .notice1,
|
||||
.dark .blox-preview .notice2,
|
||||
.dark .blox-preview .notice3,
|
||||
.dark .blox-preview .notice4{
|
||||
color: #fff;
|
||||
background: rgb(87 83 78);
|
||||
}
|
||||
.blox-preview .notice1:before,
|
||||
.blox-preview .notice2:before,
|
||||
.blox-preview .notice3:before,
|
||||
@@ -353,11 +380,13 @@
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
.blox-preview img.youtube{
|
||||
.blox-preview figure.youtube{
|
||||
position: relative;
|
||||
}
|
||||
.blox-preview button.play-video {
|
||||
|
||||
.blox-preview .youtube::before {
|
||||
position: absolute;
|
||||
left:50%;
|
||||
top: 50%;
|
||||
margin-top: -50px;
|
||||
margin-left: -50px;
|
||||
@@ -369,22 +398,22 @@
|
||||
border: 0px;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
content: '';
|
||||
}
|
||||
.blox-preview button.play-video:hover {
|
||||
background: #cc4146;
|
||||
}
|
||||
.blox-preview button.play-video::after {
|
||||
.blox-preview .youtube::after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left:50%;
|
||||
margin: -20px 0 0 -15px;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-style: solid;
|
||||
border-width: 20px 0 20px 40px;
|
||||
border-color: transparent transparent transparent rgba(255, 255, 255, 0.75);
|
||||
content: ' ';
|
||||
content: '';
|
||||
}
|
||||
|
||||
|
||||
.blox-preview ul.TOC,
|
||||
.blox-preview .TOC ul{
|
||||
list-style: none;
|
||||
@@ -402,6 +431,7 @@
|
||||
}
|
||||
.blox-preview ul.TOC{
|
||||
background: rgb(245 245 244);
|
||||
background: transparent;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
box-sizing:border-box;
|
||||
@@ -528,4 +558,18 @@
|
||||
.blox-editor input.urlinput:focus{
|
||||
outline: 0px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
/****************
|
||||
** NAVIGATION **
|
||||
****************/
|
||||
|
||||
.pl-15{
|
||||
padding-left: 3.6rem;
|
||||
}
|
||||
.pl-18{
|
||||
padding-left: 4rem;
|
||||
}
|
||||
.pl-21{
|
||||
padding-left: 5rem;
|
||||
}
|
@@ -838,6 +838,10 @@ video {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.mt-1 {
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.mt-5 {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
@@ -1266,10 +1270,6 @@ video {
|
||||
border-left-width: 4px;
|
||||
}
|
||||
|
||||
.border-l-2 {
|
||||
border-left-width: 2px;
|
||||
}
|
||||
|
||||
.border-b-8 {
|
||||
border-bottom-width: 8px;
|
||||
}
|
||||
@@ -1282,6 +1282,10 @@ video {
|
||||
border-bottom-width: 4px;
|
||||
}
|
||||
|
||||
.border-l-2 {
|
||||
border-left-width: 2px;
|
||||
}
|
||||
|
||||
.border-solid {
|
||||
border-style: solid;
|
||||
}
|
||||
@@ -1330,11 +1334,6 @@ video {
|
||||
border-color: rgb(250 204 21 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-stone-100 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(245 245 244 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-rose-500 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(244 63 94 / var(--tw-border-opacity));
|
||||
@@ -1365,6 +1364,11 @@ video {
|
||||
border-color: rgb(255 228 230 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-stone-100 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(245 245 244 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-x-transparent {
|
||||
border-left-color: transparent;
|
||||
border-right-color: transparent;
|
||||
@@ -1424,16 +1428,16 @@ video {
|
||||
background-color: rgb(254 226 226 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-stone-900 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(28 25 23 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-stone-600 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(87 83 78 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-stone-900 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(28 25 23 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-rose-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(244 63 94 / var(--tw-bg-opacity));
|
||||
@@ -1654,6 +1658,10 @@ video {
|
||||
padding-top: 0.75rem;
|
||||
}
|
||||
|
||||
.pl-24 {
|
||||
padding-left: 6rem;
|
||||
}
|
||||
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
@@ -1766,9 +1774,9 @@ video {
|
||||
color: rgb(168 162 158 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-stone-700 {
|
||||
.text-stone-900 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(68 64 60 / var(--tw-text-opacity));
|
||||
color: rgb(28 25 23 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-stone-500 {
|
||||
@@ -1776,16 +1784,16 @@ video {
|
||||
color: rgb(120 113 108 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-stone-900 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(28 25 23 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-stone-300 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(214 211 209 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-stone-700 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(68 64 60 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-red-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(239 68 68 / var(--tw-text-opacity));
|
||||
@@ -1926,11 +1934,6 @@ video {
|
||||
border-color: rgb(68 64 60 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.hover\:border-stone-200:hover {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(231 229 228 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.hover\:border-teal-500:hover {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(20 184 166 / var(--tw-border-opacity));
|
||||
@@ -2040,11 +2043,6 @@ video {
|
||||
border-color: rgb(37 99 235 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.focus\:border-stone-200:focus {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(231 229 228 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.focus\:bg-white:focus {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
@@ -2090,11 +2088,6 @@ video {
|
||||
background-color: rgb(231 229 228 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.disabled\:bg-stone-50:disabled {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(250 250 249 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.disabled\:text-stone-800:disabled {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(41 37 36 / var(--tw-text-opacity));
|
||||
@@ -2109,14 +2102,12 @@ video {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.dark .dark\:border-stone-900 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(28 25 23 / var(--tw-border-opacity));
|
||||
.dark .dark\:border {
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.dark .dark\:border-stone-200 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(231 229 228 / var(--tw-border-opacity));
|
||||
.dark .dark\:border-0 {
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
.dark .dark\:border-stone-600 {
|
||||
@@ -2129,9 +2120,14 @@ video {
|
||||
border-color: rgb(68 64 60 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:bg-stone-600 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(87 83 78 / var(--tw-bg-opacity));
|
||||
.dark .dark\:border-stone-900 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(28 25 23 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:border-stone-200 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(231 229 228 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:bg-stone-700 {
|
||||
@@ -2139,9 +2135,9 @@ video {
|
||||
background-color: rgb(68 64 60 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:bg-stone-200 {
|
||||
.dark .dark\:bg-stone-600 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(231 229 228 / var(--tw-bg-opacity));
|
||||
background-color: rgb(87 83 78 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:bg-stone-900 {
|
||||
@@ -2149,9 +2145,9 @@ video {
|
||||
background-color: rgb(28 25 23 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-gray-400 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(156 163 175 / var(--tw-text-opacity));
|
||||
.dark .dark\:bg-stone-200 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(231 229 228 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-stone-200 {
|
||||
@@ -2159,31 +2155,71 @@ video {
|
||||
color: rgb(231 229 228 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-stone-50 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(250 250 249 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-stone-900 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(28 25 23 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-stone-600 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(87 83 78 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-gray-400 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(156 163 175 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-stone-300 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(214 211 209 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-stone-50 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(250 250 249 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .hover\:dark\:border-stone-200:hover {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(231 229 228 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark .hover\:dark\:border-rose-500:hover {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(244 63 94 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark .hover\:dark\:border-stone-600:hover {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(87 83 78 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark .hover\:dark\:bg-teal-500:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(20 184 166 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .hover\:dark\:bg-rose-500:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(244 63 94 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .hover\:dark\:bg-stone-600:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(87 83 78 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .hover\:dark\:bg-stone-900:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(28 25 23 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:hover\:bg-stone-200:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(231 229 228 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .hover\:dark\:bg-stone-200:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(231 229 228 / var(--tw-bg-opacity));
|
||||
@@ -2194,11 +2230,6 @@ video {
|
||||
background-color: rgb(20 184 166 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:hover\:bg-stone-200:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(231 229 228 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .hover\:dark\:text-stone-900:hover {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(28 25 23 / var(--tw-text-opacity));
|
||||
@@ -2224,6 +2255,16 @@ video {
|
||||
color: rgb(28 25 23 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .disabled\:dark\:bg-stone-600:disabled {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(87 83 78 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .disabled\:dark\:text-stone-200:disabled {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(231 229 228 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.md\:max-w-md {
|
||||
max-width: 28rem;
|
||||
|
@@ -14,7 +14,9 @@ let typemillUtilities = {
|
||||
var youtubeItem = this.youtubeItems[i];
|
||||
this.addYoutubePlayButton(youtubeItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.info(this.youtubeItems);
|
||||
},
|
||||
|
||||
addYoutubePlayButton: function(element)
|
||||
|
@@ -71,7 +71,7 @@ bloxeditor.component('headline-component', {
|
||||
<use xlink:href="#icon-header"></use>
|
||||
</svg>
|
||||
</div>
|
||||
<button class="absolute w-6 top-0 bottom-0 left-0 border-r-2 border-stone-700 bg-stone-200 hover:bg-teal-500 hover:text-stone-50 transition-1" @click.prevent="headlinedown">
|
||||
<button class="absolute w-6 top-0 bottom-0 left-0 border-r-2 border-stone-700 bg-stone-200 dark:bg-stone-600 hover:bg-teal-500 hover:dark:bg-teal-500 hover:text-stone-50 transition-1" @click.prevent="headlinedown">
|
||||
<div class="absolute w-6 top-3 text-center">{{ level }}</div>
|
||||
</button>
|
||||
<input class="opacity-1 w-full bg-transparent pr-6 pl-10 py-3 outline-none" :class="hlevel" type="text" v-model="compmarkdown" ref="markdown" :disabled="disabled" @input="updatemarkdown">
|
||||
@@ -334,9 +334,9 @@ bloxeditor.component('code-component', {
|
||||
<use xlink:href="#icon-embed"></use>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="w-full flex p-3 border-b-2 border-stone-700 bg-stone-200">
|
||||
<div class="w-full flex p-3 border-b-2 border-stone-700 bg-stone-100 dark:bg-stone-900">
|
||||
<label class="pr-2 py-1" for="language">{{ $filters.translate('Language') }}: </label>
|
||||
<input class="px-2 py-1 flex-grow text-stone-700 focus:outline-none" name="language" type="text" v-model="language" :disabled="disabled" @input="createlanguage">
|
||||
<input class="px-2 py-1 flex-grow focus:outline-none bg-stone-200 text-stone-900" name="language" type="text" v-model="language" :disabled="disabled" @input="createlanguage">
|
||||
</div>
|
||||
<textarea class="font-mono text-sm opacity-1 w-full bg-transparent px-6 py-3 outline-none" ref="markdown" v-model="codeblock" :disabled="disabled" @input="createmarkdown"></textarea>
|
||||
</div>`,
|
||||
@@ -562,7 +562,7 @@ bloxeditor.component('notice-component', {
|
||||
<use xlink:href="#icon-exclamation-circle"></use>
|
||||
</svg>
|
||||
</div>
|
||||
<button class="absolute w-6 top-0 bottom-0 left-0 border-r-2 border-stone-700 bg-stone-200 hover:bg-teal-500 hover:text-stone-50 transition-1" :class="noteclass" @click.prevent="noticedown">
|
||||
<button class="absolute w-6 top-0 bottom-0 left-0 border-r-2 border-stone-700 bg-stone-200 dark:bg-stone-600 hover:bg-teal-500 hover:dark:bg-teal-500 hover:text-stone-50 transition-1" :class="noteclass" @click.prevent="noticedown">
|
||||
<div class="absolute w-6 top-3 text-center">{{ prefix }}</div>
|
||||
</button>
|
||||
<textarea class="opacity-1 w-full bg-transparent pr-6 pl-10 py-3 outline-none notice" ref="markdown" v-model="notice" :disabled="disabled" @input="updatemarkdown($event.target.value)"></textarea>
|
||||
@@ -884,7 +884,7 @@ bloxeditor.component('definition-component', {
|
||||
definitionList: [],
|
||||
}
|
||||
},
|
||||
template: `<div class="definitionList">
|
||||
template: `<div class="definitionList dark:border dark:border-stone-600">
|
||||
<div class="absolute top-3 -left-5 text-stone-400">
|
||||
<svg class="icon icon-dots-two-vertical">
|
||||
<use xlink:href="#icon-dots-two-vertical"></use>
|
||||
@@ -895,15 +895,15 @@ bloxeditor.component('definition-component', {
|
||||
item-key="id"
|
||||
@end="moveDefinition">
|
||||
<template #item="{element, index}">
|
||||
<div class="definitionRow border-b border-stone-300">
|
||||
<div class="definitionRow border-b border-stone-300 dark:border-stone-600">
|
||||
<div class="relative flex p-6">
|
||||
<div class="definitionTerm">
|
||||
<input type="text" class="p-2 w-100 text-stone-700 focus:outline-none" :placeholder="element.term" :value="element.term" :disabled="disabled" @input="updateterm($event,index)" @blur="updateMarkdown">
|
||||
<input type="text" class="p-2 w-100 text-stone-900 bg-stone-200 focus:outline-none" :placeholder="element.term" :value="element.term" :disabled="disabled" @input="updateterm($event,index)" @blur="updateMarkdown">
|
||||
</div>
|
||||
<div class="flex-grow">
|
||||
<div class="flex mb-2" v-for="(description,ddindex) in element.descriptions">
|
||||
<svg class="icon icon-dots-two-vertical mt-3"><use xlink:href="#icon-dots-two-vertical"></use></svg>
|
||||
<textarea class="flex-grow p-2 focus:outline-none" :placeholder="description" v-html="element.descriptions[ddindex]" :disabled="disabled" @input="updatedescription($event, index, ddindex)" @keydown.13.prevent="enter" @blur="updateMarkdown"></textarea>
|
||||
<textarea class="flex-grow p-2 focus:outline-none bg-stone-200 text-stone-900" :placeholder="description" v-html="element.descriptions[ddindex]" :disabled="disabled" @input="updatedescription($event, index, ddindex)" @keydown.13.prevent="enter" @blur="updateMarkdown"></textarea>
|
||||
<button title="delete description" class="text-white bg-stone-700 w-6 h-6 text-xs hover:bg-rose-500" @click.prevent="deleteItem($event,index,ddindex)">
|
||||
<svg class="icon icon-minus">
|
||||
<use xlink:href="#icon-minus"></use>
|
||||
@@ -1308,8 +1308,8 @@ bloxeditor.component('image-component', {
|
||||
</div>
|
||||
|
||||
<Transition name="initial" appear>
|
||||
<div v-if="showmedialib" class="fixed top-0 left-0 right-0 bottom-0 bg-stone-100 z-50">
|
||||
<button class="w-full bg-stone-200 hover:bg-rose-500 hover:text-white p-2 transition duration-100" @click.prevent="showmedialib = false">{{ $filters.translate('close library') }}</button>
|
||||
<div v-if="showmedialib" class="fixed top-0 left-0 right-0 bottom-0 bg-stone-100 dark:bg-stone-700 z-50">
|
||||
<button class="w-full bg-stone-200 dark:bg-stone-900 hover:dark:bg-rose-500 hover:bg-rose-500 hover:text-white p-2 transition duration-100" @click.prevent="showmedialib = false">{{ $filters.translate('close library') }}</button>
|
||||
<medialib parentcomponent="images" @addFromMedialibEvent="addFromMedialibFunction"></medialib>
|
||||
</div>
|
||||
</Transition>
|
||||
@@ -1326,23 +1326,23 @@ bloxeditor.component('image-component', {
|
||||
<div class="imgmeta p-8" v-if="imgmeta">
|
||||
<div class="flex mb-2">
|
||||
<label class="w-1/5 py-2" for="imgalt">{{ $filters.translate('Alt-Text') }}: </label>
|
||||
<input class="w-4/5 p-2" name="imgalt" type="text" placeholder="alt" @input="createmarkdown" v-model="imgalt" max="100" />
|
||||
<input class="w-4/5 p-2 bg-stone-200 text-stone-900" name="imgalt" type="text" placeholder="alt" @input="createmarkdown" v-model="imgalt" max="100" />
|
||||
</div>
|
||||
<div class="flex mb-2">
|
||||
<label class="w-1/5 py-2" for="imgtitle">{{ $filters.translate('Title') }}: </label>
|
||||
<input class="w-4/5 p-2" name="imgtitle" type="text" placeholder="title" v-model="imgtitle" @input="createmarkdown" max="64" />
|
||||
<input class="w-4/5 p-2 bg-stone-200 text-stone-900" name="imgtitle" type="text" placeholder="title" v-model="imgtitle" @input="createmarkdown" max="64" />
|
||||
</div>
|
||||
<div class="flex mb-2">
|
||||
<label class="w-1/5 py-2" for="imgcaption">{{ $filters.translate('Caption') }}: </label>
|
||||
<input class="w-4/5 p-2" title="imgcaption" type="text" placeholder="caption" v-model="imgcaption" @input="createmarkdown" max="140" />
|
||||
<input class="w-4/5 p-2 bg-stone-200 text-stone-900" title="imgcaption" type="text" placeholder="caption" v-model="imgcaption" @input="createmarkdown" max="140" />
|
||||
</div>
|
||||
<div class="flex mb-2">
|
||||
<label class="w-1/5 py-2" for="imgurl">{{ $filters.translate('Link') }}: </label>
|
||||
<input class="w-4/5 p-2" title="imgurl" type="url" placeholder="url" v-model="imglink" @input="createmarkdown" />
|
||||
<input class="w-4/5 p-2 bg-stone-200 text-stone-900" title="imgurl" type="url" placeholder="url" v-model="imglink" @input="createmarkdown" />
|
||||
</div>
|
||||
<div class="flex mb-2">
|
||||
<label class="w-1/5 py-2" for="imgclass">{{ $filters.translate('Class') }}: </label>
|
||||
<select class="w-4/5 p-2 bg-white" title="imgclass" v-model="imgclass" @change="createmarkdown">
|
||||
<select class="w-4/5 p-2 bg-stone-200 text-stone-900" title="imgclass" v-model="imgclass" @change="createmarkdown">
|
||||
<option value="center">{{ $filters.translate('Center') }}</option>
|
||||
<option value="left">{{ $filters.translate('Left') }}</option>
|
||||
<option value="right">{{ $filters.translate('Right') }}</option>
|
||||
@@ -1350,8 +1350,8 @@ bloxeditor.component('image-component', {
|
||||
</div>
|
||||
<div class="flex mb-2">
|
||||
<label class="w-1/5 py-2" for="imgsizes">{{ $filters.translate('width/height') }}:</label>
|
||||
<input class="w-2/5 p-2 mr-1" title="imgwidth" type="text" :placeholder="originalwidth" v-model="imgwidth" @input="changewidth" max="6" />
|
||||
<input class="w-2/5 p-2 ml-1" title="imgheight" type="text" :placeholder="originalheight" v-model="imgheight" @input="changeheight" max="6" />
|
||||
<input class="w-2/5 p-2 mr-1 bg-stone-200 text-stone-900" title="imgwidth" type="text" :placeholder="originalwidth" v-model="imgwidth" @input="changewidth" max="6" />
|
||||
<input class="w-2/5 p-2 ml-1 bg-stone-200 text-stone-900" title="imgheight" type="text" :placeholder="originalheight" v-model="imgheight" @input="changeheight" max="6" />
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label v-if="showresize" for="saveoriginal" class="flex w-full">
|
||||
@@ -1504,6 +1504,7 @@ bloxeditor.component('image-component', {
|
||||
this.imgpreview = data.urlinfo.baseurl + '/' + value;
|
||||
this.showmedialib = false;
|
||||
this.saveimage = false;
|
||||
this.imgmeta = true;
|
||||
|
||||
this.createmarkdown();
|
||||
},
|
||||
@@ -1856,11 +1857,11 @@ bloxeditor.component('file-component', {
|
||||
<input title="fileid" type="hidden" placeholder="id" v-model="fileid" @input="createmarkdown" max="140" />
|
||||
<div class="flex mb-2">
|
||||
<label class="w-1/5 py-2" for="filetitle">{{ $filters.translate('Title') }}: </label>
|
||||
<input class="w-4/5 p-2" name="filetitle" type="text" placeholder="Add a title for the download-link" v-model="filetitle" @input="createmarkdown" max="64" />
|
||||
<input class="w-4/5 p-2 bg-stone-200 text-stone-900" name="filetitle" type="text" placeholder="Add a title for the download-link" v-model="filetitle" @input="createmarkdown" max="64" />
|
||||
</div>
|
||||
<div class="flex mb-2">
|
||||
<label class="w-1/5 py-2" for="filerestriction">Access for: </label>
|
||||
<select class="w-4/5 p-2 bg-white" name="filerestriction" v-model="selectedrole" @change="updaterestriction">
|
||||
<select class="w-4/5 p-2 bg-stone-200 text-stone-900" name="filerestriction" v-model="selectedrole" @change="updaterestriction">
|
||||
<option disabled value="">{{ $filters.translate('Please select') }}</option>
|
||||
<option v-for="role in userroles">{{ role }}</option>
|
||||
</select>
|
||||
@@ -2133,10 +2134,9 @@ bloxeditor.component('video-component', {
|
||||
<use xlink:href="#icon-play"></use>
|
||||
</svg>
|
||||
</div>
|
||||
<div>{{ markdown }}</div>
|
||||
<div class="flex mt-2 mb-2">
|
||||
<label class="w-1/5 py-2" for="video">{{ $filters.translate('Link to youtube') }}: </label>
|
||||
<input class="w-4/5 p-2 bg-white" type="url" ref="markdown" placeholder="https://www.youtube.com/watch?v=" :value="markdown" :disabled="disabled" @input="updatemarkdown($event.target.value)">
|
||||
<input class="w-4/5 p-2 bg-stone-200 text-stone-900" type="url" ref="markdown" placeholder="https://www.youtube.com/watch?v=" :value="markdown" :disabled="disabled" @input="updatemarkdown($event.target.value)">
|
||||
</div>
|
||||
</div>`,
|
||||
data: function(){
|
||||
@@ -2268,14 +2268,14 @@ bloxeditor.component('shortcode-component', {
|
||||
<use xlink:href="#icon-square-brackets"></use>
|
||||
</svg>
|
||||
</div>
|
||||
<div v-if="shortcodedata" class="p-8 bg-stone-100" ref="markdown">
|
||||
<div v-if="shortcodedata" class="p-8 bg-stone-100 dark:bg-stone-900" ref="markdown">
|
||||
<div class="flex mt-2 mb-2">
|
||||
<label class="w-1/5 py-2" for="shortcodename">{{ $filters.translate('Shortcode') }}: </label>
|
||||
<select class="w-4/5 p-2 bg-white" title="shortcodename" v-model="shortcodename" @change="createmarkdown(shortcodename)"><option v-for="shortcode,name in shortcodedata" :value="name">{{ name }}</option></select>
|
||||
<select class="w-4/5 p-2 bg-stone-200 text-stone-900" title="shortcodename" v-model="shortcodename" @change="createmarkdown(shortcodename)"><option v-for="shortcode,name in shortcodedata" :value="name">{{ name }}</option></select>
|
||||
</div>
|
||||
<div class="flex mt-2 mb-2" v-for="key,attribute in shortcodedata[shortcodename]">
|
||||
<label class="w-1/5 py-2" for="key">{{ attribute }}: </label>
|
||||
<input class="w-4/5 p-2 bg-white" type="search" list="shortcodedata[shortcodename][attribute]" v-model="shortcodedata[shortcodename][attribute].value" @input="createmarkdown(shortcodename,attribute)">
|
||||
<input class="w-4/5 p-2 bg-stone-200 text-stone-900" type="search" list="shortcodedata[shortcodename][attribute]" v-model="shortcodedata[shortcodename][attribute].value" @input="createmarkdown(shortcodename,attribute)">
|
||||
<datalist id="shortcodedata[shortcodename][attribute]">
|
||||
<option v-for="item in shortcodedata[shortcodename][attribute].content" @click="selectsearch(item,attribute)" :value="item"></option>
|
||||
</datalist>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
const bloxeditor = Vue.createApp({
|
||||
template: `<div v-if="showblox" class="px-12 py-8 bg-stone-50 shadow-md mb-16">
|
||||
template: `<div v-if="showblox" class="px-12 py-8 bg-stone-50 dark:bg-stone-700 dark:text-stone-200 shadow-md mb-16">
|
||||
<draggable
|
||||
v-model="content"
|
||||
@start="onStart"
|
||||
@@ -100,19 +100,19 @@ bloxeditor.component('new-block',{
|
||||
props: ['markdown', 'index'],
|
||||
template: `
|
||||
<div class="w-full mb-4">
|
||||
<div v-if="!componentType" class="w-full flex p-4">
|
||||
<div v-if="!componentType" class="w-full flex p-4 dark:bg-stone-900">
|
||||
<button v-for="button in formats"
|
||||
class="p-2 m-1 border border-stone-300 bg-stone-100 hover:bg-stone-700 hover:text-stone-50 transition-1"
|
||||
class="p-2 m-1 border border-stone-300 bg-stone-100 dark:border-stone-700 dark:bg-stone-700 hover:bg-stone-700 hover:dark:bg-stone-600 hover:text-stone-50 transition-1"
|
||||
@click.prevent="setComponentType( $event, button.component )"
|
||||
:title="button.title"
|
||||
v-html="button.label">
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="componentType" class="relative bg-stone-100">
|
||||
<div v-if="componentType" class="relative bg-stone-100 dark:bg-stone-900">
|
||||
<component ref="activeComponent" :disabled="disabled" :markdown="newblockmarkdown" :index="index" @saveBlockEvent="saveNewBlock" @updateMarkdownEvent="updateMarkdownFunction" :is="componentType"></component>
|
||||
<div class="edit-buttons absolute -bottom-3 right-4 z-2 text-xs">
|
||||
<button class="cancel w-20 p-1 border-r border-stone-700 bg-stone-200 hover:bg-rose-500 hover:text-white transition-1" :disabled="disabled" @click.prevent="closeComponent">{{ $filters.translate('cancel') }}</button>
|
||||
<button class="save w-20 p-1 border-l border-stone-700 bg-stone-200 hover:bg-teal-500 hover:text-white transition-1" :disabled="disabled" @click.prevent="beforeSaveNew()">{{ $filters.translate('save') }}</button>
|
||||
<button class="cancel w-20 p-1 border-r border-stone-700 bg-stone-200 dark:bg-stone-600 hover:bg-rose-500 hover:dark:bg-rose-500 hover:text-white transition-1" :disabled="disabled" @click.prevent="closeComponent">{{ $filters.translate('cancel') }}</button>
|
||||
<button class="save w-20 p-1 border-l border-stone-700 bg-stone-200 dark:bg-stone-600 hover:bg-teal-500 hover:dark:bg-teal-500 hover:text-white transition-1" :disabled="disabled" @click.prevent="beforeSaveNew()">{{ $filters.translate('save') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -232,8 +232,8 @@ bloxeditor.component('content-block', {
|
||||
props: ['element', 'index'],
|
||||
template: `
|
||||
<div :class="{'edit': edit}">
|
||||
<div v-if="newblock" class="bg-stone-100">
|
||||
<div class="w-full flex justify-between bg-stone-200">
|
||||
<div v-if="newblock" class="bg-stone-100 dark:bg-stone-600">
|
||||
<div class="w-full flex justify-between bg-stone-200 dark:bg-stone-600">
|
||||
<p class="p-2 pl-4">Choose a content type</p>
|
||||
<button class="p-2 border-l border-stone-700 hover:text-white hover:bg-rose-500 transition-1" @click="closeNewBlock">{{ $filters.translate('close') }}</button>
|
||||
</div>
|
||||
@@ -241,11 +241,11 @@ bloxeditor.component('content-block', {
|
||||
</div>
|
||||
<div class="relative blox-wrapper mb-1">
|
||||
<div v-if="index != 0" class="sideaction hidden absolute -top-3 left-1/2 -translate-x-1/2 z-10 text-xs">
|
||||
<button class="delete w-16 p-1 border-r border-stone-700 bg-stone-200 hover:bg-rose-500 hover:text-white transition-1" @mousedown.prevent="disableSort()" @click.prevent="deleteBlock">{{ $filters.translate('delete') }}</button>
|
||||
<button class="add w-16 p-1 border-l border-stone-700 bg-stone-200 hover:bg-teal-500 hover:text-white transition-1" :disabled="disabled" @mousedown.prevent="disableSort()" @click.prevent="openNewBlock">{{ $filters.translate('add') }}</button>
|
||||
<button class="delete w-16 p-1 border-r border-stone-700 bg-stone-200 dark:bg-stone-600 hover:bg-rose-500 hover:dark:bg-rose-500 hover:text-white transition-1" @mousedown.prevent="disableSort()" @click.prevent="deleteBlock">{{ $filters.translate('delete') }}</button>
|
||||
<button class="add w-16 p-1 border-l border-stone-700 bg-stone-200 dark:bg-stone-600 hover:bg-teal-500 hover:dark:bg-teal-500 hover:text-white transition-1" :disabled="disabled" @mousedown.prevent="disableSort()" @click.prevent="openNewBlock">{{ $filters.translate('add') }}</button>
|
||||
</div>
|
||||
<div v-if="!edit" class="blox-preview px-6 py-3 hover:bg-stone-100 overflow-hidden transition-1" @click="showEditor" v-html="getHtml(element.html)"></div>
|
||||
<div v-else class="blox-editor bg-stone-100">
|
||||
<div v-if="!edit" class="blox-preview px-6 py-3 hover:bg-stone-100 hover:dark:bg-stone-900 overflow-hidden transition-1" @click="showEditor" v-html="getHtml(element.html)"></div>
|
||||
<div v-else class="blox-editor bg-stone-100 dark:bg-stone-900">
|
||||
<div v-if="load" class="absolute right-0 top-0 left-0 bottom-0 bg-stone-100 opacity-75">
|
||||
<svg class="animate-spin h-5 w-5 text-stone-900 absolute top-0 right-0 bottom-0 left-0 m-auto" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
@@ -254,8 +254,8 @@ bloxeditor.component('content-block', {
|
||||
</div>
|
||||
<component ref="activeComponent" :disabled="disabled" :markdown="updatedmarkdown" :index="index" @saveBlockEvent="saveBlock" @updateMarkdownEvent="updateMarkdownFunction" :is="componentType"></component>
|
||||
<div class="edit-buttons absolute -bottom-3 right-4 z-10 text-xs">
|
||||
<button class="cancel w-20 p-1 border-r border-stone-700 bg-stone-200 hover:bg-rose-500 hover:text-white transition-1" :disabled="disabled" @click.prevent="closeEditor">{{ $filters.translate('cancel') }}</button>
|
||||
<button class="save w-20 p-1 border-l border-stone-700 bg-stone-200 hover:bg-teal-500 hover:text-white transition-1" :disabled="disabled" @click.prevent="beforeSave()">{{ $filters.translate('save') }}</button>
|
||||
<button class="cancel w-20 p-1 border-r border-stone-700 bg-stone-200 dark:bg-stone-600 hover:bg-rose-500 hover:dark:bg-rose-500 hover:text-white transition-1" :disabled="disabled" @click.prevent="closeEditor">{{ $filters.translate('cancel') }}</button>
|
||||
<button class="save w-20 p-1 border-l border-stone-700 bg-stone-200 dark:bg-stone-600 hover:bg-teal-500 hover:dark:bg-teal-500 hover:text-white transition-1" :disabled="disabled" @click.prevent="beforeSave()">{{ $filters.translate('save') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -7,11 +7,11 @@ const navigation = Vue.createApp({
|
||||
</div>
|
||||
<div class="flex w-full my-px border-y border-stone-200 dark:border-stone-900 font-bold">
|
||||
<div class="border-l-4" :class="getStatusClass(home.status)"></div>
|
||||
<a :href="getUrl(home.urlRelWoF)" class="flex-grow p-1 pl-3 border-stone-50 hover:bg-teal-500 hover:text-stone-50 dark:hover:bg-stone-200 hover:dark:text-stone-900" :class="home.active ? 'text-stone-50 bg-teal-500' : ''">
|
||||
<a :href="getUrl(home.urlRelWoF)" class="flex-grow p-1 pl-3 border-stone-50 hover:bg-teal-500 hover:text-stone-50 dark:hover:bg-stone-200 hover:dark:text-stone-900" :class="home.active ? 'text-stone-50 bg-teal-500 dark:bg-stone-200 dark:text-stone-900' : 'dark:bg-stone-700'">
|
||||
{{ $filters.translate(home.name) }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="pl-2 pl-3 pl-4 pl-6 pl-8 pl-9 pl-10 pl-12 pl-15 text-stone-50"></div>
|
||||
<div class="pl-2 pl-3 pl-4 pl-6 pl-8 pl-9 pl-10 pl-12 pl-15 pl-18 pl-21 pl-24 text-stone-50"></div>
|
||||
<navilevel :navigation="navigation" :expanded="expanded" />
|
||||
</div>`,
|
||||
data: function () {
|
||||
@@ -183,10 +183,10 @@ navigation.component('navilevel',{
|
||||
</template>
|
||||
<template #footer>
|
||||
<li>
|
||||
<div class="flex w-full my-px border-b border-stone-200 hover:bg-stone-200 group">
|
||||
<div class="flex w-full my-px border mt-1 mb-1 border-stone-300 dark:border-stone-600 hover:bg-stone-200 group">
|
||||
<div class="border-l-4 border-stone-200"></div>
|
||||
<div class="flex-grow">
|
||||
<input :class="getNaviInputLevel(parentId)" class="w-full p-1 bg-transparent border-0 border-stone-100 hover:border-stone-200 focus:border-stone-200 focus:bg-stone-200 focus:outline-none" placeholder="..." v-model="newItem">
|
||||
<input :class="getNaviInputLevel(parentId)" class="w-full p-1 bg-transparent focus:bg-stone-200 focus:outline-none dark:text-stone-600" placeholder="..." v-model="newItem">
|
||||
</div>
|
||||
<!-- <div class="w-1/4 invisible group-hover:visible"> -->
|
||||
<div class="flex">
|
||||
|
@@ -2,8 +2,9 @@ app.component('component-text', {
|
||||
props: ['id', 'description', 'maxlength', 'hidden', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'css', 'errors'],
|
||||
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>
|
||||
<input type="text" class="text-stone-900 h-12 w-full border px-2 py-3" :class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
<input type="text" class="text-stone-900 h-12 w-full border px-2 py-3"
|
||||
:id="id"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:maxlength="maxlength"
|
||||
:readonly="readonly"
|
||||
:hidden="hidden"
|
||||
@@ -30,6 +31,7 @@ app.component('component-textarea', {
|
||||
<label :for="name" class="block mb-1 font-medium">{{ $filters.translate(label) }}</label>
|
||||
<textarea rows="8" class="w-full border border-stone-300 text-stone-900 bg-stone-200 px-2 py-3"
|
||||
:id="id"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:class="css"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
@@ -72,6 +74,7 @@ app.component('component-codearea', {
|
||||
<div class="codearea">
|
||||
<textarea data-el="editor" class="editor" ref="editor"
|
||||
:id="id"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
:disabled="disabled"
|
||||
@@ -130,6 +133,7 @@ app.component('component-select', {
|
||||
<label :for="name" class="block mb-1 font-medium">{{ $filters.translate(label) }}</label>
|
||||
<select class="form-select block w-full border border-stone-300 text-stone-900 bg-stone-200 px-2 py-3 h-12 transition ease-in-out"
|
||||
:id="id"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:name="name"
|
||||
:required="required"
|
||||
:disabled="disabled"
|
||||
@@ -159,8 +163,9 @@ app.component('component-checkbox', {
|
||||
template: `<div :class="css ? css : ''" class="w-full mt-5 mb-5">
|
||||
<div class="block mb-1 font-medium">{{ $filters.translate(label) }}</div>
|
||||
<label :for="name" class="inline-flex items-start">
|
||||
<input type="checkbox" class="w-6 h-6"
|
||||
<input type="checkbox" class="w-6 h-6"
|
||||
:id="id"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
:disabled="disabled"
|
||||
@@ -199,6 +204,7 @@ app.component('component-checkboxlist', {
|
||||
<label class="flex items-start mb-2 mt-2" v-for="option, optionvalue in options" >
|
||||
<input type="checkbox" class="w-6 h-6"
|
||||
:id="optionvalue"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:value="optionvalue"
|
||||
v-model="checkedoptions"
|
||||
@change="update(checkedoptions, name)">
|
||||
@@ -234,6 +240,7 @@ app.component('component-radio', {
|
||||
<label class="flex items-start mb-2 mt-2" v-for="option,optionvalue in options">
|
||||
<input type="radio" class="w-6 h-6"
|
||||
:id="id"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
:disabled="disabled"
|
||||
@@ -260,6 +267,7 @@ app.component('component-number', {
|
||||
<label :for="name" class="block mb-1 font-medium">{{ $filters.translate(label) }}</label>
|
||||
<input type="number" class="h-12 w-full border border-stone-300 text-stone-900 bg-stone-200 px-2 py-3"
|
||||
:id="id"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:min="min"
|
||||
:max="max"
|
||||
:maxlength="maxlength"
|
||||
@@ -291,8 +299,9 @@ app.component('component-date', {
|
||||
<path fill-rule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<input type="date" class="h-12 w-full border pl-10 pr-2 py-3 text-stone-900" :class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
<input type="date" class="h-12 w-full border pl-10 pr-2 py-3 text-stone-900"
|
||||
:id="id"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
:disabled="disabled"
|
||||
@@ -323,8 +332,9 @@ app.component('component-email', {
|
||||
<path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<input type="email" class="h-12 w-full border pl-10 pr-2 py-3 text-stone-900" :class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
<input type="email" class="h-12 w-full border pl-10 pr-2 py-3 text-stone-900"
|
||||
:id="id"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:maxlength="maxlength"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
@@ -355,8 +365,9 @@ app.component('component-tel', {
|
||||
<path d="M22 20c-2 2-2 4-4 4s-4-2-6-4-4-4-4-6 2-2 4-4-4-8-6-8-6 6-6 6c0 4 4.109 12.109 8 16s12 8 16 8c0 0 6-4 6-6s-6-8-8-6z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<input type="tel" class="h-12 w-full border pl-10 pr-2 py-3 text-stone-900" :class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
<input type="tel" class="h-12 w-full border pl-10 pr-2 py-3 text-stone-900"
|
||||
:id="id"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:maxlength="maxlength"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
@@ -388,8 +399,9 @@ app.component('component-url', {
|
||||
<path d="M8 31.625c-2.037 0-3.952-0.793-5.392-2.233-2.973-2.973-2.973-7.81 0-10.783l2.743-2.743c0.635-0.635 1.664-0.635 2.298 0s0.635 1.663 0 2.298l-2.743 2.743c-1.706 1.706-1.706 4.481 0 6.187 0.826 0.826 1.925 1.281 3.094 1.281s2.267-0.455 3.094-1.281l6-6c1.706-1.706 1.706-4.481 0-6.187-0.635-0.635-0.635-1.663 0-2.298s1.663-0.635 2.298 0c2.973 2.973 2.973 7.81 0 10.783l-6 6c-1.44 1.44-3.355 2.233-5.392 2.233z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<input type="url" class="h-12 w-full border pl-10 pr-2 py-3 text-stone-900" :class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
<input type="url" class="h-12 w-full border pl-10 pr-2 py-3 text-stone-900"
|
||||
:id="id"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:maxlength="maxlength"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
@@ -420,9 +432,10 @@ app.component('component-color', {
|
||||
<path d="M30.828 1.172c-1.562-1.562-4.095-1.562-5.657 0l-5.379 5.379-3.793-3.793-4.243 4.243 3.326 3.326-14.754 14.754c-0.252 0.252-0.358 0.592-0.322 0.921h-0.008v5c0 0.552 0.448 1 1 1h5c0 0 0.083 0 0.125 0 0.288 0 0.576-0.11 0.795-0.329l14.754-14.754 3.326 3.326 4.243-4.243-3.793-3.793 5.379-5.379c1.562-1.562 1.562-4.095 0-5.657zM5.409 30h-3.409v-3.409l14.674-14.674 3.409 3.409-14.674 14.674z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<input type="color" class="h-12 w-full border pl-10 pr-1 py-1" :class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
<input type="color" class="h-12 w-full border pl-10 pr-1 py-1"
|
||||
:id="id"
|
||||
:maxlength="maxlength"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:maxlength="maxlength"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
:disabled="disabled"
|
||||
@@ -457,8 +470,9 @@ app.component('component-password', {
|
||||
<path d="M18.5 14h-0.5v-6c0-3.308-2.692-6-6-6h-4c-3.308 0-6 2.692-6 6v6h-0.5c-0.825 0-1.5 0.675-1.5 1.5v15c0 0.825 0.675 1.5 1.5 1.5h17c0.825 0 1.5-0.675 1.5-1.5v-15c0-0.825-0.675-1.5-1.5-1.5zM6 8c0-1.103 0.897-2 2-2h4c1.103 0 2 0.897 2 2v6h-8v-6z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<input :type="fieldType" class="h-12 w-full border pl-10 pr-10 py-1 text-stone-900" :class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
<input :type="fieldType" class="h-12 w-full border pl-10 pr-10 py-1 text-stone-900"
|
||||
:id="id"
|
||||
:class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:maxlength="maxlength"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
@@ -740,17 +754,17 @@ app.component('component-image', {
|
||||
</div>
|
||||
</div>
|
||||
<div class="lg:w-half w-full ph3 lh-copy f6 relative">
|
||||
<div class="relative w-full bg-stone-700 hover:bg-stone-900">
|
||||
<p class="relative w-full text-white text-center px-2 py-3"><svg class="icon icon-upload baseline"><use xlink:href="#icon-upload"></use></svg> {{ $filters.translate('upload an image') }}</p>
|
||||
<div class="relative w-full bg-stone-600 hover:bg-stone-900">
|
||||
<p class="relative w-full text-white text-center px-2 py-3"><svg class="icon icon-upload mr-1"><use xlink:href="#icon-upload"></use></svg> {{ $filters.translate('upload an image') }}</p>
|
||||
<input class="absolute w-full top-0 opacity-0 bg-stone-900 cursor-pointer px-2 py-3" type="file" name="image" accept="image/*" @change="onFileChange( $event )" />
|
||||
</div>
|
||||
<div class="w-full mt-3">
|
||||
<button class="w-full bg-stone-700 hover:bg-stone-900 text-white px-2 py-3 text-center cursor-pointer transition duration-100" @click.prevent="showmedialib = true"><svg class="icon icon-image baseline"><use xlink:href="#icon-image"></use></svg> {{ $filters.translate('select from medialib') }}</button>
|
||||
<button class="w-full bg-stone-600 hover:bg-stone-900 text-white px-2 py-3 text-center cursor-pointer transition duration-100" @click.prevent="showmedialib = true"><svg class="icon icon-image mr-1"><use xlink:href="#icon-image"></use></svg> {{ $filters.translate('select from medialib') }}</button>
|
||||
</div>
|
||||
<div class="w-full mt-3">
|
||||
<label class="block mb-1">{{ $filters.translate('Image URL (read only)') }}</label>
|
||||
<div class="flex">
|
||||
<button @click.prevent="deleteImage()" class="w-1/6 bg-stone-200 hover:bg-rose-500 hover:text-white">x</button>
|
||||
<button @click.prevent="deleteImage()" class="w-1/6 bg-stone-200 dark:bg-stone-600 hover:bg-rose-500 hover:dark:bg-rose-500 hover:text-white">x</button>
|
||||
<input type="text" class="h-12 w-5/6 border px-1 py-1 text-stone-900" :class="errors[name] ? ' border-red-500 bg-red-100' : ' border-stone-300 bg-stone-200'"
|
||||
:id="id"
|
||||
:maxlength="maxlength"
|
||||
@@ -764,7 +778,7 @@ app.component('component-image', {
|
||||
@input="update($event, name)">
|
||||
</div>
|
||||
<div v-if="qualitylabel" class="w-full mt-3">
|
||||
<button class="w-full cursor-pointer bg-stone-200 hover:bg-stone-300 text-center px-1 py-1 transition duration-100" @click.prevent="switchQuality(value)">{{ qualitylabel }}</button>
|
||||
<button class="w-full cursor-pointer bg-stone-200 dark:bg-stone-600 hover:bg-stone-300 hover:dark:bg-stone-900 text-center px-1 py-1 transition duration-100" @click.prevent="switchQuality(value)">{{ qualitylabel }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="errors[name]" class="text-xs text-red-500">{{ errors[name] }}</p>
|
||||
@@ -773,11 +787,11 @@ app.component('component-image', {
|
||||
</div>
|
||||
|
||||
<Transition name="initial" appear>
|
||||
<div v-if="showmedialib" class="fixed top-0 left-0 right-0 bottom-0 bg-stone-100 z-50">
|
||||
<button class="w-full bg-stone-200 hover:bg-rose-500 hover:text-white p-2 transition duration-100" @click.prevent="showmedialib = false">{{ $filters.translate('close library') }}</button>
|
||||
<div v-if="showmedialib" class="fixed top-0 left-0 right-0 bottom-0 bg-stone-100 dark:bg-stone-700 z-50">
|
||||
<button class="w-full bg-stone-200 dark:bg-stone-900 hover:dark:bg-rose-500 hover:bg-rose-500 hover:text-white p-2 transition duration-100" @click.prevent="showmedialib = false">{{ $filters.translate('close library') }}</button>
|
||||
<medialib parentcomponent="images" @addFromMedialibEvent="addFromMedialibFunction"></medialib>
|
||||
</div>
|
||||
</Transition>
|
||||
</Transition>
|
||||
|
||||
</div>`,
|
||||
mounted: function() {
|
||||
@@ -896,7 +910,7 @@ app.component('component-image', {
|
||||
sharedself.load = false;
|
||||
if(error.response)
|
||||
{
|
||||
console.info(error.response);
|
||||
console.info(error.response);
|
||||
/* publishController.errors.message = error.response.data.errors; */
|
||||
}
|
||||
});
|
||||
|
@@ -5,8 +5,8 @@ const medialib = {
|
||||
<div class="w-1/4">
|
||||
<div class="w-full relative">
|
||||
<div class="flex">
|
||||
<input v-model="search" class="h-12 px-2 py-3 border border-stone-300 bg-stone-200">
|
||||
<div class="w-1/4 h-12 px-2 py-3 center bg-stone-700 hover:bg-stone-900 text-white">
|
||||
<input v-model="search" class="h-12 px-2 py-3 text-stone-900 border border-stone-300 bg-stone-200">
|
||||
<div class="w-1/4 h-12 px-2 py-3 center text-center bg-stone-700 dark:bg-stone-600 hover:bg-stone-900 hover:dark:bg-stone-900 text-white">
|
||||
<svg class="icon icon-search">
|
||||
<use xlink:href="#icon-search"></use>
|
||||
</svg>
|
||||
@@ -16,8 +16,8 @@ const medialib = {
|
||||
<div v-if="showimages">
|
||||
<h3 class="border-b-2 border-stone-700 pt-6 pb-3">Images</h3>
|
||||
<div class="my-3">
|
||||
<button @click.prevent="showImages('pageImages')" :class="isActive('pageImages')" class="px-2 py-1 mr-2 hover:bg-stone-700 hover:text-stone-50 transition duration-100">{{ $filters.translate('this page') }}</button>
|
||||
<button @click.prevent="showImages('allImages')" :class="isActive('allImages')" class="px-2 py-1 hover:bg-stone-700 hover:text-stone-50 transition duration-100">{{ $filters.translate('all pages') }}</button>
|
||||
<button @click.prevent="showImages('pageImages')" :class="isActive('pageImages')" class="px-2 py-1 mr-2 hover:bg-stone-700 hover:dark:bg-stone-900 hover:text-stone-50 transition duration-100">{{ $filters.translate('this page') }}</button>
|
||||
<button @click.prevent="showImages('allImages')" :class="isActive('allImages')" class="px-2 py-1 hover:bg-stone-700 hover:dark:bg-stone-900 hover:text-stone-50 transition duration-100">{{ $filters.translate('all pages') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showfiles">
|
||||
@@ -40,10 +40,10 @@ const medialib = {
|
||||
</svg> click to select
|
||||
</span>
|
||||
</a>
|
||||
<div class="flex">
|
||||
<div class="flex bg-stone-50 dark:bg-stone-600">
|
||||
<div class="w-3/4 truncate p-3">{{ image.name }}</div>
|
||||
<div class="w-1/4 flex">
|
||||
<button @click.prevent="showImageDetails(image,index)" class="w-1/2 bg-stone-50 hover:bg-teal-500 hover:text-white transition duration-100">
|
||||
<button @click.prevent="showImageDetails(image,index)" class="w-1/2 hover:bg-teal-500 hover:text-white transition duration-100">
|
||||
<svg class="icon icon-info">
|
||||
<use xlink:href="#icon-info"></use>
|
||||
</svg>
|
||||
@@ -61,41 +61,41 @@ const medialib = {
|
||||
<Transition name="fade">
|
||||
<div class="px-5" v-if="showimagedetails">
|
||||
<div class="flex flex-wrap item-start relative">
|
||||
<div class="w-1/2 bg-stone-50">
|
||||
<div class="w-1/2 bg-stone-50 dark:bg-stone-600">
|
||||
<div class="w-80 h-80 table-cell align-middle bg-chess">
|
||||
<img :src="getImageUrl(imagedetaildata.src_live)" class="max-w-xs max-h-80 table mx-auto">
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-1/2 bg-stone-50 p-4 text-xs">
|
||||
<div class="text-stone-500 mt-3 mb-1">Name</div>
|
||||
<div class="w-1/2 bg-stone-50 dark:bg-stone-600 p-4 text-xs">
|
||||
<div class="text-stone-500 dark:text-stone-300 mt-3 mb-1">Name</div>
|
||||
<div class="font-bold">{{ imagedetaildata.name}}</div>
|
||||
<div class="text-stone-500 mt-3 mb-1">URL</div>
|
||||
<div class="text-stone-500 dark:text-stone-300 mt-3 mb-1">URL</div>
|
||||
<div class="font-bold">{{ getImageUrl(imagedetaildata.src_live)}}</div>
|
||||
<div class="flex flex-wrap item-start">
|
||||
<div class="w-1/2">
|
||||
<div class="text-stone-500 mt-3 mb-1">Size</div>
|
||||
<div class="text-stone-500 dark:text-stone-300 mt-3 mb-1">Size</div>
|
||||
<div class="font-bold">{{ getSize(imagedetaildata.bytes) }}</div>
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<div class="text-stone-500 mt-3 mb-1">Dimensions</div>
|
||||
<div class="text-stone-500 dark:text-stone-300 mt-3 mb-1">Dimensions</div>
|
||||
<div class="font-bold">{{ imagedetaildata.width }}x{{ imagedetaildata.height }} px</div>
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<div class="text-stone-500 mt-3 mb-1">Type</div>
|
||||
<div class="text-stone-500 dark:text-stone-300 mt-3 mb-1">Type</div>
|
||||
<div class="font-bold">{{ imagedetaildata.type }}</div>
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<div class="text-stone-500 mt-3 mb-1">Date</div>
|
||||
<div class="text-stone-500 dark:text-stone-300 mt-3 mb-1">Date</div>
|
||||
<div class="font-bold">{{ getDate(imagedetaildata.timestamp) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full flex justify-between mt-8">
|
||||
<button @click.prevent="selectImage(imagedetaildata)" class="w-1/2 p-2 mr-2 bg-stone-200 hover:bg-teal-500 hover:text-white transition duration-100">
|
||||
<button @click.prevent="selectImage(imagedetaildata)" class="w-1/2 p-2 mr-2 bg-stone-200 dark:bg-stone-900 hover:bg-teal-500 hover:dark:bg-teal-500 hover:text-white transition duration-100">
|
||||
<svg class="icon icon-check">
|
||||
<use xlink:href="#icon-check"></use>
|
||||
</svg> select
|
||||
</button>
|
||||
<button @click.prevent="deleteImage(imagedetaildata, detailindex)" class="w-1/2 p-2 bg-stone-200 hover:bg-rose-500 hover:text-white transition duration-100">
|
||||
<button @click.prevent="deleteImage(imagedetaildata, detailindex)" class="w-1/2 p-2 bg-stone-200 dark:bg-stone-900 hover:bg-rose-500 hover:dark:bg-rose-500 hover:text-white transition duration-100">
|
||||
<svg class="icon icon-trash-o baseline">
|
||||
<use xlink:href="#icon-trash-o"></use>
|
||||
</svg> delete
|
||||
@@ -316,9 +316,9 @@ const medialib = {
|
||||
{
|
||||
if(this.active == activestring)
|
||||
{
|
||||
return 'bg-stone-700 text-stone-50';
|
||||
return 'bg-stone-700 dark:bg-stone-900 text-stone-50';
|
||||
}
|
||||
return 'bg-stone-200';
|
||||
return 'bg-stone-200 dark:bg-stone-600';
|
||||
},
|
||||
getBackgroundImage(image)
|
||||
{
|
||||
|
@@ -5,8 +5,8 @@ const app = Vue.createApp({
|
||||
v-for="tab in tabs"
|
||||
v-on:click="currentTab = tab"
|
||||
:key="tab"
|
||||
class="px-4 py-2 border-b-2 border-stone-200 hover:border-stone-700 hover:bg-stone-50 transition duration-100"
|
||||
:class="(tab == currentTab) ? 'bg-stone-50 border-stone-700' : ''"
|
||||
class="px-4 py-2 border-b-2 border-stone-200 hover:border-stone-700 hover:bg-stone-50 dark:text-stone-200 dark:bg-stone-700 dark:border-stone-600 hover:dark:bg-stone-200 hover:dark:text-stone-900 transition duration-100"
|
||||
:class="(tab == currentTab) ? 'bg-stone-50 border-stone-700 dark:bg-stone-200 dark:text-stone-900' : ''"
|
||||
>
|
||||
{{ $filters.translate(tab) }}
|
||||
</button>
|
||||
@@ -146,18 +146,17 @@ const app = Vue.createApp({
|
||||
{
|
||||
if(error.response)
|
||||
{
|
||||
self.message = 'please correct the errors above';
|
||||
self.messageClass = 'bg-rose-500';
|
||||
self.formErrors = error.response.data.errors;
|
||||
self.message = 'please correct the errors above';
|
||||
|
||||
let message = handleErrorMessage(error);
|
||||
|
||||
/* does it make sense to change logic and show errors in publisher?
|
||||
if(message)
|
||||
if(typeof error.response.data.message != "undefined")
|
||||
{
|
||||
eventBus.$emit('publishermessage', message);
|
||||
self.message = error.response.data.message;
|
||||
}
|
||||
if(typeof error.response.data.errors != "undefined")
|
||||
{
|
||||
self.formErrors = error.response.data.errors;
|
||||
}
|
||||
*/
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -174,14 +173,14 @@ app.component('tab-meta', {
|
||||
disabled: true,
|
||||
}
|
||||
},
|
||||
template: `<section>
|
||||
template: `<section class="dark:bg-stone-700 dark:text-stone-200">
|
||||
<form>
|
||||
<div v-if="slug !== false">
|
||||
<div class="w-full relative">
|
||||
<label class="block mb-1 font-medium">{{ $filters.translate('Slug') }}</label>
|
||||
<div class="flex">
|
||||
<input
|
||||
class="h-12 w-3/4 border px-2 py-3 border-stone-300 bg-stone-200"
|
||||
class="h-12 w-3/4 border px-2 py-3 border-stone-300 bg-stone-200 text-stone-900"
|
||||
type="text"
|
||||
v-model="slug"
|
||||
pattern="[a-z0-9]"
|
||||
@@ -223,7 +222,7 @@ app.component('tab-meta', {
|
||||
</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">{{ $filters.translate(message) }}</div>
|
||||
<input type="submit" @click.prevent="saveInput()" :value="$filters.translate('save')" class="w-full p-3 my-1 bg-stone-700 hover:bg-stone-900 text-white cursor-pointer transition duration-100">
|
||||
<input type="submit" @click.prevent="saveInput()" :value="$filters.translate('save')" class="w-full p-3 my-1 bg-stone-700 dark:bg-stone-600 hover:bg-stone-900 hover:dark:bg-stone-900 text-white cursor-pointer transition duration-100">
|
||||
</div>
|
||||
</form>
|
||||
</section>`,
|
||||
|
@@ -2,7 +2,7 @@ const app = Vue.createApp({
|
||||
template: `<Transition name="initial" appear>
|
||||
<div class="w-full">
|
||||
<ul>
|
||||
<li v-for="(plugin,pluginname) in formDefinitions" class="w-full my-8 bg-stone-100 dark:bg-stone-600 border border-stone-200">
|
||||
<li v-for="(plugin,pluginname) in formDefinitions" class="w-full my-8 bg-stone-100 dark:bg-stone-700 border border-stone-200">
|
||||
<p v-if="versions[pluginname] !== undefined"><a href="https://plugins.typemill.net" class="block p-2 text-center bg-rose-500 text-white">Please update to version {{ versions[pluginname].version }}</a></p>
|
||||
<div class="flex justify-between w-full px-8 py-3 border-b border-white" :class="getActiveClass(pluginname)">
|
||||
<p class="py-2">License: {{ plugin.license }}</p>
|
||||
@@ -21,7 +21,7 @@ const app = Vue.createApp({
|
||||
<p>{{plugin.description}}</p>
|
||||
</div>
|
||||
<div class="w-full mt-6 flex justify-between">
|
||||
<button v-if="hasSettings(pluginname)" @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">
|
||||
<button v-if="hasSettings(pluginname)" @click="setCurrent(pluginname)" class="flex-1 flex items-center justify-center space-x-4 p-3 bg-stone-700 dark:bg-stone-600 hover:bg-stone-900 hover:dark:bg-stone-900 text-white cursor-pointer transition duration-100">
|
||||
<span>{{ $filters.translate('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>
|
||||
@@ -56,7 +56,7 @@ const app = Vue.createApp({
|
||||
<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 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">{{ $filters.translate('Save') }}</button>
|
||||
<button type="submit" @click.prevent="save()" class="flex-1 p-3 bg-stone-700 dark:bg-stone-600 hover:bg-stone-900 hover:dark:bg-stone-900 text-white cursor-pointer transition duration-100">{{ $filters.translate('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">{{ $filters.translate('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">{{ $filters.translate('Donate') }} {{plugin.amount}},-</a>
|
||||
</div>
|
||||
|
@@ -2,16 +2,16 @@ const publisher = Vue.createApp({
|
||||
template: `
|
||||
<div id="publishController" class="text-sm" v-cloak>
|
||||
<div v-if="message" :class="messageClass" class="block w-full px-3 py-1 text-white transition duration-100">{{ message }}</div>
|
||||
<div class="flex justify-between px-6 py-3">
|
||||
<div class="flex justify-between px-6 py-3 dark:bg-stone-900">
|
||||
<div class="flex">
|
||||
<div class="border-l-4 w-32 px-2 py-2" :class="getStatusClass(item.status)">
|
||||
<div class="border-l-4 w-32 px-2 py-2 dark:text-stone-200" :class="getStatusClass(item.status)">
|
||||
{{ $filters.translate(item.status) }}
|
||||
</div>
|
||||
<button
|
||||
v-if="raw"
|
||||
@click.prevent="saveDraft"
|
||||
:disabled="nochanges"
|
||||
class="cursor-pointer ml-1 w-24 px-4 py-2 border border-stone-200 text-white disabled:bg-stone-50 disabled:text-stone-900 disabled:cursor-not-allowed transition"
|
||||
class="cursor-pointer ml-1 w-24 px-4 py-2 border dark:border-0 border-stone-200 text-white disabled:bg-stone-200 disabled:text-stone-900 disabled:dark:bg-stone-600 disabled:dark:text-stone-200 disabled:cursor-not-allowed transition"
|
||||
:class="publishClass"
|
||||
>
|
||||
{{ $filters.translate('draft') }}
|
||||
@@ -20,7 +20,7 @@ const publisher = Vue.createApp({
|
||||
v-if="raw"
|
||||
@click.prevent="publishDraft"
|
||||
:disabled="nopublish"
|
||||
class="cursor-pointer ml-1 w-24 px-4 py-2 border border-stone-200 text-white disabled:bg-stone-50 disabled:text-stone-900 disabled:cursor-not-allowed transition"
|
||||
class="cursor-pointer ml-1 w-24 px-4 py-2 border dark:border-0 border-stone-200 text-white disabled:bg-stone-200 disabled:text-stone-900 disabled:dark:bg-stone-600 disabled:dark:text-stone-200 disabled:cursor-not-allowed transition"
|
||||
:class="publishClass"
|
||||
>
|
||||
{{ $filters.translate('publish') }}
|
||||
@@ -29,7 +29,7 @@ const publisher = Vue.createApp({
|
||||
v-if="visual"
|
||||
@click.prevent="publishArticle"
|
||||
:disabled="isPublished"
|
||||
class="cursor-pointer ml-1 w-24 px-4 py-2 border border-stone-200 text-white disabled:bg-stone-50 disabled:text-stone-900 disabled:cursor-not-allowed transition"
|
||||
class="cursor-pointer ml-1 w-24 px-4 py-2 border dark:border-0 border-stone-200 text-white disabled:bg-stone-200 disabled:text-stone-900 disabled:dark:bg-stone-600 disabled:dark:text-stone-200 disabled:cursor-not-allowed transition"
|
||||
:class="publishClass"
|
||||
>
|
||||
{{ $filters.translate('publish') }}
|
||||
@@ -37,7 +37,7 @@ const publisher = Vue.createApp({
|
||||
<button
|
||||
@click.prevent="showModal = 'discard'"
|
||||
:disabled="!isModified"
|
||||
class="cursor-pointer ml-1 w-24 px-4 py-2 border border-stone-200 text-white bg-yellow-500 hover:bg-yellow-600 disabled:bg-stone-50 disabled:text-stone-900 disabled:cursor-not-allowed transition"
|
||||
class="cursor-pointer ml-1 w-24 px-4 py-2 border dark:border-0 border-stone-200 text-white bg-yellow-500 hover:bg-yellow-600 disabled:bg-stone-200 disabled:text-stone-900 disabled:dark:bg-stone-600 disabled:dark:text-stone-200 disabled:cursor-not-allowed transition"
|
||||
>
|
||||
{{ $filters.translate('discard') }}
|
||||
</button>
|
||||
@@ -45,14 +45,14 @@ const publisher = Vue.createApp({
|
||||
v-if="item.originalName != 'home'"
|
||||
@click.prevent="checkUnpublish"
|
||||
:disabled="isUnpublished"
|
||||
class="cursor-pointer ml-1 w-24 px-4 py-2 border border-stone-200 text-white bg-teal-500 hover:bg-teal-600 disabled:bg-stone-50 disabled:text-stone-900 disabled:cursor-not-allowed transition"
|
||||
class="cursor-pointer ml-1 w-24 px-4 py-2 border dark:border-0 border-stone-200 text-white bg-teal-500 hover:bg-teal-600 disabled:bg-stone-200 disabled:text-stone-900 disabled:dark:bg-stone-600 disabled:dark:text-stone-200 disabled:cursor-not-allowed transition"
|
||||
>
|
||||
{{ $filters.translate('unpublish') }}
|
||||
</button>
|
||||
<button
|
||||
v-if="item.originalName != 'home'"
|
||||
@click.prevent="showModal = 'delete'"
|
||||
class="cursor-pointer ml-1 w-24 px-4 py-2 border border-stone-200 bg-stone-50 hover:bg-rose-500 hover:text-white transition"
|
||||
class="cursor-pointer ml-1 w-24 px-4 py-2 border dark:border-0 border-stone-200 bg-stone-50 hover:bg-rose-500 hover:text-white transition"
|
||||
>
|
||||
{{ $filters.translate('delete') }}
|
||||
</button>
|
||||
|
@@ -1,12 +1,12 @@
|
||||
const raweditor = Vue.createApp({
|
||||
template: `
|
||||
<fieldset v-if="showraw" class="px-12 py-8 bg-stone-50 shadow-md mb-16">
|
||||
<fieldset v-if="showraw" class="px-12 py-8 bg-stone-50 dark:bg-stone-700 dark:text-stone-200 shadow-md mb-16">
|
||||
<div class="w-full px-6 py-3" :class="{'error' : errors.title}">
|
||||
<label class="block mb-1 font-medium" for="title">{{ $filters.translate('Title') }}*</label>
|
||||
<input
|
||||
name="title"
|
||||
type="text"
|
||||
class="w-full p-4 text-white bg-stone-700 text-3xl"
|
||||
class="w-full p-4 text-white bg-stone-700 dark:bg-stone-900 text-3xl"
|
||||
v-model="title"
|
||||
@input="updateTitle"
|
||||
required
|
||||
@@ -20,7 +20,7 @@ const raweditor = Vue.createApp({
|
||||
id="rawcontent"
|
||||
name="raweditor"
|
||||
data-el="editor"
|
||||
class="editor"
|
||||
class="editor dark:bg-stone-900 dark:border-stone-600"
|
||||
ref="raweditor"
|
||||
v-model="content"
|
||||
@input="updateBody"
|
||||
|
@@ -4,12 +4,12 @@ const modal = {
|
||||
<div class="fixed w-full h-100 inset-0 z-50 overflow-hidden flex justify-center items-center bg-stone-700 bg-opacity-90">
|
||||
<div class="border border-teal-500 dark:border-stone-200 shadow-lg bg-white dark:bg-stone-600 w-11/12 md:max-w-md mx-auto shadow-lg z-50 overflow-y-auto">
|
||||
<div class="text-left p-6">
|
||||
<div class="text-2xl font-bold">
|
||||
<div class="text-2xl font-bold text-stone-900 dark:text-stone-200">
|
||||
<slot name="header">
|
||||
default header
|
||||
</slot>
|
||||
</div>
|
||||
<div class="my-5">
|
||||
<div class="my-5 text-stone-900 dark:text-stone-200">
|
||||
<slot name="body">
|
||||
default body
|
||||
</slot>
|
||||
@@ -72,7 +72,7 @@ const loginform = Vue.createApp({
|
||||
template: `<transition name="initial" appear>
|
||||
<div v-if="show" class="fixed w-full h-100 inset-0 z-50 overflow-hidden flex justify-center items-center bg-stone-700 bg-opacity-90">
|
||||
<div class="border border-teal-500 dark:border-stone-200 shadow-lg bg-white dark:bg-stone-600 w-11/12 md:max-w-md mx-auto shadow-lg z-50 overflow-y-auto">
|
||||
<div class="text-left p-6">
|
||||
<div class="text-stone-900 dark:text-stone-200 text-left p-6">
|
||||
<div class="text-2xl font-bold"><h2>You are logged out</h2></div>
|
||||
<div class="my-5">
|
||||
<p>You can visit the login page and authenticate again. Or you can close this window but you cannot perform any actions.</p>
|
||||
|
@@ -7,7 +7,7 @@ const systemnavi = Vue.createApp({
|
||||
</button>
|
||||
<div class="lg:block" :class="expanded ? '' : 'hidden'">
|
||||
<li v-for="(navitem, name) in systemnavi" :key="name" class="mb-1">
|
||||
<a :href="navitem.url" class="block p-2 border-l-4 hover:bg-stone-50 hover:border-teal-500 dark:border-stone-200 dark:bg-stone-700 hover:dark:bg-stone-200 dark:text-stone-50 hover:dark:text-stone-900 transition duration-100" :class="navitem.active ? ' active bg-stone-50 border-cyan-500 dark:bg-stone-200 dark:text-stone-900' : ' border-slate-200'">
|
||||
<a :href="navitem.url" class="block p-2 border-l-4 hover:bg-stone-50 hover:border-teal-500 dark:border-stone-200 dark:bg-stone-700 hover:dark:bg-stone-200 hover:dark:text-stone-900 transition duration-100" :class="navitem.active ? ' active bg-stone-50 border-cyan-500 dark:bg-stone-200 dark:text-stone-900' : ' border-slate-200 dark:text-stone-50'">
|
||||
<svg class="icon {{ navitem.icon }} mr-2"><use xlink:href="#{{ navitem.icon }}"></use></svg> {{ $filters.translate(navitem.title) }}
|
||||
</a>
|
||||
</li>
|
||||
|
@@ -2,7 +2,7 @@ const app = Vue.createApp({
|
||||
template: `<Transition name="initial" appear>
|
||||
<div class="w-full">
|
||||
<ul>
|
||||
<li v-for="(theme,themename) in formDefinitions" class="w-full my-8 bg-stone-100 dark:bg-stone-600 border border-stone-200">
|
||||
<li v-for="(theme,themename) in formDefinitions" class="w-full my-8 bg-stone-100 dark:bg-stone-700 border border-stone-200">
|
||||
<p v-if="versions[themename] !== undefined"><a href="https://themes.typemill.net" class="block p-2 text-center bg-rose-500 text-white">Please update to version {{ versions[themename].version }}</a></p>
|
||||
<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>
|
||||
@@ -26,7 +26,7 @@ const app = Vue.createApp({
|
||||
</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">
|
||||
<button @click="setCurrent(themename)" class="flex-1 flex items-center justify-center space-x-4 p-3 bg-stone-700 dark:bg-stone-600 hover:bg-stone-900 hover:dark: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>
|
||||
@@ -61,7 +61,7 @@ const app = Vue.createApp({
|
||||
<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 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>
|
||||
<button type="submit" @click.prevent="save()" class="flex-1 p-3 bg-stone-700 dark:bg-stone-600 hover:bg-stone-900 hover:dark: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>
|
||||
|
@@ -31,7 +31,7 @@ const app = Vue.createApp({
|
||||
</div>
|
||||
</form>
|
||||
<div class="my-5 text-center">
|
||||
<button @click.prevent="showModal = true" class="p-3 px-4 text-rose-500 border border-rose-100 hover:border-rose-500 cursor-pointer transition duration-100">{{ $filters.translate('delete user') }}</button>
|
||||
<button @click.prevent="showModal = true" class="p-3 px-4 text-rose-500 border border-rose-100 dark:border-stone-600 hover:dark:border-rose-500 hover:border-rose-500 cursor-pointer transition duration-100">{{ $filters.translate('delete user') }}</button>
|
||||
<modal v-if="showModal" @close="showModal = false">
|
||||
<template #header>
|
||||
<h3>{{ $filters.translate('Delete user') }}</h3>
|
||||
|
@@ -184,7 +184,7 @@ app.component('searchbox', {
|
||||
<button @click.prevent="setFilter('usermail')" :class="checkActive('usermail')" class="px-2 py-2 border-b-4 hover:bg-stone-200 hover:border-stone-700 transition duration-100">{{ $filters.translate('e-mail') }}</button>
|
||||
</div>
|
||||
<div class="w-100 lg:flex">
|
||||
<select v-if="this.filter == 'userrole'" v-model="searchterm" class="lg:w-3/4 w-full h-12 px-2 py-3 border border-stone-300 bg-stone-200">
|
||||
<select v-if="this.filter == 'userrole'" v-model="searchterm" class="lg:w-3/4 w-full h-12 px-2 py-3 text-stone-900 border border-stone-300 bg-stone-200">
|
||||
<option v-for="role in userroles">{{role}}</option>
|
||||
</select>
|
||||
<input v-else type="text" v-model="searchterm" class="lg:w-3/4 w-full h-12 px-2 py-3 border border-stone-300 bg-stone-200 text-stone-900">
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="{{ settings.darkmode ? 'dark' : 'darkmodeoff' }}" >
|
||||
<html lang="en" class="{{ darkmode ? 'dark' : 'darkmodeoff' }}" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="{{ settings.darkmode ? 'dark' : 'darkmodeoff' }}" >
|
||||
<html lang="en" class="{{ darkmode ? 'dark' : 'darkmodeoff' }}" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="{{ settings.darkmode ? 'dark' :'darkmodeoff' }}" >
|
||||
<html lang="en" class="{{ darkmode ? 'dark' :'darkmodeoff' }}" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
|
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
<ul class="flex border-l-2 border-stone-200 dark:border-stone-600">
|
||||
{% for name,navitem in mainnavi %}
|
||||
{% if settings.darkmode %}
|
||||
{% if darkmode %}
|
||||
<li class="border-r-2 border-stone-200 dark:border-stone-600">
|
||||
<a class="inline-block lg:px-4 lg:pt-4 lg:pb-3 lg:border-b-4 px-3 pt-3 pb-3 border-b-2 dark:text-stone-200 hover:bg-stone-50 hover:dark:bg-stone-200 hover:dark:text-stone-900 focus:dark:text-stone-900 active:dark:text-stone-900 hover:dark:border-stone-600 focus:dark:border-stone-600 active:dark:border-stone-600 transition duration-100{{ navitem.active ? ' dark:bg-stone-200 dark:text-stone-900 dark:border-stone-600' : ' dark:border-stone-900' }}" href="{{ url_for(navitem.routename) }}">{{ translate(navitem.title)|capitalize }}</a>
|
||||
</li>
|
||||
|
@@ -64,7 +64,7 @@ $app->group('/api/v1', function (RouteCollectorProxy $group) use ($acl) {
|
||||
$group->post('/article/rename', ControllerApiAuthorArticle::class . ':renameArticle')->setName('api.article.rename')->add(new ApiAuthorization($acl, 'content', 'publish'));
|
||||
$group->post('/article/publish', ControllerApiAuthorArticle::class . ':publishArticle')->setName('api.article.publish')->add(new ApiAuthorization($acl, 'content', 'publish'));
|
||||
$group->delete('/article/unpublish', ControllerApiAuthorArticle::class . ':unpublishArticle')->setName('api.article.unpublish')->add(new ApiAuthorization($acl, 'content', 'unpublish'));
|
||||
$group->delete('/article/discard', ControllerApiAuthorArticle::class . ':discardArticleChanges')->setName('api.article.discard')->add(new ApiAuthorization($acl, 'content', 'edit'));
|
||||
$group->delete('/article/discard', ControllerApiAuthorArticle::class . ':discardArticleChanges')->setName('api.article.discard')->add(new ApiAuthorization($acl, 'content', 'update'));
|
||||
$group->delete('/article', ControllerApiAuthorArticle::class . ':deleteArticle')->setName('api.article.delete')->add(new ApiAuthorization($acl, 'content', 'delete'));
|
||||
$group->post('/article', ControllerApiAuthorArticle::class . ':createArticle')->setName('api.article.create')->add(new ApiAuthorization($acl, 'content', 'create')); # author
|
||||
$group->put('/draft', ControllerApiAuthorArticle::class . ':updateDraft')->setName('api.draft.update')->add(new ApiAuthorization($acl, 'content', 'create')); # author
|
||||
@@ -72,10 +72,10 @@ $app->group('/api/v1', function (RouteCollectorProxy $group) use ($acl) {
|
||||
$group->post('/post', ControllerApiAuthorArticle::class . ':createPost')->setName('api.post.create')->add(new ApiAuthorization($acl, 'content', 'create'));
|
||||
|
||||
# BLOCKS
|
||||
$group->post('/block', ControllerApiAuthorBlock::class . ':addBlock')->setName('api.block.add')->add(new ApiAuthorization($acl, 'mycontent', 'create'));
|
||||
$group->post('/block', ControllerApiAuthorBlock::class . ':addBlock')->setName('api.block.add')->add(new ApiAuthorization($acl, 'mycontent', 'update'));
|
||||
$group->put('/block/move', ControllerApiAuthorBlock::class . ':moveBlock')->setName('api.block.move')->add(new ApiAuthorization($acl, 'mycontent', 'view'));
|
||||
$group->put('/block', ControllerApiAuthorBlock::class . ':updateBlock')->setName('api.block.update')->add(new ApiAuthorization($acl, 'mycontent', 'update'));
|
||||
$group->delete('/block', ControllerApiAuthorBlock::class . ':deleteBlock')->setName('api.block.delete')->add(new ApiAuthorization($acl, 'mycontent', 'delete'));
|
||||
$group->delete('/block', ControllerApiAuthorBlock::class . ':deleteBlock')->setName('api.block.delete')->add(new ApiAuthorization($acl, 'mycontent', 'update'));
|
||||
$group->post('/video', ControllerApiImage::class . ':saveVideoImage')->setName('api.video.save')->add(new ApiAuthorization($acl, 'mycontent', 'view'));
|
||||
|
||||
# SHORTCODE
|
||||
|
@@ -77,4 +77,13 @@ if(isset($routes['web']) && !empty($routes['web']))
|
||||
}
|
||||
}
|
||||
|
||||
$app->get('/[{route:.*}]', ControllerWebFrontend::class . ':index')->setName('home');
|
||||
if(isset($settings['access']) && $settings['access'] != '')
|
||||
{
|
||||
# if access for website is restricted
|
||||
$app->get('/[{route:.*}]', ControllerWebFrontend::class . ':index')->setName('home')->add(new WebAuthorization($routeParser, $acl, 'account', 'view'));
|
||||
}
|
||||
else
|
||||
{
|
||||
# if access is not restricted
|
||||
$app->get('/[{route:.*}]', ControllerWebFrontend::class . ':index')->setName('home');
|
||||
}
|
||||
|
@@ -78,20 +78,20 @@ meta:
|
||||
hidden: true
|
||||
css: hidden
|
||||
pattern: '[0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
|
||||
fieldsetreference:
|
||||
type: fieldset
|
||||
legend: Reference
|
||||
fields:
|
||||
reference:
|
||||
type: text
|
||||
label: Reference to page
|
||||
maxlength: 60
|
||||
referencetype:
|
||||
type: radio
|
||||
label: Type of reference
|
||||
options:
|
||||
copy: Copy (copy the content of the referenced page)
|
||||
redirect: Redirect (redirect the user to the referenced page)
|
||||
# fieldsetreference:
|
||||
# type: fieldset
|
||||
# legend: Reference
|
||||
# fields:
|
||||
# reference:
|
||||
# type: text
|
||||
# label: Reference to page
|
||||
# maxlength: 60
|
||||
# referencetype:
|
||||
# type: radio
|
||||
# label: Type of reference
|
||||
# options:
|
||||
# copy: Copy (copy the content of the referenced page)
|
||||
# redirect: Redirect (redirect the user to the referenced page)
|
||||
fieldsetvisibility:
|
||||
type: fieldset
|
||||
legend: Visibility
|
||||
|
@@ -14,22 +14,22 @@ contributor:
|
||||
- 'view'
|
||||
- 'create'
|
||||
- 'update'
|
||||
- 'delete'
|
||||
author:
|
||||
name: author
|
||||
inherits: contributor
|
||||
permissions:
|
||||
content:
|
||||
- 'create'
|
||||
- 'view'
|
||||
editor:
|
||||
name: editor
|
||||
inherits: author
|
||||
permissions:
|
||||
mycontent:
|
||||
- 'delete'
|
||||
- 'publish'
|
||||
- 'unpublish'
|
||||
content:
|
||||
- 'create'
|
||||
- 'update'
|
||||
- 'delete'
|
||||
- 'publish'
|
||||
|
@@ -53,11 +53,6 @@ fieldsetsystem:
|
||||
label: Google sitemap (readonly)
|
||||
css: lg:w-half
|
||||
disabled: true
|
||||
darkmode:
|
||||
type: checkbox
|
||||
label: Darkmode
|
||||
checkboxlabel: Switch to darkmode for the authoring area
|
||||
css: lg:w-half
|
||||
fieldsetmedia:
|
||||
type: fieldset
|
||||
legend: Media
|
||||
|
@@ -31,4 +31,9 @@ newpassword:
|
||||
label: 'New Password'
|
||||
type: 'password'
|
||||
autocomplete: 'new-password'
|
||||
generator: true
|
||||
generator: true
|
||||
darkmode:
|
||||
name: darkmode
|
||||
label: 'Darkmode'
|
||||
checkboxlabel: 'Activate the darkmode for me'
|
||||
type: 'checkbox'
|
@@ -1,10 +1,10 @@
|
||||
{% set home = {
|
||||
"landingpageIntro" : settings.themes.cyanine.landingpageIntro,
|
||||
"landingpageInfo" : settings.themes.cyanine.landingpageInfo,
|
||||
"landingpageTeaser" : settings.themes.cyanine.landingpageTeaser,
|
||||
"landingpageContrast" : settings.themes.cyanine.landingpageContrast,
|
||||
"landingpageNavi" : settings.themes.cyanine.landingpageNavi,
|
||||
"landingpageNews" : settings.themes.cyanine.landingpageNews
|
||||
"landingpageIntro" : settings.themes.cyanine.introPosition,
|
||||
"landingpageInfo" : settings.themes.cyanine.infoPosition,
|
||||
"landingpageTeaser" : settings.themes.cyanine.teaserPosition,
|
||||
"landingpageContrast" : settings.themes.cyanine.contrastPosition,
|
||||
"landingpageNavi" : settings.themes.cyanine.naviPosition,
|
||||
"landingpageNews" : settings.themes.cyanine.newsPosition
|
||||
}
|
||||
%}
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
{% block title %}{{ metatabs.meta.title }} | {{ settings.title }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
{% if home and settings.themes.cyanine.landingpage %}
|
||||
|
||||
{% include 'home.twig' %}
|
||||
|