1
0
mirror of https://github.com/typemill/typemill.git synced 2025-01-17 05:18:19 +01:00

Version 1.3.2: Rename and Hide navigation

This commit is contained in:
trendschau 2020-01-20 18:52:57 +01:00
parent 00368397ce
commit 53f17927fd
26 changed files with 443 additions and 85 deletions

1
.gitignore vendored
View File

@ -1,5 +1,4 @@
cache
cache/lastCache.txt
content/index.yaml
content/00-Welcome/index.yaml
content/00-Welcome/00-Setup.yaml

1
cache/lastCache.txt vendored
View File

@ -1 +0,0 @@
1578580890

View File

@ -246,9 +246,12 @@ class ContentApiController extends ContentController
# update the live structure
$this->setStructure($draft = false, $cache = false);
#update the backend structure
# update the backend structure
$this->setStructure($draft = true, $cache = false);
# check if page is in extended structure and delete it
$this->deleteFromExtended();
# dispatch event
$this->c->dispatcher->dispatch('onPageDeleted', new OnPageDeleted($this->item));
@ -324,12 +327,6 @@ class ContentApiController extends ContentController
$parentKeyFrom = explode('.', $this->params['parent_id_from']);
$parentKeyTo = explode('.', $this->params['parent_id_to']);
/*
echo '<pre>';
print_r(array($itemKeyPath 0,$parentKeyFrom navi,$parentKeyTo 2));
die();
*/
# get the item from structure
$item = Folder::getItemWithKeyPath($this->structure, $itemKeyPath);
@ -362,10 +359,16 @@ class ContentApiController extends ContentController
# delete item from folderContent
unset($folderContent[$itemKey]);
}
elseif($this->params['active'] == 'active')
else
{
# rename links in extended file
$this->renameExtended($item, $newFolder);
# an active file has been moved to another folder, so send new url with response
$url = $this->uri->getBaseUrl() . '/tm/content/' . $this->settings['editor'] . $newFolder->urlRelWoF . '/' . $item->slug;
if($this->params['active'] == 'active')
{
$url = $this->uri->getBaseUrl() . '/tm/content/' . $this->settings['editor'] . $newFolder->urlRelWoF . '/' . $item->slug;
}
}
# add item to newFolder

View File

@ -9,6 +9,7 @@ use Typemill\Models\Validation;
use Typemill\Models\Folder;
use Typemill\Models\Write;
use Typemill\Models\WriteCache;
use Typemill\Models\WriteYaml;
abstract class ContentController
{
@ -182,7 +183,7 @@ abstract class ContentController
# set variables and objects
$this->write = new writeCache();
# check, if cached structure is still valid
if($cache && $this->write->validate('cache', 'lastCache.txt', 600))
{
@ -199,18 +200,76 @@ abstract class ContentController
# if there is content, then get the content details
if(count($structure) > 0)
{
# create an array of object with the whole content of the folder
$structure = Folder::getFolderContentDetails($structure, $this->uri->getBaseUrl(), $this->uri->getBasePath());
# get the extended structure files with changes like navigation title or hidden pages
$yaml = new writeYaml();
$extended = $yaml->getYaml('cache', 'structure-extended.yaml');
# create an array of object with the whole content of the folder and changes from extended file
$structure = Folder::getFolderContentDetails($structure, $extended, $this->uri->getBaseUrl(), $this->uri->getBasePath());
}
# cache navigation
$this->write->updateCache('cache', $filename, 'lastCache.txt', $structure);
}
$this->structure = $structure;
return true;
}
protected function renameExtended($item, $newFolder)
{
# get the extended structure files with changes like navigation title or hidden pages
$yaml = new writeYaml();
$extended = $yaml->getYaml('cache', 'structure-extended.yaml');
if(isset($extended[$item->urlRelWoF]))
{
$newUrl = $newFolder->urlRelWoF . '/' . $item->slug;
$entry = $extended[$item->urlRelWoF];
unset($extended[$item->urlRelWoF]);
$extended[$newUrl] = $entry;
$yaml->updateYaml('cache', 'structure-extended.yaml', $extended);
}
return true;
}
protected function deleteFromExtended()
{
# get the extended structure files with changes like navigation title or hidden pages
$yaml = new writeYaml();
$extended = $yaml->getYaml('cache', 'structure-extended.yaml');
if($this->item->elementType == "file" && isset($extended[$this->item->urlRelWoF]))
{
unset($extended[$this->item->urlRelWoF]);
$yaml->updateYaml('cache', 'structure-extended.yaml', $extended);
}
if($this->item->elementType == "folder")
{
$changed = false;
# delete all entries with that folder url
foreach($extended as $url => $entries)
{
if( strpos($url, $this->item->urlRelWoF) !== false )
{
$changed = true;
unset($extended[$url]);
}
}
if($changed)
{
$yaml->updateYaml('cache', 'structure-extended.yaml', $extended);
}
}
}
protected function setHomepage()
{
$contentFolder = Folder::scanFolderFlat($this->settings['rootPath'] . $this->settings['contentFolder']);
@ -251,6 +310,7 @@ abstract class ContentController
}
$this->errors = ['errors' => ['message' => 'requested page-url not found']];
return false;
}
@ -334,6 +394,9 @@ abstract class ContentController
}
return rmdir($path);
}
# delete all files from the extended file
$this->deleteFromExtended();
}
return false;
}

