mirror of
https://github.com/typemill/typemill.git
synced 2025-04-30 08:38:21 +02:00
Version 1.2.7: Reorder Content
This commit is contained in:
parent
cf737368c0
commit
2633ab69be
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,8 +4,8 @@ plugins/demo
|
||||
plugins/disqus
|
||||
plugins/download
|
||||
plugins/finalwords
|
||||
plugins/version
|
||||
plugins/textadds
|
||||
plugins/version
|
||||
settings/settings.yaml
|
||||
settings/users
|
||||
system/vendor
|
||||
|
2
cache/lastCache.txt
vendored
2
cache/lastCache.txt
vendored
@ -1 +1 @@
|
||||
1540919595
|
||||
1541750318
|
23
content/00-Welcome/00-Setup.md
Normal file
23
content/00-Welcome/00-Setup.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Setup the System
|
||||
|
||||
Typemil is a flat file cms that runs out of the box without a complicated installation process. You can create a user account with the [simple setup page](/setup) and then login to the author panel. In the author panel, you can configure your page, use plugins, choose a theme and edit your content.
|
||||
|
||||
## If it does not work
|
||||
|
||||
If you face any problems, then please make sure, that your system meets these requirements:
|
||||
|
||||
- PHP version 7+.
|
||||
- Apache Server.
|
||||
- The module `mod_rewrite` and `htaccess`.
|
||||
|
||||
If you run a linux-systems like Debian or Ubuntu, then please double check that `mod_rewrite` or `htaccess` are activated. Check this issue on GitHub for help.
|
||||
|
||||
Please make the following folders writable with permission 774 (you can use your ftp-software for it):
|
||||
|
||||
- Cache
|
||||
- Content
|
||||
- Media
|
||||
- Settings
|
||||
|
||||
If you still get an error, then you can post an issue on [GitHub](https://github.com/trendschau/typemill).
|
||||
|
1
content/00-Welcome/01-demo.txt
Normal file
1
content/00-Welcome/01-demo.txt
Normal file
@ -0,0 +1 @@
|
||||
["# demo page","Typemil is a flat file cms that runs out of the box without a complicated installation process. You can create a user account with the [simple setup page](\/setup) and then login to the author panel. In the author panel, you can configure your page, use plugins, choose a theme and edit your content.","## Headline","* This is\n* A list"]
|
1
content/00-Welcome/index.txt
Normal file
1
content/00-Welcome/index.txt
Normal file
@ -0,0 +1 @@
|
||||
["# Welcome to Typemill","Great that you give Typemill a try!! Typemill is a small open source cms and a project in work. You will probably miss some important features, but I am working hard to add everything that is needed for a really productive little writing-system.","Before you start, please read the short introduction about \"writing content\". Or simply play around, I hope that Typemill is already quite intuitive to use..."]
|
@ -602,26 +602,32 @@ class ContentApiController extends ContentController
|
||||
# if it is a new content-block
|
||||
if($this->params['block_id'] == 99999)
|
||||
{
|
||||
# update the markdown block in the page content
|
||||
$pageMarkdown[] = $blockMarkdown;
|
||||
$id = (count($pageMarkdown)-1);
|
||||
# set the id of the markdown-block (it will be one more than the actual array, so count is perfect)
|
||||
$id = count($pageMarkdown);
|
||||
|
||||
# set the id with prefix "blox-"
|
||||
$blockId = 'blox-' . $id;
|
||||
|
||||
# add the new markdown block to the page content
|
||||
$pageMarkdown[] = $blockMarkdown;
|
||||
}
|
||||
elseif(!isset($pageMarkdown[$this->params['block_id']]))
|
||||
{
|
||||
# return error
|
||||
# if the block does not exists, return an error
|
||||
return $response->withJson(array('data' => false, 'errors' => 'The ID of the content-block is wrong.'), 404);
|
||||
}
|
||||
elseif($this->params['block_id'] == 0)
|
||||
{
|
||||
# update the markdown block in the page content
|
||||
# if it is the title, then delete the "# " if it exists
|
||||
$blockMarkdown = trim($blockMarkdown, "# ");
|
||||
|
||||
# store the markdown-headline in a separate variable
|
||||
$blockMarkdownTitle = '# ' . $blockMarkdown;
|
||||
|
||||
$pageMarkdown[$this->params['block_id']] = $blockMarkdownTitle;
|
||||
$id = $this->params['block_id'];
|
||||
$blockId = $this->params['block_id'];
|
||||
# add the markdown-headline to the page-markdown
|
||||
$pageMarkdown[0] = $blockMarkdownTitle;
|
||||
$id = 0;
|
||||
$blockId = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -635,7 +641,7 @@ class ContentApiController extends ContentController
|
||||
$pageJson = json_encode($pageMarkdown);
|
||||
|
||||
# set path for the file (or folder)
|
||||
$this->setItemPath('txt');
|
||||
$this->setItemPath('txt');
|
||||
|
||||
/* update the file */
|
||||
if($this->write->writeFile($this->settings['contentFolder'], $this->path, $pageJson))
|
||||
@ -666,6 +672,83 @@ class ContentApiController extends ContentController
|
||||
|
||||
return $response->withJson(array('content' => $blockHTML, 'markdown' => $blockMarkdown, 'blockId' => $blockId, 'id' => $id, 'errors' => false));
|
||||
}
|
||||
|
||||
public function moveBlock(Request $request, Response $response, $args)
|
||||
{
|
||||
# get params from call
|
||||
$this->params = $request->getParams();
|
||||
$this->uri = $request->getUri();
|
||||
|
||||
# validate input
|
||||
# if(!$this->validateBlockInput()){ return $response->withJson($this->errors,422); }
|
||||
|
||||
# set structure
|
||||
if(!$this->setStructure($draft = true)){ return $response->withJson(array('data' => false, 'errors' => $this->errors), 404); }
|
||||
|
||||
# set item
|
||||
if(!$this->setItem()){ return $response->withJson($this->errors, 404); }
|
||||
|
||||
# set the status for published and drafted
|
||||
$this->setPublishStatus();
|
||||
|
||||
# set path
|
||||
$this->setItemPath($this->item->fileType);
|
||||
|
||||
# read content from file
|
||||
if(!$this->setContent()){ return $response->withJson(array('data' => false, 'errors' => $this->errors), 404); }
|
||||
|
||||
# make it more clear which content we have
|
||||
$pageMarkdown = $this->content;
|
||||
|
||||
if($pageMarkdown == '')
|
||||
{
|
||||
$pageMarkdown = [];
|
||||
}
|
||||
|
||||
# initialize parsedown extension
|
||||
$parsedown = new ParsedownExtension();
|
||||
|
||||
# if content is not an array, then transform it
|
||||
if(!is_array($pageMarkdown))
|
||||
{
|
||||
# turn markdown into an array of markdown-blocks
|
||||
$pageMarkdown = $parsedown->markdownToArrayBlocks($pageMarkdown);
|
||||
}
|
||||
|
||||
$oldIndex = ($this->params['old_index'] + 1);
|
||||
$newIndex = ($this->params['new_index'] + 1);
|
||||
|
||||
if(!isset($pageMarkdown[$oldIndex]))
|
||||
{
|
||||
# if the block does not exists, return an error
|
||||
return $response->withJson(array('data' => false, 'errors' => 'The ID of the content-block is wrong.'), 404);
|
||||
}
|
||||
|
||||
$extract = array_splice($pageMarkdown, $oldIndex, 1);
|
||||
array_splice($pageMarkdown, $newIndex, 0, $extract);
|
||||
|
||||
# encode the content into json
|
||||
$pageJson = json_encode($pageMarkdown);
|
||||
|
||||
# set path for the file (or folder)
|
||||
$this->setItemPath('txt');
|
||||
|
||||
/* update the file */
|
||||
if($this->write->writeFile($this->settings['contentFolder'], $this->path, $pageJson))
|
||||
{
|
||||
# update the internal structure
|
||||
$this->setStructure($draft = true, $cache = false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $response->withJson(['errors' => ['message' => 'Could not write to file. Please check if the file is writable']], 404);
|
||||
}
|
||||
|
||||
# if it is the title, then delete the "# " if it exists
|
||||
$pageMarkdown[0] = trim($pageMarkdown[0], "# ");
|
||||
|
||||
return $response->withJson(array('markdown' => $pageMarkdown, 'errors' => false));
|
||||
}
|
||||
|
||||
public function deleteBlock(Request $request, Response $response, $args)
|
||||
{
|
||||
@ -713,10 +796,12 @@ class ContentApiController extends ContentController
|
||||
unset($this->content[$this->params['block_id']]);
|
||||
$this->content = array_values($this->content);
|
||||
|
||||
$pageMarkdown = $this->content;
|
||||
|
||||
# delete markdown from title
|
||||
if(isset($this->content[0]))
|
||||
if(isset($pageMarkdown[0]))
|
||||
{
|
||||
$this->content[0] = trim($this->content[0], "# ");
|
||||
$pageMarkdown[0] = trim($pageMarkdown[0], "# ");
|
||||
}
|
||||
|
||||
# encode the content into json
|
||||
@ -735,6 +820,7 @@ class ContentApiController extends ContentController
|
||||
{
|
||||
return $response->withJson(['errors' => ['message' => 'Could not write to file. Please check if the file is writable']], 404);
|
||||
}
|
||||
return $response->withJson(array('markdown' => $this->content, 'errors' => false));
|
||||
|
||||
return $response->withJson(array('markdown' => $pageMarkdown, 'errors' => false));
|
||||
}
|
||||
}
|
@ -111,7 +111,6 @@ class ContentBackendController extends ContentController
|
||||
if(!$this->setContent()){ return $this->renderIntern404($response, array( 'navigation' => $this->structure, 'settings' => $this->settings, 'content' => $this->errors )); }
|
||||
|
||||
$content = $this->content;
|
||||
$title = false;
|
||||
|
||||
if($content == '')
|
||||
{
|
||||
@ -136,7 +135,11 @@ class ContentBackendController extends ContentController
|
||||
/* parse markdown-content-array to content-string */
|
||||
$content[$key] = $parsedown->markup($contentArray);
|
||||
}
|
||||
|
||||
|
||||
# extract title and delete from content array, array will start at 1 after that.
|
||||
$title = $content[0];
|
||||
unset($content[0]);
|
||||
|
||||
return $this->render($response, 'editor/editor-blox.twig', array('navigation' => $this->structure, 'title' => $title, 'content' => $content, 'item' => $this->item, 'settings' => $this->settings ));
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ class PageController extends Controller
|
||||
|
||||
/* get the first image from content array */
|
||||
$firstImage = $this->getFirstImage($contentArray);
|
||||
|
||||
|
||||
/* parse markdown-content-array to content-string */
|
||||
$contentHTML = $parsedown->markup($contentArray);
|
||||
$contentHTML = $this->c->dispatcher->dispatch('onHtmlLoaded', new OnHtmlLoaded($contentHTML))->getData();
|
||||
@ -216,11 +216,11 @@ class PageController extends Controller
|
||||
foreach($contentBlocks as $block)
|
||||
{
|
||||
/* is it a paragraph? */
|
||||
if(isset($block['element']['name']) && $block['element']['name'] == 'p')
|
||||
if(isset($block['name']) && $block['name'] == 'p')
|
||||
{
|
||||
if(isset($block['element']['handler']['argument']) && substr($block['element']['handler']['argument'], 0, 2) == '![' )
|
||||
if(isset($block['handler']['argument']) && substr($block['handler']['argument'], 0, 2) == '![' )
|
||||
{
|
||||
return $block['element']['handler']['argument'];
|
||||
return $block['handler']['argument'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
24
system/Extensions/TwigMarkdownExtension.php
Normal file
24
system/Extensions/TwigMarkdownExtension.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Typemill\Extensions;
|
||||
|
||||
use Typemill\Extensions\ParsedownExtension;
|
||||
|
||||
class TwigMarkdownExtension extends \Twig_Extension
|
||||
{
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFunction('markdown', array($this, 'renderMarkdown' ))
|
||||
];
|
||||
}
|
||||
|
||||
public function renderMarkdown($markdown)
|
||||
{
|
||||
$parsedown = new ParsedownExtension();
|
||||
|
||||
$markdownArray = $parsedown->text($markdown);
|
||||
|
||||
return $parsedown->markup($markdownArray);
|
||||
}
|
||||
}
|
@ -17,4 +17,5 @@ $app->post('/api/v1/article/sort', ContentApiController::class . ':sortArticle')
|
||||
$app->post('/api/v1/basefolder', ContentApiController::class . ':createBaseFolder')->setName('api.basefolder.create')->add(new RestrictApiAccess($container['router']));
|
||||
|
||||
$app->put('/api/v1/block', ContentApiController::class . ':updateBlock')->setName('api.block.update')->add(new RestrictApiAccess($container['router']));
|
||||
$app->delete('/api/v1/block', ContentApiController::class . ':deleteBlock')->setName('api.block.delete')->add(new RestrictApiAccess($container['router']));
|
||||
$app->delete('/api/v1/block', ContentApiController::class . ':deleteBlock')->setName('api.block.delete')->add(new RestrictApiAccess($container['router']));
|
||||
$app->put('/api/v1/moveblock', ContentApiController::class . ':moveBlock')->setName('api.block.move')->add(new RestrictApiAccess($container['router']));
|
@ -6,12 +6,6 @@
|
||||
"units_per_em": 1000,
|
||||
"ascent": 850,
|
||||
"glyphs": [
|
||||
{
|
||||
"uid": "c5845105a87df2ee1999826d90622f6a",
|
||||
"css": "paragraph",
|
||||
"code": 61917,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "f9cbf7508cd04145ade2800169959eef",
|
||||
"css": "font",
|
||||
@ -60,6 +54,12 @@
|
||||
"code": 61618,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "5408be43f7c42bccee419c6be53fdef5",
|
||||
"css": "doc-text",
|
||||
"code": 61686,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "b091a8bd0fdade174951f17d936f51e4",
|
||||
"css": "folder-empty",
|
||||
@ -67,9 +67,21 @@
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "5408be43f7c42bccee419c6be53fdef5",
|
||||
"css": "doc-text",
|
||||
"code": 61686,
|
||||
"uid": "d3b3f17bc3eb7cd809a07bbd4d178bee",
|
||||
"css": "resize-vertical",
|
||||
"code": 59398,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "6605ee6441bf499ffa3c63d3c7409471",
|
||||
"css": "move",
|
||||
"code": 61511,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "5211af474d3a9848f67f945e2ccaf143",
|
||||
"css": "cancel",
|
||||
"code": 59399,
|
||||
"src": "fontawesome"
|
||||
}
|
||||
]
|
||||
|
@ -5,8 +5,10 @@
|
||||
.icon-off:before { content: '\e803'; } /* '' */
|
||||
.icon-home:before { content: '\e804'; } /* '' */
|
||||
.icon-plus:before { content: '\e805'; } /* '' */
|
||||
.icon-resize-vertical:before { content: '\e806'; } /* '' */
|
||||
.icon-cancel:before { content: '\e807'; } /* '' */
|
||||
.icon-move:before { content: '\f047'; } /* '' */
|
||||
.icon-link-ext:before { content: '\f08e'; } /* '' */
|
||||
.icon-resize-full-alt:before { content: '\f0b2'; } /* '' */
|
||||
.icon-doc-text:before { content: '\f0f6'; } /* '' */
|
||||
.icon-folder-empty:before { content: '\f114'; } /* '' */
|
||||
.icon-paragraph:before { content: '\f1dd'; } /* '' */
|
||||
.icon-folder-empty:before { content: '\f114'; } /* '' */
|
File diff suppressed because one or more lines are too long
@ -5,8 +5,10 @@
|
||||
.icon-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-home { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-resize-vertical { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-move { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-resize-full-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-doc-text { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-folder-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-paragraph { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-folder-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
@ -16,8 +16,10 @@
|
||||
.icon-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-home { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-resize-vertical { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-move { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-resize-full-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-doc-text { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-folder-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-paragraph { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-folder-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
20
system/author/css/fontello/css/fontello.css
vendored
20
system/author/css/fontello/css/fontello.css
vendored
@ -1,11 +1,11 @@
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('../font/fontello.eot?94639617');
|
||||
src: url('../font/fontello.eot?94639617#iefix') format('embedded-opentype'),
|
||||
url('../font/fontello.woff2?94639617') format('woff2'),
|
||||
url('../font/fontello.woff?94639617') format('woff'),
|
||||
url('../font/fontello.ttf?94639617') format('truetype'),
|
||||
url('../font/fontello.svg?94639617#fontello') format('svg');
|
||||
src: url('../font/fontello.eot?89525311');
|
||||
src: url('../font/fontello.eot?89525311#iefix') format('embedded-opentype'),
|
||||
url('../font/fontello.woff2?89525311') format('woff2'),
|
||||
url('../font/fontello.woff?89525311') format('woff'),
|
||||
url('../font/fontello.ttf?89525311') format('truetype'),
|
||||
url('../font/fontello.svg?89525311#fontello') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@ -15,7 +15,7 @@
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('../font/fontello.svg?94639617#fontello') format('svg');
|
||||
src: url('../font/fontello.svg?89525311#fontello') format('svg');
|
||||
}
|
||||
}
|
||||
*/
|
||||
@ -61,8 +61,10 @@
|
||||
.icon-off:before { content: '\e803'; } /* '' */
|
||||
.icon-home:before { content: '\e804'; } /* '' */
|
||||
.icon-plus:before { content: '\e805'; } /* '' */
|
||||
.icon-resize-vertical:before { content: '\e806'; } /* '' */
|
||||
.icon-cancel:before { content: '\e807'; } /* '' */
|
||||
.icon-move:before { content: '\f047'; } /* '' */
|
||||
.icon-link-ext:before { content: '\f08e'; } /* '' */
|
||||
.icon-resize-full-alt:before { content: '\f0b2'; } /* '' */
|
||||
.icon-doc-text:before { content: '\f0f6'; } /* '' */
|
||||
.icon-folder-empty:before { content: '\f114'; } /* '' */
|
||||
.icon-paragraph:before { content: '\f1dd'; } /* '' */
|
||||
.icon-folder-empty:before { content: '\f114'; } /* '' */
|
@ -229,11 +229,11 @@ body {
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('./font/fontello.eot?32756715');
|
||||
src: url('./font/fontello.eot?32756715#iefix') format('embedded-opentype'),
|
||||
url('./font/fontello.woff?32756715') format('woff'),
|
||||
url('./font/fontello.ttf?32756715') format('truetype'),
|
||||
url('./font/fontello.svg?32756715#fontello') format('svg');
|
||||
src: url('./font/fontello.eot?63828600');
|
||||
src: url('./font/fontello.eot?63828600#iefix') format('embedded-opentype'),
|
||||
url('./font/fontello.woff?63828600') format('woff'),
|
||||
url('./font/fontello.ttf?63828600') format('truetype'),
|
||||
url('./font/fontello.svg?63828600#fontello') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@ -306,13 +306,17 @@ body {
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xe804"><i class="demo-icon icon-home"></i> <span class="i-name">icon-home</span><span class="i-code">0xe804</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe805"><i class="demo-icon icon-plus"></i> <span class="i-name">icon-plus</span><span class="i-code">0xe805</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf08e"><i class="demo-icon icon-link-ext"></i> <span class="i-name">icon-link-ext</span><span class="i-code">0xf08e</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf0b2"><i class="demo-icon icon-resize-full-alt"></i> <span class="i-name">icon-resize-full-alt</span><span class="i-code">0xf0b2</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe806"><i class="demo-icon icon-resize-vertical"></i> <span class="i-name">icon-resize-vertical</span><span class="i-code">0xe806</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe807"><i class="demo-icon icon-cancel"></i> <span class="i-name">icon-cancel</span><span class="i-code">0xe807</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xf047"><i class="demo-icon icon-move"></i> <span class="i-name">icon-move</span><span class="i-code">0xf047</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf08e"><i class="demo-icon icon-link-ext"></i> <span class="i-name">icon-link-ext</span><span class="i-code">0xf08e</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf0b2"><i class="demo-icon icon-resize-full-alt"></i> <span class="i-name">icon-resize-full-alt</span><span class="i-code">0xf0b2</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf0f6"><i class="demo-icon icon-doc-text"></i> <span class="i-name">icon-doc-text</span><span class="i-code">0xf0f6</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xf114"><i class="demo-icon icon-folder-empty"></i> <span class="i-name">icon-folder-empty</span><span class="i-code">0xf114</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf1dd"><i class="demo-icon icon-paragraph"></i> <span class="i-name">icon-paragraph</span><span class="i-code">0xf1dd</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container footer">Generated by <a href="http://fontello.com">fontello.com</a></div>
|
||||
|
Binary file not shown.
@ -18,6 +18,12 @@
|
||||
|
||||
<glyph glyph-name="plus" unicode="" d="M786 439v-107q0-22-16-38t-38-15h-232v-233q0-22-16-37t-38-16h-107q-22 0-38 16t-15 37v233h-232q-23 0-38 15t-16 38v107q0 23 16 38t38 16h232v232q0 22 15 38t38 16h107q23 0 38-16t16-38v-232h232q23 0 38-16t16-38z" horiz-adv-x="785.7" />
|
||||
|
||||
<glyph glyph-name="resize-vertical" unicode="" d="M393 671q0-14-11-25t-25-10h-71v-572h71q15 0 25-10t11-25-11-25l-143-143q-10-11-25-11t-25 11l-143 143q-10 10-10 25t10 25 25 10h72v572h-72q-14 0-25 10t-10 25 10 26l143 142q11 11 25 11t25-11l143-142q11-11 11-26z" horiz-adv-x="428.6" />
|
||||
|
||||
<glyph glyph-name="cancel" unicode="" d="M724 112q0-22-15-38l-76-76q-16-15-38-15t-38 15l-164 165-164-165q-16-15-38-15t-38 15l-76 76q-16 16-16 38t16 38l164 164-164 164q-16 16-16 38t16 38l76 76q16 16 38 16t38-16l164-164 164 164q16 16 38 16t38-16l76-76q15-15 15-38t-15-38l-164-164 164-164q15-15 15-38z" horiz-adv-x="785.7" />
|
||||
|
||||
<glyph glyph-name="move" unicode="" d="M1000 350q0-14-11-25l-142-143q-11-11-26-11t-25 11-10 25v72h-215v-215h72q14 0 25-10t11-25-11-25l-143-143q-10-11-25-11t-25 11l-143 143q-11 10-11 25t11 25 25 10h72v215h-215v-72q0-14-10-25t-25-11-25 11l-143 143q-11 11-11 25t11 25l143 143q10 11 25 11t25-11 10-25v-72h215v215h-72q-14 0-25 10t-11 25 11 26l143 142q11 11 25 11t25-11l143-142q11-11 11-26t-11-25-25-10h-72v-215h215v72q0 14 10 25t25 11 26-11l142-143q11-10 11-25z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="link-ext" unicode="" d="M786 332v-178q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h393q7 0 12-5t5-13v-36q0-8-5-13t-12-5h-393q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v178q0 8 5 13t13 5h36q8 0 13-5t5-13z m214 482v-285q0-15-11-25t-25-11-25 11l-98 98-364-364q-5-6-13-6t-12 6l-64 64q-6 5-6 12t6 13l364 364-98 98q-11 11-11 25t11 25 25 11h285q15 0 25-11t11-25z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="resize-full-alt" unicode="" d="M716 548l-198-198 198-198 80 80q17 18 39 8 22-9 22-33v-250q0-14-10-25t-26-11h-250q-23 0-32 23-10 21 7 38l81 81-198 198-198-198 80-81q17-17 8-38-10-23-33-23h-250q-15 0-25 11t-11 25v250q0 24 22 33 22 10 39-8l80-80 198 198-198 198-80-80q-11-11-25-11-7 0-14 3-22 9-22 33v250q0 14 11 25t25 11h250q23 0 33-23 9-21-8-38l-80-81 198-198 198 198-81 81q-17 17-7 38 9 23 32 23h250q15 0 26-11t10-25v-250q0-24-22-33-7-3-14-3-14 0-25 11z" horiz-adv-x="857.1" />
|
||||
@ -25,8 +31,6 @@
|
||||
<glyph glyph-name="doc-text" unicode="" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-572 483q0 7 5 12t13 5h393q8 0 13-5t5-12v-36q0-8-5-13t-13-5h-393q-8 0-13 5t-5 13v36z m411-125q8 0 13-5t5-13v-36q0-8-5-13t-13-5h-393q-8 0-13 5t-5 13v36q0 8 5 13t13 5h393z m0-143q8 0 13-5t5-13v-36q0-8-5-13t-13-5h-393q-8 0-13 5t-5 13v36q0 8 5 13t13 5h393z" horiz-adv-x="857.1" />
|
||||
|
||||
<glyph glyph-name="folder-empty" unicode="" d="M857 118v393q0 22-15 38t-38 15h-393q-23 0-38 16t-16 38v36q0 22-15 38t-38 15h-179q-22 0-38-15t-16-38v-536q0-22 16-38t38-16h679q22 0 38 16t15 38z m72 393v-393q0-51-37-88t-88-37h-679q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h375q51 0 88-37t37-88z" horiz-adv-x="928.6" />
|
||||
|
||||
<glyph glyph-name="paragraph" unicode="" d="M713 745v-41q0-16-10-34t-24-18q-28 0-30-1-14-3-18-17-1-6-1-36v-643q0-14-11-24t-24-10h-60q-14 0-24 10t-10 24v680h-80v-680q0-14-9-24t-25-10h-60q-14 0-24 10t-10 24v277q-82 7-137 33-70 33-107 100-36 65-36 145 0 92 50 159 49 66 116 89 62 21 233 21h267q14 0 24-10t10-24z" horiz-adv-x="714.3" />
|
||||
</font>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 6.0 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1394,22 +1394,32 @@ label .help, .label .help{
|
||||
border: 1px solid #e0474c;
|
||||
color: #eee;
|
||||
}
|
||||
.blox-editor button.delete{
|
||||
.blox-editor .sideaction{
|
||||
position: absolute;
|
||||
right: 1px;
|
||||
top: 1px;
|
||||
font-weight: 700;
|
||||
right: -22px;
|
||||
top: 0px;
|
||||
}
|
||||
.blox-editor button.delete, .blox-editor .icon-resize-full-alt{
|
||||
display: block;
|
||||
font-weight: 300;
|
||||
font-size: 0.9em;
|
||||
background: #fff;
|
||||
color: #fff;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
padding: 0px;
|
||||
margin: 0px 0px 1px;
|
||||
border: 0px;
|
||||
border-radius: 2px;
|
||||
padding: 2px 4px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.blox-editor:hover button.delete{
|
||||
background: #e0474c;
|
||||
color: #fff;
|
||||
}
|
||||
.blox-editor button.delete:hover{
|
||||
cursor: pointer;
|
||||
background: #cc4146;
|
||||
}
|
||||
.blox-editor button.edit:disabled, .blox-editor button.cancel:disabled{
|
||||
|
@ -6,24 +6,24 @@
|
||||
<div class="formWrapper">
|
||||
|
||||
<section id="blox">
|
||||
|
||||
<div class="blox-title"></div>
|
||||
|
||||
<div class="blox-body">
|
||||
|
||||
<content-block class="title" :body="false">
|
||||
<div class="blox title" @click="setData( $event, 'text-markdown')" data-id="0" id="blox-0">{{ title }}</div>
|
||||
</content-block>
|
||||
|
||||
<div id="sortblox">
|
||||
|
||||
{% for id, block in content %}
|
||||
{% if loop.first %}
|
||||
<content-block class="title" :body="false">
|
||||
<div class="blox title" @click="setData( $event, 'text-markdown')" data-id="{{ id }}" id="blox-{{id}}">{{block}}</div>
|
||||
</content-block>
|
||||
{% else %}
|
||||
{% for id, block in content %}
|
||||
<content-block :body="true">
|
||||
<div class="blox" @click="setData( $event, 'textarea-markdown' )" data-id="{{ id }}" id="blox-{{id}}">{{block}}</div>
|
||||
</content-block>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
<content-block :body="true" v-for="newBlock in newBlocks"><div class="blox" @click="setData( $event, 'textarea-markdown' )" :data-id="newBlock.id" :id="newBlock.blockId" v-html="newBlock.content"></div></content-block>
|
||||
<content-block :body="true" v-for="newBlock in newBlocks"><div class="blox" @click="setData( $event, 'textarea-markdown' )" :data-id="newBlock.id" :id="newBlock.blockId" v-html="newBlock.content"></div></content-block>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="format-bar">
|
||||
<content-block :body="false">
|
||||
|
@ -301,4 +301,26 @@
|
||||
|
||||
|
||||
})(thisTarget);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Element.closest() polyfill
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
|
||||
*/
|
||||
if (!Element.prototype.closest) {
|
||||
if (!Element.prototype.matches) {
|
||||
Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
|
||||
}
|
||||
Element.prototype.closest = function (s) {
|
||||
var el = this;
|
||||
var ancestor = this;
|
||||
if (!document.documentElement.contains(el)) return null;
|
||||
do {
|
||||
if (ancestor.matches(s)) return ancestor;
|
||||
ancestor = ancestor.parentElement;
|
||||
} while (ancestor !== null);
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ const contentComponent = Vue.component('content-block', {
|
||||
},
|
||||
methods: {
|
||||
getData: function()
|
||||
{
|
||||
{
|
||||
self = this;
|
||||
|
||||
if(self.$root.$data.freeze == false && self.$root.$data.blockType != '')
|
||||
@ -21,7 +21,25 @@ const contentComponent = Vue.component('content-block', {
|
||||
this.edit = true;
|
||||
this.compmarkdown = self.$root.$data.blockMarkdown;
|
||||
this.componentType = self.$root.$data.blockType;
|
||||
self.$root.sortable.option("disabled",true);
|
||||
}
|
||||
/*
|
||||
window.addEventListener('click', function(e)
|
||||
{
|
||||
if (!e.target.closest('.editactive'))
|
||||
{
|
||||
console.info('not found');
|
||||
publishController.errors.message = false;
|
||||
|
||||
this.preview = 'visible';
|
||||
this.edit = false;
|
||||
this.compmarkdown = '';
|
||||
self.componentType = false;
|
||||
self.$root.$data.freeze = false;
|
||||
self.$root.sortable.option("disabled",false);
|
||||
}
|
||||
});
|
||||
*/
|
||||
},
|
||||
cancelBlock: function()
|
||||
{
|
||||
@ -32,6 +50,7 @@ const contentComponent = Vue.component('content-block', {
|
||||
this.componentType = false;
|
||||
self = this;
|
||||
self.$root.$data.freeze = false;
|
||||
self.$root.sortable.option("disabled",false);
|
||||
},
|
||||
submitBlock: function(e){
|
||||
var emptyline = /^\s*$(?:\r\n?|\n)/gm;
|
||||
@ -47,9 +66,11 @@ const contentComponent = Vue.component('content-block', {
|
||||
this.componentType = false;
|
||||
self = this;
|
||||
self.$root.$data.freeze = false;
|
||||
self.$root.sortable.option("disabled",false);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.$root.sortable.option("disabled",false);
|
||||
this.saveBlock();
|
||||
}
|
||||
}
|
||||
@ -129,8 +150,9 @@ const contentComponent = Vue.component('content-block', {
|
||||
}, method, url, params);
|
||||
},
|
||||
deleteBlock: function(event)
|
||||
{
|
||||
var bloxeditor = event.target.parentElement;
|
||||
{
|
||||
var bloxeditor = event.target.parentElement.parentElement;
|
||||
console.info(bloxeditor);
|
||||
var bloxid = bloxeditor.getElementsByClassName('blox')[0].dataset.id;
|
||||
bloxeditor.id = "delete-"+bloxid;
|
||||
|
||||
@ -181,6 +203,7 @@ const contentComponent = Vue.component('content-block', {
|
||||
var length = blox.length;
|
||||
for (var i = 0; i < length; i++ ) {
|
||||
blox[i].id = "blox-" + i;
|
||||
blox[i].dataset.id = i;
|
||||
}
|
||||
|
||||
self.$root.$data.freeze = false;
|
||||
@ -195,7 +218,26 @@ const contentComponent = Vue.component('content-block', {
|
||||
}, method, url, params);
|
||||
},
|
||||
},
|
||||
template: '<div class="blox-editor"><div><div @keyup.enter="submitBlock" @click="getData"><transition name="fade-editor"><component :disabled="disabled" :compmarkdown="compmarkdown" @updatedMarkdown="compmarkdown = $event" :is="componentType"></component></transition><div :class="preview"><slot></slot></div></div><div class="blox-buttons" v-if="edit"><button class="edit" :disabled="disabled" @click.prevent="saveBlock">save</button><button class="cancel" :disabled="disabled" @click.prevent="cancelBlock">cancel</button></div><button v-if="body" class="delete" :disabled="disabled" title="delete content-block" @click.prevent="deleteBlock($event)">x</button></div></div>',
|
||||
/*
|
||||
mounted: function() {
|
||||
var self = this;
|
||||
|
||||
self.sortable = new Sortable(sortblox, {
|
||||
animation: 150,
|
||||
onEnd: function (evt) {
|
||||
var params = {
|
||||
'url': document.getElementById("path").value,
|
||||
'old_index': evt.oldIndex,
|
||||
'new_index': evt.newIndex,
|
||||
'csrf_name': document.getElementById("csrf_name").value,
|
||||
'csrf_value': document.getElementById("csrf_value").value,
|
||||
};
|
||||
self.moveBlock(params);
|
||||
},
|
||||
});
|
||||
},
|
||||
*/
|
||||
template: '<div class="blox-editor"><div :class="{ editactive: edit }"><div @keyup.enter="submitBlock" @click="getData"><transition name="fade-editor"><component :disabled="disabled" :compmarkdown="compmarkdown" @updatedMarkdown="compmarkdown = $event" :is="componentType"></component></transition><div :class="preview"><slot></slot></div></div><div class="blox-buttons" v-if="edit"><button class="edit" :disabled="disabled" @click.prevent="saveBlock">save</button><button class="cancel" :disabled="disabled" @click.prevent="cancelBlock">cancel</button></div><div class="sideaction" v-if="body"><button class="delete" :disabled="disabled" title="delete content-block" @click.prevent="deleteBlock($event)"><i class="icon-cancel"></i></button></div></div></div>',
|
||||
})
|
||||
|
||||
const textareaComponent = Vue.component('textarea-markdown', {
|
||||
@ -291,6 +333,20 @@ let editor = new Vue({
|
||||
}
|
||||
}
|
||||
}, method, url, params);
|
||||
|
||||
self.sortable = new Sortable(sortblox, {
|
||||
animation: 150,
|
||||
onEnd: function (evt) {
|
||||
var params = {
|
||||
'url': document.getElementById("path").value,
|
||||
'old_index': evt.oldIndex,
|
||||
'new_index': evt.newIndex,
|
||||
'csrf_name': document.getElementById("csrf_name").value,
|
||||
'csrf_value': document.getElementById("csrf_value").value,
|
||||
};
|
||||
self.moveBlock(params);
|
||||
},
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
setData: function(event, blocktype, body)
|
||||
@ -299,5 +355,51 @@ let editor = new Vue({
|
||||
this.blockType = blocktype;
|
||||
this.blockMarkdown = this.markdown[this.blockId];
|
||||
},
|
||||
moveBlock: function(params)
|
||||
{
|
||||
publishController.errors.message = false;
|
||||
|
||||
var url = this.root + '/api/v1/moveblock';
|
||||
|
||||
var self = this;
|
||||
|
||||
var method = 'PUT';
|
||||
|
||||
sendJson(function(response, httpStatus)
|
||||
{
|
||||
if(httpStatus == 400)
|
||||
{
|
||||
}
|
||||
if(response)
|
||||
{
|
||||
|
||||
var result = JSON.parse(response);
|
||||
|
||||
if(result.errors)
|
||||
{
|
||||
publishController.errors.message = result.errors;
|
||||
publishController.publishDisabled = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var blox = document.getElementsByClassName("blox");
|
||||
var length = blox.length;
|
||||
for (var i = 0; i < length; i++ ) {
|
||||
blox[i].id = "blox-" + i;
|
||||
blox[i].dataset.id = i;
|
||||
}
|
||||
|
||||
self.freeze = false;
|
||||
self.markdown = result.markdown;
|
||||
self.blockMarkdown = '';
|
||||
self.blockType = '';
|
||||
|
||||
publishController.publishDisabled = false;
|
||||
publishController.publishResult = "";
|
||||
}
|
||||
}
|
||||
}, method, url, params);
|
||||
},
|
||||
}
|
||||
});
|
@ -164,6 +164,7 @@ $container['view'] = function ($container)
|
||||
$view->addExtension(new Slim\Views\TwigExtension($container['router'], $basePath));
|
||||
$view->addExtension(new Twig_Extension_Debug());
|
||||
$view->addExtension(new Typemill\Extensions\TwigUserExtension());
|
||||
$view->addExtension(new Typemill\Extensions\TwigMarkdownExtension());
|
||||
|
||||
/* use {{ base_url() }} in twig templates */
|
||||
$view['base_url'] = $container['request']->getUri()->getBaseUrl();
|
||||
|
Loading…
x
Reference in New Issue
Block a user