View File

@ -5,6 +5,7 @@ namespace Typemill\Controllers;
use Slim\Http\Request;
use Slim\Http\Response;
use Typemill\Models\WriteYaml;
use Typemill\Models\Folder;
class MetaApiController extends ContentController
{
@ -23,10 +24,6 @@ class MetaApiController extends ContentController
$metatabs = $writeYaml->getYaml('system' . DIRECTORY_SEPARATOR . 'author', 'metatabs.yaml');
# load cached metadefinitions
# check if valid
# if not, refresh cache
# loop through all plugins
foreach($this->settings['plugins'] as $name => $plugin)
{
@ -39,6 +36,14 @@ class MetaApiController extends ContentController
}
}
}
# add the meta from theme settings here
$themeSettings = \Typemill\Settings::getObjectSettings('themes', $this->settings['theme']);
if($themeSettings && isset($themeSettings['metatabs']))
{
$metatabs = array_merge_recursive($metatabs, $themeSettings['metatabs']);
}
return $metatabs;
}
@ -77,32 +82,37 @@ class MetaApiController extends ContentController
$metadefinitions = $this->aggregateMetaDefinitions();
$metadata = [];
$metascheme = [];
foreach($metadefinitions as $tabname => $tab )
{
$metadata[$tabname] = [];
$metadata[$tabname] = [];
foreach($tab['fields'] as $fieldname => $fielddefinitions)
{
$metascheme[$tabname][$fieldname] = true;
$metadata[$tabname][$fieldname] = isset($pagemeta[$tabname][$fieldname]) ? $pagemeta[$tabname][$fieldname] : null;
}
}
# store the metascheme in cache for frontend
$writeYaml->updateYaml('cache', 'metatabs.yaml', $metascheme);
return $response->withJson(array('metadata' => $metadata, 'metadefinitions' => $metadefinitions, 'errors' => false));
}
public function updateArticleMeta(Request $request, Response $response, $args)
{
/* get params from call */
# get params from call
$this->params = $request->getParams();
$this->uri = $request->getUri();
$tab = isset($this->params['tab']) ? $this->params['tab'] : false;
$metaData = isset($this->params['data']) ? $this->params['data'] : false ;
$metaInput = isset($this->params['data']) ? $this->params['data'] : false ;
$objectName = 'meta';
$errors = false;
if(!$tab or !$metaData)
if(!$tab or !$metaInput)
{
return $response->withJson($this->errors, 404);
}
@ -114,7 +124,7 @@ class MetaApiController extends ContentController
$validate = $this->getValidator();
# take the user input data and iterate over all fields and values
foreach($metaData as $fieldName => $fieldValue)
foreach($metaInput as $fieldName => $fieldValue)
{
# get the corresponding field definition from original plugin settings */
$fieldDefinition = isset($metaDefinitions[$tab]['fields'][$fieldName]) ? $metaDefinitions[$tab]['fields'][$fieldName] : false;
@ -147,16 +157,66 @@ class MetaApiController extends ContentController
$writeYaml = new writeYaml();
# get existing metadata for page
$meta = $writeYaml->getYaml($this->settings['contentFolder'], $this->item->pathWithoutType . '.yaml');
$metaPage = $writeYaml->getYaml($this->settings['contentFolder'], $this->item->pathWithoutType . '.yaml');
# get extended structure
$extended = $writeYaml->getYaml('cache', 'structure-extended.yaml');
# flag for changed structure
$structure = false;
if($tab == 'meta')
{
# normalize the meta-input
$metaInput['navtitle'] = (isset($metaInput['navtitle']) && $metaInput['navtitle'] !== null )? $metaInput['navtitle'] : '';
$metaInput['hide'] = (isset($metaInput['hide']) && $metaInput['hide'] !== null) ? $metaInput['hide'] : false;
# input values are empty but entry in structure exists
if(!$metaInput['hide'] && $metaInput['navtitle'] == "" && isset($extended[$this->item->urlRelWoF]))
{
# delete the entry in the structure
unset($extended[$this->item->urlRelWoF]);
$structure = true;
}
# check if navtitle or hide-value has been changed
elseif(
($metaPage['meta']['navtitle'] != $metaInput['navtitle'])
OR
($metaPage['meta']['hide'] != $metaInput['hide'])
)
{
# add new file data. Also makes sure that the value is set.
$extended[$this->item->urlRelWoF] = ['hide' => $metaInput['hide'], 'navtitle' => $metaInput['navtitle']];
$structure = true;
}
if($structure)
{
# store the file
$writeYaml->updateYaml('cache', 'structure-extended.yaml', $extended);
# recreate the draft structure
$this->setStructure($draft = true, $cache = false);
# set item in navigation active again
$activeItem = Folder::getItemForUrl($this->structure, $this->item->urlRel, $this->uri->getBaseUrl());
# send new structure to frontend
$structure = $this->structure;
}
}
# add the new/edited metadata
$meta[$tab] = $metaData;
$meta[$tab] = $metaInput;
# store the metadata
$writeYaml->updateYaml($this->settings['contentFolder'], $this->item->pathWithoutType . '.yaml', $meta);
# return with the new metadata
return $response->withJson(array('metadata' => $metaData, 'errors' => false));
return $response->withJson(array('metadata' => $metaInput, 'structure' => $structure, 'errors' => false));
}
}

View File

@ -40,7 +40,7 @@ class PageController extends Controller
try
{
/* if the cached structure is still valid, use it */
if($cache->validate('cache', 'lastCache.txt',600))
if($cache->validate('cache', 'lastCache.txt', 600))
{
$structure = $this->getCachedStructure($cache);
}
@ -75,7 +75,15 @@ class PageController extends Controller
echo $e->getMessage();
exit(1);
}
# get the cached navigation here (structure without hidden files )
$navigation = $cache->getCache('cache', 'navigation.txt');
if(!$navigation)
{
# use the structure as navigation if there is no difference
$navigation = $structure;
}
# if the user is on startpage
if(empty($args))
{
@ -93,7 +101,7 @@ class PageController extends Controller
/* if there is still no item, return a 404-page */
if(!$item)
{
return $this->render404($response, array( 'navigation' => $structure, 'settings' => $settings, 'base_url' => $base_url ));
return $this->render404($response, array( 'navigation' => $navigation, 'settings' => $settings, 'base_url' => $base_url ));
}
/* get breadcrumb for page */
@ -124,7 +132,6 @@ class PageController extends Controller
# get meta-Information
$writeYaml = new WriteYaml();
$metatabs = $writeYaml->getPageMeta($settings, $item);
if(!$metatabs)
@ -196,12 +203,19 @@ class PageController extends Controller
$theme = $settings['theme'];
$route = empty($args) && isset($settings['themes'][$theme]['cover']) ? '/cover.twig' : '/index.twig';
# check if there is a custom theme css
$customcss = $writeYaml->checkFile('cache', $theme . '-custom.css');
if($customcss)
{
$this->c->assets->addCSS($base_url . '/cache/' . $theme . '-custom.css');
}
return $this->render($response, $route, [
'home' => $home,
'navigation' => $structure,
'title' => $title,
'navigation' => $navigation,
'title' => $title,
'content' => $contentHTML,
'item' => $item,
'item' => $item,
'breadcrumb' => $breadcrumb,
'settings' => $settings,
'metatabs' => $metatabs,
@ -225,15 +239,62 @@ class PageController extends Controller
return false;
}
/* create an array of object with the whole content of the folder */
$structure = Folder::getFolderContentDetails($structure, $uri->getBaseUrl(), $uri->getBasePath());
# get the extended structure files with changes like navigation title or hidden pages
$yaml = new writeYaml();
$extended = $yaml->getYaml('cache', 'structure-extended.yaml');
/* cache navigation */
/* create an array of object with the whole content of the folder */
$structure = Folder::getFolderContentDetails($structure, $extended, $uri->getBaseUrl(), $uri->getBasePath());
/* cache structure */
$cache->updateCache('cache', 'structure.txt', 'lastCache.txt', $structure);
if($this->containsHiddenPages($extended))
{
# generate the navigation (delete empty pages)
$navigation = $this->createNavigationFromStructure($structure);
# cache navigation
$cache->updateCache('cache', 'navigation.txt', false, $navigation);
}
else
{
# make sure no separate navigation file is set
$cache->deleteFileWithPath('cache' . DIRECTORY_SEPARATOR . 'navigation.txt');
}
return $structure;
}
protected function containsHiddenPages($extended)
{
foreach($extended as $element)
{
if(isset($element['hide']) && $element['hide'] === true)
{
return true;
}
}
return false;
}
protected function createNavigationFromStructure($navigation)
{
foreach ($navigation as $key => $element)
{
if($element->hide === true)
{
unset($navigation[$key]);
}
elseif(isset($element->folderContent))
{
$navigation[$key]->folderContent = $this->createNavigationFromStructure($element->folderContent);
}
}
return $navigation;
}
protected function updateVersion($baseUrl)
{
/* check the latest public typemill version */

View File

@ -3,6 +3,7 @@
namespace Typemill\Controllers;
use \Symfony\Component\Yaml\Yaml;
use Typemill\Models\Write;
use Typemill\Models\Fields;
use Typemill\Models\Validation;
use Typemill\Models\User;
@ -91,7 +92,7 @@ class SettingsController extends Controller
public function showThemes($request, $response, $args)
{
$userSettings = $this->c->get('settings');
$userSettings = $this->c->get('settings');
$themes = $this->getThemes();
$themedata = array();
$fieldsModel = new Fields();
@ -109,24 +110,40 @@ class SettingsController extends Controller
}
$themeSettings = \Typemill\Settings::getObjectSettings('themes', $themeName);
# add standard-textarea for custom css
$themeSettings['forms']['fields']['customcss'] = ['type' => 'textarea', 'label' => 'Custom CSS', 'rows' => 10, 'class' => 'codearea', 'description' => 'You can overwrite the theme-css with your own css here.'];
# load custom css-file
$write = new write();
$customcss = $write->getFile('cache', $themeName . '-custom.css');
$themeSettings['settings']['customcss'] = $customcss;
if($themeSettings)
{
/* store them as default theme data with author, year, default settings and field-definitions */
$themedata[$themeName] = $themeSettings;
}
if(isset($themeSettings['forms']['fields']))
{
$fields = $fieldsModel->getFields($userSettings, 'themes', $themeName, $themeSettings);
$fields = $fieldsModel->getFields($userSettings, 'themes', $themeName, $themeSettings);
/* overwrite original theme form definitions with enhanced form objects */
$themedata[$themeName]['forms']['fields'] = $fields;
}
/* add the preview image */
$img = getcwd() . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $themeName . DIRECTORY_SEPARATOR . $themeName . '.jpg';
$img = file_exists($img) ? $img : false;
$img = getcwd() . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $themeName . DIRECTORY_SEPARATOR . $themeName;
$jpg = $img . '.jpg';
$png = $img . '.png';
$img = file_exists($jpg) ? $jpg : false;
if(!$img)
{
$img = file_exists($png) ? $png : false;
}
$themedata[$themeName]['img'] = $img;
}
@ -134,7 +151,7 @@ class SettingsController extends Controller
$user = new User();
$users = $user->getUsers();
$route = $request->getAttribute('route');
return $this->render($response, 'settings/themes.twig', array('settings' => $userSettings, 'themes' => $themedata, 'users' => $users, 'route' => $route->getName() ));
}
@ -245,6 +262,34 @@ class SettingsController extends Controller
/* set theme name and delete theme settings from user settings for the case, that the new theme has no settings */
$userSettings['theme'] = $themeName;
# extract the custom css from user input
$customcss = isset($userInput['customcss']) ? $userInput['customcss'] : false;
# delete custom css from userinput
unset($userInput['customcss']);
$write = new write();
# make sure no file is set if there is no custom css
if(!$customcss OR $customcss == '')
{
# delete the css file if exists
$write->deleteFileWithPath('cache' . DIRECTORY_SEPARATOR . $themeName . '-custom.css');
}
else
{
if ( $customcss != strip_tags($customcss) )
{
$_SESSION['errors'][$themeName]['customcss'][] = 'custom css contains html';
}
else
{
# store css
$write = new write();
$write->writeFile('cache', $themeName . '-custom.css', $customcss);
}
}
if($userInput)
{
/* validate the user-input */

View File

@ -16,7 +16,7 @@ class Folder
{
$folderItems = scandir($folderPath);
$folderContent = array();
foreach ($folderItems as $key => $item)
{
if (!in_array($item, array(".","..")))
@ -96,8 +96,8 @@ class Folder
* vars: multidimensional array with folder- and file-names
* returns: array of objects. Each object contains information about an item (file or folder).
*/
public static function getFolderContentDetails(array $folderContent, $baseUrl, $fullSlugWithFolder = NULL, $fullSlugWithoutFolder = NULL, $fullPath = NULL, $keyPath = NULL, $chapter = NULL)
{
public static function getFolderContentDetails(array $folderContent, $extended, $baseUrl, $fullSlugWithFolder = NULL, $fullSlugWithoutFolder = NULL, $fullPath = NULL, $keyPath = NULL, $chapter = NULL)
{
$contentDetails = [];
$iteration = 0;
$chapternr = 1;
@ -147,8 +147,16 @@ class Folder
$item->chapter = $chapter ? $chapter . '.' . $chapternr : $chapternr;
$item->active = false;
$item->activeParent = false;
$item->hide = false;
$item->folderContent = self::getFolderContentDetails($name, $baseUrl, $item->urlRel, $item->urlRelWoF, $item->path, $item->keyPath, $item->chapter);
# check if there are extended information
if($extended && isset($extended[$item->urlRelWoF]))
{
$item->name = ($extended[$item->urlRelWoF]['navtitle'] != '') ? $extended[$item->urlRelWoF]['navtitle'] : $item->name;
$item->hide = ($extended[$item->urlRelWoF]['hide'] === true) ? true : false;
}
$item->folderContent = self::getFolderContentDetails($name, $extended, $baseUrl, $item->urlRel, $item->urlRelWoF, $item->path, $item->keyPath, $item->chapter);
}
else
{
@ -196,6 +204,14 @@ class Folder
$item->urlAbs = $baseUrl . $fullSlugWithoutFolder . '/' . $item->slug;
$item->active = false;
$item->activeParent = false;
$item->hide = false;
# check if there are extended information
if($extended && isset($extended[$item->urlRelWoF]))
{
$item->name = ($extended[$item->urlRelWoF]['navtitle'] != '') ? $extended[$item->urlRelWoF]['navtitle'] : $item->name;
$item->hide = ($extended[$item->urlRelWoF]['hide'] === true) ? true : false;
}
}
$iteration++;
@ -223,9 +239,9 @@ class Folder
foreach($folderContentDetails as $key => $item)
{
# set item active, needed to move item in navigation
if($item->urlRel === $url)
{
# set item active, needed for move item in navigation
$item->active = true;
$result = $item;
}
@ -234,6 +250,7 @@ class Folder
$result = self::getItemForUrl($item->folderContent, $url, $baseUrl, $result);
}
}
return $result;
}
@ -378,6 +395,30 @@ class Folder
return array('structure' => $structure, 'item' => $item);
}
# NOT IN USE
public static function deleteItemWithKeyPath($structure, array $keys)
{
$result = &$structure;
$last = array_pop($keys);
foreach ($keys as $key)
{
if(isset($result[$key]->folderContent))
{
$result = &$result[$key]->folderContent;
}
else
{
$result = &$result[$key];
}
}
$item = $result[$last];
unset($result[$last]);
return $structure;
}
/* get breadcrumb as copied array, set elements active in original and mark parent element in original */
public static function getBreadcrumb($content, $searchArray, $i = NULL, $breadcrumb = NULL)

View File

@ -23,6 +23,5 @@ class Helpers{
}
$table .= '</table></body></html>';
echo $table;
exit;
}
}

View File

@ -41,7 +41,7 @@ class Write
return true;
}
protected function checkFile($folder, $file)
public function checkFile($folder, $file)
{
if(!file_exists($this->basePath . $folder . DIRECTORY_SEPARATOR . $file))
{
@ -50,7 +50,7 @@ class Write
return true;
}
protected function checkFileWithPath($filepath)
public function checkFileWithPath($filepath)
{
if(!file_exists($this->basePath . $filepath))
{
@ -62,7 +62,7 @@ class Write
public function writeFile($folder, $file, $data)
{
if($this->checkPath($folder))
{
{
$filePath = $this->basePath . $folder . DIRECTORY_SEPARATOR . $file;
$openFile = @fopen($filePath, "w");
@ -70,11 +70,11 @@ class Write
if(!$openFile)
{
return false;
}
}
fwrite($openFile, $data);
fclose($openFile);
return true;
}
return false;
@ -118,8 +118,10 @@ class Write
$newOrder = ($index < 10) ? '0' . $index : $index;
# create new path with foldername or filename but without file-type
$newPath = $this->basePath . 'content' . $folderPath . DIRECTORY_SEPARATOR . $newOrder . '-' . str_replace(" ", "-", $item->name);
# $newPath = $this->basePath . 'content' . $folderPath . DIRECTORY_SEPARATOR . $newOrder . '-' . str_replace(" ", "-", $item->name);
$newPath = $this->basePath . 'content' . $folderPath . DIRECTORY_SEPARATOR . $newOrder . '-' . $item->slug;
if($item->elementType == 'folder')
{
$oldPath = $this->basePath . 'content' . $item->path;

View File

@ -10,7 +10,7 @@ class WriteCache extends Write
* @return boolean for an invalid cache (false) and for a valid cache (true).
*/
public function validate($folderName, $fileName, $duration)
{
{
if(isset($_SERVER['HTTP_CACHE_CONTROL']) && $_SERVER['HTTP_CACHE_CONTROL'] == 'max-age=0')
{
return false;
@ -28,7 +28,7 @@ class WriteCache extends Write
}
$lastRefresh = file_get_contents($folderName . DIRECTORY_SEPARATOR . $fileName);
if(time() - $lastRefresh > $duration)
{
return false;

View File

@ -48,6 +48,14 @@ class WriteYaml extends Write
return false;
}
# compare with meta that are in use right now (e.g. changed theme, disabled plugin)
$metascheme = $this->getYaml('cache', 'metatabs.yaml');
if($metascheme)
{
$meta = $this->whitelistMeta($meta,$metascheme);
}
$meta = $this->addFileTimeToMeta($meta, $item, $settings);
return $meta;
@ -117,6 +125,27 @@ class WriteYaml extends Write
return $meta;
}
private function whitelistMeta($meta, $metascheme)
{
# we have only 2 dimensions, so no recursive needed
foreach($meta as $tab => $values)
{
if(!isset($metascheme[$tab]))
{
unset($meta[$tab]);
}
foreach($values as $key => $value)
{
if(!isset($metascheme[$tab][$key]))
{
unset($meta[$tab][$key]);
}
}
}
return $meta;
}
private function addFileTimeToMeta($meta, $item, $settings)
{
$filePath = $settings['contentFolder'] . $item->path;

View File

@ -16,11 +16,10 @@ class Settings
$settings = array_merge($defaultSettings, $userSettings);
}
// i18n
// load the strings of the set language
$language = $settings['language'];
$settings['labels'] = self::getLanguageLabels($language);
# i18n
# load the strings of the set language
$language = $settings['language'];
$settings['labels'] = self::getLanguageLabels($language);
# We know the used theme now so create the theme path
$settings['themePath'] = $settings['rootPath'] . $settings['themeFolder'] . DIRECTORY_SEPARATOR . $settings['theme'];
@ -77,15 +76,16 @@ class Settings
}
// i18n
public static function getLanguageLabels($language)
# i18n
public static function getLanguageLabels($language)
{
// if not present, set the English language
if( empty($language) ){
$language = 'en';
}
# if not present, set the English language
if( empty($language) )
{
$language = 'en';
}
// load the strings of the set language
# load the strings of the set language
$yaml = new Models\WriteYaml();
$labels = $yaml->getYaml('settings/languages', $language.'.yaml');
@ -124,7 +124,7 @@ class Settings
if($userSettings)
{
# whitelist settings that can be stored in usersettings (values are not relevant here, only keys)
$allowedUserSettings = ['displayErrorDetails' => false,
$allowedUserSettings = ['displayErrorDetails' => true,
'title' => false,
'copyright' => false,
'language' => false,
@ -151,7 +151,7 @@ class Settings
# merge usersettings with new settings
$settings = array_merge($userSettings, $settings);
/* write settings to yaml */
# write settings to yaml
$yaml = new Models\WriteYaml();
$yaml->updateYaml('settings', 'settings.yaml', $settings);
}

View File

@ -411,7 +411,6 @@ footer{
margin: 0 0 20px 0;
}
/************************
* OPEN-CLOSE BUTTON *
************************/
@ -972,6 +971,15 @@ ul.cardInfo{
.cardField input, .cardField select, .cardField textarea{
background-color: #FFF;
}
textarea.codearea, .cardField textarea.codearea{
font-family: monospace;
background: #333;
color: #fff;
}
textarea.codearea:focus, .cardField textarea.codearea:focus{
border: 1px solid #333;
}
.cardFields fieldset.subfield{
padding: 20px;
border: 1px solid #ddd;
@ -1018,7 +1026,7 @@ span.error{
line-height: 1em;
}
.cardInner span.error{
display: block;
display: inline-block;
margin-top: -8px;
margin-bottom: 8px;
}

View File

@ -439,6 +439,10 @@ let meta = new Vue({
.then(function (response) {
self.saved = true;
self.formErrors = self.formErrorsReset;
if(response.data.structure)
{
navi.items = response.data.structure;
}
})
.catch(function (error)
{

View File

@ -1,6 +1,6 @@
const navcomponent = Vue.component('navigation', {
template: '#navigation-template',
props: ['homepage', 'showForm', 'name', 'newItem', 'parent', 'active', 'filetype', 'status', 'elementtype', 'element', 'folder', 'level', 'url', 'root', 'freeze'],
props: ['homepage', 'showForm', 'name', 'hide', 'newItem', 'parent', 'active', 'filetype', 'status', 'elementtype', 'element', 'folder', 'level', 'url', 'root', 'freeze'],
data: function () {
return {
showForm: false,
@ -88,8 +88,12 @@ const navcomponent = Vue.component('navigation', {
level = level.split('.').length;
return 'level-' + level;
},
getIcon : function(elementtype, filetype)
getIcon : function(elementtype, filetype, hide)
{
if(hide)
{
return '#icon-eye-blocked';
}
if(elementtype == 'file')
{
return '#icon-file-text-o';
@ -99,8 +103,12 @@ const navcomponent = Vue.component('navigation', {
return '#icon-folder-o';
}
},
getIconClass : function(elementtype, filetype)
getIconClass : function(elementtype, filetype, hide)
{
if(hide)
{
return 'icon-eye-blocked ' + filetype;
}
if(elementtype == 'file')
{
return 'icon-file-text-o ' + filetype;

View File

@ -142,6 +142,12 @@
<title>cross</title>
<path d="M14.348 14.849c-0.469 0.469-1.229 0.469-1.697 0l-2.651-3.030-2.651 3.029c-0.469 0.469-1.229 0.469-1.697 0-0.469-0.469-0.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-0.469-0.469-0.469-1.228 0-1.697s1.228-0.469 1.697 0l2.652 3.031 2.651-3.031c0.469-0.469 1.228-0.469 1.697 0s0.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c0.469 0.469 0.469 1.229 0 1.698z"></path>
</symbol>
<symbol id="icon-eye-blocked" viewBox="0 0 32 32">
<title>eye-blocked</title>
<path d="M29.561 0.439c-0.586-0.586-1.535-0.586-2.121 0l-6.318 6.318c-1.623-0.492-3.342-0.757-5.122-0.757-6.979 0-13.028 4.064-16 10 1.285 2.566 3.145 4.782 5.407 6.472l-4.968 4.968c-0.586 0.586-0.586 1.535 0 2.121 0.293 0.293 0.677 0.439 1.061 0.439s0.768-0.146 1.061-0.439l27-27c0.586-0.586 0.586-1.536 0-2.121zM13 10c1.32 0 2.44 0.853 2.841 2.037l-3.804 3.804c-1.184-0.401-2.037-1.521-2.037-2.841 0-1.657 1.343-3 3-3zM3.441 16c1.197-1.891 2.79-3.498 4.67-4.697 0.122-0.078 0.246-0.154 0.371-0.228-0.311 0.854-0.482 1.776-0.482 2.737 0 1.715 0.54 3.304 1.459 4.607l-1.904 1.904c-1.639-1.151-3.038-2.621-4.114-4.323z"></path>
<path d="M24 13.813c0-0.849-0.133-1.667-0.378-2.434l-10.056 10.056c0.768 0.245 1.586 0.378 2.435 0.378 4.418 0 8-3.582 8-8z"></path>
<path d="M25.938 9.062l-2.168 2.168c0.040 0.025 0.079 0.049 0.118 0.074 1.88 1.199 3.473 2.805 4.67 4.697-1.197 1.891-2.79 3.498-4.67 4.697-2.362 1.507-5.090 2.303-7.889 2.303-1.208 0-2.403-0.149-3.561-0.439l-2.403 2.403c1.866 0.671 3.873 1.036 5.964 1.036 6.978 0 13.027-4.064 16-10-1.407-2.81-3.504-5.2-6.062-6.938z"></path>
</symbol>
{{ assets.renderSvg() }}
</defs>
</svg>

View File

@ -29,4 +29,33 @@ meta:
type: date
label: Created at (readonly)
readonly: readonly
class: medium
class: medium
navtitle:
type: text
label: Navigation Title
class: medium
maxlength: 60
hide:
type: checkbox
label: Hide
checkboxlabel: Hide page from navigation
class: medium
# roles:
# type: select
# label: Show page to
# class: medium
# options:
# null: null
# public: Public (standard)
# members: Members only (logged in)
# customers: Customers only (paying)
# list:
# type: select
# label: List sub-pages
# class: medium
# options:
# null: null
# standard: Standard order
# revert: Reverse order
# asc: Date ascending
# desc: Date descending

View File

@ -20,11 +20,12 @@
v-for="item in items"
ref="draggit"
:freeze="freeze"
:name="item.name"
:name="item.name"
:hide="item.hide"
:active="item.active"
:parent="item.activeParent"
:level="item.keyPath"
:root="root"
:level="item.keyPath"
:root="root"
:url="item.urlRelWoF"
:id="item.keyPath"
:key="item.keyPath"
@ -57,7 +58,7 @@
<template id="navigation-template">
<li class="navi-item" :class="elementtype">
<div class="status" :class="status"></div>
<a v-bind:href="getUrl(root, url)" :class="checkActive(active,parent)"><span class="iconwrapper"><svg class="icon" :class="getIconClass(elementtype, filetype)"><use :xlink:href="getIcon(elementtype, filetype)"></use></svg></span><span :class="getLevel(level)">{{ name }}</span><span class="movewrapper"><span class="movewrapper"><svg class="icon icon-arrows-v"><use xlink:href="#icon-arrows-v"></use></svg></span></a>
<a v-bind:href="getUrl(root, url)" :class="checkActive(active,parent)"><span class="iconwrapper"><svg class="icon" :class="getIconClass(elementtype, filetype, hide)"><use :xlink:href="getIcon(elementtype, filetype, hide)"></use></svg></span><span :class="getLevel(level)">{{ name }}</span><span class="movewrapper"><span class="movewrapper"><svg class="icon icon-arrows-v"><use xlink:href="#icon-arrows-v"></use></svg></span></a>
<draggable v-if="folder" class="navi-list" tag="ul"
@start="onStart"
@end="onEnd"
@ -71,6 +72,7 @@
ref="draggit"
:freeze="freeze"
:name="item.name"
:hide="item.hide"
:active="item.active"
:parent="item.activeParent"
:level="item.keyPath"

View File

@ -9,7 +9,7 @@
{{ content }}
<div class="actionLink">
<a href="{{ navigation[0].urlRel }}">{{ settings.themes.typemill.start ? __(settings.themes.typemill.start) : __('Start')}}</a>
<a href="{{ navigation[0].urlRel }}">{{ settings.themes.typemill.start ? settings.themes.typemill.start : __('Start')}}</a>
{% if settings.setup %}
<a href="{{ base_url }}/setup">{{ __('Setup') }}</a>

View File

@ -1,5 +1,5 @@
name: Typemill Theme
version: 1.2.1
version: 1.2.2
description: The standard theme for Typemill. Responsive, minimal and without any dependencies. It uses the system fonts Calibri and Helvetica. No JavaScript is used.
author: Sebastian Schürmanns
homepage: https://typemill.net