Compare commits

..

No commits in common. "beta" and "b2.5.0" have entirely different histories.
beta ... b2.5.0

99 changed files with 32024 additions and 34384 deletions

16
.gitignore vendored
View file

@ -12,21 +12,13 @@ public/*
public/assets/* public/assets/*
!public/assets/css !public/assets/css
public/assets/css/* public/assets/css/*
!public/assets/css/dash !public/assets/css/dash.css
!public/assets/scripts !public/assets/scripts
public/assets/scripts/* public/assets/scripts/*
<<<<<<< HEAD
!public/assets/scripts/Start.js !public/assets/scripts/Start.js
/public/assets/images/global/rikc-logo.svg /public/assets/images/global/rikc-logo.svg
=======
!public/assets/scripts/dash.js
<<<<<<< HEAD
>>>>>>> develop
=======
!public/assets/scripts/dash.js.map
>>>>>>> develop
!public/assets/images !public/assets/images
public/assets/images/* public/assets/images/*
!public/assets/images/global/ !public/assets/images/global/
@ -52,7 +44,5 @@ config/tags.json
config.codekit3 config.codekit3
/config/backups /config/backups
src/com/* src/com/
src/styles/* src/styles/
src/com/ui/TextEditor.js

View file

@ -1,74 +0,0 @@
<?php
$config = new PhpCsFixer\Config();
return $config
->setRiskyAllowed(true)
->setRules([
'@PSR12' => true,
'array_indentation' => true,
'array_syntax' => [
'syntax' => 'short',
],
'combine_consecutive_unsets' => true,
'method_chaining_indentation' => true,
'class_attributes_separation' => [
'elements' => [
'const' => 'none',
'method' => 'one',
'property' => 'none',
'trait_import' => 'none',
],
],
'multiline_whitespace_before_semicolons' => [
'strategy' => 'no_multi_line',
],
'single_quote' => false,
'binary_operator_spaces' => [
'default' => 'single_space',
'operators' => [
'=' => 'align_single_space_minimal',
'=>' => 'align_single_space_minimal',
],
],
'braces' => [
'allow_single_line_closure' => true,
],
'concat_space' => [
'spacing' => 'one',
],
'declare_equal_normalize' => true,
'function_typehint_space' => true,
'single_line_comment_style' => [
'comment_types' => [
'hash',
],
],
'include' => true,
'lowercase_cast' => true,
'no_extra_blank_lines' => [
'tokens' => [
'curly_brace_block',
'extra',
'parenthesis_brace_block',
'throw',
]
],
'no_multiline_whitespace_around_double_arrow' => true,
'no_spaces_around_offset' => true,
'no_unused_imports' => true,
'no_whitespace_before_comma_in_array' => true,
'no_whitespace_in_blank_line' => true,
'object_operator_without_whitespace' => true,
'single_blank_line_before_namespace' => true,
'ternary_operator_spaces' => true,
'trim_array_spaces' => true,
'unary_operator_spaces' => true,
'whitespace_after_comma_in_array' => true,
'single_line_after_imports' => true,
'ordered_imports' => [
'sort_algorithm' => 'none',
],
//Other rules here...
])
->setLineEnding("\n");

View file

@ -1,27 +1,11 @@
{ {
"overrides": [
{
"files": ".prettierrc",
"options": { "parser": "json" }
},
{
"files": "*.scss",
"options": {
"tabWidth": 4,
"semi": false,
"singleQuote": true,
"printWidth": 90
}
},
{
"files": "*.js",
"options": {
"arrowParens": "avoid", "arrowParens": "avoid",
"bracketSpacing": true, "bracketSpacing": true,
"htmlWhitespaceSensitivity": "css", "htmlWhitespaceSensitivity": "css",
"insertPragma": false, "insertPragma": false,
"bracketSameLine": false, "bracketSameLine": false,
"jsxSingleQuote": true, "jsxSingleQuote": true,
"parser": "babel",
"proseWrap": "preserve", "proseWrap": "preserve",
"requirePragma": false, "requirePragma": false,
"semi": true, "semi": true,
@ -31,6 +15,3 @@
"tabWidth": 4, "tabWidth": 4,
"printWidth": 90 "printWidth": 90
} }
}
]
}

View file

@ -1,3 +0,0 @@
{
"extends": ["stylelint-config-standard"]
}

View file

@ -1,9 +1,13 @@
![This is Fipamo](https://playvicio.us/base-assets/images/fipamo-brand.png)
# Fipamo means to save # Fipamo means to save
The Fipamo project was born from a need for a simple, easy to use no data blog platform that doesn't require much effort to set up and maintain. Fipamo uses Markdown to handle posts and renders them to flat html so you can serve them from anywhere. No complicated set ups. No long list of dependencies. Just set up and go. The Fipamo project was born from a need for a simple, easy to use no data blog platform that doesn't require much effort to set up and maintain. Fipamo uses Markdown to handle posts and renders them to flat html so you can serve them from anywhere. No complicated set ups. No long list of dependencies. Just write and publish.
Because nobody has time for all that. Because nobody has time for all that.
## Check the (WIP) Docs to get you started. <br> ## Check the (WIP) Docs to get you started. <br>
[Getting Started](https://koodu.ubiqueros.com/are0h/Fipamo/wiki/00---Start) <br> [Getting Started](https://code.playvicio.us/Are0h/Fipamo/wiki/00---Start) <br>
[Install](https://code.playvicio.us/Are0h/Fipamo/wiki/01---Install) <br>
[Using Fipamo](https://code.playvicio.us/Are0h/Fipamo/wiki/02-Usage) <br>

View file

@ -1,10 +0,0 @@
<?php
spl_autoload_register(function ($className) {
$file = dirname(__DIR__) . '\\' . $className . '.php';
$file = str_replace('\\', DIRECTORY_SEPARATOR, $file);
//echo $file;
if (file_exists($file)) {
include $file;
}
});

View file

@ -17,14 +17,14 @@ class AuthAPI
//internal check for admin action //internal check for admin action
if (Auth::status()) { if (Auth::status()) {
$result = [ $result = [
'message' => 'Authorized', "message" => "Authorized",
'type' => 'apiUseAuthorized', "type" => "apiUseAuthorized",
'token' => Session::get('token'), "token" => Session::get("token"),
]; ];
} else { } else {
$result = [ $result = [
'message' => 'Not Authorized', "message" => "Not Authorized",
'type' => 'apiUseNotAuthorized', "type" => "apiUseNotAuthorized",
]; ];
} }
return $result; return $result;
@ -34,22 +34,22 @@ class AuthAPI
{ {
$result = []; $result = [];
switch (Auth::login($body)) { switch (Auth::login($body)) {
case 'no_name': case "no_name":
$result = [ $result = [
'message' => 'Need to see some id, champ', "message" => "Need to see some id, champ",
'type' => 'requestLame', "type" => "requestLame",
]; ];
break; break;
case 'bad_pass': case "bad_pass":
$result = [ $result = [
'message' => 'Check your password, sport', "message" => "Check your password, sport",
'type' => 'requestLame', "type" => "requestLame",
]; ];
break; break;
default: default:
$result = [ $result = [
'message' => 'Welcome back', "message" => "Welcome back",
'type' => 'requestGood', "type" => "requestGood",
]; ];
break; break;
} }
@ -61,18 +61,16 @@ class AuthAPI
{ {
Auth::logout($body); Auth::logout($body);
$result = [ $result = [
'message' => 'Till next time, g.', "message" => "Till next time, g.",
'type' => 'TASK_LOGOUT', "type" => "TASK_LOGOUT",
]; ];
return $result; return $result;
} }
public static function requestSecret($body) public static function requestSecret($body)
{ {
$result = Auth::findSecret($body); $result = Auth::findSecret($body);
return $result; return $result;
} }
public static function resetPassword($body) public static function resetPassword($body)
{ {
$result = Auth::makeNewPassword($body); $result = Auth::makeNewPassword($body);

View file

@ -1,73 +0,0 @@
<?php
namespace brain\api\v1;
use brain\utility\FileUploader;
use brain\data\Settings;
use brain\data\Member;
class FilesAPI
{
public function __construct()
{
}
public static function uploadFiles($request, $type = null)
{
$upload = $request->getUploadedFiles(); //grab uploaded files
$options = $request->getParsedBody();
$file = $upload['upload_files'][0]; //front end sends one by one for progress tracking, so grab first
$type = $file->getClientMediaType();
$filesPath = '';
$path = date('Y') . '/' . date('m');
$response = [];
switch ($type) {
case 'image/jpeg':
case 'image/png':
case 'image/gif':
case 'image/svg':
if (isset($options["source"])) {
if ($options["source"] == "avatar-upload") {
$filesPath = '/assets/images/user/' . $path . '/';
Member::updateData(
'avi',
$filesPath . $file->getClientFileName()
);
} else {
$filesPath = '/assets/images/user/' . $path . '/';
Settings::updateGlobalData(
'background',
$filesPath . '/' . $file->getClientFileName()
);
}
} else {
$filesPath = '/assets/images/blog/' . $path . '/';
}
break;
case 'video/mp4':
$filesPath = '/assets/video/blog/' . $path . '/';
break;
case 'audio/mpeg':
$filesPath = '/assets/sound/blog/' . $path . '/';
break;
case 'application/pdf':
case 'text/plain':
case 'text/rtf':
$filesPath = '/assets/docs/blog/' . $path . '/';
break;
}
FileUploader::uploadFile('../public' . $filesPath, $file);
$response = [
'message' => "File Uploaded. Great!",
"filePath" => $filesPath . urlencode($file->getClientFileName()),
"fileName" => urlencode($file->getClientFileName()),
'type' => $type,
];
return $response;
}
}

View file

@ -4,7 +4,6 @@ namespace brain\api\v1;
use brain\data\Member; use brain\data\Member;
use brain\data\Settings; use brain\data\Settings;
use brain\utility\FileUploader;
class ImagesAPI class ImagesAPI
{ {
@ -15,61 +14,64 @@ class ImagesAPI
public static function uploadImage($request, $type = null) public static function uploadImage($request, $type = null)
{ {
$file = $request->getUploadedFiles(); $file = $request->getUploadedFiles();
$uploadPath = ''; $uploadPath = "";
$path = date('Y') . '/' . date('m'); $path = date("Y") . "/" . date("m");
$response = []; $response = [];
switch ($type) { switch ($type) {
case 'avatar': case "avatar":
$image = $file['avatar_upload']; $image = $file["avatar_upload"];
$uploadPath = '../public/assets/images/user/' . $path; $uploadPath = "../public/assets/images/user/" . $path;
break; break;
case 'background': case "background":
$image = $file['background_upload']; $image = $file["background_upload"];
$uploadPath = '../public/assets/images/user/' . $path; $uploadPath = "../public/assets/images/user/" . $path;
break; break;
default: default:
$image = $file['post_image']; $image = $file["post_image"];
$path = date('Y') . '/' . date('m'); $path = date("Y") . "/" . date("m");
$uploadPath = '../public/assets/images/blog/' . $path; $uploadPath = "../public/assets/images/blog/" . $path;
break; break;
} }
$result = FileUploader::uploadFile($uploadPath, $image); $result = FileUploader::uploadFile($uploadPath, $image);
switch ($type) { switch ($type) {
case 'avatar': case "avatar":
$response = [ $response = [
'message' => 'Avatar Added. You look great!', "message" => "Avatar Added. You look great!",
'type' => 'avatarUploaded', "type" => "avatarUploaded",
'url' => '/assets/images/user/' . $path . '/' . $image->getClientFileName(), "url" =>
"/assets/images/user/" . $path . "/" . $image->getClientFileName(),
]; ];
//update member data //update member data
Member::updateData( Member::updateData(
'avi', "avi",
'/assets/images/user/' . $path . '/' . $image->getClientFileName() "/assets/images/user/" . $path . "/" . $image->getClientFileName()
); );
break; break;
case 'background': case "background":
$response = [ $response = [
'message' => "Background plugged in. That's nice!", "message" => "Background plugged in. That's nice!",
'type' => 'siteBackgroundUploaded', "type" => "siteBackgroundUploaded",
'url' => '/assets/images/user/' . $path . '/' . $image->getClientFileName(), "url" =>
"/assets/images/user/" . $path . "/" . $image->getClientFileName(),
]; ];
//update settings file //update settings file
Settings::updateGlobalData( Settings::updateGlobalData(
'background', "background",
'/assets/images/user/' . $path . '/' . $image->getClientFileName() "/assets/images/user/" . $path . "/" . $image->getClientFileName()
); );
break; break;
default: default:
$response = [ $response = [
'message' => 'Image Added. Very slick', "message" => "Image Added. Very slick",
'type' => 'postImageAdded', "type" => "postImageAdded",
'url' => '/assets/images/blog/' . $path . '/' . $image->getClientFileName(), "url" =>
"/assets/images/blog/" . $path . "/" . $image->getClientFileName(),
]; ];
break; break;
} }

View file

@ -17,13 +17,13 @@ class InitAPI
//through settings. //through settings.
if (Setup::status()) { if (Setup::status()) {
$result = ['type' => 'blogInitFail', 'message' => 'Site already set up']; $result = ["type" => "blogInitFail", "message" => "Site already set up"];
} else { } else {
switch ($task) { switch ($task) {
case 'init': case "init":
$result = Setup::init($request); $result = Setup::init($request);
break; break;
case 'restore': case "restore":
$result = Setup::restore($request); $result = Setup::restore($request);
break; break;
} }

View file

@ -14,14 +14,13 @@ class MailerAPI
public static function handleMail($request, $body, $response) public static function handleMail($request, $body, $response)
{ {
//if testing, verify session is active //if testing, verify session is active
// add clean method for sending programmtic emails if ($body["mail_task"] == "TESTING") {
if ($body['mail_task'] == 'TESTING') {
if (Session::active()) { if (Session::active()) {
$result = Mailer::sendmail($body); $result = Mailer::sendmail($body);
} else { } else {
$result = [ $result = [
'message' => 'You need to be logged in for this, champ.', "message" => "You need to be logged in for this, champ.",
'type' => 'MAILER_ERROR', "type" => "MAILER_ERROR",
]; ];
} }
} else { } else {

View file

@ -2,6 +2,8 @@
namespace brain\api\v1; namespace brain\api\v1;
use Mni\FrontYAML\Parser;
use brain\api\v1\ImagesAPI;
use brain\data\Book; use brain\data\Book;
use brain\data\Settings; use brain\data\Settings;
use brain\data\Session; use brain\data\Session;
@ -17,87 +19,87 @@ class PagesAPI
public static function getPageContent($request, $args) public static function getPageContent($request, $args)
{ {
$task = $args['fourth']; $task = $args["fourth"];
$pages = (new Book('../content/pages'))->getContents(); $pages = (new Book("../content/pages"))->getContents();
$content = []; $content = [];
foreach ($pages as $page) { foreach ($pages as $page) {
$entry = [ $entry = [
'id' => $page['id'], "id" => $page["id"],
'uuid' => $page['uuid'], "uuid" => $page["uuid"],
'title' => $page['title'], "title" => $page["title"],
'feature' => $page['feature'], "feature" => $page["feature"],
'path' => $page['path'], "path" => $page["path"],
'layout' => $page['layout'], "layout" => $page["layout"],
'tags' => $page['tags'], "tags" => $page["tags"],
'author' => $page['author'], "author" => $page["author"],
'created' => $page['created'], "created" => $page["created"],
'updated' => $page['updated'], "updated" => $page["updated"],
'deleted' => $page['deleted'], "deleted" => $page["deleted"],
'menu' => $page['menu'], "menu" => $page["menu"],
'featured' => $page['featured'], "featured" => $page["featured"],
'published' => $page['published'], "published" => $page["published"],
'slug' => $page['slug'], "slug" => $page["slug"],
'content' => StringTools::sanitizeContent($page['content']), "content" => StringTools::sanitizeContent($page["content"]),
]; ];
array_push($content, $entry); array_push($content, $entry);
} }
switch ($task) { switch ($task) {
case 'published': case "published":
$published = filter($content, function ($item) { $published = filter($content, function ($item) {
return $item['published'] == true && $item['deleted'] == false; return $item["published"] == true && $item["deleted"] == false;
}); });
$result = ['pages' => $published, 'totalItems' => count($published)]; $result = ["pages" => $published, "totalItems" => count($published)];
break; break;
case 'featured': case "featured":
$featured = filter($content, function ($item) { $featured = filter($content, function ($item) {
return $item['featured'] == true && $item['deleted'] == false; return $item["featured"] == true && $item["deleted"] == false;
}); });
$result = [ $result = [
'pages' => $featured, "pages" => $featured,
'totalItems' => count($featured), "totalItems" => count($featured),
]; ];
break; break;
case 'menu': case "menu":
$menu = filter($content, function ($item) { $menu = filter($content, function ($item) {
return $item['menu'] == true && $item['deleted'] == false; return $item["menu"] == true && $item["deleted"] == false;
}); });
$result = ['pages' => $menu, 'totalItems' => count($menu)]; $result = ["pages" => $menu, "totalItems" => count($menu)];
break; break;
case 'single': case "single":
$uuid = $args['fifth']; $uuid = $args["fifth"];
$page = (new Book('../content/pages'))->findPageById($uuid); $page = (new Book("../content/pages"))->findPageById($uuid);
$entry = [ $entry = [
'id' => $page['id'], "id" => $page["id"],
'uuid' => $page['uuid'], "uuid" => $page["uuid"],
'title' => $page['title'], "title" => $page["title"],
'feature' => $page['feature'], "feature" => $page["feature"],
'path' => $page['path'], "path" => $page["path"],
'layout' => $page['layout'], "layout" => $page["layout"],
'tags' => $page['tags'], "tags" => $page["tags"],
'author' => $page['author'], "author" => $page["author"],
'created' => $page['created'], "created" => $page["created"],
'updated' => $page['updated'], "updated" => $page["updated"],
'deleted' => $page['deleted'], "deleted" => $page["deleted"],
'menu' => $page['menu'], "menu" => $page["menu"],
'featured' => $page['featured'], "featured" => $page["featured"],
'published' => $page['published'], "published" => $page["published"],
'slug' => $page['slug'], "slug" => $page["slug"],
'content' => StringTools::sanitizeContent($page['content']), "content" => StringTools::sanitizeContent($page["content"]),
]; ];
$result = $entry; $result = $entry;
break; break;
case 'tags': case "tags":
$result = Settings::getTags(); $result = Settings::getTags();
break; break;
default: default:
$result = [ $result = [
'message' => "Hm, no task. That's unfortunate", "message" => "Hm, no task. That's unfortunate",
'type' => 'TASK_NONE', "type" => "TASK_NONE",
]; ];
break; break;
} }
@ -106,43 +108,41 @@ class PagesAPI
public static function handlePageTask($request, $args) public static function handlePageTask($request, $args)
{ {
$task = $args['fourth']; $task = $args["fourth"];
switch ($task) { switch ($task) {
case 'delete': case "delete":
case 'create': case "create":
case 'write': case "write":
$body = json_decode(file_get_contents("php://input"), true); $body = $request->getParsedBody();
$passed = true; $passed = true;
if (!isset($body['form_token'])) { if (!isset($body["form_token"])) {
$result = [ $result = [
'message' => 'No form token. Not good, sport.', "message" => "No form token. Not good, sport.",
'type' => 'TASK_FORM_AUTH', "type" => "TASK_FORM_AUTH",
]; ];
} else { } else {
if ($body['form_token'] == Session::get('form_token')) { if ($body["form_token"] == Session::get("form_token")) {
//TODO: Verify form fields
$keys = [ $keys = [
'id', "id",
'uuid', "uuid",
'layout', "layout",
'current_title', "current_title",
'content', "content",
'title', "title",
'created', "created",
'slug', "slug",
'tags', "tags",
'menu', "menu",
'featured', "featured",
'published', "published",
'form_token', "form_token",
'imageList', "feature_image",
"fileList",
"remote"
]; ];
foreach ($body as $key => $item) { foreach ($body as $key => $item) {
if (!in_array($key, $keys)) { if (!in_array($key, $keys)) {
//found unnecessary key, so reject submission //found unnecessary key, so reject submission
var_dump($key);
$passed = false; $passed = false;
} }
} }
@ -150,26 +150,27 @@ class PagesAPI
$result = (new Book())->editPage($task, $request); $result = (new Book())->editPage($task, $request);
} else { } else {
$result = [ $result = [
'message' => 'Unneccessary key found. Post not authorized, slick.', "message" =>
'type' => 'TASK_FORM_AUTH', "Unneccessary key found. Post not authorized, slick.",
"type" => "TASK_FORM_AUTH",
]; ];
} }
} else { } else {
$result = [ $result = [
'message' => 'Form token, auth failed. Uh oh.', "message" => "Form token, auth failed. Uh oh.",
'type' => 'TASK_FORM_AUTH', "type" => "TASK_FORM_AUTH",
]; ];
} }
} }
break; break;
case 'add-entry-image': case "add-entry-image":
$result = ImagesAPI::uploadImage($request); $result = ImagesAPI::uploadImage($request);
break; break;
default: default:
$result = [ $result = [
'message' => "Hm, no task. That's unfortunate", "message" => "Hm, no task. That's unfortunate",
'type' => 'TASK_NONE', "type" => "TASK_NONE",
]; ];
break; break;
} }

View file

@ -2,6 +2,8 @@
namespace brain\api\v1; namespace brain\api\v1;
use Slim\Views\Twig;
use brain\api\v1\ImagesApi;
use brain\data\Render; use brain\data\Render;
use brain\data\Settings; use brain\data\Settings;
use brain\data\Session; use brain\data\Session;
@ -15,43 +17,42 @@ class SettingsAPI
public static function handleSettingsTask($request, $args, $body = null) public static function handleSettingsTask($request, $args, $body = null)
{ {
$task = $args['fourth']; $task = $args["fourth"];
switch ($task) { switch ($task) {
case 'publish': case "publish":
//check settings to see if site is a one pager //check settings to see if site is a one pager
$config = new Settings(); $config = new Settings();
$settings = $config->getSettings(); $settings = $config->getSettings();
$theme = $settings['global']['theme']; $theme = $settings["global"]["theme"];
$themeConfig = json_decode( $themeConfig = json_decode(
file_get_contents('../content/themes/' . $theme . '/theme.json'), file_get_contents("../content/themes/" . $theme . "/theme.json"),
true true
); );
//check to see if dynamic rendering is active //check to see if dynamic rendering is active
if ( if (
isset($settings['global']['dynamicRender']) && isset($settings["global"]["dynamicRender"]) &&
$settings['global']['dynamicRender'] === 'true' $settings["global"]["dynamicRender"] === "true"
) { ) {
$result = [ $result = [
'message' => "Dynamic Render Active! You're good!", "message" => "Dynamic Render Active! You're good!",
'type' => 'RENDER_SUCCESS', "type" => "RENDER_SUCCESS",
]; ];
} else { } else {
$render = new Render(); $render = new Render();
if (isset($themeConfig['render'])) { if (isset($themeConfig["render"])) {
//rendering for one page sites if (!$themeConfig["render"] || $themeConfig["render"] === "false") {
if (!$themeConfig['render'] || $themeConfig['render'] === 'false') {
$render->renderIndex(); $render->renderIndex();
$result = [ $result = [
'message' => 'Index Rendered. HAND CLAPS', "message" => "Index Rendered. HAND CLAPS",
'type' => 'RENDER_SUCCESS', "type" => "RENDER_SUCCESS",
]; ];
} else { } else {
$render->renderTags(); $render->renderTags();
$render->renderArchive(); $render->renderArchive();
$render->renderPages(); $render->renderPages();
$result = [ $result = [
'message' => 'Site Rendered. GOOD EFFORT', "message" => "Site Rendered. GOOD EFFORT",
'type' => 'RENDER_SUCCESS', "type" => "RENDER_SUCCESS",
]; ];
} }
} else { } else {
@ -60,8 +61,8 @@ class SettingsAPI
$render->renderArchive(); $render->renderArchive();
$render->renderPages(); $render->renderPages();
$result = [ $result = [
'message' => 'Site Rendered. GOOD EFFORT', "message" => "Site Rendered. GOOD EFFORT",
'type' => 'RENDER_SUCCESS', "type" => "RENDER_SUCCESS",
]; ];
} }
} }
@ -70,30 +71,30 @@ class SettingsAPI
//otherwise, render all pages according to theme template files //otherwise, render all pages according to theme template files
break; break;
case 'add-avatar': case "add-avatar":
$result = ImagesAPI::uploadImage($request, 'avatar'); $result = ImagesAPI::uploadImage($request, "avatar");
break; break;
case 'add-feature-background': case "add-feature-background":
$result = ImagesAPI::uploadImage($request, 'background'); $result = ImagesAPI::uploadImage($request, "background");
break; break;
case 'sync': case "sync":
Settings::sync($body); Settings::sync($body);
$result = [ $result = [
'message' => "Settings Synced. You're doing great!", "message" => "Settings Synced. You're doing great!",
'type' => 'settingsUpdated', "type" => "settingsUpdated",
]; ];
break; break;
case 'nav-sync': case "nav-sync":
Settings::navSync($body); Settings::navSync($body);
$result = [ $result = [
'message' => 'Navigation updated. Very slick!', "message" => "Navigation updated. Very slick!",
'type' => 'menuUpdated', "type" => "menuUpdated",
]; ];
break; break;
default: default:
$result = [ $result = [
'message' => "Hm, no task. That's unfortunate", "message" => "Hm, no task. That's unfortunate",
'type' => 'TASK_NONE', "type" => "TASK_NONE",
]; ];
break; break;
} }
@ -103,42 +104,42 @@ class SettingsAPI
public static function getInfo($request, $args) public static function getInfo($request, $args)
{ {
$task = $args['fourth']; $task = $args["fourth"];
switch ($task) { switch ($task) {
case 'site': case "site":
$config = new Settings(); $config = new Settings();
$settings = $config->getSettings(); $settings = $config->getSettings();
$data = [ $data = [
'title' => $settings['global']['title'], "title" => $settings["global"]["title"],
'base_url' => $settings['global']['base_url'], "base_url" => $settings["global"]["base_url"],
'description' => $settings['global']['descriptions'], "description" => $settings["global"]["descriptions"],
]; ];
$result = [ $result = [
'message' => 'Settings Found', "message" => "Settings Found",
'type' => 'GET_SETTINGS', "type" => "GET_SETTINGS",
'data' => $data, "data" => $data,
]; ];
break; break;
case 'member': case "member":
if (Session::active()) { if (Session::active()) {
$member = $member = Session::get('member'); $member = $member = Session::get("member");
$data = ['handle' => $member['handle'], 'email' => $member['email']]; $data = ["handle" => $member["handle"], "email" => $member["email"]];
$result = [ $result = [
'message' => 'Member Info Found', "message" => "Member Info Found",
'type' => 'GET_MEMBER_INFO', "type" => "GET_MEMBER_INFO",
'data' => $data, "data" => $data,
]; ];
} else { } else {
$result = [ $result = [
'message' => "Not logged in. C'mon, bruh", "message" => "Not logged in. C'mon, bruh",
'type' => 'TASK_NONE', "type" => "TASK_NONE",
]; ];
} }
break; break;
default: default:
$result = [ $result = [
'message' => 'No Settings found. Frowny Face', "message" => "No Settings found. Frowny Face",
'type' => 'TASK_NONE', "type" => "TASK_NONE",
]; ];
break; break;
} }

View file

@ -5,8 +5,8 @@ namespace brain\controller;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use brain\api\v1\AuthAPI; use brain\api\v1\AuthAPI;
use brain\api\v1\ImagesAPI;
use brain\api\v1\PagesAPI; use brain\api\v1\PagesAPI;
use brain\api\v1\FilesAPI;
use brain\api\v1\SettingsAPI; use brain\api\v1\SettingsAPI;
use brain\api\v1\InitAPI; use brain\api\v1\InitAPI;
use brain\api\v1\MailerAPI; use brain\api\v1\MailerAPI;
@ -20,54 +20,54 @@ class APIControl
ResponseInterface $response, ResponseInterface $response,
array $args array $args
): ResponseInterface { ): ResponseInterface {
$filename = ''; $filename = "";
switch (isset($args['third']) ? $args['third'] : 'none') { switch (isset($args["third"]) ? $args["third"] : "none") {
case 'status': case "status":
$result = AuthAPI::status(); $result = AuthAPI::status();
break; break;
case 'page': case "page":
//echo //echo
if (Member::verifyKey($_GET['key'])) { if (Member::verifyKey($_GET["key"])) {
$result = PagesAPI::getPageContent($request, $args); $result = PagesAPI::getPageContent($request, $args);
} else { } else {
$result = [ $result = [
'message' => 'API access denied, homie', "message" => "API access denied, homie",
'type' => 'API_ERROR', "type" => "API_ERROR",
]; ];
} }
break; break;
case 'settings': case "settings":
$token = $request->getHeader('fipamo-access-token'); $token = $request->getHeader("fipamo-access-token");
//Verify token to get site info //Verify token to get site info
if (isset($token[0])) { if (isset($token[0])) {
if (Session::verifyToken($token[0])) { if (Session::verifyToken($token[0])) {
$result = SettingsAPI::getInfo($request, $args); $result = SettingsAPI::getInfo($request, $args);
} else { } else {
$result = [ $result = [
'message' => 'Invalid token, API access denied, homie', "message" => "Invalid token, API access denied, homie",
'type' => 'API_ERROR', "type" => "API_ERROR",
]; ];
} }
} else { } else {
$result = [ $result = [
'message' => 'No token, API access denied, homie', "message" => "No token, API access denied, homie",
'type' => 'API_ERROR', "type" => "API_ERROR",
]; ];
} }
break; break;
case 'files': case "files":
if (Session::active()) { if (Session::active()) {
if ($args['third'] == 'backup') { if ($args["third"] == "backup") {
$filename = '../config/backups/latest_backup.zip'; $filename = "../config/backups/latest_backup.zip";
if (file_exists($filename)) { if (file_exists($filename)) {
header('Content-Type: application/zip'); header("Content-Type: application/zip");
header( header(
'Content-Disposition: attachment; filename="' . 'Content-Disposition: attachment; filename="' .
basename($filename) . basename($filename) .
'"' '"'
); );
header('Content-Length: ' . filesize($filename)); header("Content-Length: " . filesize($filename));
flush(); flush();
// return readfile($filename); // return readfile($filename);
@ -78,8 +78,8 @@ class APIControl
} }
} else { } else {
$result = [ $result = [
'message' => 'API access denied, homie', "message" => "API access denied, homie",
'type' => 'API_ERROR', "type" => "API_ERROR",
]; ];
} }
// no break // no break
@ -89,47 +89,46 @@ class APIControl
$freshResponse = $response; $freshResponse = $response;
if ($args['third'] == 'files') { if ($args["third"] == "files") {
$freshResponse $freshResponse
->getBody() ->getBody()
->write(file_get_contents('../config/backups/latest_back.zip')); ->write(file_get_contents("../config/backups/latest_back.zip"));
$freshResponse->withHeader('Content-Type', 'application/zip'); $freshResponse->withHeader("Content-Type", "application/zip");
return $freshResponse->withAddedHeader( return $freshResponse->withAddedHeader(
'Content-Disposition', "Content-Disposition",
'attachment; filename=latest_backup.zip' "attachment; filename=latest_backup.zip"
); );
} else { } else {
$response->getBody()->write(json_encode($result)); $response->getBody()->write(json_encode($result));
return $response->withHeader('Content-Type', 'application/json'); return $response->withHeader("Content-Type", "application/json");
} }
} }
public static function post( public static function post(
ServerRequestInterface $request, ServerRequestInterface $request,
ResponseInterface $response, ResponseInterface $response,
array $args array $args
): ResponseInterface { ): ResponseInterface {
$contentType = $request->getHeader('Content-Type'); $contentType = $request->getHeader("Content-Type");
switch ($contentType[0]) { switch ($contentType[0]) {
case 'application/json': case "application/json":
$body = json_decode(file_get_contents('php://input'), true); $body = json_decode(file_get_contents("php://input"), true);
break; break;
default: default:
break; break;
} }
switch (isset($args['third']) ? $args['third'] : 'none') { switch (isset($args["third"]) ? $args["third"] : "none") {
case 'restore': //move to 'api/auth' case "restore": //move to 'api/auth'
case 'init': //move to 'api/auth' case "init": //move to 'api/auth'
$task = $args['third']; $task = $args["third"];
$result = InitApi::handleInitTasks( $result = InitApi::handleInitTasks(
$task, $task,
$task == 'init' ? $body : $request $task == "init" ? $body : $request
); );
break; break;
case 'backup': //move to 'api/auth' case "backup": //move to 'api/auth'
$token = $request->getHeader('fipamo-access-token'); $token = $request->getHeader("fipamo-access-token");
//Verify token for admin tasks //Verify token for admin tasks
$result = SettingsAPI::createBackup(); $result = SettingsAPI::createBackup();
/* /*
@ -144,15 +143,15 @@ class APIControl
} }
*/ */
break; break;
case 'login': //move to 'api/auth' case "login": //move to 'api/auth'
//check if request is remote and if so, verify token //check if request is remote and if so, verify token
if ($body['remote'] || $body['remote'] == 'true') { if ($body["remote"] || $body["remote"] == "true") {
if (Member::verifyKey($body['key'])) { if (Member::verifyKey($body["key"])) {
$result = AuthAPI::login($body); $result = AuthAPI::login($body);
} else { } else {
$result = [ $result = [
'message' => 'API access denied, homie', "message" => "API access denied, homie",
'type' => 'API_ERROR', "type" => "API_ERROR",
]; ];
} }
} else { } else {
@ -161,64 +160,46 @@ class APIControl
} }
break; break;
case 'logout': //move to 'api/auth' case "logout": //move to 'api/auth'
$result = AuthAPI::logout($body); $result = AuthAPI::logout($body);
break; break;
case 'get-secret': //move to 'api/auth' case "get-secret": //move to 'api/auth'
$result = AuthAPI::requestSecret($body); $result = AuthAPI::requestSecret($body);
break; break;
case 'reset-password': //move to 'api/auth' case "reset-password": //move to 'api/auth'
$result = AuthAPI::resetPassword($body); $result = AuthAPI::resetPassword($body);
break; break;
case 'page': case "page":
$token = $request->getHeader('fipamo-access-token'); $token = $request->getHeader("fipamo-access-token");
//Verify token for admin tasks //Verify token for admin tasks
if (isset($token[0])) { if (isset($token[0])) {
if (Session::verifyToken($token[0])) { if (Session::verifyToken($token[0])) {
$result = PagesAPI::handlePageTask($request, $args); $result = PagesAPI::handlePageTask($request, $args);
} else { } else {
$result = [ $result = [
'message' => 'Invalid token, API access denied, homie', "message" => "Invalid token, API access denied, homie",
'type' => 'API_ERROR', "type" => "API_ERROR",
]; ];
} }
} else { } else {
$result = [ $result = [
'message' => 'No token, API access denied, homie', "message" => "No token, API access denied, homie",
'type' => 'API_ERROR', "type" => "API_ERROR",
]; ];
} }
break; break;
case "files": case "settings":
$token = $request->getHeader('fipamo-access-token');
if (isset($token[0])) {
if (Session::verifyToken($token[0])) {
$result = FilesAPI::uploadFiles($request, $args);
} else {
$result = [
'message' => 'Invalid token, API access denied, homie',
'type' => 'API_ERROR',
];
}
} else {
$result = [
'message' => 'No token, API access denied, homie',
'type' => 'API_ERROR',
];
}
break;
case 'settings':
if (isset($body)) { if (isset($body)) {
$postBody = $body; $postBody = $body;
} else { } else {
$postBody = null; $postBody = null;
} }
$task = $args['fourth']; $task = $args["fourth"];
if ($task == 'add-feature-background' || $task == 'add-avatar') { if ($task == "add-feature-background" || $task == "add-avatar") {
$result = SettingsAPI::handleSettingsTask($request, $args, $postBody); $result = SettingsAPI::handleSettingsTask($request, $args, $postBody);
} else { } else {
$token = $request->getHeader('fipamo-access-token'); $token = $request->getHeader("fipamo-access-token");
if (Session::verifyToken($token[0])) { if (Session::verifyToken($token[0])) {
$result = SettingsAPI::handleSettingsTask( $result = SettingsAPI::handleSettingsTask(
$request, $request,
@ -227,24 +208,25 @@ class APIControl
); );
} else { } else {
$result = [ $result = [
'message' => 'API access denied, homie', "message" => "API access denied, homie",
'type' => 'API_ERROR', "type" => "API_ERROR",
]; ];
} }
} }
break; break;
case 'mailer': case "mailer":
$result = MailerAPI::handleMail($request, $body, $response); $result = MailerAPI::handleMail($request, $body, $response);
break; break;
default: default:
$result = [ $result = [
'message' => "Oh, nothing to do. That's unfortunate", "message" => "Oh, nothing to do. That's unfortunate",
'type' => 'TASK_NONE', "type" => "TASK_NONE",
]; ];
break; break;
} }
$response->getBody()->write(json_encode($result)); $response->getBody()->write(json_encode($result));
return $response->withHeader('Content-Type', 'application/json'); return $response->withHeader("Content-Type", "application/json");
} }
} }

View file

@ -7,8 +7,6 @@ use brain\data\Session;
use brain\data\Settings; use brain\data\Settings;
use brain\data\Themes; use brain\data\Themes;
use brain\utility\Setup; use brain\utility\Setup;
use brain\utility\Sorting;
use Carbon\Carbon;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Slim\Views\Twig; use Slim\Views\Twig;
@ -33,9 +31,9 @@ class DashControl
$template = 'dash/settings.twig'; $template = 'dash/settings.twig';
$member = Session::get('member'); $member = Session::get('member');
$form_token = Session::get('form_token'); $form_token = Session::get('form_token');
$updated = new Carbon($settings['global']['last_backup']); $updated = new \Moment\Moment($settings['global']['last_backup']);
$pageOptions = [ $pageOptions = [
'title' => 'Settings', 'title' => 'Dash Settings',
'private' => $settings['global']['private'], 'private' => $settings['global']['private'],
'renderOnSave' => $settings['global']['renderOnSave'], 'renderOnSave' => $settings['global']['renderOnSave'],
'background' => $settings['global']['background'], 'background' => $settings['global']['background'],
@ -71,7 +69,7 @@ class DashControl
$settings = $config->getSettings(); $settings = $config->getSettings();
$template = 'dash/navigation.twig'; $template = 'dash/navigation.twig';
$pageOptions = [ $pageOptions = [
'title' => 'Edit Menu', 'title' => 'Edit Dash Navigation',
'status' => Session::active(), 'status' => Session::active(),
'menu' => $settings['menu'], 'menu' => $settings['menu'],
]; ];
@ -112,22 +110,14 @@ class DashControl
case 'edit': case 'edit':
$page = (new Book())->findPageById($uuid); $page = (new Book())->findPageById($uuid);
$views = []; $views = [];
if (!isset($page['layout'])) {
$page['layout'] = "page";
}
if (str_contains($page['layout'], 'index')) { if (str_contains($page['layout'], 'index')) {
$views = (new Themes())->getCustomIndex(); $views = (new Themes())->getCustomIndex();
} else { } else {
$views = (new Themes())->getCustomViews(); $views = (new Themes())->getCustomViews();
} }
$imageList = [];
$fileList = [];
if (isset($page['feature'])) {
$imageList = explode(',', $page['feature']); $imageList = explode(',', $page['feature']);
}
if (isset($page['files'])) {
$fileList = explode(',', $page['files']); $fileList = explode(',', $page['files']);
}
$images = []; $images = [];
$files = []; $files = [];
@ -146,7 +136,7 @@ class DashControl
} }
$pageOptions = [ $pageOptions = [
'title' => $page['title'], 'title' => 'Fipamo | Edit Page',
'page' => $page, 'page' => $page,
'mode' => $mode, 'mode' => $mode,
'token' => Session::get('form_token'), 'token' => Session::get('form_token'),
@ -160,15 +150,17 @@ class DashControl
$config = new Settings(); $config = new Settings();
$settings = $config->getSettings(); $settings = $config->getSettings();
$loader = new \Twig\Loader\FilesystemLoader( $loader = new \Twig\Loader\FilesystemLoader(
'../content/themes/' . $settings['global']['theme'] . '../content/themes'
'/'
); );
$display = new \Twig\Environment($loader, []); $display = new \Twig\Environment($loader, []);
$book = new Book(); $book = new Book();
$page = $book->findPageById($uuid); $page = $book->findPageById($uuid);
$pageOptions = Sorting::page($page); $pageOptions = Sorting::page($page);
$preview = $page['layout'] . $preview =
$settings['global']['theme'].
'/'.
$page['layout'].
'.twig'; '.twig';
$html = $display->render($preview, $pageOptions); $html = $display->render($preview, $pageOptions);
$response->getBody()->write($html); $response->getBody()->write($html);
@ -204,7 +196,7 @@ class DashControl
$template = 'dash/start.twig'; $template = 'dash/start.twig';
if (Session::active()) { if (Session::active()) {
$pageOptions = [ $pageOptions = [
'title' => 'Start', 'title' => 'Welcome Back',
'status' => Session::active(), 'status' => Session::active(),
'data' => (new Book())->getPages(1, 4), 'data' => (new Book())->getPages(1, 4),
]; ];

View file

@ -22,48 +22,49 @@ class IndexControl
$settings = $config->getSettings(); $settings = $config->getSettings();
$view = Twig::fromRequest($request); $view = Twig::fromRequest($request);
//checks dynamic render flag for site render status //checks dynamic render flag for site render status
if ($settings['global']['dynamicRender']) { if ($settings["global"]["dynamicRender"]) {
if ($settings['global']['dynamicRender'] == 'true') { if ($settings["global"]["dynamicRender"] == "true") {
$loader = new \Twig\Loader\FilesystemLoader('../content/themes'); $loader = new \Twig\Loader\FilesystemLoader("../content/themes");
$display = new \Twig\Environment($loader, []); $display = new \Twig\Environment($loader, []);
$template = ''; $template = "";
$pageOptions = []; $pageOptions = [];
$pageInfo = [ $pageInfo = [
'keywords' => isset($settings['global']['keywords']) "keywords" => isset($settings["global"]["keywords"])
? $settings['global']['keywords'] ? $settings["global"]["keywords"]
: 'fipamo, blog, jamstack, php, markdown, js', : "fipamo, blog, jamstack, php, markdown, js",
'description' => $settings['global']['descriptions'], "description" => $settings["global"]["descriptions"],
'image' => $settings['global']['base_url'] . $settings['global']['background'], "image" =>
'baseURL' => $settings['global']['base_url'], $settings["global"]["base_url"] . $settings["global"]["background"],
"baseURL" => $settings["global"]["base_url"],
]; ];
if (isset($args['first'])) { if (isset($args["first"])) {
switch ($args['first']) { switch ($args["first"]) {
case 'tags': case "tags":
$template = $settings['global']['theme'] . '/tags.twig'; $template = $settings["global"]["theme"] . "/tags.twig";
$tag = trim($args['second']); $tag = trim($args["second"]);
$taglist = Sorting::tags(); $taglist = Sorting::tags();
$item = find($taglist, ['tag_name' => $tag]); $item = find($taglist, ["tag_name" => $tag]);
$pageOptions = [ $pageOptions = [
'title' => 'Pages Tagged as ' . $item['tag_name'], "title" => "Pages Tagged as " . $item["tag_name"],
'background' => $pageInfo['image'], "background" => $pageInfo["image"],
'tag_list' => $item['pages'], "tag_list" => $item["pages"],
'info' => $pageInfo, "info" => $pageInfo,
'menu' => $settings['menu'], "menu" => $settings["menu"],
'dynamicRender' => $settings['global']['dynamicRender'], "dynamicRender" => $settings["global"]["dynamicRender"],
]; ];
break; break;
case 'archives': case "archives":
$archive = Sorting::archive(); $archive = Sorting::archive();
$template = $settings['global']['theme'] . '/archive.twig'; $template = $settings["global"]["theme"] . "/archive.twig";
$pageOptions = [ $pageOptions = [
'title' => 'Archive', "title" => "Archive",
'background' => $pageInfo['image'], "background" => $pageInfo["image"],
'archives' => $archive, "archives" => $archive,
'info' => $pageInfo, "info" => $pageInfo,
'menu' => $settings['menu'], "menu" => $settings["menu"],
'dynamicRender' => $settings['global']['dynamicRender'], "dynamicRender" => $settings["global"]["dynamicRender"],
]; ];
break; break;
@ -71,20 +72,22 @@ class IndexControl
//check if page is a menu item, if not render along path as usual //check if page is a menu item, if not render along path as usual
$page = []; $page = [];
$book = new Book(); $book = new Book();
if (is_numeric($args['first'])) { if (is_numeric($args["first"])) {
$page = $book->findPageBySlug($args['third']); $page = $book->findPageBySlug($args["third"]);
} else { } else {
$page = $book->findPageBySlug($args['first']); $page = $book->findPageBySlug($args["first"]);
} }
$template = $settings['global']['theme'] . '/' . $page['layout'] . '.twig'; $template =
$settings["global"]["theme"] . "/" . $page["layout"] . ".twig";
$pageOptions = Sorting::page($page); $pageOptions = Sorting::page($page);
break; break;
} }
} else { } else {
//index //index
$template = $settings['global']['theme'] . '/' . $page['layout'] . '.twig'; $template =
$book = new Book(''); $settings["global"]["theme"] . "/" . $page["layout"] . ".twig";
$book = new Book("");
$page = $book->findPageBySlug(); $page = $book->findPageBySlug();
$pageOptions = Sorting::page($page); $pageOptions = Sorting::page($page);
} }
@ -95,14 +98,14 @@ class IndexControl
} else { } else {
//if dynamic flag is false, load up html //if dynamic flag is false, load up html
$view = Twig::fromRequest($request); $view = Twig::fromRequest($request);
$html = file_get_contents('../public/index.html'); $html = file_get_contents("../public/index.html");
$response->getBody()->write($html); $response->getBody()->write($html);
return $response; return $response;
} }
} else { } else {
//if flag is not present, default to static html //if flag is not present, default to static html
$view = Twig::fromRequest($request); $view = Twig::fromRequest($request);
$html = file_get_contents('../public/index.html'); $html = file_get_contents("../public/index.html");
$response->getBody()->write($html); $response->getBody()->write($html);
return $response; return $response;
} }

View file

@ -4,20 +4,22 @@ namespace brain\controller;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use brain\controller\DashControl;
use brain\controller\APIControl;
use brain\controller\IndexControl;
class RouteControl class RouteControl
{ {
//TODO: Add additional HTTP Methods to better organize API control paths
public function get( public function get(
ServerRequestInterface $request, ServerRequestInterface $request,
ResponseInterface $response, ResponseInterface $response,
array $args array $args
): ResponseInterface { ): ResponseInterface {
switch (isset($args['first']) ? $args['first'] : 'index') { switch (isset($args["first"]) ? $args["first"] : "index") {
case 'dashboard': case "dashboard":
return DashControl::start($request, $response, $args); return DashControl::start($request, $response, $args);
break; break;
case 'api': case "api":
return APIControl::get($request, $response, $args); return APIControl::get($request, $response, $args);
break; break;
default: default:
@ -31,17 +33,16 @@ class RouteControl
ResponseInterface $response, ResponseInterface $response,
array $args array $args
): ResponseInterface { ): ResponseInterface {
switch (isset($args['first']) ? $args['first'] : 'index') { switch (isset($args["first"]) ? $args["first"] : "index") {
case 'api': case "api":
//$result = APIControl::post($request, $response, $args);
//var_dump($result);
return APIControl::post($request, $response, $args); return APIControl::post($request, $response, $args);
break; break;
default: default:
$result = [ //echo "YES";
'message' => "Nothing matches this route. That's unfortunate", //return IndexControl::start($request, $response, $args);
'type' => 'TASK_NONE', break;
];
$response->getBody()->write(json_encode($result));
return $response->withHeader('Content-Type', 'application/json');
} }
} }
} }

View file

@ -3,6 +3,8 @@
namespace brain\data; namespace brain\data;
use ReallySimpleJWT\Token; use ReallySimpleJWT\Token;
use brain\data\Settings;
use brain\data\Session;
use function _\find; use function _\find;
@ -14,7 +16,7 @@ class Auth
public static function sessionStatus() public static function sessionStatus()
{ {
if (isset($_SESSION['member'])) { if (isset($_SESSION["member"])) {
return true; return true;
} else { } else {
return false; return false;
@ -24,7 +26,7 @@ class Auth
public static function status() public static function status()
{ {
$result = ''; $result = "";
if (Session::active()) { if (Session::active()) {
$result = true; $result = true;
} else { } else {
@ -37,39 +39,39 @@ class Auth
{ {
//grab member list //grab member list
$folks = (new Settings())->getFolks(); $folks = (new Settings())->getFolks();
$found = find($folks, ['handle' => $who['handle']]); $found = find($folks, ["handle" => $who["handle"]]);
if ($found) { if ($found) {
//name is found, verify password //name is found, verify password
if (password_verify($who['password'], $found['password'])) { if (password_verify($who["password"], $found["password"])) {
$member = [ $member = [
'handle' => $found['handle'], "handle" => $found["handle"],
'email' => $found['email'], "email" => $found["email"],
'role' => $found['role'], "role" => $found["role"],
'avatar' => $found['avi'], "avatar" => $found["avi"],
'key' => $found['key'], "key" => $found["key"],
]; ];
$token = Token::create( $token = Token::create(
$found['key'], $found["key"],
$found['secret'], $found["secret"],
time() + 3600, time() + 3600,
'localhost' "localhost"
); //expires in an hour ); //expires in an hour
$form_token = md5(uniqid(microtime(), true)); $form_token = md5(uniqid(microtime(), true));
Session::start(); Session::start();
Session::set('member', $member); Session::set("member", $member);
Session::set('token', $token); Session::set("token", $token);
Session::set('form_token', $form_token); Session::set("form_token", $form_token);
$result = 'good_login'; $result = "good_login";
} else { } else {
$result = 'bad_pass'; $result = "bad_pass";
} }
} else { } else {
//if name is not found //if name is not found
$result = 'no_name'; $result = "no_name";
} }
return $result; return $result;
} }
@ -79,35 +81,38 @@ class Auth
$result = []; $result = [];
$folks = (new Settings())->getFolks(); $folks = (new Settings())->getFolks();
if (!empty($data['email']) && filter_var($data['email'], FILTER_VALIDATE_EMAIL)) { if (
$found = find($folks, ['email' => $data['email']]); !empty($data["email"]) &&
filter_var($data["email"], FILTER_VALIDATE_EMAIL)
) {
$found = find($folks, ["email" => $data["email"]]);
if ($found) { if ($found) {
//if email is cool, check mail relay status //if email is cool, check mail relay status
//if set up, send secret there, if not just return it //if set up, send secret there, if not just return it
$config = new Settings(); $config = new Settings();
$settings = $config->getSettings(); $settings = $config->getSettings();
$email = $settings['email']['active']; $email = $settings["email"]["active"];
if ($email != 'option-none') { if ($email != "option-none") {
$data['mail_task'] = 'SEND_SECRET'; $data["mail_task"] = "SEND_SECRET";
$data['secret'] = $found['secret']; $data["secret"] = $found["secret"];
$result = Mailer::sendmail($data); $result = Mailer::sendmail($data);
} else { } else {
$result = [ $result = [
'message' => 'Valid email, but no email set up!', "message" => "Valid email, but no email set up!",
'type' => 'secretFound', "type" => "secretFound",
'secret' => $found['secret'], "secret" => $found["secret"],
]; ];
} }
} else { } else {
$result = [ $result = [
'message' => 'No valid email, no goodies, pleighboi', "message" => "No valid email, no goodies, pleighboi",
'type' => 'secretNotFound', "type" => "secretNotFound",
]; ];
} }
} else { } else {
$result = [ $result = [
'message' => 'Aye, this address is not right, slick.', "message" => "Aye, this address is not right, slick.",
'type' => 'secretNotFound', "type" => "secretNotFound",
]; ];
} }
@ -117,30 +122,30 @@ class Auth
public static function makeNewPassword($data) public static function makeNewPassword($data)
{ {
//check if passwordsmatch //check if passwordsmatch
if ($data['newPass'] == $data['newPassConfirm']) { if ($data["newPass"] == $data["newPassConfirm"]) {
//verify secret //verify secret
$folks = (new Settings())->getFolks(); $folks = (new Settings())->getFolks();
$found = find($folks, ['secret' => $data['secret']]); $found = find($folks, ["secret" => $data["secret"]]);
if ($found) { if ($found) {
//create new pass and secret key, then update file //create new pass and secret key, then update file
$hash = password_hash($data['newPass'], PASSWORD_DEFAULT); $hash = password_hash($data["newPass"], PASSWORD_DEFAULT);
$freshSecret = StringTools::randomString(12); $freshSecret = StringTools::randomString(12);
Member::updateData('password', $hash, $data['secret']); Member::updateData("password", $hash, $data["secret"]);
Member::updateData('secret', $freshSecret, $data['secret']); Member::updateData("secret", $freshSecret, $data["secret"]);
$result = [ $result = [
'message' => 'Password Updated. Very nice!', "message" => "Password Updated. Very nice!",
'type' => 'passCreated', "type" => "passCreated",
]; ];
} else { } else {
$result = [ $result = [
'message' => 'Secret key is invalid. Try to retrieve it again', "message" => "Secret key is invalid. Try to retrieve it again",
'type' => 'passNotCreated', "type" => "passNotCreated",
]; ];
} }
} else { } else {
$result = [ $result = [
'message' => "Passwords don't match. Try it again.", "message" => "Passwords don't match. Try it again.",
'type' => 'passNotCreated', "type" => "passNotCreated",
]; ];
} }

View file

@ -2,12 +2,11 @@
namespace brain\data; namespace brain\data;
use Carbon\Carbon;
use brain\utility\DocTools;
use brain\utility\StringTools;
use function _\find;
use function _\filter; use function _\filter;
use function _\find;
use brain\utility\DocTools;
use brain\utility\FileUploader;
use brain\utility\StringTools;
class Book class Book
{ {
@ -38,8 +37,13 @@ class Book
public function editPage($task, $request) public function editPage($task, $request)
{ {
$content = $this->getContents(); $content = $this->getContents();
$body = json_decode(file_get_contents("php://input"), true); if ($task == 'delete') {
// $parsed = json_decode(file_get_contents("php://input"), true);
// $body = find($content, ["uuid" => $parsed["id"]]); // $body = find($content, ["uuid" => $parsed["id"]]);
$body = $request->getParsedBody();
} else {
$body = $request->getParsedBody();
}
$page = find($content, ['uuid' => $body['uuid']]); $page = find($content, ['uuid' => $body['uuid']]);
$files = $request->getUploadedFiles(); $files = $request->getUploadedFiles();
@ -47,7 +51,8 @@ class Book
$member = Session::get('member'); $member = Session::get('member');
if ($task != 'create') { if ($task != 'create') {
$path = date('Y', date($page['rawCreated'])) . $path =
date('Y', date($page['rawCreated'])).
'/'. '/'.
date('m', date($page['rawCreated'])); date('m', date($page['rawCreated']));
} else { } else {
@ -57,6 +62,66 @@ class Book
$page_feature = ''; $page_feature = '';
$page_files = ''; $page_files = '';
if (isset($files['page_files'])) {
$imageList = '';
$fileList = '';
// var_dump($files["page_files"] );
foreach ($files['page_files'] as $file) {
$type = $file->getClientMediaType();
switch ($type) {
case 'image/jpeg':
case 'image/png':
case 'image/gif':
case 'image/svg':
$imagesPath = '/assets/images/blog/'.$path.'/';
$imageList =
$imageList.$imagesPath.urlencode($file->getClientFileName()).', ';
FileUploader::uploadFile(
'../public/assets/images/blog/'.$path.'/',
$file
);
break;
case 'video/mp4':
$videosPath = '/assets/video/blog/'.$path.'/';
$imageList =
$imageList.$videosPath.urlencode($file->getClientFileName()).', ';
FileUploader::uploadFile(
'../public/assets/video/blog/'.$path.'/',
$file
);
break;
case 'audio/mpeg':
$soundPath = '/assets/sound/blog/'.$path.'/';
$fileList = $fileList.$soundPath.urlencode($file->getClientFileName()).', ';
FileUploader::uploadFile(
'../public/assets/sound/blog/'.$path.'/',
$file
);
break;
case 'application/pdf':
case 'text/plain':
case 'text/rtf':
$docPath = '/assets/docs/blog/'.$path.'/';
$fileList = $fileList.$docPath.urlencode($file->getClientFileName()).', ';
FileUploader::uploadFile(
'../public/assets/docs/blog/'.$path.'/',
$file
);
break;
}
}
$page_feature = $imageList;
$page_files = $fileList;
} else {
// if no files, just reset string from page object
$page_feature = $page['feature'];
$page_files = $page['files'];
}
if ($task == 'delete') { if ($task == 'delete') {
$deleted = 'true'; $deleted = 'true';
$body['menu'] = 'false'; $body['menu'] = 'false';
@ -66,8 +131,11 @@ class Book
$deleted = isset($page['deleted']) ? $page['deleted'] : 'false'; $deleted = isset($page['deleted']) ? $page['deleted'] : 'false';
} }
$created = $task != 'create' ? new Carbon($page['rawCreated']) : Carbon::now(); $created =
$updated = Carbon::now(); $task != 'create'
? new \Moment\Moment($page['rawCreated'])
: new \Moment\Moment();
$updated = new \Moment\Moment();
// grab current index from settings and update // grab current index from settings and update
$id = $task != 'create' ? $body['id'] : Settings::getCurrentIndex(); $id = $task != 'create' ? $body['id'] : Settings::getCurrentIndex();
@ -76,8 +144,8 @@ class Book
$body['id'] = $id; $body['id'] = $id;
$body['uuid'] = $uuid; $body['uuid'] = $uuid;
//$body['feature'] = $page_feature; $body['feature'] = $page_feature;
//$body['files'] = $page_files; $body['files'] = $page_files;
$body['path'] = $path; $body['path'] = $path;
$body['author'] = $member['handle']; $body['author'] = $member['handle'];
$body['created'] = $created->format("Y-m-d\TH:i:sP"); $body['created'] = $created->format("Y-m-d\TH:i:sP");

View file

@ -2,18 +2,18 @@
namespace brain\data; namespace brain\data;
use HtmlSanitizer\SanitizerBuilder;
use League\CommonMark\MarkdownConverter;
use League\CommonMark\Environment\Environment; use League\CommonMark\Environment\Environment;
use HtmlSanitizer\Extension\Basic\BasicExtension;
use HtmlSanitizer\Extension\Listing\ListExtension;
use HtmlSanitizer\Extension\Iframe\IframeExtension;
use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\Extension\Attributes\AttributesExtension;
use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension; use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension; use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
use League\CommonMark\Extension\Attributes\AttributesExtension;
use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter; use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;
use League\CommonMark\MarkdownConverter;
use League\CommonMark\CommonMarkConverter;
use HtmlSanitizer\Extension\Basic\BasicExtension;
use HtmlSanitizer\Extension\Iframe\IframeExtension;
use HtmlSanitizer\Extension\Listing\ListExtension;
use HtmlSanitizer\SanitizerBuilder;
use function _\orderBy; use function _\orderBy;
@ -21,12 +21,10 @@ class Contents
{ {
public $files = []; public $files = [];
public $config = []; public $config = [];
public function __construct($folder) public function __construct($folder)
{ {
$this->read($folder); $this->read($folder);
} }
public function read($folder) public function read($folder)
{ {
$folders = glob("$folder/*", GLOB_ONLYDIR); $folders = glob("$folder/*", GLOB_ONLYDIR);
@ -34,7 +32,7 @@ class Contents
//$this->files[] = $folder . "/"; //$this->files[] = $folder . "/";
$this->read($folder); $this->read($folder);
} }
$files = array_filter(glob("$folder/*md"), 'is_file'); $files = array_filter(glob("$folder/*md"), "is_file");
foreach ($files as $file) { foreach ($files as $file) {
$this->files[] = $file; $this->files[] = $file;
} }
@ -54,9 +52,6 @@ class Contents
//add attributes to elements in markdown //add attributes to elements in markdown
$environment->addExtension(new AttributesExtension()); $environment->addExtension(new AttributesExtension());
//add table rendering
$environment->addExtension(new TableExtension());
// Instantiate the converter engine and start converting some Markdown! // Instantiate the converter engine and start converting some Markdown!
$converter = new MarkdownConverter($environment); $converter = new MarkdownConverter($environment);
@ -81,8 +76,6 @@ class Contents
$builder->registerExtension(new BasicExtension()); $builder->registerExtension(new BasicExtension());
$builder->registerExtension(new IframeExtension()); $builder->registerExtension(new IframeExtension());
$builder->registerExtension(new ListExtension()); $builder->registerExtension(new ListExtension());
//just add it straight because classname is already in use
$builder->registerExtension(new \HtmlSanitizer\Extension\Table\TableExtension());
//relative-a and relative-image //relative-a and relative-image
$builder->registerExtension( $builder->registerExtension(
@ -93,32 +86,28 @@ class Contents
); );
$detergent = [ $detergent = [
'extensions' => ['basic', 'list', 'relative-a', 'relative-image', 'iframe', 'table'], "extensions" => ["basic", "list","relative-a", "relative-image", "iframe"],
'tags' => [ "tags" => [
'div' => [ "div" => [
'allowed_attributes' => ['class', 'title', 'id', 'style'], "allowed_attributes" => ["class", "title", "id", "style"],
], ],
'img' => [ "img" => [
'allowed_attributes' => ['src', 'alt', 'title', 'class'], "allowed_attributes" => ["src", "alt", "title", "class"],
], ],
'iframe' => [ "iframe" => [
'allowed_attributes' => ['height', 'width', 'title', 'src'], "allowed_attributes" => ["height", "width", "title", "src"],
], ],
], ],
]; ];
$sanitizer = $builder->build($detergent); $sanitizer = $builder->build($detergent);
$scrubbed = $sanitizer->sanitize($result->getContent());
if (isset($meta['feature'])) {
$featureList = explode(',', $meta['feature']);
} else {
$featureList = "";
}
$scrubbed = $sanitizer->sanitize($result->getContent());
$featureList = explode(",", $meta["feature"]);
$docs = ''; $docs = '';
if (isset($meta['files'])) { if (isset($meta["files"])) {
$fileList = explode(',', $meta['files']); $fileList = explode(",", $meta["files"]);
$docs = $meta['files']; $docs = $meta["files"];
} else { } else {
$fileList = []; $fileList = [];
$docs = ''; $docs = '';
@ -126,59 +115,55 @@ class Contents
$media = []; $media = [];
$files = []; $files = [];
if ($featureList != '') {
foreach ($featureList as $file) { foreach ($featureList as $file) {
$item = trim($file); $item = trim($file);
$ext = pathinfo($item, PATHINFO_EXTENSION); $ext = pathinfo($item, PATHINFO_EXTENSION);
if ($item != null || $item != '') { if ($item != null || $item != "") {
array_push($media, ['file' => $item, 'type' => trim($ext)]); array_push($media, ["file" => $item, "type" => trim($ext)]);
}
} }
} }
if ($fileList != "") {
foreach ($fileList as $file) { foreach ($fileList as $file) {
$item = trim($file); $item = trim($file);
$ext = pathinfo($item, PATHINFO_EXTENSION); $ext = pathinfo($item, PATHINFO_EXTENSION);
if ($item != null || $item != '') { if ($item != null || $item != "") {
array_push($files, ['file' => $item, 'type' => trim($ext)]); array_push($files, ["file" => $item, "type" => trim($ext)]);
}
} }
} }
//sort attributes into page object //sort attributes into page object
$page = [ $page = [
'id' => $meta['id'], "id" => $meta["id"],
'uuid' => $meta['uuid'], "uuid" => $meta["uuid"],
'title' => $meta['title'], "title" => $meta["title"],
'feature' => $meta['feature'], "feature" => $meta["feature"],
'files' => $docs, "files" => $docs,
'path' => $meta['path'], "path" => $meta["path"],
'layout' => $meta['layout'], "layout" => $meta["layout"],
'tags' => $meta['tags'], "tags" => $meta["tags"],
'author' => $meta['author'], "author" => $meta["author"],
'created' => date('Y M D d', $meta['created']), "created" => date("Y M D d", $meta["created"]),
'updated' => date('Y M D d', $meta['updated']), "updated" => date("Y M D d", $meta["updated"]),
'rawCreated' => $meta['created'], "rawCreated" => $meta["created"],
'rawUpdated' => $meta['updated'], "rawUpdated" => $meta["updated"],
'createdYear' => date('Y', $meta['created']), "createdYear" => date("Y", $meta["created"]),
'createdMonth' => date('m', $meta['created']), "createdMonth" => date("m", $meta["created"]),
'deleted' => $meta['deleted'], "deleted" => $meta["deleted"],
'menu' => $meta['menu'], "menu" => $meta["menu"],
'featured' => $meta['featured'], "featured" => $meta["featured"],
'published' => $meta['published'], "published" => $meta["published"],
'slug' => $meta['slug'], "slug" => $meta["slug"],
'filePath' => $file, "filePath" => $file,
'content' => $parsed->getContent(), "content" => $parsed->getContent(),
'html' => $scrubbed, "html" => $scrubbed,
'media' => $media, "media" => $media,
'docs' => $files "docs" => $files
]; ];
//checks for duplicates //checks for duplicates
$uuid = $meta['uuid']; $uuid = $meta["uuid"];
$found = current( $found = current(
array_filter($contents, function ($item) use ($uuid) { array_filter($contents, function ($item) use ($uuid) {
return isset($item['uuid']) && $uuid == $item['uuid']; return isset($item["uuid"]) && $uuid == $item["uuid"];
}) })
); );
@ -187,7 +172,7 @@ class Contents
array_push($contents, $page); array_push($contents, $page);
} }
} }
$contents = orderBy($contents, ['id'], ['desc']); $contents = orderBy($contents, ["id"], ["desc"]);
return $contents; return $contents;
} }
} }

View file

@ -2,7 +2,8 @@
namespace brain\data; namespace brain\data;
use Carbon\Carbon; use brain\data\Settings;
use brain\data\Session;
use brain\utility\DocTools; use brain\utility\DocTools;
use function _\find; use function _\find;
@ -17,7 +18,7 @@ class Member
{ {
if (isset($key)) { if (isset($key)) {
$folks = (new Settings())->getFolks(); $folks = (new Settings())->getFolks();
$found = find($folks, ['key' => $key]); $found = find($folks, ["key" => $key]);
if ($found) { if ($found) {
return true; return true;
} else { } else {
@ -32,30 +33,30 @@ class Member
{ {
$folks = (new Settings())->getFolks(); $folks = (new Settings())->getFolks();
if (isset($secret)) { if (isset($secret)) {
$found = find($folks, ['secret' => $secret]); $found = find($folks, ["secret" => $secret]);
} else { } else {
$member = Session::get('member'); $member = Session::get("member");
$found = find($folks, ['handle' => $member['handle']]); $found = find($folks, ["handle" => $member["handle"]]);
} }
$found[$key] = $data; $found[$key] = $data;
//record time updated //record time updated
$updated = Carbon::now(); $updated = new \Moment\Moment();
$found['updated'] = $updated->format("Y-m-d\TH:i:sP"); $found["updated"] = $updated->format("Y-m-d\TH:i:sP");
$newFolks = []; $newFolks = [];
array_push($newFolks, $found); array_push($newFolks, $found);
//save updated file //save updated file
DocTools::writeSettings('../config/folks.json', $newFolks); DocTools::writeSettings("../config/folks.json", $newFolks);
//update member data in session //update member data in session
if (!isset($secret)) { if (!isset($secret)) {
$member = [ $member = [
'handle' => $found['handle'], "handle" => $found["handle"],
'email' => $found['email'], "email" => $found["email"],
'role' => $found['role'], "role" => $found["role"],
'avatar' => $found['avi'], "avatar" => $found["avi"],
'key' => $found['key'], "key" => $found["key"],
]; ];
Session::set('member', $member); Session::set("member", $member);
} }
} }
} }

View file

@ -2,6 +2,9 @@
namespace brain\data; namespace brain\data;
use Mni\FrontYAML\Parser;
use brain\data\Settings;
use brain\data\Book;
use brain\utility\Sorting; use brain\utility\Sorting;
use brain\utility\DocTools; use brain\utility\DocTools;
@ -14,38 +17,38 @@ class Render
public $pageInfo; public $pageInfo;
public $menu; public $menu;
public $background; public $background;
public function __construct() public function __construct()
{ {
$config = new Settings(); $config = new Settings();
//TODO: Add theme folder to loader //TODO: Add theme folder to loader
$settings = $config->getSettings(); $settings = $config->getSettings();
$this->menu = $settings['menu']; $this->menu = $settings["menu"];
$this->theme = $settings['global']['theme']; $this->theme = $settings["global"]["theme"];
$this->loader = new \Twig\Loader\FilesystemLoader('../content/themes/' . $this->theme); $this->loader = new \Twig\Loader\FilesystemLoader("../content/themes/" . $this->theme);
$this->twig = new \Twig\Environment($this->loader, []); $this->twig = new \Twig\Environment($this->loader, []);
$this->pageInfo = [ $this->pageInfo = [
'keywords' => isset($settings['global']['keywords']) "keywords" => isset($settings["global"]["keywords"])
? $settings['global']['keywords'] ? $settings["global"]["keywords"]
: 'fipamo, blog, jamstack, php, markdown, js', : "fipamo, blog, jamstack, php, markdown, js",
'description' => $settings['global']['descriptions'], "description" => $settings["global"]["descriptions"],
'image' => $settings['global']['base_url'] . $settings['global']['background'], "image" =>
'baseURL' => $settings['global']['base_url'], $settings["global"]["base_url"] . $settings["global"]["background"],
"baseURL" => $settings["global"]["base_url"],
]; ];
//move global theme image assets to public folder //move global theme image assets to public folder
foreach ( foreach (
new \DirectoryIterator('../content/themes/' . $this->theme . '/assets/images/global/') as $file new \DirectoryIterator("../content/themes/" . $this->theme . "/assets/images/global/") as $file
) { ) {
if ($file->isDot()) { if ($file->isDot()) {
continue; continue;
} }
if (!is_file('../public/assets/images/global/' . $file->getFileName())) { if (!is_file("../public/assets/images/global/" . $file->getFileName())) {
copy( copy(
'../content/themes/' . "../content/themes/" .
$this->theme . $this->theme .
'/assets/images/global/' . "/assets/images/global/" .
$file->getFileName(), $file->getFileName(),
'../public/assets/images/global/' . $file->getFileName() "../public/assets/images/global/" . $file->getFileName()
); );
} else { } else {
//image is already there, so chill //image is already there, so chill
@ -69,24 +72,24 @@ class Render
$scripts = glob('../public/assets/scripts/*'); // get all file names $scripts = glob('../public/assets/scripts/*'); // get all file names
foreach ($scripts as $file) { // iterate files foreach ($scripts as $file) { // iterate files
if (is_file($file)) { if (is_file($file)) {
if (!$file == '../public/assets/scripts/Start.js') { if (!$file == "../public/assets/scripts/Start.js") {
unlink($file); // delete file unlink($file); // delete file
} }
} }
} }
//copy theme assets to public //copy theme assets to public
$newcss = glob('../content/themes/' . $this->theme . '/assets/css/*'); $newcss = glob("../content/themes/" . $this->theme . "/assets/css/*");
foreach ($newcss as $file) { // iterate files foreach ($newcss as $file) { // iterate files
if (is_file($file)) { if (is_file($file)) {
$path = explode('/', $file); $path = explode("/", $file);
copy($file, '../public/assets/css/' . $path[6]); copy($file, "../public/assets/css/" . $path[6]);
} }
} }
$newjs = glob('../content/themes/' . $this->theme . '/assets/scripts/*'); $newjs = glob("../content/themes/" . $this->theme . "/assets/scripts/*");
foreach ($newjs as $file) { // iterate files foreach ($newjs as $file) { // iterate files
if (is_file($file)) { if (is_file($file)) {
$path = explode('/', $file); $path = explode("/", $file);
copy($file, '../public/assets/scripts/' . $path[6]); copy($file, "../public/assets/scripts/" . $path[6]);
} }
} }
} }
@ -100,24 +103,25 @@ class Render
foreach ($pages as $page) { foreach ($pages as $page) {
$pageOptions = Sorting::page($page); $pageOptions = Sorting::page($page);
$layout = $page['layout']; $layout = $page["layout"];
//new pages have no layout, so defautl for now //new pages have no layout, so defautl for now
if ($layout == '' || $layout == null) { if ($layout == "" || $layout == null) {
$layout = 'page'; $layout = "page";
} }
$template = $layout . '.twig'; $template = $layout . ".twig";
if (str_contains($layout, 'index')) { if (str_contains($page["layout"], "index")) {
$location = '../public/index.html'; $location = "../public/index.html";
$dir = null; $dir = null;
} else { } else {
// if page is a menu item, render the page on public root // if page is a menu item, render the page on public root
if ($page['menu'] == 'true') { if ($page["menu"] == "true") {
$location = '../public/' . $page['slug'] . '.html'; $location = "../public/" . $page["slug"] . ".html";
$dir = '../public/'; $dir = "../public/";
} else { } else {
$location = '../public/' . $page['path'] . '/' . $page['slug'] . '.html'; $location =
$dir = '../public/' . $page['path']; "../public/" . $page["path"] . "/" . $page["slug"] . ".html";
$dir = "../public/" . $page["path"];
} }
} }
@ -129,18 +133,17 @@ class Render
public function renderArchive() public function renderArchive()
{ {
$archive = Sorting::archive(); $archive = Sorting::archive();
$template = 'archive.twig'; $template = "archive.twig";
$pageOptions = [ $pageOptions = [
'title' => 'Archive', "title" => "Archive",
'background' => $this->pageInfo['image'], "background" => $this->pageInfo["image"],
'archives' => $archive, "archives" => $archive,
'info' => $this->pageInfo, "info" => $this->pageInfo,
'menu' => $this->menu, "menu" => $this->menu,
'media' => [['file' => $this->pageInfo['image'], 'type' => trim(pathinfo($this->pageInfo['image'], PATHINFO_EXTENSION))]],
]; ];
$html = $this->twig->render($template, $pageOptions); $html = $this->twig->render($template, $pageOptions);
$location = '../public/archives.html'; $location = "../public/archives.html";
DocTools::writeHTML($location, $html); DocTools::writeHTML($location, $html);
} }
@ -148,30 +151,29 @@ class Render
{ {
$list = Sorting::tags(); $list = Sorting::tags();
foreach ($list as $item) { foreach ($list as $item) {
$template = 'tags.twig'; $template = "tags.twig";
$pageOptions = [ $pageOptions = [
'title' => 'Pages Tagged as ' . $item['tag_name'], "title" => "Pages Tagged as " . $item["tag_name"],
'background' => $this->pageInfo['image'], "background" => $this->pageInfo["image"],
'tag_list' => $item['pages'], "tag_list" => $item["pages"],
'info' => $this->pageInfo, "info" => $this->pageInfo,
'menu' => $this->menu, "menu" => $this->menu,
'media' => [['file' => $this->pageInfo['image'], 'type' => trim(pathinfo($this->pageInfo['image'], PATHINFO_EXTENSION))]],
]; ];
$html = $this->twig->render($template, $pageOptions); $html = $this->twig->render($template, $pageOptions);
$location = '../public/tags/' . $item['slug'] . '.html'; $location = "../public/tags/" . $item["slug"] . ".html";
//if tags folder doesn't exist, make it //if tags folder doesn't exist, make it
if (!is_dir('../public/tags')) { if (!is_dir("../public/tags")) {
mkdir('../public/tags', 0755, true); mkdir("../public/tags", 0755, true);
} else { } else {
} }
if (!is_file($location)) { if (!is_file($location)) {
file_put_contents($location, $html); file_put_contents($location, $html);
} else { } else {
($new = fopen($location, 'w')) or die('Unable to open file!'); ($new = fopen($location, "w")) or die("Unable to open file!");
fwrite($new, $html); fwrite($new, $html);
fclose($new); fclose($new);
} }
@ -182,20 +184,20 @@ class Render
{ {
//TODO: Need to fix this to account for new index templating system //TODO: Need to fix this to account for new index templating system
$pages = (new Book())->getContents(); $pages = (new Book())->getContents();
$index = find($pages, ['layout' => 'index']); $index = find($pages, ["layout" => "index"]);
$template = 'index.twig'; $template = "index.twig";
$location = '../public/index.html'; $location = "../public/index.html";
$dir = null; $dir = null;
$meta = [ $meta = [
'who' => $index['author'], "who" => $index["author"],
'when' => $index['created'], "when" => $index["created"],
]; ];
$pageOptions = [ $pageOptions = [
'title' => $index['title'], "title" => $index["title"],
'background' => $index['feature'], "background" => $index["feature"],
'meta' => $meta, "meta" => $meta,
]; ];
$html = $this->twig->render($template, $pageOptions); $html = $this->twig->render($template, $pageOptions);

View file

@ -4,21 +4,22 @@ namespace brain\data;
use ReallySimpleJWT\Token; use ReallySimpleJWT\Token;
use function _\find;
class Session class Session
{ {
private static $file = '../content/.session'; private static $file = "../content/.session";
private static $data = [ private static $data = [
'member' => '', "member" => "",
'token' => '', "token" => "",
'form_token' => '', "form_token" => "",
]; ];
public static function start() public static function start()
{ {
if (!is_file(self::$file)) { if (!is_file(self::$file)) {
file_put_contents(self::$file, json_encode(self::$data)); file_put_contents(self::$file, json_encode(self::$data));
} else { } else {
($new = fopen(self::$file, 'w')) or die('Unable to open file!'); ($new = fopen(self::$file, "w")) or die("Unable to open file!");
fwrite($new, json_encode(self::$data)); fwrite($new, json_encode(self::$data));
fclose($new); fclose($new);
} }
@ -30,14 +31,14 @@ class Session
return false; return false;
} else { } else {
$data = json_decode(file_get_contents(self::$file), true); $data = json_decode(file_get_contents(self::$file), true);
if ($data['member'] != null) { if ($data["member"] != null) {
$secret = (new Settings())->getFolks('secret'); $secret = (new Settings())->getFolks("secret");
if ($secret == null) { if ($secret == null) {
return false; return false;
} else { } else {
if ( if (
Token::validate($data['token'], $secret) && Token::validate($data["token"], $secret) &&
Token::validateExpiration($data['token'], $secret) Token::validateExpiration($data["token"], $secret)
) { ) {
return true; return true;
} else { } else {
@ -53,8 +54,8 @@ class Session
public static function verifyToken($token) public static function verifyToken($token)
{ {
$data = json_decode(file_get_contents(self::$file), true); $data = json_decode(file_get_contents(self::$file), true);
if ($data['member'] != null) { if ($data["member"] != null) {
$secret = (new Settings())->getFolks('secret'); $secret = (new Settings())->getFolks("secret");
if ( if (
Token::validate($token, $secret) && Token::validate($token, $secret) &&
Token::validateExpiration($token, $secret) Token::validateExpiration($token, $secret)
@ -72,7 +73,7 @@ class Session
{ {
$data = json_decode(file_get_contents(self::$file), true); $data = json_decode(file_get_contents(self::$file), true);
$data[$key] = $value; $data[$key] = $value;
($fresh = fopen(self::$file, 'w')) or die('Unable to open file!'); ($fresh = fopen(self::$file, "w")) or die("Unable to open file!");
fwrite($fresh, json_encode($data)); fwrite($fresh, json_encode($data));
fclose($fresh); fclose($fresh);
} }
@ -86,7 +87,7 @@ class Session
public static function kill() public static function kill()
{ {
($fresh = fopen(self::$file, 'w')) or die('Unable to open file!'); ($fresh = fopen(self::$file, "w")) or die("Unable to open file!");
fwrite($fresh, json_encode(self::$data)); fwrite($fresh, json_encode(self::$data));
fclose($fresh); fclose($fresh);
} }

View file

@ -2,9 +2,9 @@
namespace brain\data; namespace brain\data;
use brain\data\Member;
use brain\utility\DocTools; use brain\utility\DocTools;
use brain\utility\Sorting; use brain\utility\Sorting;
use Carbon\Carbon;
use function _\find; use function _\find;
use function _\pull; use function _\pull;
@ -19,10 +19,10 @@ class Settings
public function __construct() public function __construct()
{ {
//gets all settings files and converts to php objects //gets all settings files and converts to php objects
$this->folks = json_decode(file_get_contents('../config/folks.json'), true); $this->folks = json_decode(file_get_contents("../config/folks.json"), true);
self::$tags = json_decode(file_get_contents('../config/tags.json'), true); self::$tags = json_decode(file_get_contents("../config/tags.json"), true);
self::$settings = json_decode( self::$settings = json_decode(
file_get_contents('../config/settings.json'), file_get_contents("../config/settings.json"),
true true
); );
} }
@ -30,80 +30,81 @@ class Settings
public static function sync($data) public static function sync($data)
{ {
$settings = self::$settings; $settings = self::$settings;
$settings['global']['base_url'] = $data['global']['base_url']; $settings["global"]["base_url"] = $data["global"]["base_url"];
$settings['global']['title'] = $data['global']['title']; $settings["global"]["title"] = $data["global"]["title"];
$settings['global']['descriptions'] = $data['global']['descriptions']; $settings["global"]["descriptions"] = $data["global"]["descriptions"];
$settings['global']['base_url'] = $data['global']['base_url']; $settings["global"]["base_url"] = $data["global"]["base_url"];
$settings['global']['private'] = $data['global']['private']; $settings["global"]["private"] = $data["global"]["private"];
$settings['global']['renderOnSave'] = $data['global']['renderOnSave']; $settings["global"]["renderOnSave"] = $data["global"]["renderOnSave"];
$settings['global']['theme'] = $data['global']['theme']; $settings["global"]["theme"] = $data["global"]["theme"];
$settings['global']['externalAPI'] = $data['global']['externalAPI']; $settings["global"]["externalAPI"] = $data["global"]["externalAPI"];
$settings['global']['dynamicRender'] = $data['global']['dynamicRender']; $settings["global"]["dynamicRender"] = $data["global"]["dynamicRender"];
Member::updateData('handle', $data['member']['handle']); Member::updateData("handle", $data["member"]["handle"]);
Member::updateData('email', $data['member']['email']); Member::updateData("email", $data["member"]["email"]);
$settings['email']['active'] = $data['email']['active']; $settings["email"]["active"] = $data["email"]["active"];
$settings['email']['smtp'] = $data['email']['smtp']; $settings["email"]["smtp"] = $data["email"]["smtp"];
$settings['email']['mailgun'] = $data['email']['mailgun']; $settings["email"]["mailgun"] = $data["email"]["mailgun"];
DocTools::writeSettings('../config/settings.json', $settings); DocTools::writeSettings("../config/settings.json", $settings);
} }
public static function navSync($data) public static function navSync($data)
{ {
$settings = self::$settings; $settings = self::$settings;
$remove = $data['remove']; $remove = $data["remove"];
//if remove contains id, find nav item page and set menu to false //if remove contains id, find nav item page and set menu to false
if ($remove != null || $remove != '') { if ($remove != null || $remove != "") {
$page = (new Book('../content/pages'))->findPageById($remove); $page = (new Book("../content/pages"))->findPageById($remove);
$page['menu'] = 'false'; $page["menu"] = "false";
$page['published'] $page["published"]
? ($page['published'] = 'true') ? ($page["published"] = "true")
: ($page['published'] = 'false'); : ($page["published"] = "false");
$page['featured'] $page["featured"]
? ($page['featured'] = 'true') ? ($page["featured"] = "true")
: ($page['featured'] = 'false'); : ($page["featured"] = "false");
$page['deleted'] $page["deleted"]
? ($page['deleted'] = 'true') ? ($page["deleted"] = "true")
: ($page['deleted'] = 'false'); : ($page["deleted"] = "false");
$updated = Carbon::now(); $updated = new \Moment\Moment();
$created = new Carbon($page['rawCreated']); $created = new \Moment\Moment($page["rawCreated"]);
$page['created'] = $created->format("Y-m-d\TH:i:sP"); $page["created"] = $created->format("Y-m-d\TH:i:sP");
$page['updated'] = $updated->format("Y-m-d\TH:i:sP"); $page["updated"] = $updated->format("Y-m-d\TH:i:sP");
$md = DocTools::objectToMD($page); $md = DocTools::objectToMD($page);
if ($page['layout'] == 'index') { if ($page["layout"] == "index") {
$writePath = '../content/pages/start/index.md'; $writePath = "../content/pages/start/index.md";
} else { } else {
$writePath = '../content/pages/' . $page['path'] . '/' . $page['slug'] . '.md'; $writePath =
"../content/pages/" . $page["path"] . "/" . $page["slug"] . ".md";
} }
DocTools::writePages('write', $page['path'], $writePath, $md); DocTools::writePages("write", $page["path"], $writePath, $md);
} }
$settings['menu'] = []; $settings["menu"] = [];
$items = $data['menu']; $items = $data["menu"];
foreach ($items as $item) { foreach ($items as $item) {
array_push($settings['menu'], [ array_push($settings["menu"], [
'title' => $item['title'], "title" => $item["title"],
'id' => $item['id'], "id" => $item["id"],
'uuid' => $item['uuid'], "uuid" => $item["uuid"],
'slug' => $item['slug'], "slug" => $item["slug"],
'path' => $item['path'], "path" => $item["path"],
]); ]);
} }
DocTools::writeSettings('../config/settings.json', $settings); DocTools::writeSettings("../config/settings.json", $settings);
} }
public function getFolks($key = null) public function getFolks($key = null)
{ {
if (isset($key)) { if (isset($key)) {
$member = Session::get('member'); $member = Session::get("member");
$found = find($this->folks, ['handle' => $member['handle']]); $found = find($this->folks, ["handle" => $member["handle"]]);
if ($found) { if ($found) {
return $found[$key]; return $found[$key];
} }
@ -125,23 +126,24 @@ class Settings
public static function updateGlobalData($key, $data) public static function updateGlobalData($key, $data)
{ {
$settings = self::$settings; $settings = self::$settings;
$settings['global'][$key] = $data; $settings["global"][$key] = $data;
DocTools::writeSettings('../config/settings.json', $settings); DocTools::writeSettings("../config/settings.json", $settings);
} }
public static function getCurrentIndex() public static function getCurrentIndex()
{ {
$settings = self::$settings; $settings = self::$settings;
return $settings['library_stats']['current_index']; return $settings["library_stats"]["current_index"];
} }
public static function updateIndex() public static function updateIndex()
{ {
$settings = self::$settings; $settings = self::$settings;
$settings['library_stats']['current_index'] = $settings['library_stats']['current_index'] + 1; $settings["library_stats"]["current_index"] =
$settings["library_stats"]["current_index"] + 1;
DocTools::writeSettings('../config/settings.json', $settings); DocTools::writeSettings("../config/settings.json", $settings);
} }
public static function updateMenu($body) public static function updateMenu($body)
@ -149,27 +151,27 @@ class Settings
$settings = self::$settings; $settings = self::$settings;
//$menu = $settings["menu"]; //$menu = $settings["menu"];
$item = [ $item = [
'title' => $body['title'], "title" => $body["title"],
'id' => $body['id'], "id" => $body["id"],
'uuid' => $body['uuid'], "uuid" => $body["uuid"],
'slug' => $body['slug'], "slug" => $body["slug"],
'path' => $body['path'], "path" => $body["path"],
]; ];
if ($body['menu'] == 'true') { if ($body["menu"] == "true") {
if (!find($settings['menu'], ['uuid' => $item['uuid']])) { if (!find($settings["menu"], ["uuid" => $item["uuid"]])) {
array_push($settings['menu'], $item); array_push($settings["menu"], $item);
} }
} else { } else {
if (find($settings['menu'], ['uuid' => $item['uuid']])) { if (find($settings["menu"], ["uuid" => $item["uuid"]])) {
pull($settings['menu'], $item); pull($settings["menu"], $item);
} }
} }
DocTools::writeSettings('../config/settings.json', $settings); DocTools::writeSettings("../config/settings.json", $settings);
} }
public static function updateTags() public static function updateTags()
{ {
$tags = Sorting::tags(); $tags = Sorting::tags();
DocTools::writeSettings('../config/tags.json', $tags); DocTools::writeSettings("../config/tags.json", $tags);
} }
} }

View file

@ -2,17 +2,19 @@
namespace brain\data; namespace brain\data;
use brain\data\Settings;
class Themes class Themes
{ {
private $themes = []; private $themes = [];
public function __construct() public function __construct()
{ {
$_themes = glob('../content/themes/*', GLOB_ONLYDIR); $_themes = glob("../content/themes/*", GLOB_ONLYDIR);
foreach ($_themes as $theme) { foreach ($_themes as $theme) {
array_push( array_push(
$this->themes, $this->themes,
json_decode(file_get_contents($theme . '/theme.json'), true) json_decode(file_get_contents($theme . "/theme.json"), true)
); );
} }
} }
@ -25,16 +27,16 @@ class Themes
public function getCustomIndex() public function getCustomIndex()
{ {
$settings = (new Settings())->getSettings(); $settings = (new Settings())->getSettings();
$currentTheme = $settings['global']['theme']; $currentTheme = $settings["global"]["theme"];
$folder = '../content/themes/' . $currentTheme; $folder = "../content/themes/" . $currentTheme;
$files = array_filter(glob("$folder/*twig"), 'is_file'); $files = array_filter(glob("$folder/*twig"), "is_file");
$views = []; $views = [];
foreach ($files as $file) { foreach ($files as $file) {
$path = explode('/', $file); $path = explode("/", $file);
$fileName = $path[4]; $fileName = $path[4];
if (str_contains($fileName, 'index')) { if (str_contains($fileName, "index")) {
$page = explode('.', $fileName); $page = explode(".", $fileName);
$views[] = $page[0]; $views[] = $page[0];
} }
} }
@ -44,16 +46,16 @@ class Themes
public function getCustomViews() public function getCustomViews()
{ {
$settings = (new Settings())->getSettings(); $settings = (new Settings())->getSettings();
$currentTheme = $settings['global']['theme']; $currentTheme = $settings["global"]["theme"];
$folder = '../content/themes/' . $currentTheme; $folder = "../content/themes/" . $currentTheme;
$files = array_filter(glob("$folder/*twig"), 'is_file'); $files = array_filter(glob("$folder/*twig"), "is_file");
$views = []; $views = [];
foreach ($files as $file) { foreach ($files as $file) {
$path = explode('/', $file); $path = explode("/", $file);
$fileName = $path[4]; $fileName = $path[4];
if (str_contains($fileName, 'page')) { if (str_contains($fileName, "page")) {
$page = explode('.', $fileName); $page = explode(".", $fileName);
$views[] = $page[0]; $views[] = $page[0];
} }
} }

View file

@ -2,10 +2,13 @@
namespace brain\init; namespace brain\init;
use brain\utility\HandleCors; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory; use Slim\Factory\AppFactory;
use Slim\Views\Twig; use Slim\Views\Twig;
use Slim\Views\TwigMiddleware; use Slim\Views\TwigMiddleware;
// Fipamo Core Classes
use brain\utility\HandleCors;
class App class App
{ {
@ -15,15 +18,15 @@ class App
// set up cors // set up cors
new HandleCors(); new HandleCors();
$app = AppFactory::create(); $app = AppFactory::create();
$twig = Twig::create('../brain/views/'); $twig = Twig::create("../brain/views/");
$app->add(TwigMiddleware::create($app, $twig)); $app->add(TwigMiddleware::create($app, $twig));
//set up routing //set up routing
$app->get( $app->get(
'/[{first}[/{second}[/{third}[/{fourth}[/{fifth}]]]]]', "/[{first}[/{second}[/{third}[/{fourth}[/{fifth}]]]]]",
"brain\controller\RouteControl:get" "brain\controller\RouteControl:get"
); );
$app->post( $app->post(
'/[{first}[/{second}[/{third}[/{fourth}]]]]', "/[{first}[/{second}[/{third}[/{fourth}]]]]",
"brain\controller\RouteControl:post" "brain\controller\RouteControl:post"
); );
//start the app //start the app

View file

@ -11,14 +11,14 @@ class DocTools
public static function writePages($task, $path, $fileLocation, $fileContents) public static function writePages($task, $path, $fileLocation, $fileContents)
{ {
try { try {
if ($task == 'create') { if ($task == "create") {
if (!is_dir('../content/pages/' . $path)) { if (!is_dir("../content/pages/" . $path)) {
//Directory does not exist, so lets create it. //Directory does not exist, so lets create it.
mkdir('../content/pages/' . $path, 0755, true); mkdir("../content/pages/" . $path, 0755, true);
} }
file_put_contents($fileLocation, $fileContents); file_put_contents($fileLocation, $fileContents);
} else { } else {
($new = fopen($fileLocation, 'w')) or die('Unable to open file!'); ($new = fopen($fileLocation, "w")) or die("Unable to open file!");
fwrite($new, $fileContents); fwrite($new, $fileContents);
fclose($new); fclose($new);
} }
@ -34,7 +34,7 @@ class DocTools
if (!is_file($fileLocation)) { if (!is_file($fileLocation)) {
file_put_contents($fileLocation, json_encode($fileContents)); file_put_contents($fileLocation, json_encode($fileContents));
} else { } else {
($new = fopen($fileLocation, 'w')) or die('Unable to open file!'); ($new = fopen($fileLocation, "w")) or die("Unable to open file!");
fwrite($new, json_encode($fileContents)); fwrite($new, json_encode($fileContents));
fclose($new); fclose($new);
} }
@ -51,7 +51,7 @@ class DocTools
if (!is_file($location)) { if (!is_file($location)) {
file_put_contents($location, $html); file_put_contents($location, $html);
} else { } else {
($new = fopen($location, 'w')) or die('Unable to open file!'); ($new = fopen($location, "w")) or die("Unable to open file!");
fwrite($new, $html); fwrite($new, $html);
fclose($new); fclose($new);
} }
@ -86,58 +86,59 @@ class DocTools
public static function objectToMD($object) public static function objectToMD($object)
{ {
$markdown = "---\n" . $markdown =
'id: ' . "---\n" .
$object['id'] . "id: " .
$object["id"] .
"\n" . "\n" .
'uuid: ' . "uuid: " .
$object['uuid'] . $object["uuid"] .
"\n" . "\n" .
'title: ' . "title: " .
"'" . "'" .
$object['title'] . $object["title"] .
"'" . "'" .
"\n" . "\n" .
'feature: ' . "feature: " .
$object['imageList'] . $object["feature"] .
"\n" . "\n" .
'files: ' . "files: " .
$object['fileList'] . $object["files"] .
"\n" . "\n" .
'path: ' . "path: " .
$object['path'] . $object["path"] .
"\n" . "\n" .
'layout: ' . "layout: " .
$object['layout'] . $object["layout"] .
"\n" . "\n" .
'tags: ' . "tags: " .
$object['tags'] . $object["tags"] .
"\n" . "\n" .
'author: ' . "author: " .
$object['author'] . $object["author"] .
"\n" . "\n" .
'created: ' . "created: " .
$object['created'] . $object["created"] .
"\n" . "\n" .
'updated: ' . "updated: " .
$object['updated'] . $object["updated"] .
"\n" . "\n" .
'deleted: ' . "deleted: " .
$object['deleted'] . $object["deleted"] .
"\n" . "\n" .
'slug: ' . "slug: " .
$object['slug'] . $object["slug"] .
"\n" . "\n" .
'menu: ' . "menu: " .
$object['menu'] . $object["menu"] .
"\n" . "\n" .
'published: ' . "published: " .
$object['published'] . $object["published"] .
"\n" . "\n" .
'featured: ' . "featured: " .
$object['featured'] . $object["featured"] .
"\n---\n" . "\n---\n" .
$object['content']; $object["content"];
return $markdown; return $markdown;
} }

View file

@ -9,38 +9,37 @@ class HandleCors
public function __construct() public function __construct()
{ {
//look to see if settings file exists. kinda important //look to see if settings file exists. kinda important
if (file_exists('../config/settings.json')) { if (file_exists("../config/settings.json")) {
//check settings to see if external api access is allowed //check settings to see if external api access is allowed
$config = new Settings(); $config = new Settings();
$settings = $config->getSettings(); $settings = $config->getSettings();
if ($settings['global']['externalAPI']) { if ($settings["global"]["externalAPI"]) {
//echo "API STATUS: " . $settings["global"]["externalAPI"]; //echo "API STATUS: " . $settings["global"]["externalAPI"];
if ($settings['global']['externalAPI'] == 'true') { if ($settings["global"]["externalAPI"] == "true") {
//echo "API ACCESS ACTIVE"; //echo "API ACCESS ACTIVE";
// checks to see if origin is set // checks to see if origin is set
if (isset($_SERVER['HTTP_ORIGIN'])) { if (isset($_SERVER["HTTP_ORIGIN"])) {
// You can decide if the origin in $_SERVER['HTTP_ORIGIN'] // You can decide if the origin in $_SERVER['HTTP_ORIGIN'] is something you want to allow, or as we do here, just allow all
//is something you want to allow, or as we do here, just allow all header("Access-Control-Allow-Origin: {$_SERVER["HTTP_ORIGIN"]}");
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
} else { } else {
//No HTTP_ORIGIN set, so we allow any. You can disallow if needed here //No HTTP_ORIGIN set, so we allow any. You can disallow if needed here
//never allow just any domain, so turn CORS off if no No HTTP_ORIGIN is set //never allow just any domain, so turn CORS off if no No HTTP_ORIGIN is set
//header("Access-Control-Allow-Origin: *"); //header("Access-Control-Allow-Origin: *");
} }
header('Access-Control-Allow-Credentials: true'); header("Access-Control-Allow-Credentials: true");
header('Access-Control-Max-Age: 600'); // cache for 10 minutes header("Access-Control-Max-Age: 600"); // cache for 10 minutes
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { if ($_SERVER["REQUEST_METHOD"] == "OPTIONS") {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) { if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"])) {
header( header(
'Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT' "Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT"
); );
} //Make sure you remove those you do not want to support } //Make sure you remove those you do not want to support
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) { if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"])) {
header( header(
"Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}" "Access-Control-Allow-Headers: {$_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"]}"
); );
} }

View file

@ -2,6 +2,7 @@
namespace brain\utility; namespace brain\utility;
use Slim\Views\Twig;
use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception; use PHPMailer\PHPMailer\Exception;
use brain\data\Settings; use brain\data\Settings;
@ -13,56 +14,58 @@ class Mailer
{ {
$config = new Settings(); $config = new Settings();
$settings = $config->getSettings(); $settings = $config->getSettings();
$mailConfig = $settings['email']; $mailConfig = $settings["email"];
$mail = new PHPMailer(); $mail = new PHPMailer();
switch ($body['mail_task']) { switch ($body["mail_task"]) {
case 'TESTING': case "TESTING":
$html = "<h1>Hi! It's Fipamo!</h1><br>" . $html =
"<h1>Hi! It's Fipamo!</h1><br>" .
"<strong>It's just a test</strong><br>" . "<strong>It's just a test</strong><br>" .
$body['content']; $body["content"];
$member = Session::get('member'); $member = Session::get("member");
$mail->addAddress($member['email'], ''); //pull email address from current user $mail->addAddress($member["email"], ""); //pull email address from current user
$mail->Subject = 'A test email'; $mail->Subject = "A test email";
break; break;
case 'SEND_SECRET': case "SEND_SECRET":
$html = "<h1>Hi! It's Fipamo!</h1><br>" . $html =
'<strong>This is your secret key.</strong><br><br>' . "<h1>Hi! It's Fipamo!</h1><br>" .
'<h3>' . "<strong>This is your secret key.</strong><br><br>" .
$body['secret'] . "<h3>" .
'</h3>' . $body["secret"] .
'<br> Use this key to reset your password.'; "</h3>" .
$mail->addAddress($body['email'], ''); //pull email address from current user "<br> Use this key to reset your password.";
$mail->addAddress($body["email"], ""); //pull email address from current user
$mail->Subject = "Shhhh! It's a secret!"; $mail->Subject = "Shhhh! It's a secret!";
break; break;
default: default:
return $result = [ return $result = [
'type' => 'noMailService', "type" => "noMailService",
'message' => 'Mail task is undefined. What are you doing??', "message" => "Mail task is undefined. What are you doing??",
]; ];
break; break;
} }
//set values based on current active protocol //set values based on current active protocol
switch ($mailConfig['active']) { switch ($mailConfig["active"]) {
case 'option-smtp': case "option-smtp":
$mail->setFrom($mailConfig['smtp']['email'], 'System Email'); $mail->setFrom($mailConfig["smtp"]["email"], "System Email");
$mail->Host = 'playvicio.us'; $mail->Host = "playvicio.us";
$mail->Username = $mailConfig['smtp']['email']; $mail->Username = $mailConfig["smtp"]["email"];
$mail->Password = $mailConfig['smtp']['password']; $mail->Password = $mailConfig["smtp"]["password"];
break; break;
case 'option-mg': case "option-mg":
$mail->setFrom($mailConfig['mailgun']['domain'], 'No Reply'); $mail->setFrom($mailConfig["mailgun"]["domain"], "No Reply");
$mail->Host = 'smtp.mailgun.org'; $mail->Host = "smtp.mailgun.org";
$mail->Username = $mailConfig['mailgun']['domain']; $mail->Username = $mailConfig["mailgun"]["domain"];
$mail->Password = $mailConfig['mailgun']['key']; $mail->Password = $mailConfig["mailgun"]["key"];
break; break;
default: default:
//no mail service //no mail service
return $result = [ return $result = [
'type' => 'noMailService', "type" => "noMailService",
'message' => 'Mail is not configured. Handle that.', "message" => "Mail is not configured. Handle that.",
]; ];
break; break;
} }
@ -71,7 +74,7 @@ class Mailer
$mail->IsHTML(true); $mail->IsHTML(true);
$mail->isSMTP(); $mail->isSMTP();
$mail->SMTPAuth = true; $mail->SMTPAuth = true;
$mail->SMTPSecure = 'ssl'; $mail->SMTPSecure = "ssl";
$mail->Port = 465; $mail->Port = 465;
// Uncomment for debug info // Uncomment for debug info
@ -80,13 +83,13 @@ class Mailer
/* Finally send the mail. */ /* Finally send the mail. */
try { try {
$mail->send(); $mail->send();
$result = ['type' => 'mailSent', 'message' => 'Message Away!']; $result = ["type" => "mailSent", "message" => "Message Away!"];
} catch (Exception $e) { } catch (Exception $e) {
//echo $e->errorMessage(); //echo $e->errorMessage();
$result = [ $result = [
'type' => 'mailNotSent', "type" => "mailNotSent",
'message' => 'Message Not Away!', "message" => "Message Not Away!",
'error' => $e->errorMessage(), "error" => $e->errorMessage(),
]; ];
} }

View file

@ -3,7 +3,6 @@
namespace brain\utility; namespace brain\utility;
use brain\data\Settings; use brain\data\Settings;
use Carbon\Carbon;
class Maintenance class Maintenance
{ {
@ -14,90 +13,92 @@ class Maintenance
public static function makeBackup() public static function makeBackup()
{ {
//make sure back directory is there //make sure back directory is there
if (!is_dir('../config/backups')) { if (!is_dir("../config/backups")) {
mkdir('../config/backups', 0755, true); mkdir("../config/backups", 0755, true);
} }
//creat backup zip //creat backup zip
$zip = new \ZipArchive(); $zip = new \ZipArchive();
$zip->open( $zip->open(
'../config/backups/latest_back.zip', "../config/backups/latest_back.zip",
\ZipArchive::CREATE | \ZipArchive::OVERWRITE \ZipArchive::CREATE | \ZipArchive::OVERWRITE
); );
//gather data and path info for md pages //gather data and path info for md pages
$pagePath = '../content/pages'; $pagePath = "../content/pages";
$yearPaths = glob($pagePath . '/*', GLOB_ONLYDIR); $yearPaths = glob($pagePath . "/*", GLOB_ONLYDIR);
foreach ($yearPaths as $years) { foreach ($yearPaths as $years) {
$year = explode('/', $years); $year = explode("/", $years);
//grap the index and save it //grap the index and save it
if (trim($year[3]) == 'start') { if (trim($year[3]) == "start") {
$options = [ $options = [
'add_path' => 'content/pages/' . $year[3] . '/', "add_path" => "content/pages/" . $year[3] . "/",
'remove_all_path' => true, "remove_all_path" => true,
]; ];
$zip->addGlob($years . '/*.md', GLOB_BRACE, $options); $zip->addGlob($years . "/*.md", GLOB_BRACE, $options);
} }
$monthsPath = glob($pagePath . '/' . $year[3] . '/*', GLOB_ONLYDIR); $monthsPath = glob($pagePath . "/" . $year[3] . "/*", GLOB_ONLYDIR);
foreach ($monthsPath as $months) { foreach ($monthsPath as $months) {
$month = explode('/', $months); $month = explode("/", $months);
//once info is collected, add md pages to zip //once info is collected, add md pages to zip
$options = [ $options = [
'add_path' => 'content/pages/' . $year[3] . '/' . $month[4] . '/', "add_path" => "content/pages/" . $year[3] . "/" . $month[4] . "/",
'remove_all_path' => true, "remove_all_path" => true,
]; ];
$zip->addGlob($months . '/*.md', GLOB_BRACE, $options); $zip->addGlob($months . "/*.md", GLOB_BRACE, $options);
} }
} }
//gather data and path info for blog images //gather data and path info for blog images
$blogImagesPath = '../public/assets/images/blog'; $blogImagesPath = "../public/assets/images/blog";
$yearPaths = glob($blogImagesPath . '/*', GLOB_ONLYDIR); $yearPaths = glob($blogImagesPath . "/*", GLOB_ONLYDIR);
foreach ($yearPaths as $years) { foreach ($yearPaths as $years) {
$year = explode('/', $years); $year = explode("/", $years);
$monthsPath = glob($blogImagesPath . '/' . $year[5] . '/*', GLOB_ONLYDIR); $monthsPath = glob($blogImagesPath . "/" . $year[5] . "/*", GLOB_ONLYDIR);
foreach ($monthsPath as $months) { foreach ($monthsPath as $months) {
$month = explode('/', $months); $month = explode("/", $months);
//once info is collected, add images pages to zip //once info is collected, add images pages to zip
$options = [ $options = [
'add_path' => 'public/assets/images/blog/' . $year[5] . '/' . $month[6] . '/', "add_path" =>
'remove_all_path' => true, "public/assets/images/blog/" . $year[5] . "/" . $month[6] . "/",
"remove_all_path" => true,
]; ];
$zip->addGlob($months . '/*.*', GLOB_BRACE, $options); $zip->addGlob($months . "/*.*", GLOB_BRACE, $options);
} }
} }
//gather data and path info for user images //gather data and path info for user images
$userImagesPath = '../public/assets/images/user'; $userImagesPath = "../public/assets/images/user";
$yearPaths = glob($userImagesPath . '/*', GLOB_ONLYDIR); $yearPaths = glob($userImagesPath . "/*", GLOB_ONLYDIR);
foreach ($yearPaths as $years) { foreach ($yearPaths as $years) {
$year = explode('/', $years); $year = explode("/", $years);
$monthsPath = glob($userImagesPath . '/' . $year[5] . '/*', GLOB_ONLYDIR); $monthsPath = glob($userImagesPath . "/" . $year[5] . "/*", GLOB_ONLYDIR);
foreach ($monthsPath as $months) { foreach ($monthsPath as $months) {
$month = explode('/', $months); $month = explode("/", $months);
//once info is collected, add images pages to zip //once info is collected, add images pages to zip
$options = [ $options = [
'add_path' => 'public/assets/images/user/' . $year[5] . '/' . $month[6] . '/', "add_path" =>
'remove_all_path' => true, "public/assets/images/user/" . $year[5] . "/" . $month[6] . "/",
"remove_all_path" => true,
]; ];
$zip->addGlob($months . '/*.*', GLOB_BRACE, $options); $zip->addGlob($months . "/*.*", GLOB_BRACE, $options);
} }
} }
//add directory for settings and save them //add directory for settings and save them
$zip->addEmptyDir('settings'); $zip->addEmptyDir("settings");
$zip->addFile('../config/settings.json', 'settings/settings.json'); $zip->addFile("../config/settings.json", "settings/settings.json");
$zip->addFile('../config/folks.json', 'settings/folks.json'); $zip->addFile("../config/folks.json", "settings/folks.json");
$zip->addFile('../config/tags.json', 'settings/tags.json'); $zip->addFile("../config/tags.json", "settings/tags.json");
//save zip file //save zip file
$zip->close(); $zip->close();
//update settings file with latest back up date //update settings file with latest back up date
$updated = Carbon::now(); $updated = new \Moment\Moment();
Settings::updateGlobalData( Settings::updateGlobalData(
'last_backup', "last_backup",
$updated->format("Y-m-d\TH:i:sP") $updated->format("Y-m-d\TH:i:sP")
); );
$result = ['message' => 'Backup created. THIS IS A SAFE SPACE!']; $result = ["message" => "Backup created. THIS IS A SAFE SPACE!"];
return $result; return $result;
} }
} }

View file

@ -2,15 +2,13 @@
namespace brain\utility; namespace brain\utility;
use Carbon\Carbon;
use function _\find; use function _\find;
class SetUp class SetUp
{ {
public static function status() public static function status()
{ {
if (file_exists('../config/settings.json')) { if (file_exists("../config/settings.json")) {
return true; return true;
} else { } else {
return false; return false;
@ -21,78 +19,79 @@ class SetUp
{ {
//grab template files //grab template files
$newFolks = json_decode( $newFolks = json_decode(
file_get_contents('../config/init/folks-template.json'), file_get_contents("../config/init/folks-template.json"),
true true
); );
$newSettings = json_decode( $newSettings = json_decode(
file_get_contents('../config/init/settings-template.json'), file_get_contents("../config/init/settings-template.json"),
true true
); );
//get form values //get form values
//$body = $request->getParsedBody(); //$body = $request->getParsedBody();
$handle = $body['new_member_handle']; $handle = $body["new_member_handle"];
$email = $body['new_member_email']; $email = $body["new_member_email"];
$pass = $body['new_member_pass']; $pass = $body["new_member_pass"];
$title = $body['new_member_title']; $title = $body["new_member_title"];
$now = Carbon::now(); $now = new \Moment\Moment();
//setup folks config //setup folks config
$hash = password_hash($pass, PASSWORD_DEFAULT); $hash = password_hash($pass, PASSWORD_DEFAULT);
$newFolks[0]['id'] = 0; $newFolks[0]["id"] = 0;
$newFolks[0]['handle'] = $handle; $newFolks[0]["handle"] = $handle;
$newFolks[0]['email'] = $email; $newFolks[0]["email"] = $email;
$newFolks[0]['password'] = $hash; $newFolks[0]["password"] = $hash;
$newFolks[0]['key'] = password_hash($email, PASSWORD_DEFAULT); $newFolks[0]["key"] = password_hash($email, PASSWORD_DEFAULT);
$newFolks[0]['secret'] = StringTools::randomString(12); $newFolks[0]["secret"] = StringTools::randomString(12);
$newFolks[0]['role'] = 'hnic'; $newFolks[0]["role"] = "hnic";
$newFolks[0]['created'] = $now->format("Y-m-d\TH:i:sP"); $newFolks[0]["created"] = $now->format("Y-m-d\TH:i:sP");
$newFolks[0]['updated'] = $now->format("Y-m-d\TH:i:sP"); $newFolks[0]["updated"] = $now->format("Y-m-d\TH:i:sP");
//set up settings config //set up settings config
$newSettings['global']['title'] = $title; $newSettings["global"]["title"] = $title;
//create index file //create index file
//$rightNow = $now->format("Y-m-d\TH:i:sP"); //$rightNow = $now->format("Y-m-d\TH:i:sP");
//var_dump($now->format("Y-m-d\TH:i:sP")); //var_dump($now->format("Y-m-d\TH:i:sP"));
$index = [ $index = [
'id' => 1, "id" => 1,
'uuid' => StringTools::createUUID(), "uuid" => StringTools::createUUID(),
'title' => 'FIRST!', "title" => "FIRST!",
'imageList' => '/assets/images/global/default-bg.jpg', "feature" => "/assets/images/global/default-bg.jpg",
'fileList' => '', "files" => "",
'path' => 'content/pages/start', "path" => "content/pages/start",
'layout' => 'index', "layout" => "index",
'tags' => 'start, welcome', "tags" => "start, welcome",
'author' => $handle, "author" => $handle,
'created' => $now->format("Y-m-d\TH:i:sP"), "created" => $now->format("Y-m-d\TH:i:sP"),
'updated' => $now->format("Y-m-d\TH:i:sP"), "updated" => $now->format("Y-m-d\TH:i:sP"),
'deleted' => 'false', "deleted" => "false",
'slug' => 'first', "slug" => "first",
'menu' => 'false', "menu" => "false",
'featured' => 'false', "featured" => "false",
'published' => 'true', "published" => "true",
'content' => "# F**k Yes \n\nIf you're seeing this, you're up and running. NICE WORK!\n\nFrom here, feel free to start dropping pages to your heart's content.\n\nFor some tips about using Fipamo, check out the ![docs](https://code.playvicio.us/Are0h/Fipamo/wiki/02-Usage)\n\nAll good? Feel free to edit this page to whatever you want!\n\nYOU'RE THE CAPTAIN NOW.", "content" =>
"# F**k Yes \n\nIf you're seeing this, you're up and running. NICE WORK!\n\nFrom here, feel free to start dropping pages to your heart's content.\n\nFor some tips about using Fipamo, check out the ![docs](https://code.playvicio.us/Are0h/Fipamo/wiki/02-Usage)\n\nAll good? Feel free to edit this page to whatever you want!\n\nYOU'RE THE CAPTAIN NOW.",
]; ];
$freshIndex = DocTools::objectToMD($index); $freshIndex = DocTools::objectToMD($index);
//once all files created, write down //once all files created, write down
DocTools::writeSettings('../config/settings.json', $newSettings); DocTools::writeSettings("../config/settings.json", $newSettings);
DocTools::writeSettings('../config/folks.json', $newFolks); DocTools::writeSettings("../config/folks.json", $newFolks);
DocTools::writeSettings('../config/tags.json', []); DocTools::writeSettings("../config/tags.json", []);
DocTools::writePages( DocTools::writePages(
'create', "create",
'start', "start",
'../content/pages/start/index.md', "../content/pages/start/index.md",
$freshIndex $freshIndex
); );
//if there is an older session file, get rid of it //if there is an older session file, get rid of it
if (is_file('../content/.session')) { if (is_file("../content/.session")) {
unlink('../content/.session'); unlink("../content/.session");
} }
$result = ['type' => 'blogInitGood', 'message' => 'Site Created']; $result = ["type" => "blogInitGood", "message" => "Site Created"];
return $result; return $result;
} }
@ -100,39 +99,39 @@ class SetUp
public static function restore($request) public static function restore($request)
{ {
$result = [ $result = [
'type' => 'requestLame', "type" => "requestLame",
'message' => 'Still working on it.', "message" => "Still working on it.",
]; ];
$body = $request->getParsedBody(); $body = $request->getParsedBody();
$backup = $request->getUploadedFiles(); $backup = $request->getUploadedFiles();
$file = $backup['backup-upload']; $file = $backup["backup-upload"];
//NOTE: If this fails check 'post_max_size' in php.ini //NOTE: If this fails check 'post_max_size' in php.ini
$size = $file->getSize(); $size = $file->getSize();
$name = $file->getClientFileName(); $name = $file->getClientFileName();
//park it so it can be read //park it so it can be read
$file->moveTo('../content' . '/' . $name); $file->moveTo("../content" . "/" . $name);
//open it and get files to verify user //open it and get files to verify user
$zip = new \ZipArchive(); $zip = new \ZipArchive();
if ($zip->open('../content' . '/' . $name) === true) { if ($zip->open("../content" . "/" . $name) === true) {
$folks = json_decode($zip->getFromName('settings/folks.json'), true); $folks = json_decode($zip->getFromName("settings/folks.json"), true);
$found = find($folks, ['handle' => $body['restore_member_handle']]); $found = find($folks, ["handle" => $body["restore_member_handle"]]);
//if member is found in back up, check pass //if member is found in back up, check pass
if ($found) { if ($found) {
if (password_verify($body['restore_member_pass'], $found['password'])) { if (password_verify($body["restore_member_pass"], $found["password"])) {
//backup verified, restore site //backup verified, restore site
//set new secret key for older folks configs //set new secret key for older folks configs
$newFolks = []; $newFolks = [];
if (!isset($found['secret'])) { if (!isset($found["secret"])) {
$found['secret'] = StringTools::randomString(12); $found["secret"] = StringTools::randomString(12);
} }
array_push($newFolks, $found); array_push($newFolks, $found);
//dump files in folder //dump files in folder
$zip->extractTo('../content'); $zip->extractTo("../content");
//move to appropriate spots //move to appropriate spots
/* /*
@ -144,49 +143,49 @@ class SetUp
//load up old config file //load up old config file
$newConfig = json_decode( $newConfig = json_decode(
file_get_contents('../content/settings/settings.json'), file_get_contents("../content/settings/settings.json"),
true true
); );
//check for key, add if not there //check for key, add if not there
if (!isset($newConfig['global']['externalAPI'])) { if (!isset($newConfig["global"]["externalAPI"])) {
$newConfig['global']['externalAPI'] = 'false'; $newConfig["global"]["externalAPI"] = "false";
} }
//write new config file //write new config file
DocTools::writeSettings('../config/settings.json', $newConfig); DocTools::writeSettings("../config/settings.json", $newConfig);
//rename("../content/settings/folks.json", "../config/folks.json"); //rename("../content/settings/folks.json", "../config/folks.json");
DocTools::writeSettings('../config/folks.json', $newFolks); DocTools::writeSettings("../config/folks.json", $newFolks);
rename('../content/settings/tags.json', '../config/tags.json'); rename("../content/settings/tags.json", "../config/tags.json");
//images path for blog and user //images path for blog and user
$blogImagePath = '../public/assets/images/blog'; $blogImagePath = "../public/assets/images/blog";
$userImagePath = '../public/assets/images/user'; $userImagePath = "../public/assets/images/user";
//check to see if image dirs are empty, if not chill //check to see if image dirs are empty, if not chill
if ($globs = glob($blogImagePath . '/*')) { if ($globs = glob($blogImagePath . "/*")) {
//directory not empty, relax //directory not empty, relax
} else { } else {
rename('../content/public/assets/images/blog', $blogImagePath); rename("../content/public/assets/images/blog", $blogImagePath);
} }
if ($globs = glob($userImagePath . '/*')) { if ($globs = glob($userImagePath . "/*")) {
//directory not empty, relax //directory not empty, relax
} else { } else {
rename('../content/public/assets/images/user', $userImagePath); rename("../content/public/assets/images/user", $userImagePath);
} }
rename('../content/content/pages/', '../content/pages'); rename("../content/content/pages/", "../content/pages");
//legacy check for old file structure //legacy check for old file structure
if (is_file('../content/pages/index.md')) { if (is_file("../content/pages/index.md")) {
if (!is_dir('../content/pages/start')) { if (!is_dir("../content/pages/start")) {
//Directory does not exist, so lets create it. //Directory does not exist, so lets create it.
mkdir('../content/pages/start', 0755, true); mkdir("../content/pages/start", 0755, true);
//move start page to appropriate spot //move start page to appropriate spot
rename( rename(
'../content/pages/index.md', "../content/pages/index.md",
'../content/pages/start/index.md' "../content/pages/start/index.md"
); );
} }
} else { } else {
@ -195,34 +194,34 @@ class SetUp
//clean up //clean up
DocTools::deleteFolder('../content/settings'); DocTools::deleteFolder("../content/settings");
DocTools::deleteFolder('../content/public'); DocTools::deleteFolder("../content/public");
DocTools::deleteFolder('../content/content'); DocTools::deleteFolder("../content/content");
$result = [ $result = [
'type' => 'requestGood', "type" => "requestGood",
'message' => 'Site Restored! Redirecting', "message" => "Site Restored! Redirecting",
]; ];
} else { } else {
$result = [ $result = [
'type' => 'requestLame', "type" => "requestLame",
'message' => 'Check that password, champ.', "message" => "Check that password, champ.",
]; ];
} }
} else { } else {
$result = [ $result = [
'type' => 'requestLame', "type" => "requestLame",
'message' => 'No member found by that name, hoss', "message" => "No member found by that name, hoss",
]; ];
} }
$zip->close(); $zip->close();
$zipPath = '../content/' . $name; $zipPath = "../content/" . $name;
//trash zip when done //trash zip when done
unlink($zipPath); unlink($zipPath);
} else { } else {
$result = [ $result = [
'type' => 'requestLame', "type" => "requestLame",
'message' => 'Could not open backup. RATS!', "message" => "Could not open backup. RATS!",
]; ];
} }
return $result; return $result;

View file

@ -2,116 +2,104 @@
namespace brain\utility; namespace brain\utility;
use Mni\FrontYAML\Parser;
use brain\data\Book; use brain\data\Book;
use brain\data\Settings; use brain\data\Settings;
use Mni\FrontYAML\Parser;
use function _\filter;
use function _\find; use function _\find;
use function _\filter;
class Sorting class Sorting
{ {
private static $p_tags = []; private static $_tags = [];
private static $p_archive = []; private static $_archive = [];
public function __construct() public function __construct()
{ {
} }
public static function tags() public static function tags()
{ {
$pages = (new Book('../content/pages'))->getContents(); $pages = (new Book("../content/pages"))->getContents();
foreach ($pages as $page) { foreach ($pages as $page) {
$temp = []; $temp = [];
if (isset($page['tags'])) { $temp = explode(",", $page["tags"]);
$temp = explode(',', $page['tags']);
foreach ($temp as $tag) { foreach ($temp as $tag) {
$label = trim($tag); $label = trim($tag);
if (!find(self::$p_tags, ['tag_name' => $label])) { if (!find(self::$_tags, ["tag_name" => $label])) {
array_push(self::$p_tags, [ array_push(self::$_tags, [
'tag_name' => $label, "tag_name" => $label,
'slug' => StringTools::safeString($label), "slug" => StringTools::safeString($label),
'pages' => self::tagPages($label, $pages), "pages" => self::tagPages($label, $pages),
]); ]);
} }
} }
} }
}
return self::$p_tags; return self::$_tags;
} }
private static function tagPages($tag, $pages) private static function tagPages($tag, $pages)
{ {
$tagged = []; $tagged = [];
foreach ($pages as $page) { foreach ($pages as $page) {
if (isset($page['tags'])) { if (strpos($page["tags"], $tag) !== false) {
if (strpos($page['tags'], $tag) !== false) {
array_push($tagged, [ array_push($tagged, [
'title' => $page['title'], "title" => $page["title"],
'slug' => $page['slug'], "slug" => $page["slug"],
'path' => $page['path'], "path" => $page["path"],
'feature' => $page['feature'], "feature" => $page["feature"],
]); ]);
} }
} }
}
return $tagged; return $tagged;
} }
public static function archive() public static function archive()
{ {
$pages = (new Book('../content/pages'))->getContents(); $pages = (new Book("../content/pages"))->getContents();
$years = []; $years = [];
$archive = []; $archive = [];
foreach ($pages as $page) { foreach ($pages as $page) {
//$year = date("Y", date($page["rawCreated"])); //$year = date("Y", date($page["rawCreated"]));
$date = explode('/', $page['path']); $date = explode("/", $page["path"]);
//echo $page["title"] . " : " . $year . "\n"; //echo $page["title"] . " : " . $year . "\n";
if (!find($years, ['year' => trim($date[0])])) { if (!find($years, ["year" => trim($date[0])])) {
$findPages = filter($pages, ['createdYear' => trim($date[0])]); $findPages = filter($pages, ["createdYear" => trim($date[0])]);
//var_dump($findPages); //var_dump($findPages);
array_push( array_push($years, [
$years, "year" => trim($date[0]),
[ "count" => count($findPages),
'year' => trim($date[0]), ]);
'count' => count($findPages),
]
);
} }
} }
foreach ($years as $year) { foreach ($years as $year) {
$sorted = []; $sorted = [];
$filtered = filter($pages, ['createdYear' => $year['year']]); $filtered = filter($pages, ["createdYear" => $year["year"]]);
foreach ($filtered as $obj) { foreach ($filtered as $obj) {
$month = date('m', date($obj['rawCreated'])); $month = date("m", date($obj["rawCreated"]));
if (!find($sorted, ['month' => $month])) { if (!find($sorted, ["month" => $month])) {
$perMonth = filter( $perMonth = filter($pages, [
$pages, "path" => $year["year"] . "/" . $month,
[ "deleted" => false,
'path' => $year['year'] . '/' . $month, "published" => true,
'deleted' => false, "layout" => "page",
'published' => true, ]);
'layout' => 'page',
]
);
array_push($sorted, [ array_push($sorted, [
'month' => $month, "month" => $month,
'full_month' => date('F', date($obj['rawCreated'])), "full_month" => date("F", date($obj["rawCreated"])),
'count' => count($perMonth), "count" => count($perMonth),
'pages' => $perMonth, "pages" => $perMonth,
]); ]);
} }
} }
array_push(self::$p_archive, [ array_push(self::$_archive, [
'year' => $year['year'], "year" => $year["year"],
'year_data' => $sorted, "year_data" => $sorted,
]); ]);
} }
return self::$_archive;
return self::$p_archive;
} }
public static function page($page) public static function page($page)
@ -121,40 +109,40 @@ class Sorting
$pageOption = []; $pageOption = [];
$pageInfo = [ $pageInfo = [
'keywords' => isset($settings['global']['keywords']) "keywords" => isset($settings["global"]["keywords"])
? $settings['global']['keywords'] ? $settings["global"]["keywords"]
: 'fipamo, blog, jamstack, php, markdown, js', : "fipamo, blog, jamstack, php, markdown, js",
'description' => $settings['global']['descriptions'], "description" => $settings["global"]["descriptions"],
'image' => $settings['global']['base_url'] . $settings['global']['background'], "image" =>
'baseURL' => $settings['global']['base_url'], $settings["global"]["base_url"] . $settings["global"]["background"],
"baseURL" => $settings["global"]["base_url"],
]; ];
$taglist = explode(",", $page["tags"]);
$tags = []; $tags = [];
if (isset($page['tags'])) {
$taglist = explode(',', $page['tags']);
foreach ($taglist as $tag) { foreach ($taglist as $tag) {
$label = trim($tag); $label = trim($tag);
array_push($tags, [ array_push($tags, [
'label' => $label . ' ', "label" => $label . " ",
'slug' => StringTools::safeString($label), "slug" => StringTools::safeString($label),
]); ]);
} }
}
$meta = [ $meta = [
'who' => $page['author'], "who" => $page["author"],
'when' => $page['created'], "when" => $page["created"],
'tags' => $tags, "tags" => $tags,
]; ];
//render markdown content and clean it //render markdown content and clean it
$parser = new Parser(); $parser = new Parser();
$rendered = $parser->parse($page['content']); $rendered = $parser->parse($page["content"]);
$sanitizer = \HtmlSanitizer\Sanitizer::create([ $sanitizer = \HtmlSanitizer\Sanitizer::create([
'extensions' => ['basic', 'image', 'list', 'code'], "extensions" => ["basic", "image", "list", "code"],
'tags' => [ "tags" => [
'img' => [ "img" => [
'allowed_attributes' => ['src', 'alt', 'title', 'class'], "allowed_attributes" => ["src", "alt", "title", "class"],
'allowed_hosts' => null, "allowed_hosts" => null,
], ],
], ],
]); ]);
@ -164,41 +152,32 @@ class Sorting
//just clean renderd string for now, Sanitize doesn't like relative img urls //just clean renderd string for now, Sanitize doesn't like relative img urls
//so another option is needed //so another option is needed
$cleaned = strip_tags($rendered->getContent(), [ $cleaned = strip_tags($rendered->getContent(), [
'a', "a",
'br', "br",
'p', "p",
'strong', "strong",
'br', "br",
'img', "img",
'iframe', "iframe",
'ul', "ul",
'li', "li",
'i', "i",
'em', "em",
'h1', "h1",
'h2', "h2",
'h3', "h3",
'pre', "pre",
'code', "code",
]); ]);
//$cleaned = preg_replace('/(?:\r\n|[\r\n]){2,}/', "\n\n", $cleaned);
//$cleaned = html_entity_decode($cleaned, ENT_QUOTES, "UTF-8");
// if page feature isn't empty, find image from list and set it as background image //if page feature isn't empty, replace page info meta image
// if it is empty, just use global background if ($page["feature"] != "" || $page["feature"] != null) {
if ($page['feature'] != '' || $page['feature'] != null) { $pageInfo["image"] = $pageInfo["baseURL"] . $page["feature"];
$media = explode(',', $page['feature']);
$set = false;
foreach ($media as $file) {
$item = trim($file);
$ext = pathinfo($item, PATHINFO_EXTENSION);
if ($ext != 'mp4' && !$set) {
$pageInfo['image'] = $pageInfo['baseURL'] . $item;
$set = true;
}
}
} }
if ($page['layout'] == 'index') { if ($page["layout"] == "index") {
//$template = $this->theme . "/index.twig"; //$template = $this->theme . "/index.twig";
//$location = "../public/index.html"; //$location = "../public/index.html";
//$dir = null; //$dir = null;
@ -208,26 +187,27 @@ class Sorting
$limit = 4; $limit = 4;
$pages = (new Book())->getContents(); $pages = (new Book())->getContents();
foreach ($pages as $item) { foreach ($pages as $item) {
if (!$item['deleted'] && if (
$item['published'] && !$item["deleted"] &&
$item['menu'] != 'true' $item["published"] &&
$item["menu"] != "true"
) { ) {
if (count($recent) < $limit) { if (count($recent) < $limit) {
array_push($recent, [ array_push($recent, [
'path' => $item['path'], "path" => $item["path"],
'slug' => $item['slug'], "slug" => $item["slug"],
'title' => $item['title'], "title" => $item["title"],
'feature' => $item['feature'], "feature" => $item["feature"],
]); ]);
} }
if ($item['featured'] == true) { if ($item["featured"] == true) {
if (count($featured) < $limit) { if (count($featured) < $limit) {
array_push($featured, [ array_push($featured, [
'path' => $item['path'], "path" => $item["path"],
'slug' => $item['slug'], "slug" => $item["slug"],
'title' => $item['title'], "title" => $item["title"],
'feature' => $item['feature'], "feature" => $item["feature"],
]); ]);
} }
} }
@ -235,35 +215,34 @@ class Sorting
} }
$pageOptions = [ $pageOptions = [
'title' => $page['title'], "title" => $page["title"],
'background' => $page['feature'], "background" => $page["feature"],
'content' => $page['html'], // $cleaned, "content" => $page["html"], //$cleaned,
'meta' => $meta, "meta" => $meta,
'recent' => $recent, "recent" => $recent,
'featured' => $featured, "featured" => $featured,
'info' => $pageInfo, "info" => $pageInfo,
'menu' => $settings['menu'], "menu" => $settings["menu"],
'dynamicRender' => $settings['global']['dynamicRender'], "dynamicRender" => $settings["global"]["dynamicRender"],
'media' => $page['media'], "media" => $page["media"],
'files' => $page['docs'], "files" => $page["docs"],
]; ];
} else { } else {
//$template = $this->theme . "/page.twig"; //$template = $this->theme . "/page.twig";
//$location = "../public/" . $page["path"] . "/" . $page["slug"] . ".html"; //$location = "../public/" . $page["path"] . "/" . $page["slug"] . ".html";
//$dir = "../public/" . $page["path"]; //$dir = "../public/" . $page["path"];
$pageOptions = [ $pageOptions = [
'title' => $page['title'], "title" => $page["title"],
'background' => $page['feature'], "background" => $page["feature"],
'content' => $page['html'], // $cleaned, "content" => $page["html"], //$cleaned,
'meta' => $meta, "meta" => $meta,
'info' => $pageInfo, "info" => $pageInfo,
'menu' => $settings['menu'], "menu" => $settings["menu"],
'dynamicRender' => $settings['global']['dynamicRender'], "dynamicRender" => $settings["global"]["dynamicRender"],
'media' => $page['media'], "media" => $page["media"],
'files' => $page['docs'], "files" => $page["docs"],
]; ];
} }
return $pageOptions; return $pageOptions;
} }
} }

View file

@ -10,12 +10,12 @@ class StringTools
{ {
public static function createUUID() public static function createUUID()
{ {
if (function_exists('com_create_guid') === true) { if (function_exists("com_create_guid") === true) {
return trim(com_create_guid(), '{}'); return trim(com_create_guid(), "{}");
} }
return sprintf( return sprintf(
'%04X%04X-%04X-%04X-%04X-%04X%04X%04X', "%04X%04X-%04X-%04X-%04X-%04X%04X%04X",
mt_rand(0, 65535), mt_rand(0, 65535),
mt_rand(0, 65535), mt_rand(0, 65535),
mt_rand(0, 65535), mt_rand(0, 65535),
@ -32,11 +32,11 @@ class StringTools
$parser = new Parser(); $parser = new Parser();
$rendered = $parser->parse($entry); $rendered = $parser->parse($entry);
$sanitizer = HtmlSanitizer\Sanitizer::create([ $sanitizer = HtmlSanitizer\Sanitizer::create([
'extensions' => ['basic', 'image', 'list', 'code'], "extensions" => ["basic", "image", "list", "code"],
'tags' => [ "tags" => [
'img' => [ "img" => [
'allowed_attributes' => ['src', 'alt', 'title', 'class'], "allowed_attributes" => ["src", "alt", "title", "class"],
'allowed_hosts' => null, "allowed_hosts" => null,
], ],
], ],
]); ]);
@ -44,21 +44,21 @@ class StringTools
$preclean = $sanitizer->sanitize($rendered->getContent()); $preclean = $sanitizer->sanitize($rendered->getContent());
$cleaned = strip_tags($rendered->getContent(), [ $cleaned = strip_tags($rendered->getContent(), [
'a', "a",
'br', "br",
'p', "p",
'strong', "strong",
'br', "br",
'img', "img",
'iframe', "iframe",
'ul', "ul",
'li', "li",
'i', "i",
'h1', "h1",
'h2', "h2",
'h3', "h3",
'pre', "pre",
'code', "code",
]); ]);
return $cleaned; return $cleaned;
@ -69,31 +69,32 @@ class StringTools
return strtolower( return strtolower(
trim( trim(
preg_replace( preg_replace(
'~[^0-9a-z]+~i', "~[^0-9a-z]+~i",
'_', "_",
html_entity_decode( html_entity_decode(
preg_replace( preg_replace(
'~&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i', "~&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i",
'$1', '$1',
htmlentities($string, ENT_QUOTES, 'UTF-8') htmlentities($string, ENT_QUOTES, "UTF-8")
), ),
ENT_QUOTES, ENT_QUOTES,
'UTF-8' "UTF-8"
) )
), ),
'-' "-"
) )
); );
} }
public static function randomString(int $length) public static function randomString(int $length)
{ {
$alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; $alphanum =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
$special = '*&!@%^#$'; $special = '*&!@%^#$';
$alphabet = $alphanum . $special; $alphabet = $alphanum . $special;
$random = openssl_random_pseudo_bytes($length); $random = openssl_random_pseudo_bytes($length);
$alphabet_length = strlen($alphabet); $alphabet_length = strlen($alphabet);
$string = ''; $string = "";
for ($i = 0; $i < $length; ++$i) { for ($i = 0; $i < $length; ++$i) {
$string .= $alphabet[ord($random[$i]) % $alphabet_length]; $string .= $alphabet[ord($random[$i]) % $alphabet_length];
} }
@ -101,7 +102,7 @@ class StringTools
//secret needs to be a valid token //secret needs to be a valid token
if ($length == 12) { if ($length == 12) {
try { try {
$secret = Token::create(12, $string, time() + 3600, 'localhost'); $secret = Token::create(12, $string, time() + 3600, "localhost");
return $string; return $string;
} catch (BuildException $e) { } catch (BuildException $e) {
//bad secret, so try agiain //bad secret, so try agiain
@ -119,7 +120,7 @@ class StringTools
private static function checkSpecial($string) private static function checkSpecial($string)
{ {
$specials = ['*', '&', '!', '@', '%', '^', '#', '$']; $specials = ["*", "&", "!", "@", "%", "^", "#", "$"];
$valid = false; $valid = false;
foreach ($specials as $item) { foreach ($specials as $item) {
if (strpos($string, $item)) { if (strpos($string, $item)) {

View file

@ -2,8 +2,6 @@
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="theme-color" content="#FFFFFF"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title> <title>
{% block title %} {% block title %}
{{ title }} {{ title }}
@ -12,38 +10,56 @@
{% block stylesheets %}{% endblock %} {% block stylesheets %}{% endblock %}
</head> </head>
<body> <body>
<div id="notifications" class="notifications">
<div id="notifyMessage" class="notifyMessage">
<div id="notify-good" class="notify-icon">
<svg viewbox="0 0 20 20" class="icons"><use xlink:href="/assets/images/global/sprite.svg#entypo-emoji-flirt"/></svg>
</div>
<div id="notify-lame" class="notify-icon">
<svg viewbox="0 0 20 20" class="icons"><use xlink:href="/assets/images/global/sprite.svg#entypo-emoji-sad"/></svg>
</div>
<div id="notify-working" class="notify-icon">
<svg id="notify-working-icon" viewbox="0 0 20 20" class="icons"><use xlink:href="/assets/images/global/sprite.svg#entypo-cog"/></svg>
</div>
<div id="notify-text">
<div id="notify-progress"></div>
<p id="message-text">MESSAGE TEXT</p>
</div>
</div>
</div>
<div id="main-content" class="main-container">
<section id="dash-index-content">
{% if status %} {% if status %}
<header> <header id="header">
<div id="wrapper">
{% apply spaceless %} {% apply spaceless %}
<nav role="top-nav"> <div id="left">
<div role="nav-left">
<a href="/dashboard"><img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/></a> <a href="/dashboard"><img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/></a>
</div> </div>
<div role="title"> <div id="right">
<h1>{{ title }}</h1>
</div>
<div role="nav-right">
{% if status %} {% if status %}
{% apply spaceless %} {% apply spaceless %}
{{ include("dash/partials/navigation.twig") }} {{ include("dash/partials/navigation.twig") }}
{% endapply %} {% endapply %}
{% endif %} {% endif %}
</div> </div>
</nav>
<div role="notify">
{% apply spaceless %}
{{ include("dash/partials/notifications.twig") }}
{% endapply %} {% endapply %}
</div> </div>
{% endapply %}
{% endif %}
</header> </header>
<main> {% endif %}
{% apply spaceless %} {% apply spaceless %}
{% block mainContent %}{% endblock %} {% block mainContent %}{% endblock %}
{% endapply %} {% endapply %}
</main>
</section>
</div>
<footer></footer> <footer></footer>
<script type="module" src="/assets/scripts/dash.js"></script> {% block javascripts %}{% endblock %}
</body> </body>
</html> </html>

View file

@ -5,36 +5,45 @@
{% endblock %} {% endblock %}
{% block stylesheets %} {% block stylesheets %}
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css?=vdthg"> <link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=dfvgy">
{% endblock %} {% endblock %}
{% block mainContent %} {% block mainContent %}
<section role="book-index-header"> <div id="post-index">
<div role="book-index-header-left"> <div id="post-index-wrapper">
{{ filter }} <div id="post-index-header">
Pages <div id="post-index-header-left">
{{ filter }} Pages
</div> </div>
<div role="book-index-header-right"> <div id="post-index-header-right">
<a href="/dashboard/pages/all" title="view all pages"> <a href="/dashboard/pages/all" title="view all pages">
<button> <button>
<i class="ti ti-clipboard-list"></i> <svg >
<use xlink:href="/assets/images/global/sprite.svg#entypo-archive"/>
</svg>
{{ stats['all'] }} {{ stats['all'] }}
</button> </button>
</a> </a>
<a href="/dashboard/pages/published" title="view publised pages"> <a href="/dashboard/pages/published" title="view publised pages">
<button> <button>
<i class="ti ti-clipboard-check"></i> <svg >
<use xlink:href="/assets/images/global/sprite.svg#entypo-globe"/>
</svg>
{{ stats['published'] }} {{ stats['published'] }}
</button> </button>
</a> </a>
<a href="/dashboard/pages/deleted" title="view deleted pages"> <a href="/dashboard/pages/deleted" title="view deleted pages">
<button> <button>
<i class="ti ti-clipboard-off"></i> <svg >
<use xlink:href="/assets/images/global/sprite.svg#entypo-circle-with-cross"/>
</svg>
{{ stats['deleted'] }} {{ stats['deleted'] }}
</button> </button>
</a> </a>
</section> </div>
<section role="book-index-pages">
</div>
<div id="posts-list">
{% for page in pages %} {% for page in pages %}
{% if page.media[0].type == 'mp4' %} {% if page.media[0].type == 'mp4' %}
<a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="page-link"> <a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="page-link">
@ -44,16 +53,23 @@
Sorry, your browser doesn't support embedded videos. Sorry, your browser doesn't support embedded videos.
</video> </video>
<label>
{{ page.title }}
</label>
<div id="meta"> <div id="meta">
{{ include("dash/partials/recent-meta.twig") }} {{ include("dash/partials/recent-options.twig") }}
</div> </div>
</div> </div>
</a> </a>
{% else %} {% else %}
<a class="page-link" href="/dashboard/page/edit/{{ page.uuid }}"> <a class="page-link" href="/dashboard/page/edit/{{ page.uuid }}">
<div class="page-bg" style="background: url({{ page.media[0].file }}) no-repeat center center / cover #fc6399"> <div class="page-bg" style="background: url({{ page.media[0].file }}) no-repeat center center / cover">
<label>
{{ page.title }}
</label>
<div id="meta"> <div id="meta">
{{ include("dash/partials/recent-meta.twig") }} {{ include("dash/partials/recent-options.twig") }}
</div> </div>
</div> </div>
</a> </a>
@ -61,9 +77,9 @@
{% endfor %} {% endfor %}
{% if numOfPages > 1 %} {% if numOfPages > 1 %}
<div role="paginate"> <div class="paginate">
<a class="page-btns" href="/dashboard/pages/{{ paginate['sort'] }}/{{ paginate['prevPage'] }}"> <a class="page-btns" href="/dashboard/pages/{{ paginate['sort'] }}/{{ paginate['prevPage'] }}">
<i class="ti ti-square-arrow-left"></i> <svg viewbox="0 0 20 20" class="icons"><use xlink:href="/assets/images/global/sprite.svg#entypo-chevron-left"/></svg>
</a> </a>
<span class="count"> <span class="count">
{{ currentPage }} {{ currentPage }}
@ -71,10 +87,16 @@
{{ numOfPages }} {{ numOfPages }}
</span> </span>
<a class="page-btns" href="/dashboard/pages/{{ paginate['sort'] }}/{{ paginate['nextPage'] }}"> <a class="page-btns" href="/dashboard/pages/{{ paginate['sort'] }}/{{ paginate['nextPage'] }}">
<i class="ti ti-square-arrow-right"></i> <svg viewbox="0 0 20 20" class="icons"><use xlink:href="/assets/images/global/sprite.svg#entypo-chevron-right"/></svg>
</a> </a>
</div> </div>
{% endif %} {% endif %}
</section> </div>
</div>
</div>
{% endblock %}
{% block javascripts %}
<script src="/assets/scripts/Start.js" type="text/javascript"></script>
{% endblock %} {% endblock %}

View file

@ -1,16 +0,0 @@
<div>
<a href="/dashboard">
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
</a>
</div>
<form id="init-restore" method="POST">
<input type="text" name="restore_member_handle" id="restore_member_handle" placeholder="handle"/><input type="password" name="restore_member_pass" id="restore_member_pass" placeholder="password"/>
<div>
<label>Grab your backup zip</label>
<input id="backup-upload" type="file" name="backup-upload" placeholder="Backup Zip"/>
</div>
<br/><br/>
<button id="blog-restore" data-action='blog-restore' type='submit'>RESTORE</button>
<br/><br/>
<button class="init-option" id="init-switch-fresh">OR INSTALL FROM SCRATCH</button>
</form>

View file

@ -1,15 +0,0 @@
<div>
<a href="/dashboard">
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
</a>
</div>
<form id="init-form" method="POST" onsubmit="return false;">
<input type="text" name="new_member_handle" id="new_member_handle" placeholder="handle"/>
<input type="text" name="new_member_email" id="new_member_email" placeholder="email"/>
<input type="text" name="new_member_pass" id="new_member_pass" placeholder="password"/>
<input type="text" name="new_member_pass2" id="new_member_pass2" placeholder="password confirm"/>
<input type="text" name="new_member_title" id="new_member_title" placeholder="title"/>
<button id="init-blog" data-action='blog-init' type='submit'>SET UP YOUR SITE</button>
<br/><br/>
<button class="init-option" id="init-switch-restore">RESTORE FROM BACKUP</button>
</form>

View file

@ -1,13 +1,13 @@
<section role="login"> <div id="dash-login">
<div> <div id="dash-form" class="dash-form">
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/> <img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
</div> <form id="login" class='login' name="login" method="POST">
<form id="login" class='login' name="login" method="POST" onsubmit="return false;"> <input type="text" name="handle" class="form-control" placeholder="Handle" required ">
<input type="text" name="handle" class="form-control" placeholder="Handle" required/> <input type="password" name="password" class="form-control" placeholder="Password" required">
<input type="password" name="password" class="form-control" placeholder="Password" required/> <button id="login-btn" class='login-btn' type='submit'>
<button id="login-btn" class='login-btn'>
ID, PLEASE ID, PLEASE
</button> </button><br /><br />
<a href="/dashboard/reset-password">?</a> <a href="/dashboard/reset-password"> Forgot Password?</a>
</form> </form>
</section> </div>
</div>

View file

@ -1,21 +0,0 @@
<div>
<a href="/dashboard">
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
</a>
</div>
<form id="reset" class='login' name="reset" action="/dashboard/login" method="POST">
<input type="password" id="new_password" name="new_password" class="form-control" placeholder="New Password" required/>
<input type="password" id="new_password2" name="new_password2" class="form-control" placeholder="New Password Confirm" required">
<input type="password" id="secret" name="secret" class="form-control" placeholder="Account Secret" required/>
<button id="reset-btn" class='login-btn' type='submit'>
RESET PASSWORD
</button><br/>
<p>
Use this to get your secret to verify it's you. If your email is set up, the secret will be sent there. If not, the form will be updated automatically(but please set up your email, once you reset your password).
</p>
<input type="text" id="email" name="email" class="form-control" placeholder="email to verify" required/>
<button id="get-secret-btn" class='login-btn' type='submit'>
VERIFY EMAIL
</button><br/><br/>
</form>

View file

@ -5,20 +5,44 @@
{% endblock %} {% endblock %}
{% block stylesheets %} {% block stylesheets %}
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css"> <link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=adfa">
{% endblock %} {% endblock %}
{% block mainContent %} {% block mainContent %}
<article role="site-restore"> <div id="dash-index">
<section role="restore-fresh"> <div id="dash-index-wrapper">
{% apply spaceless %} <div id="dash-init" class="dash-init">
{{ include("dash/forms/init-fresh.twig") }} <form id="init-form" method="POST">
{% endapply %} <img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
</section> <input type="text" name="new_member_handle" id="new_member_handle" placeholder="handle"/>
<section role="restore-backup"> <input type="text" name="new_member_email" id="new_member_email" placeholder="email"/>
{% apply spaceless %} <input type="text" name="new_member_pass" id="new_member_pass" placeholder="password"/>
{{ include("dash/forms/init-backup.twig") }} <input type="text" name="new_member_pass2" id="new_member_pass2" placeholder="password confirm"/>
{% endapply %} <input type="text" name="new_member_title" id="new_member_title" placeholder="title"/>
</section> <button id="init-blog" data-action='blog-init' type='submit'>SET UP YOUR SITE</button>
</article> <br /><br />
<button class="init-option" id="init-switch-restore">RESTORE FROM BACKUP</button>
</form>
</div>
<div id="dash-restore" class="dash-restore">
<form id="init-restore" method="POST">
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
<input type="text" name="restore_member_handle" id="restore_member_handle" placeholder="handle"/><input type="password" name="restore_member_pass" id="restore_member_pass" placeholder="password"/>
<div>
<label>Grab your backup zip</label>
<input id="backup-upload" type="file" name="backup-upload" placeholder="Backup Zip"/>
</div>
<br /><br />
<button id="blog-restore" data-action='blog-restore' type='submit'>RESTORE</button>
<br /><br />
<button class="init-option" id="init-switch-fresh">OR INSTALL FROM SCRATCH</button>
</form>
</div>
</div>
</div>
{% endblock %}
{% block javascripts %}
<script src="/assets/scripts/Start.js?=sdfsdf" type="text/javascript"></script>
{% endblock %} {% endblock %}

View file

@ -5,26 +5,39 @@
{% endblock %} {% endblock %}
{% block stylesheets %} {% block stylesheets %}
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css?=sdsdsds"> <link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=sdsdsds">
{% endblock %} {% endblock %}
{% block mainContent %} {% block mainContent %}
<article role="navigation"> <div id="nav-index">
<section id="nav-items"> <div id="nav-index-wrapper">
<div id="nav-pages">
{% for item in menu %} {% for item in menu %}
<div id="{{item.id}}" class="nav-item" data-slug="{{item.slug}}" data-uuid="{{item.uuid}}" data-path="{{item.path}}"> <div id="{{item.id}}" class="nav-item" data-slug="{{item.slug}}" data-uuid="{{item.uuid}}" data-path="{{item.path}}">
<i class="ti ti-arrows-move-vertical"></i> <svg id="item-arrows">
<use xlink:href="/assets/images/global/sprite.svg#entypo-select-arrows"/>
</svg>
<label>{{item.title}}</label> <label>{{item.title}}</label>
<div id="nav-btns"> <div id="nav-btns">
<button id="edit-item" class="nav-btn" data-id="{{item.uuid}}" title="edit page"> <button id="edit-item" class="nav-btn" data-id="{{item.uuid}}" title="edit page">
<i class="ti ti-edit"></i> <svg>
<use xlink:href="/assets/images/global/sprite.svg#entypo-edit"/>
</svg>
</button> </button>
<button id="remove-item" class="nav-btn" data-uuid="{{item.uuid}}" data-id="{{item.id}}" title="delete from menu"> <button id="remove-item" class="nav-btn" data-uuid="{{item.uuid}}" data-id="{{item.id}}" title="delete from menu">
<i class="ti ti-x"></i> <svg>
<use xlink:href="/assets/images/global/sprite.svg#entypo-cross"/>
</svg>
</button> </button>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
</section> </div>
</article> </div>
</div>
{% endblock %}
{% block javascripts %}
<script src="/assets/scripts/Start.js?=cvfggt" type="text/javascript"></script>
{% endblock %} {% endblock %}

View file

@ -9,6 +9,7 @@
{% set slug = page['slug'] %} {% set slug = page['slug'] %}
{% set layout = page['layout'] %} {% set layout = page['layout'] %}
{% set feature = page['feature'] %} {% set feature = page['feature'] %}
{% set _title = page['title'] %}
{% set tags = page['tags'] %} {% set tags = page['tags'] %}
{% set content = page['content'] %} {% set content = page['content'] %}
{% set date = page['created'] %} {% set date = page['created'] %}
@ -35,107 +36,70 @@
{% endblock %} {% endblock %}
{% block stylesheets %} {% block stylesheets %}
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css?=vdthg"> <link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=vbhj">
{% endblock %} {% endblock %}
{% block mainContent %} {% block mainContent %}
<section data-index="{{ id }}" data-uuid="{{ uuid }}" data-slug="{{ slug }}" data-layout="{{ layout }}" role="file-manager"> <div id="post-edit-index" data-index="{{ id }}" data-uuid="{{ uuid }}" data-slug="{{ slug }}" data-layout="{{ layout }}">
<div id="post-edit-index-wrapper">
<div id="post-feature">
{% if page['feature'] == null %} {% if page['feature'] == null %}
<div role="file-drop"> <div id="page-file-manager">
<div id="page-file-wrapper">
<div id="page-file-drop">
<label for="page-files-upload">DRAG AND DROP FILES OR CLICK TO SELECT</label> <label for="page-files-upload">DRAG AND DROP FILES OR CLICK TO SELECT</label>
</div> </div>
<label role="list-title">IMAGES AND VIDEO</label> IMAGES AND VIDEO
<div role="page-images-list"></div> <div id="page-images-list"></div>
<label role="list-title">FILES</label> FILES
<div role="page-files-list"></div> <div id="page-files-list"></div>
</div>
</div>
{% else %} {% else %}
<div role="file-drop"> <div id="page-file-manager">
<div id="page-file-wrapper">
<div id="page-file-drop">
<label for="page-files-upload">DRAG AND DROP FILES OR CLICK TO SELECT</label> <label for="page-files-upload">DRAG AND DROP FILES OR CLICK TO SELECT</label>
</div> </div>
<label role="list-title">IMAGES AND VIDEO</label> IMAGES AND VIDEO
<div role="page-images-list"> <div id="page-images-list">
{% if media|length > 1 %} {% if media|length > 1 %}
{% for item in media %} {% for item in media %}
{% set fileName = item.file|split('/') %}
{% if item.type == "mp4"%} {% if item.type == "mp4"%}
<div id="{{loop.index0}}" class="video-item" data-source="{{ item.file }}"></div>
<div id="{{ loop.index0 }}" class="video-item" data-source="{{ item.file }}">
<video>
<source src="{{ item.file }}"/>
</video>
<button id="{{ loop.index0 }}" class="media-remove">
<i class="ti ti-x"></i>
</button>
</div>
{% else %} {% else %}
<div id="{{ loop.index0 }}" class="img-item" data-source="{{ item.file }}" style="background: url({{ item.file }}) no-repeat center center / cover"> <div id="{{loop.index0}}" class="img-item" style="background: url({{ item.file }}) no-repeat center center / cover"></div>
<button id="{{ loop.index0 }}" class="media-remove">
<i class="ti ti-x"></i>
</button>
</div>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% else %} {% else %}
{% if media[0] != '' %} {% if media[0] != '' %}
{% set fileName = media[0].file|split('/') %}
{% if media[0].type == "mp4"%} {% if media[0].type == "mp4"%}
<div id="0" class="video-item" data-source="{{ media[0].file }}"> <div id="0" class="video-item" data-source="{{ media[0].file }}"></div>
<button id="{{ loop.index0 }}" class="media-remove">X</button> {% else %}
</div> <div id="0" class="img-item" style="background: url({{ media[0].file }}) no-repeat center center / cover"></div>
{% endif %}
{% else %}
{% endif %}
{% endif %}
{% else %}
<div id="0" class="img-item" data-source="{{ media[0].file }}" style="background: url({{ media[0].file }}) no-repeat center center / cover">
<button id="{{ loop.index0 }}" class="media-remove">
<i class="ti ti-x"></i>
</button>
</div> </div>
{% endif %} FILES
{% else %} <div id="page-files-list">
{% endif %}
{% endif %}
</div>
<label role="list-title">FILES</label>
<div role="page-files-list">
{% if files|length > 1 %} {% if files|length > 1 %}
{% for item in files %} {% for item in files %}
{% set fileName = item.file|split('/') %}
{% if item.type == "mp3"%} {% if item.type == "mp3"%}
<div id="{{ loop.index0 }}" class="audio-item" data-source="{{ item.file }}"> <div id="{{loop.index0}}" class="audio-item" data-source="{{ item.file }}"></div>
<audio controls>
<source src="{{ item.file }}"/>
</audio>
<button id="{{ loop.index0 }}" class="media-remove">
<i class="ti ti-x"></i>
</button>
</div>
{% else %} {% else %}
<div id="{{ loop.index0 }}" class="file-item" data-source="{{ item.file }}"> <div id="{{loop.index0}}" class="file-item" data-source="{{ item.file }}"></div>
<a href="{{ item.file }}" target="_blank">{{ fileName[6] }}"</a>
<button id="{{ loop.index0 }}" class="media-remove">
<i class="ti ti-x"></i>
</button>
</div>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% else %} {% else %}
{% if files[0] != '' %} {% if files[0] != '' %}
{% set fileName = files[0].file|split('/') %}
{% if files[0].type == "mp3"%} {% if files[0].type == "mp3"%}
<div id="0" class="audio-item" data-source="{{ files[0].file }}"> <div id="0" class="audio-item" data-source="{{ files[0].file }}"></div>
<audio controls>
<source src="{{ files[0].file }}"/>
</audio>
<button id="{{ loop.index0 }}" class="media-remove">
<i class="ti ti-x"></i>
</button>
</div>
{% else %} {% else %}
<div id="0" class="file-item" data-source="{{ files[0].file }}"> <div id="0" class="file-item" data-source="{{ files[0].file }}"></div>
<a href="{{ item.file }}" target="_blank">{{ fileName[6] }}"</a>
<button id="{{ loop.index0 }}" class="media-remove">
<i class="ti ti-x"></i>
</button>
</div>
{% endif %} {% endif %}
{% else %} {% else %}
@ -143,21 +107,23 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
</div>
</div>
</div> </div>
{% endif %} {% endif %}
</section>
<section role="page-meta">
<div role="page-meta-wrapper">
<div role="page-title">
<strong>TITLE</strong>
<textarea id="post-title-text" type="text" name="post-title-text" class="post-edit" placeholder="TITLE">{{ title }}</textarea>
</div> </div>
<div role="page-tags"> <div id="post-header">
<strong>TAGS</strong> <div id="post-header-wrapper" class="columns">
<textarea id="post-tags" type="text" name="post-tags" class="form-control" placeholder="tags [comma seperated]">{{ tags }}</textarea> <div id="post-title" class="column">
</div> <label>TITLE</label>
<div role="page-layouts"> <textarea id="post_title" type="text" name="post_title" class="post-edit" placeholder="TITLE">
<strong>LAYOUTS</strong> {{- _title -}}
</textarea>
<div id="layouts">
<label>LAYOUTS</label>
<select id="page-templates"> <select id="page-templates">
{% for view in views %} {% for view in views %}
{% if view == page['layout'] %} {% if view == page['layout'] %}
@ -169,38 +135,47 @@
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
<div role="page-options"> <label>CREATED</label>
<strong>OPTIONS</strong>
{% apply spaceless %}
{{ include("dash/partials/options.twig") }}
{% endapply %}
</div>
<div role="page-updated">
<strong>UPDATED</strong>
<span id="post-date" type="text">
{{ updated }}
</span>
</div>
<div role="page-created">
<strong>CREATED</strong>
<span id="post-date" type="text"> <span id="post-date" type="text">
{{ date }} {{ date }}
</span> </span>
</div>
<div id="post-meta" class="column">
<label>TAGS</label>
<textarea id="post_tags" type="text" name="post_tags" class="form-control" placeholder="tags [comma seperated]">
{{- tags -}}
</textarea>
<label>OPTIONS</label>
{% apply spaceless %}
{{ include("dash/partials/options.twig") }}
{% endapply %}
<label>UPDATED</label>
<span id="post-date" type="text">
{{ updated }}
</span>
<input id="page-files-upload" type="file" name="page-files-upload" multiple/> <input id="page-files-upload" type="file" name="page-files-upload" multiple/>
<input id="post-image-upload" type="file" name="post-image-upload"/> <input id="post-image-upload" type="file" name="post-image-upload"/>
<input id="form_token" name="token" type="hidden" value="{{ token }}"></div> <input id="form_token" name="token" type="hidden" value="{{ token }}">
</div> </div>
</div> </div>
</section> </div>
<section role="text-editor"> <div id="edit-post">
{% apply spaceless %} {% apply spaceless %}
{{ include("dash/partials/editor.twig") }} {{ include("dash/partials/editor.twig") }}
{% endapply %} {% endapply %}
<div role="edit-post-wrapper"> <div id="edit-post-wrapper">
<textarea id="edit" spellcheck="false" class="language-md">{{ content }}</textarea> <textarea id="edit" spellcheck="false">{{- content -}}</textarea>
<pre id="highlight"> <pre id="highlight">
<code id="highlight-content" class="language-md"></code> <code id="highlight-content" class="language-md">
</code>
</pre> </pre>
</div> </div>
</section> </div>
</div>
</div>
{% endblock %}
{% block javascripts %}
<script src="/assets/scripts/Start.js?=erty" type="text/javascript"></script>
{% endblock %} {% endblock %}

View file

@ -1,38 +1,45 @@
<div role="text-editor-control"> <div id="edit-control">
<button id="edit-bold" class="content-editor-btn-text editor-button" title="bold"> <button id="edit-bold" class="content-editor-btn-text editor-button" title="bold">B</button>
<i id="edit-bold" class="ti ti-bold"></i> <button id="edit-italic" class="content-editor-btn-text editor-button" title="italic">I</button>
</button> <button id="edit-strikethrough" class="content-editor-btn-text editor-button" title="strikethrough">D</button>
<button id="edit-italic" class="content-editor-btn-text editor-button" title="italic">
<i id="edit-italic" class="ti ti-italic"></i>
</button>
<button id="edit-strikethrough" class="content-editor-btn-text editor-button" title="strikethrough">
<i id="edit-strikethrough" class="ti ti-strikethrough"></i>
</button>
<button id="edit-link" class="content-editor-btn-icon editor-button" title="insert link"> <button id="edit-link" class="content-editor-btn-icon editor-button" title="insert link">
<i id="edit-link" class="ti ti-link"></i> <svg id="edit-link" viewbox="0 0 20 20" class="icons">
</button> <use id="edit-link" xlink:href="/assets/images/global/sprite.svg#entypo-link"/>
<button id="edit-header1" class="content-editor-btn-text editor-button" title="header 1"> </svg>
<i id="edit-header1" class="ti ti-h-1"></i>
</button>
<button id="edit-header2" class="content-editor-btn-text editor-button" title="header 2">
<i id="edit-header2" class="ti ti-h-2"></i>
</button>
<button id="edit-header3" class="content-editor-btn-text editor-button" title="header 3">
<i id="edit-header3" class="ti ti-h-3"></i>
</button> </button>
<button id="edit-header1" class="content-editor-btn-text editor-button" title="header 1">H1</button>
<button id="edit-header2" class="content-editor-btn-text editor-button" title="header 2">H2</button>
<button id="edit-header3" class="content-editor-btn-text editor-button" title="header 3">H3</button>
<button id="edit-image" class="content-editor-btn-icon editor-button" title="insert image"> <button id="edit-image" class="content-editor-btn-icon editor-button" title="insert image">
<i id="edit-image" class="ti ti-photo"></i> <svg id="edit-image" viewbox="0 0 20 20" class="icons">
<use id="edit-image" xlink:href="/assets/images/global/sprite.svg#entypo-image"/>
</svg>
</button> </button>
{% if mode == "edit" %} {% if mode == "edit" %}
<button id="edit-update" class="post-sumbit-btn submit-start editor-button" data-action='blog-update' data-id="{{ page['uuid'] }} type='submit' title=" bold"> <button id="edit-update" class="post-sumbit-btn submit-start editor-button" data-action='blog-update' data-id=page.id type='submit' title="bold">
<i id="edit-update" class="ti ti-device-floppy"></i> <svg id="submit-update" viewbox="0 0 20 20" class="icons">
<use id="submit-update" xlink:href="/assets/images/global/sprite.svg#entypo-save" data-action='blog-update' data-id="{{ page['uuid'] }}"/>
</svg>
<svg id="submit-good" class="icon-hide" viewbox="0 0 20 20" class="icons">
<use xlink:href="/assets/images/global/sprite.svg#entypo-thumbs-up"/>
</svg>
<svg id="submit-error" class="icon-hide" viewbox="0 0 20 20" class="icons">
<use xlink:href="/assets/images/global/sprite.svg#entypo-thumbs-down"/>
</svg>
</button> </button>
<button id="edit-delete" class="content-editor-btn-icon editor-button submit-delete" for="post-delete" title='delete post'> <button id="edit-delete" class="content-editor-btn-icon editor-button submit-delete" for="post-delete" title='delete post'>
<i id="edit-delete" class="ti ti-x"></i> <svg id="edit-delete" viewbox="0 0 20 20" class="icons">
<use id="edit-delete" xlink:href="/assets/images/global/sprite.svg#entypo-cross"/>
</svg>
</button> </button>
{% else %} {% else %}
<button id="edit-save" class="post-sumbit-btn submit-start editor-button" data-action='blog-add' type='submit'> <button id="edit-save" class="post-sumbit-btn submit-start editor-button" data-action='blog-add' type='submit'>
<i id="edit-save" class="ti ti-file-plus"></i> <svg id="submit-save" viewbox="0 0 20 20" class="icons">
<use id="submit-save" xlink:href="/assets/images/global/sprite.svg#entypo-plus"/>
</svg>
</button> </button>
{% endif %} {% endif %}
</div> </div>

View file

@ -1,30 +1,58 @@
<section role="index-header"> <div id="dash-recent">
<div role="index-header-left"> <div id="recent-list">
<h1>Recent</h1> <div class="recent-header">
<div class="index-header-left">
Recent
</div> </div>
<div role="index-header-right"></div> <div class="index-header-right">
</section> <a href='/dashboard/pages' title="view pages">
<section role="index-recent-pages"> <button>
<svg class="page-link">
<use xlink:href="/assets/images/global/sprite.svg#entypo-archive"/>
</svg>
</button>
</a>
<a href='/dashboard/page/add/new' title="add new page">
<button>
<svg class="page-link">
<use xlink:href="/assets/images/global/sprite.svg#entypo-plus"/>
</svg>
</button>
</a>
</div>
</div>
<br/>
{% if data["entryCount"] != 0 %} {% if data["entryCount"] != 0 %}
{% for page in data['pages'] %} {% for page in data['pages'] %}
{% if page.media[0].type == 'mp4' %} {% if page.media[0].type == 'mp4' %}
<a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="post-video-link recent-link"> <a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="post-video-link">
{{ include("dash/partials/recent-meta.twig") }}
<video class="post-video" loop muted autoplay> <video class="post-video" loop muted autoplay>
<source src="{{ page.media[0].file }}" type="video/mp4"> <source src="{{ page.media[0].file }}" type="video/mp4">
Sorry, your browser doesn't support embedded videos. Sorry, your browser doesn't support embedded videos.
</video> </video>
<label>
{{ page.title }}
</label>
{{ include("dash/partials/recent-options.twig") }}
</a> </a>
{% else %} {% else %}
<a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="post-link recent-link" style="background: url({{ page.media[0].file }}) no-repeat center center / cover #fc6399"> <a href="/dashboard/page/edit/{{ page.uuid }}" id="{{ page.uuid }}" class="post-link" style="background: url({{ page.media[0].file }}) no-repeat center center / cover">
{{ include("dash/partials/recent-meta.twig") }} <label>
{{ page.title }}
</label>
{{ include("dash/partials/recent-options.twig") }}
</a> </a>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% else %} {% else %}
There are no pages There are no pages
{% endif %} {% endif %}
</section> </div>
</div>

View file

@ -1,57 +1,23 @@
<div role="menu"> <div id="dash-menu">
{% if title == "Settings" %}
{% apply spaceless %}
{{ include("dash/partials/submenu_settings.twig") }}
{% endapply %}
{% elseif title=="Start" %}
{% apply spaceless %}
{{ include("dash/partials/submenu_start.twig") }}
{% endapply %}
{% endif %}
<a id="settings" href="/dashboard/settings" title="settings"> <a id="settings" href="/dashboard/settings" title="settings">
<button> <button>
<i class="ti ti-home-cog"></i> <svg class="menu">
<use xlink:href="/assets/images/global/sprite.svg#entypo-sound-mix"/>
</svg>
</button> </button>
</a> </a> .
<a id="navigation" href="/dashboard/navigation" title="edit navigation"> <a id="navigation" href="/dashboard/navigation" title="edit navigation">
<button> <button>
<i class="ti ti-arrow-autofit-height"></i> <svg class="menu">
<use xlink:href="/assets/images/global/sprite.svg#entypo-list"/>
</svg>
</button> </button>
</a> </a> .
<a id="navigation" href="/dashboard/logout" title="log out"> <a id="navigation" href="/dashboard/logout" title="log out">
<button> <button>
<i class="ti ti-logout"></i> <svg class="menu">
</button> <use xlink:href="/assets/images/global/sprite.svg#entypo-log-out"/>
</a> </svg>
</div>
<button role="menu-toggle">
<i class="ti ti-menu-2"></i>
</button>
<div role="mobile-menu">
{% if title == "Settings" %}
{% apply spaceless %}
{{ include("dash/partials/submenu_settings.twig") }}
{% endapply %}
{% elseif title=="Start" %}
{% apply spaceless %}
{{ include("dash/partials/submenu_start.twig") }}
{% endapply %}
{% endif %}
<a id="settings" href="/dashboard/settings" title="settings">
<button>
<i class="ti ti-home-cog"></i>
</button>
</a>
<a id="navigation" href="/dashboard/navigation" title="edit navigation">
<button>
<i class="ti ti-arrow-autofit-height"></i>
</button>
</a>
<a id="navigation" href="/dashboard/logout" title="log out">
<button>
<i class="ti ti-logout"></i>
</button> </button>
</a> </a>
</div> </div>

View file

@ -1,10 +0,0 @@
<div role="notify-message">
<div role="notify-icons">
<i class="ti ti-mood-smile" role="notify-good"></i>
<i class="ti ti-mood-sad" role="notify-notgood"></i>
<i class="ti ti-settings" role="notify-working"></i>
</div>
<div role="notify-text">
<span role="response-text">Hey Hey</span>
</div>
</div>

View file

@ -15,26 +15,28 @@
{% else %} {% else %}
{% set published = 'false' %} {% set published = 'false' %}
{% endif %} {% endif %}
<br>
<div id="post-options">
<button id="option-menu-pin" class="option-inactive post-option-btn" data-active="{{ menu }}" title='Pin to Menu'> <button id="option-menu-pin" class="option-inactive post-option-btn" data-active="{{ menu }}" title='Pin to Menu'>
<svg id="option-page-icon" role="icon"> <svg id="option-page-icon" viewbox="0 0 20 20" class="icons">
<use id="option-page-icon" xlink:href="/assets/images/global/sprite.svg#entypo-add-to-list"/> <use id="option-page-icon" xlink:href="/assets/images/global/sprite.svg#entypo-add-to-list"/>
</svg> </svg>
</button> </button>
<button id="option-feature" class="option-inactive post-option-btn" data-active="{{ featured }}" title='Feature'> <button id="option-feature" class="option-inactive post-option-btn" data-active="{{ featured }}" title='Feature'>
<svg id="option-feature-icon" role="icon"> <svg id="option-feature-icon" viewbox="0 0 20 20" class="icons">
<use id="option-feature-icon" xlink:href="/assets/images/global/sprite.svg#entypo-star"/> <use id="option-feature-icon" xlink:href="/assets/images/global/sprite.svg#entypo-star"/>
</svg> </svg>
</button> </button>
<button id="option-published" class="option-inactive post-option-btn" data-active="{{ published }}" title='Published'> <button id="option-published" class="option-inactive post-option-btn" data-active="{{ published }}" title='Published'>
<svg id="option-published-icon" role="icon"> <svg id="option-published-icon" viewbox="0 0 20 20" class="icons">
<use id="option-published-icon" xlink:href="/assets/images/global/sprite.svg#entypo-globe"/> <use id="option-published-icon" xlink:href="/assets/images/global/sprite.svg#entypo-globe"/>
</svg> </svg>
</button> </button>
<a href="/dashboard/page/preview/{{ uuid }}" target="_blank"> <a href="/dashboard/page/preview/{{ uuid }}" target="_blank">
<button id="option-preview" class="option-inactive post-option-btn" data-active="false" title='preview page'> <button id="option-preview" class="option-inactive post-option-btn" data-active="false" title='preview page'>
<svg id="option-preview-icon" role="icon"> <svg id="option-preview-icon" viewbox="0 0 20 20" class="icons">
<use id="option-preview-icon" xlink:href="/assets/images/global/sprite.svg#entypo-eye"/> <use id="option-preview-icon" xlink:href="/assets/images/global/sprite.svg#entypo-eye"/>
</svg> </svg>
</button> </button>
</a> </a>
</div>

View file

@ -1,37 +0,0 @@
{% if page.menu == 'true' %}
{% set menu = "true" %}
{% else %}
{% set menu = "false" %}
{% endif %}
{% if page.published == 'true' %}
{% set published = "true" %}
{% else %}
{% set published = "false" %}
{% endif %}
{% if page.featured == 'true' %}
{% set featured = "true" %}
{% else %}
{% set featured = "false" %}
{% endif %}
<aside>
<strong>
{{ page.updated }}
</strong>
<hr/>
<strong>
{{ page.title }}
</strong>
<hr/>
<button data-active="{{ menu }}">
<i class="ti ti-navigation"></i>
</button>
<button data-active="{{ published }}">
<i class="ti ti-world"></i>
</button>
<button data-active="{{ featured }}">
<i class="ti ti-star"></i>
</button>
</aside>

View file

@ -0,0 +1,42 @@
<div id="options">
{% if page.menu == 'true' %}
{% set menu = "true" %}
{% else %}
{% set menu = "false" %}
{% endif %}
{% if page.published == 'true' %}
{% set published = "true" %}
{% else %}
{% set published = "false" %}
{% endif %}
{% if page.featured == 'true' %}
{% set featured = "true" %}
{% else %}
{% set featured = "false" %}
{% endif %}
<div id="option-left">
<button data-active="{{ menu }}">
<svg>
<use xlink:href="/assets/images/global/sprite.svg#entypo-add-to-list"/>
</svg>
</button>
<button data-active="{{ published }}">
<svg>
<use xlink:href="/assets/images/global/sprite.svg#entypo-globe"/>
</svg>
</button>
<button data-active="{{ featured }}">
<svg>
<use xlink:href="/assets/images/global/sprite.svg#entypo-star"/>
</svg>
</button>
</div>
<div id="option-right">
<span>
{{ page.updated }}
</span>
</div>
</div>

View file

@ -1,11 +0,0 @@
<div role="submenu">
<button id="save-toggle" title="save settings">
<i class="ti ti-device-floppy"></i>
</button>
<button id="publish-pages" title="publish site">
<i class="ti ti-world-upload"></i>
</button>
<button id="render-toggle" title="render on save toggle" data-render="{{ renderOnSave }}">
<i class="ti ti-circle-dashed"></i>
</button>
</div>

View file

@ -1,12 +0,0 @@
<div role="submenu">
<a href='/dashboard/pages' title="view pages">
<button>
<i class="ti ti-book-2"></i>
</button>
</a>
<a href='/dashboard/page/add/new' title="add new page">
<button>
<i class="ti ti-square-plus"></i>
</button>
</a>
</div>

View file

@ -5,14 +5,37 @@
{% endblock %} {% endblock %}
{% block stylesheets %} {% block stylesheets %}
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css"> <link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=dfdfdf">
{% endblock %} {% endblock %}
{% block mainContent %} {% block mainContent %}
<section role="password-reset"> <div id="dash-index">
{% apply spaceless %} <div id="dash-index-wrapper">
{{ include("dash/forms/reset.twig") }} <div id="dash-login">
{% endapply %} <div id="dash-reset" class="dash-reset">
<img id="the-logo" src="/assets/images/global/fipamo-logo.svg"/>
<form id="reset" class='login' name="reset" action="/dashboard/login" method="POST">
</section> <input type="password" id="new_password"name="new_password" class="form-control" placeholder="New Password" required">
<input type="password" id="new_password2" name="new_password2" class="form-control" placeholder="New Password Confirm" required">
<input type="password" id="secret" name="secret" class="form-control" placeholder="Account Secret" required">
<button id="reset-btn" class='login-btn' type='submit'>
RESET PASSWORD
</button><br />
<p>
Use this to get your secret to verify it's you. If your email is set up, the secret will be sent there. If not, the form will be updated automatically(but please set up your email, once you reset your password).
</p>
<input type="text"id="email" name="email" class="form-control" placeholder="email to verify" required">
<button id="get-secret-btn" class='login-btn' type='submit'>
VERIFY EMAIL
</button><br /><br />
</form>
</div>
</div>
</div>
</div>
{% endblock %}
{% block javascripts %}
<script src="/assets/scripts/Start.js" type="text/javascript"></script>
{% endblock %} {% endblock %}

View file

@ -5,87 +5,123 @@
{% endblock %} {% endblock %}
{% block stylesheets %} {% block stylesheets %}
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css?=cvnbm"> <link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=cvnbm">
{% endblock %} {% endblock %}
{% block mainContent %} {% block mainContent %}
<article role="settings"> <div id="settings-actions">
<section role="member-settings"> <div id="buttons">
<div role="member-avatar"> <button id="save-toggle" title="save settings">
<div role="avatar" style="background: url({{ member['avatar'] }} ) no-repeat center center / cover"></div> <svg id="submit-update" class="icons">
<use id="submit-update" xlink:href="/assets/images/global/sprite.svg#entypo-save"/>
</svg>
</button>
<button id="publish-pages" title="publish site">
<svg id="submit-update" class="icons">
<use id="submit-update" xlink:href="/assets/images/global/sprite.svg#entypo-publish"/>
</svg>
</button>
<button id="render-toggle" title="render on save toggle" data-render="{{ renderOnSave }}">
<svg id="render-toggle-icon" class="icons">
<use xlink:href="/assets/images/global/sprite.svg#entypo-circular-graph"/>
</svg>
</button>
</div>
</div>
<div id="settings-index">
<div id="settings-index-wrapper">
<div id="member-settings">
<div id="member-images" class="columns">
<div class="column is-one-third">
<div id="member-avatar-drop">
<img id="avatar" src="{{member['avatar']}}" for="avatar-upload"/>
<input id="avatar-upload" type="file" name="avatar-upload" /> <input id="avatar-upload" type="file" name="avatar-upload" />
</div> </div>
<div role="site-background"> </div>
<div role="background" style="background: url({{ background }} ) no-repeat center center / cover"></div> <div class="column is-two-thirds">
<div id="site-background">
<img id="background" src="{{background}}" alt="image for site background" for="background-upload"/>
<input id="background-upload" type="file" name="backgrond-upload" /> <input id="background-upload" type="file" name="backgrond-upload" />
</div> </div>
<div> </div>
</div>
<div id="member-meta" class="columns">
<div class="column is-one-third">
<input type='text' name='handle' id='settings-handle' placeholder='handle' value="{{member['handle']}}" autofocus /> <input type='text' name='handle' id='settings-handle' placeholder='handle' value="{{member['handle']}}" autofocus />
<input type='text' name='email' id='settings-email' placeholder='email' value="{{member['email']}}" autofocus /> <input type='text' name='email' id='settings-email' placeholder='email' value="{{member['email']}}" autofocus />
</div>
<div class="column is-one-third">
<input type='text' name='base-url' id='settings-url' placeholder='url' value="{{baseUrl}}" autofocus /> <input type='text' name='base-url' id='settings-url' placeholder='url' value="{{baseUrl}}" autofocus />
<input type='text' name='base-title' id='settings-title' placeholder='site title' value="{{siteTitle}}" autofocus /> <input type='text' name='base-title' id='settings-title' placeholder='site title' value="{{siteTitle}}" autofocus />
</div>
<div class="column is-one-third">
<textarea id="settings-desc" type='text' name='settings_desc' class='settings-dec' placeholder='description stuff', autofocus>{{desc}}</textarea> <textarea id="settings-desc" type='text' name='settings_desc' class='settings-dec' placeholder='description stuff', autofocus>{{desc}}</textarea>
</div> </div>
<div>
<button id="create-backup">
<i class="ti ti-disc"></i>
<span>BACK UP YOUR SITE</span>
</button><br/>
{% if lastBackup != '' %}
LAST BACK UP<br/>
<a href="/api/v1/files">{{ lastBackup }}</a><br/>
{% else %}
<span>span No back ups. Frowny face.</span>
{% endif %}
</div> </div>
<div role="features"> </div>
<div id="feature-settings">
<div id="features" class="columns">
<div class="column">
<div id="feature-api">
{% if apiStatus is defined and apiStatus == "true" %} {% if apiStatus is defined and apiStatus == "true" %}
<button id="api-access-toggle" title="allow external api" data-enabled="true"> <button id="api-access-toggle" title="allow external api" data-enabled="true">
<i class="ti ti-phone-incoming"></i> <svg id="api-access-toggle" class="icons">
<span id="api-status">API ACCESS ENABLED</span> <use id="api-access-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-landline"/>
</svg>
<span id="api-status">EXTERNAL API ACCESS ENABLED</span>
</button> </button>
{% else %} {% else %}
<button id="api-access-toggle" title="allow external api" data-enabled="false"> <button id="api-access-toggle" title="allow external api" data-enabled="false">
<i class="ti ti-phone-incoming"></i> <svg id="api-access-toggle" class="icons">
<span id="api-status">API ACCESS NOT ENABLED</span> <use id="api-access-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-landline"/>
</svg>
<span id="api-status">EXTERNAL API ACCESS NOT ENABLED</span>
</button> </button>
{% endif %} {% endif %}
</div>
</div>
<div class="column">
<div id="dynamic-api">
{% if dynamicRenderStatus is defined and dynamicRenderStatus == "true" %} {% if dynamicRenderStatus is defined and dynamicRenderStatus == "true" %}
<button id="dynamic-render-toggle" title="allow external api" data-enabled="true"> <button id="dynamic-render-toggle" title="allow external api" data-enabled="true">
<i class="ti ti-arrow-merge"></i> <svg id="dynamic-render-toggle" class="icons">
<use id="dynamic-render-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-text-document-inverted"/>
</svg>
<span id="dynamic-render-status">DYNAMIC PAGE RENDERING</span> <span id="dynamic-render-status">DYNAMIC PAGE RENDERING</span>
</button> </button>
{% else %} {% else %}
<button id="dynamic-render-toggle" title="allow external api" data-enabled="false"> <button id="dynamic-render-toggle" title="allow external api" data-enabled="false">
<i class="ti ti-arrow-merge"></i> <svg id="dynamic-render-toggle" class="icons">
<use id="dynamic-render-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-text-document-inverted"/>
</svg>
<span id="dynamic-render-status">STATIC PAGE RENDERING</span> <span id="dynamic-render-status">STATIC PAGE RENDERING</span>
</button> </button>
{% endif %} {% endif %}
</div> </div>
<div role="theme"> </div>
<label>Themes</label><br/> <div class="column"></div>
<div class="column"></div>
</div>
</div>
<div id="option-settings" class="columns">
<div id="theme-settings" class="column">
<label>THEMES</label>
{% for theme in themes %} {% for theme in themes %}
{% if theme.name == currentTheme %} {% if theme.name == currentTheme %}
<button id="{{ theme.name }}" class="theme-select" data-enabled="true"> <a href="#" id="{{theme.name}}" class="theme-select" data-enabled="true">{{theme['display-name']}}</a>
<i class="ti ti-brush"></i>
<span>{{ theme['display-name'] }}</span>
</button>
{% else %} {% else %}
<button href="#" id="{{ theme.name }}" class="theme-select" data-enabled="false"> <a href="#" id="{{theme.name}}" class="theme-select" data-enabled="false">{{theme['display-name']}}</a>
<i class="ti ti-brush-off"></i>
<span>{{ theme['display-name'] }}</span>
</button>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</div> </div>
<div role="mail"> <div id="mail-settings" class="column">
<label>Email</label><br/> <label>EMAIL</label>
{% if mailOption == "option-none" or mailOption == "" %} {% if mailOption == "option-none" or mailOption == "" %}
<a href="#" class="mail-option" id="option-none" data-enabled="true">NONE</a> <a href="#" class="mail-option" id="option-none" data-enabled="true">NONE</a>
{% else %} {% else %}
@ -105,19 +141,52 @@
{% apply spaceless %} {% apply spaceless %}
{{ include("dash/partials/mailforms.twig") }} {{ include("dash/partials/mailforms.twig") }}
{% endapply %} {% endapply %}
<button id="send-mail"> <button id="send-mail">TEST MAIL</button>
<i class="ti ti-mailbox"></i> <br /><br />
<span>TEST MAIL</span>
</button>
</div> </div>
<div> </div>
<div id="token-settings">
<div id="keys-tokens" class="columns">
<div class="column">
<label>API KEY</label> <label>API KEY</label>
<br/> <div id="member-api-key">
{{member['key']}} {{member['key']}}
<br/> </div>
<label>FORM TOKEN</label><br/>
</div>
<div class="column">
<label>FORM TOKEN</label>
<div id="form-token">
{{ftoken}} {{ftoken}}
</div> </div>
</section> </div>
</article> </div>
</div>
<div id="backup-settings">
<div class="columns">
<div class="column">
<button id="create-backup">BACK UP YOUR SITE</button><br />
</div>
<div class="column">
{% if lastBackup != '' %}
<div class="backup-meta">
LAST BACK UP <a href="/api/v1/files">{{lastBackup}}</a><br />
</div>
{% else %}
<span>span No back ups. Frowny face.</span>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block javascripts %}
<script src="/assets/scripts/Start.js" type="text/javascript"></script>
{% endblock %} {% endblock %}

View file

@ -5,10 +5,12 @@
{% endblock %} {% endblock %}
{% block stylesheets %} {% block stylesheets %}
<link rel="stylesheet" type="text/css" href="/assets/css/dash/start.css?=dfdfrtr"> <link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=adfdff">
{% endblock %} {% endblock %}
{% block mainContent %} {% block mainContent %}
<div id="dash-index">
<div id="dash-index-wrapper">
{% if status %} {% if status %}
{% apply spaceless %} {% apply spaceless %}
{{ include("dash/partials/index.twig") }} {{ include("dash/partials/index.twig") }}
@ -16,4 +18,10 @@
{% else %} {% else %}
{{ include("dash/forms/login.twig") }} {{ include("dash/forms/login.twig") }}
{% endif %} {% endif %}
</div>
</div>
{% endblock %}
{% block javascripts %}
<script src="/assets/scripts/Start.js?=dfdfsdf" type="text/javascript"></script>
{% endblock %} {% endblock %}

View file

@ -1,7 +1,7 @@
{ {
"name": "are0h/fipamo", "name": "are0h/fipamo",
"descriptions": "The most chill no database blog framework ever.", "descriptions": "The most chill no database blog framework ever.",
"version": "2.6.1-beta", "version": "2.1.1-beta",
"homepage": "https://fipamo.blog", "homepage": "https://fipamo.blog",
"authors": [ "authors": [
{ {
@ -9,10 +9,15 @@
"homepage": "https://roiskinda.cool" "homepage": "https://roiskinda.cool"
} }
], ],
"autoload": {
"psr-4": {
"brain\\":"brain"
}
},
"support": { "support": {
"source": "https://koodu.ubiqueros.com/are0h/Fipamo", "source": "https://code.playvicio.us/Are0h/Fipamo",
"wiki": "https://koodu.ubiqueros.com/are0h/Fipamo/wiki/?action=_pages", "wiki": "https://code.playvicio.us/Are0h/Fipamo/wiki/_pages",
"issues": "https://koodu.ubiqueros.com/are0h/Fipamo/issues" "issues": "https://code.playvicio.us/Are0h/Fipamo/issues"
}, },
"require": { "require": {
"slim/slim": "4.*", "slim/slim": "4.*",
@ -22,16 +27,11 @@
"mnapoli/front-yaml": "^1.8", "mnapoli/front-yaml": "^1.8",
"lodash-php/lodash-php": "^0.0.7", "lodash-php/lodash-php": "^0.0.7",
"rbdwllr/reallysimplejwt": "^4.0", "rbdwllr/reallysimplejwt": "^4.0",
"fightbulc/moment": "^1.33",
"tgalopin/html-sanitizer": "^1.4", "tgalopin/html-sanitizer": "^1.4",
"phpmailer/phpmailer": "^6.4", "phpmailer/phpmailer": "^6.4",
"league/commonmark": "^2.1", "league/commonmark": "^2.1",
"symfony/yaml": "^5.4", "symfony/yaml": "^5.4",
"olegatro/html-sanitizer-relative": "^1.0", "olegatro/html-sanitizer-relative": "^1.0"
"nesbot/carbon": "^2.62"
},
"scripts": {
"start": [
"@php -S localhost:8000 -t public/"
]
} }
} }

989
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -39,11 +39,8 @@
</div> </div>
<br/> <br/>
{{meta['who']}} {{meta['who']}} dropped this {{ meta['when'] }}<br />
dropped this <strong>tags: </strong>
{{ meta['when'] }}<br/>
<strong>tags:
</strong>
{% for tag in meta['tags'] %} {% for tag in meta['tags'] %}
{% if dynamicRender is defined %} {% if dynamicRender is defined %}
{% if dynamicRender == 'true' %} {% if dynamicRender == 'true' %}

28321
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,34 +1,40 @@
{ {
"name": "fipamo-dash", "name": "fipamo-dash",
"version": "2.6.1-beta", "version": "2.5.0",
"private": true, "private": true,
"apidoc": { "apidoc": {
"name": "Fipamo API", "name": "Fipamo API",
"version": "1.0.0", "version": "1.0.0",
"description": "The most chill API for the most chill blog framework" "description": "The most chill API for the most chill blog framework"
}, },
"source": "src/com/Start.js",
"main": "public/assets/scripts/dash.js",
"targets": {
"main": {
"includeNodeModules": true
}
},
"scripts": {
"watch": "parcel watch",
"build": "parcel build"
},
"devDependencies": { "devDependencies": {
"@babel/core": "^7.21.3", "@babel/preset-env": "^7.16.5",
"babel-plugin-prismjs": "^2.1.0", "babel-cli": "^6.26.0",
"parcel": "^2.8.3", "eslint": "^8.11.0",
"prettier": "^2.8.4", "eslint-plugin-babel": "^5.3.1",
"stylelint": "^15.3.0", "parcel": "^2.0.1",
"stylelint-config-standard": "^31.0.0" "prettier": "^2.6.0"
}, },
"dependencies": { "dependencies": {
"@babel/core": "^7.16.5",
"@babel/eslint-parser": "^7.16.5",
"animejs": "^3.2.1", "animejs": "^3.2.1",
"prismjs": "^1.29.0", "babel-plugin-prismjs": "^2.1.0",
"sortablejs": "^1.15.0" "babel-preset-env": "^1.7.0",
} "bulma": "^0.9.3",
"caret-pos": "^2.0.0",
"jsdoc": "^3.6.7",
"minami": "^1.2.3",
"prismjs": "^1.25.0",
"sass": "^1.45.1",
"sortablejs": "^1.14.0"
},
"license": "UNLICENSED",
"author": "Are0h",
"scripts": {
"watch": "sass --watch src/styles:public/assets/css & npx parcel watch src/com/Start.js --dist-dir public/assets/scripts --public-url /assets/scripts",
"build": "sass src/styles:public/assets/css & npx parcel build src/com/Start.js --dist-dir public/assets/scripts --public-url /assets/scripts"
},
"description": "Front end script for the most chill blog framework ever.",
"repository": "https://code.playvicio.us/Are0h/Fipamo"
} }

3872
public/assets/css/dash.css Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,109 +0,0 @@
section[role="book-index-header"] {
display: grid;
grid-template-columns: 1fr 1fr;
margin: 100px auto 20px;
width: 100%;
max-width: 900px;
}
section[role="book-index-header"] > div[role="book-index-header-left"] {
text-transform: capitalize;
display: inline-block;
color: var(--white);
font-size: 3em;
}
section[role="book-index-header"] > div[role="book-index-header-right"] {
text-align: right;
display: inline-block;
}
section[role="book-index-pages"] {
margin: 0 auto;
width: 100%;
max-width: 900px;
}
section[role="book-index-pages"] > a.page-link {
vertical-align: top;
display: inline-block;
width: 100%;
text-decoration: none;
margin: 0 0 20px;
border-radius: 3px;
height: 350px;
overflow: hidden;
}
section[role="book-index-pages"] > a.page-link div.page-video {
width: 100%;
height: 350px;
display: flex;
justify-content: left;
align-items: center;
border-radius: 5px;
border-bottom: none;
position: relative;
}
section[role="book-index-pages"] > a.page-link video {
width: 100%;
height: 100%;
position: absolute;
object-fit: cover;
}
section[role="book-index-pages"] > a.page-link > div.page-bg {
width: 100%;
height: 350px;
display: flex;
justify-content: left;
align-items: center;
border-radius: 5px;
border-bottom: none;
position: relative;
}
section[role="book-index-pages"] aside {
font-size: 1.1em;
color: var(--white);
text-shadow: 2px 2px 2px var(--black);
padding: 10px;
position: relative;
}
section[role="book-index-pages"] hr {
color: var(--white);
border: 0.1px solid;
margin: 7px 0;
}
section[role="book-index-pages"] button[data-active="true"] {
background: var(--primary);
color: var(--tertiary);
}
section[role="book-index-pages"] button[data-active="false"] {
background: var(--secondary);
}
section[role="book-index-pages"] > div[role="paginate"] {
width: fit-content;
margin: 0 auto;
font-size: 1.5em;
color: var(--highlight);
}
section[role="book-index-pages"] > div[role="paginate"] i {
color: var(--secondary);
}
section[role="book-index-pages"] > div[role="paginate"] a,
section[role="book-index-pages"] > div[role="paginate"] span {
display: inline;
}
section[role="book-index-pages"] > div[role="paginate"] span {
position: relative;
top: -15px;
}

View file

@ -1,22 +0,0 @@
:root {
/* BASE COLORS */
--primary: #1d3040;
--secondary: #b2cce5;
--tertiary: #f5ab35;
--highlight: #fc6399;
--white: #efebe3;
--grey: #abb7b7;
--black: #32302f;
/* EDITOR COLORS */
--event-cool: #32cd32;
--event-lame: #f64747;
--editor-primary: #fde3a7;
--editor-secondary: #e7903c;
--editor-tertiary: #6bb9f0;
--editor-string: #dcc6e0;
--editor-tag: #e73c4e;
/* RGB Versions */
--primary-rgb: 29 28 24;
}

View file

@ -1,54 +0,0 @@
a {
color: var(--primary);
}
p {
background: var(--tertiary);
color: var(--primary);
padding: 5px;
display: block;
border-radius: 5px;
text-align: left;
}
input[type="email"],
input[type="password"],
input[type="text"] {
border: 0;
border-radius: 5px;
font: 18px var(--base-type);
display: inline-block;
background: var(--white);
color: var(--primary);
}
textarea {
border: 0;
border-radius: 3px;
color: var(--primary);
background: var(--white);
}
button,
input[type="submit"] {
background: var(--highlight);
color: var(--primary);
font: 20px var(--base-type);
border-radius: 5px;
position: relative;
cursor: pointer;
border: 0;
transition: all 0.3s linear;
}
select {
font: 14px var(--base-type);
border: 1px solid var(--secondary);
appearance: none;
color: var(--primary);
}
::placeholder {
font: 25px var(--base-type);
color: var(--black);
}

View file

@ -1,151 +0,0 @@
html {
width: 100%;
height: 100%;
overflow: hidden;
font: 400 1.2em/1.4em var(--base-type);
}
html body {
background: var(--primary);
margin: 0;
padding: 0;
height: 100%;
width: 100%;
overflow-y: scroll;
overflow-x: hidden;
}
/* GLOBALS */
a {
color: var(--primary);
text-decoration: none;
border-bottom: 0;
transition: all 0.2s linear;
}
sup {
background: var(--black);
color: var(--white);
padding: 3px;
border-radius: 3px;
}
::selection {
background: var(--highlight);
color: var(--white);
}
#notifications {
display: none;
visibility: hidden;
}
pre,
code {
background: var(--black);
color: var(--highlight);
border-radius: 3px;
padding: 3px;
}
svg[role="icon"] {
fill: var(--white);
width: 25px;
height: 25px;
padding-top: 5px;
}
/* HEADER
Navigation
Notificiations
*/
header {
width: 100%;
max-width: 900px;
margin: 10px auto;
height: 50px;
border-radius: 5px;
left: 50%;
transform: translate(-50%, 0);
position: fixed;
z-index: 500;
}
header > nav > div[role="nav-left"] img {
width: 40px;
padding: 5px;
}
header > nav > div[role="title"] {
text-align: left;
height: 100%;
}
header > nav > div[role="title"] h1 {
color: var(--primary);
margin: 15px;
}
header > nav > div[role="nav-right"] {
padding: 5px;
}
header > nav > div > div[role="mobile-menu"] {
display: none;
position: fixed;
z-index: 1000;
left: 0;
transition: all 0.2s linear;
background: var(--white);
}
header > nav > div[role="nav-right"] button {
width: 40px;
height: 40px;
margin-left: 5px;
font-size: 0.8em;
color: var(--white);
}
header > nav > div[role="nav-right"] > button[role="menu-toggle"] {
display: none;
}
header > nav > div[role="nav-right"] div[role="submenu"] {
display: inline;
}
header > nav > div[role="nav-right"] div[role="submenu"] button {
background: var(--primary);
color: var(--white);
font-size: 0.8em;
}
header
> nav
> div[role="nav-right"]
div[role="submenu"]
button[data-render="true"] {
background: var(--tertiary);
color: var(--primary);
}
/* RESPONSIVE */
@media only screen and (max-width: 900px) {
header {
width: 97%;
}
}
@media only screen and (max-width: 530px) {
header > nav > div[role="nav-right"] > button[role="menu-toggle"] {
display: inline;
}
header > nav > div > div[role="menu"] {
display: none;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,149 +0,0 @@
section[role="index-header"] {
display: grid;
grid-template-columns: 1fr 1fr;
width: 100%;
max-width: 900px;
margin: 60px auto 0;
}
section[role="index-recent-pages"] a {
width: 100%;
height: 100%;
display: flex;
justify-content: left;
align-items: center;
border-radius: 5px;
border-bottom: none;
position: relative;
}
section[role="index-recent-pages"] a video {
width: 100%;
position: absolute;
object-fit: cover;
height: 100%;
border-radius: 5px;
}
section[role="index-recent-pages"] a:nth-child(1) {
grid-column: 1/4;
grid-row: 1/3;
}
section[role="index-recent-pages"] a:nth-child(2) {
grid-row: 3/6;
}
section[role="index-recent-pages"] a:nth-child(3) {
grid-column: 2/4;
grid-row: 3/5;
}
section[role="index-header"] div[role="index-header-right"] {
display: flex;
justify-content: right;
align-items: center;
}
section[role="index-header"] div[role="index-header-right"] a {
border-bottom: none;
margin-left: 5px;
}
section[role="index-recent-pages"] {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-rows: minmax(200px, auto);
gap: 10px;
width: 100%;
max-width: 900px;
margin: 10px auto;
}
section[role="index-recent-pages"] a button {
padding: 1px 5px;
}
section[role="index-recent-pages"] button i {
font-size: 1.8em;
}
section[role="index-recent-pages"] button[data-active="true"] {
background: var(--primary);
}
section[role="index-recent-pages"] button[data-active="true"] i {
color: var(--tertiary);
}
section[role="index-recent-pages"] button[data-active="false"] {
background: var(--secondary);
}
section[role="index-recent-pages"] button[data-active="false"] i {
fill: var(--primary);
}
section[role="index-recent-pages"] aside {
font-size: 1.1em;
color: var(--white);
text-shadow: 2px 2px 2px var(--black);
padding: 10px;
z-index: 10;
}
section[role="index-recent-pages"] hr {
color: var(--white);
border: 0.1px solid;
margin: 7px 0;
}
@media only screen and (max-width: 900px) {
section[role="index-header"],
section[role="index-recent-pages"] {
width: 97%;
}
}
@media only screen and (max-width: 520px) {
section[role="index-recent-pages"] {
grid-template-columns: 1fr 1fr;
}
section[role="index-recent-pages"] a:nth-child(1) {
grid-column: 1/3;
grid-row: 1/2;
}
section[role="index-recent-pages"] a:nth-child(2) {
grid-row: 2/3;
grid-column: 1/2;
}
section[role="index-recent-pages"] a:nth-child(3) {
grid-column: 2/3;
grid-row: 2/3;
}
}
@media only screen and (max-width: 350px) {
section[role="index-recent-pages"] a:nth-child(2) {
grid-column: 1/3;
grid-row: 2/3;
}
section[role="index-recent-pages"] a:nth-child(3) {
grid-column: 1/3;
grid-row: 3/4;
}
section[role="index-recent-pages"] a:nth-child(4) {
grid-column: 1/3;
grid-row: 4/5;
}
section[role="index-recent-pages"] a:nth-child(5) {
grid-column: 1/3;
grid-row: 5/6;
}
}

View file

@ -1,113 +0,0 @@
/* LOGIN */
section[role="login"],
section[role="password-reset"],
section[role="restore-fresh"],
section[role="restore-backup"] {
margin: 15% auto;
padding: 10px;
width: 500px;
border-radius: 5px;
display: grid;
grid-template-columns: 28.5% 1fr;
gap: 10px;
visibility: visible;
}
section[role="restore-backup"] {
display: none;
visibility: hidden;
color: var(--white);
}
section[role="login"] form input {
width: 95%;
height: 30px;
padding: 5px;
margin-bottom: 10px;
}
section[role="login"] form button {
padding: 10px 5px;
width: 82%;
}
section[role="login"] form a {
padding: 10px 5px;
border-radius: 5px;
width: 10%;
height: 20px;
display: inline-block;
background: var(--tertiary);
vertical-align: top;
text-align: center;
margin: 0 0 0 10px;
font-weight: 600;
}
/* PASSWORD-RESET */
section[role="password-reset"] form button {
padding: 10px 5px;
width: 82%;
}
section[role="password-reset"] form input {
width: 95%;
height: 30px;
padding: 5px;
margin-bottom: 10px;
}
/* SITE RESTORE */
section[role="restore-fresh"] form button {
padding: 10px 5px;
width: 82%;
}
section[role="restore-fresh"] form input {
width: 95%;
height: 30px;
padding: 5px;
margin-bottom: 10px;
}
section[role="restore-backup"] form button {
padding: 10px 5px;
width: 82%;
}
section[role="restore-backup"] form input {
width: 95%;
height: 30px;
padding: 5px;
margin-bottom: 10px;
}
/* RESPONSIVE */
@media only screen and (max-width: 500px) {
section[role="login"],
section[role="password-reset"],
section[role="restore-fresh"],
section[role="restore-backup"] {
width: 97%;
}
}
@media only screen and (max-width: 375px) {
section[role="login"],
section[role="password-reset"],
section[role="restore-fresh"],
section[role="restore-backup"] {
grid-template-columns: 1fr;
}
section[role="login"] img,
section[role="password-reset"] img,
section[role="restore-fresh"] img,
section[role="restore-backup"] img {
width: 50px;
}
}

View file

@ -1,46 +0,0 @@
article[role="navigation"] {
width: 100%;
max-width: 900px;
margin: 100px auto;
}
article[role="navigation"] > section > div.nav-item {
display: block;
width: 98%;
background: var(--white);
border-radius: 3px;
color: var(--highlight);
margin: 0 0 10px;
font-size: 1.5em;
cursor: move;
}
article[role="navigation"] > section > div.nav-item > label {
display: inline-block;
padding: 5px;
margin: 12px 0 0 10px;
vertical-align: top;
cursor: move;
}
article[role="navigation"] > section > div.nav-item > div#nav-btns {
float: right;
padding: 5px;
position: relative;
}
article[role="navigation"] > section > div.nav-item > div#nav-btns button {
margin-left: 5px;
}
@media only screen and (max-width: 500px) {
article[role="navigation"] > section > div.nav-item > label {
width: 55%;
margin: 0;
font-size: 0.8em;
}
article[role="navigation"] > section i {
font-size: 1.5em;
}
}

View file

@ -1,91 +0,0 @@
header > nav[role="top-nav"] {
display: grid;
text-align: right;
grid-template-columns: 50px auto auto;
height: 100%;
position: relative;
background: var(--white);
border-radius: 3px;
transform-style: preserve-3d;
transform-origin: 100% 50%;
transform: rotateX(0deg);
transition: all 0.1s ease-out;
perspective: 500px;
backface-visibility: hidden;
box-shadow: 2px 2px 0 rgba(var(--primary-rgb) / 30%);
}
header > div[role="notify"] {
display: grid;
height: 100%;
position: relative;
background: var(--black);
border-radius: 3px;
transform-style: preserve-3d;
transform-origin: 100% 50%;
transform: rotateX(180deg);
transition: all 0.3s ease-out;
perspective: 500px;
backface-visibility: hidden;
margin-top: -50px;
box-shadow: 2px 2px 0 rgba(var(--primary-rgb) / 30%);
}
header > div[role="notify"] > div[role="notify-message"] {
display: flex;
height: 86%;
}
header > div[role="notify"] > div[role="notify-message"] div {
display: inline-block;
transition: all 0.2s linear;
}
header
> div[role="notify"]
> div[role="notify-message"]
> div[role="notify-text"] {
color: var(--white);
border-radius: 5px;
height: 79%;
margin-top: 8px;
opacity: 0;
}
header
> div[role="notify"]
> div[role="notify-message"]
> div[role="notify-icons"] {
margin: 5px;
width: 40px;
opacity: 0;
}
header
> div[role="notify"]
> div[role="notify-message"]
> div[role="notify-text"]
span {
display: block;
padding: 5px;
}
header > div[role="notify"] > div[role="notify-message"] i {
display: none;
color: var(--white);
}
i[role="notify-working"] {
animation: 2s infinite linear spin;
height: 40px;
width: 40px;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

View file

@ -1,111 +0,0 @@
code[class*="language-"],
pre[class*="language-"] {
color: var(--editor-primary);
background: none;
font-family: var(--mono-type);
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
tab-size: 4;
hyphens: none;
}
pre[class*="language-"] {
margin: 0.1em 0;
overflow: auto;
border-radius: 0.3em;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: var(--primary);
}
:not(pre) {
& > code[class*="language-"] {
padding: 0.1em;
border-radius: 0.3em;
white-space: normal;
}
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #8292a2;
}
.token.punctuation {
color: var(--editor-secondary);
}
.token.namespace {
opacity: 0.6;
}
.token.keyword {
color: #66d9ef;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
.token.content {
color: var(--editor-tertiary);
}
.token.property,
.token.tag,
.token.constant,
.token.symbol,
.token.deleted {
color: var(--editor-tag);
}
.token.boolean,
.token.number {
color: #ae81ff;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #a6e22e;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string,
.token.variable {
color: var(--editor-string);
}
.token.atrule,
.token.attr-value,
.token.function,
.token.class-name {
color: #e6db74;
}
.token.regex,
.token.important {
color: var(--editor-secondary);
}
.token.important,
.token.bold {
font-weight: normal;
}

View file

@ -1,446 +0,0 @@
/* FILE MANAGER */
main > section[role="file-manager"] {
width: 100%;
background: var(--tertiary);
padding: 20px 0;
margin-top: 75px;
}
main > section[role="file-manager"] label[role="list-title"] {
width: 100%;
max-width: 900px;
margin: 0 auto;
display: block;
color: var(--primary);
}
main > section[role="file-manager"] > div[role="file-drop"] {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
min-height: 100px;
background: var(--white);
color: var(--primary);
vertical-align: middle;
border-radius: 5px;
max-width: 900px;
margin: 10px auto;
}
main > section[role="file-manager"] > div[role="page-images-list"],
main > section[role="file-manager"] > div[role="page-files-list"] {
max-width: 900px;
width: 100%;
margin: 10px auto;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
gap: 10px;
}
main > section[role="file-manager"] > div[role="page-images-list"] > div,
main > section[role="file-manager"] > div[role="page-files-list"] > div {
width: 100%;
height: 150px;
border-radius: 3px;
overflow: hidden;
position: relative;
cursor: pointer;
}
main
> section[role="file-manager"]
> div[role="page-images-list"]
> div
> div.item-progress {
width: 100%;
height: 100%;
background: var(--primary);
}
main > section[role="text-editor"] > div[role="text-editor-control"] button {
border-radius: 0;
}
main
> section[role="text-editor"]
> div[role="text-editor-control"]
button
> i {
font-size: 1.6em;
}
main
> section[role="text-editor"]
> div[role="text-editor-control"]
> button:nth-child(1) {
border-radius: 3px 0 0 3px;
}
main
> section[role="text-editor"]
> div[role="text-editor-control"]
> button:nth-child(10) {
border-radius: 0 3px 3px 0;
}
main
> section[role="file-manager"]
> div[role="page-images-list"]
> div
> button.media-remove,
main
> section[role="file-manager"]
> div[role="page-files-list"]
> div
> button.media-remove {
color: var(--white);
margin: 5px;
}
main
> section[role="file-manager"]
> div[role="page-images-list"]
> div.video-item
> video {
object-fit: cover;
height: 100%;
width: 100%;
}
main
> section[role="file-manager"]
> div[role="page-images-list"]
> div.video-item
> button,
main
> section[role="file-manager"]
> div[role="page-files-list"]
> div.audio-item
> button,
main
> section[role="file-manager"]
> div[role="page-files-list"]
> div.file-item
> button {
position: absolute;
top: 0;
left: 0;
}
main
> section[role="file-manager"]
> div[role="page-files-list"]
> div.audio-item {
background: url("/assets/images/global/upload-audio.png") no-repeat center
center / cover;
}
main
> section[role="file-manager"]
> div[role="page-files-list"]
> div.file-item {
background: url("/assets/images/global/upload-doc.png") no-repeat center
center / cover;
}
main
> section[role="file-manager"]
> div[role="page-files-list"]
> div.file-item
> a {
position: absolute;
bottom: 0;
background: var(--secondary);
padding: 2px;
}
main
> section[role="file-manager"]
> div[role="page-files-list"]
> div.audio-item
> audio {
height: 100%;
width: 100%;
}
/* PAGE META */
main > section[role="page-meta"] {
width: 100%;
background: var(--highlight);
}
main > section[role="page-meta"] > div[role="page-meta-wrapper"] {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
width: 100%;
max-width: 900px;
margin: 10px auto;
color: var(--white);
}
main section[role="page-meta"] textarea#post-title-text {
background: var(--white);
font-family: var(--base-type);
width: 100%;
height: 80px;
font-size: 2em;
color: var(--primary);
}
main section[role="page-meta"] textarea#post-tags {
background: var(--white);
font-family: var(--base-type);
width: 100%;
height: 80px;
color: var(--primary);
}
main section[role="page-meta"] select {
background: var(--primary);
color: var(--secondary);
border-radius: 3px;
border-color: var(--primary);
width: 100%;
height: 45px;
padding: 5px;
font-size: 1.5em;
}
main section[role="page-meta"] div[role="page-options"] {
width: 100%;
}
main
section[role="page-meta"]
div[role="page-meta-wrapper"]
div[role="page-options"]
button {
width: 25%;
height: 45px;
transition: all 0.3s linear;
margin: 0;
border-radius: 0;
display: inline-block;
vertical-align: top;
text-align: center;
}
main
> section[role="page-meta"]
> div[role="page-meta-wrapper"]
> div[role="page-options"]
> button.post-option-btn:nth-child(3) {
border-radius: 3px 0 0 3px;
}
main
> section[role="page-meta"]
> div[role="page-meta-wrapper"]
> div[role="page-options"]
> a
> button {
border-radius: 0 3px 3px 0;
}
main
section[role="page-meta"]
div[role="page-meta-wrapper"]
button[data-active="false"] {
background: var(--primary);
}
main
section[role="page-meta"]
div[role="page-meta-wrapper"]
button[data-active="false"]
svg {
fill: var(--secondary);
}
main
section[role="page-meta"]
div[role="page-meta-wrapper"]
div[role="page-options"]
button[data-active="true"] {
background: var(--tertiary);
}
main
section[role="page-meta"]
div[role="page-meta-wrapper"]
div[role="page-options"]
button[data-active="true"]
svg {
fill: var(--primary);
}
main
section[role="page-meta"]
div[role="page-meta-wrapper"]
div[role="page-created"]
input {
display: none;
visibility: hidden;
}
/* TEXT EDITOR */
main > section[role="text-editor"] {
width: 100%;
max-width: 900px;
margin: 0 auto;
}
main section[role="text-editor"] .icon-hide {
display: none;
visibility: hidden;
}
main > section[role="text-editor"] > div[role="text-editor-control"] {
display: grid;
grid-template-columns: repeat(10, 1fr);
}
.control-freeze {
position: fixed;
z-index: 300;
width: 97%;
top: 65px;
}
main > section[role="text-editor"] > div[role="edit-post-wrapper"] {
width: 100%;
max-width: 900px;
border-radius: 5px;
position: relative;
margin: 10px 0;
}
main
> section[role="text-editor"]
> div[role="edit-post-wrapper"]
textarea:focus {
outline: none;
border-color: var(--highlight);
}
main section[role="text-editor"] div[role="edit-post-wrapper"] #edit,
main section[role="text-editor"] div[role="edit-post-wrapper"] #highlight {
font-family: var(--mono-type);
border: 0;
width: 100%;
min-height: 300px;
height: auto;
position: absolute;
top: 0;
left: 0;
overflow: auto;
word-wrap: normal;
white-space: pre-wrap;
line-break: normal;
font-size: 1.1em;
line-height: 1.2;
padding: 0;
margin: 0;
}
main
section[role="text-editor"]
div[role="edit-post-wrapper"]
#highlight-content {
word-wrap: normal;
white-space: pre-wrap;
line-break: normal;
}
main > section[role="text-editor"] > div[role="edit-post-wrapper"] > #edit {
z-index: 1;
background: transparent;
color: transparent;
caret-color: var(--highlight);
}
main
> section[role="text-editor"]
> div[role="edit-post-wrapper"]
> #highlight {
z-index: 0;
}
main section[role="text-editor"] div[role="edit-post-wrapper"] pre,
main section[role="text-editor"] div[role="edit-post-wrapper"] pre code {
padding: 0;
margin: 0;
}
/* RESPONSIVE */
@media only screen and (max-width: 900px) {
main > section[role="file-manager"] > div[role="file-drop"],
main > section[role="file-manager"] > div[role="page-images-list"],
main > section[role="file-manager"] > div[role="page-files-list"],
main > section[role="page-meta"] > div[role="page-meta-wrapper"],
main > section[role="text-editor"] {
width: 97%;
}
}
@media only screen and (max-width: 480px) {
main > section[role="file-manager"] > div[role="page-images-list"],
main > section[role="file-manager"] > div[role="page-files-list"] {
grid-template-columns: 1fr 1fr 1fr;
}
main > section[role="file-manager"] > div[role="file-drop"],
main > section[role="file-manager"] > div[role="page-images-list"],
main > section[role="file-manager"] > div[role="page-files-list"],
main > section[role="page-meta"] > div[role="page-meta-wrapper"],
main > section[role="text-editor"] {
width: 95%;
}
main > section[role="page-meta"] > div[role="page-meta-wrapper"] {
grid-template-columns: 1fr;
}
main > section[role="text-editor"] > div[role="text-editor-control"] {
display: grid;
grid-template-columns: repeat(5, 1fr);
}
main
> section[role="text-editor"]
> div[role="text-editor-control"]
> button:nth-child(1) {
border-radius: 3px 0;
}
main
> section[role="text-editor"]
> div[role="text-editor-control"]
> button:nth-child(5) {
border-radius: 0 3px;
}
main
> section[role="text-editor"]
> div[role="text-editor-control"]
> button:nth-child(6) {
border-radius: 0 0 0 3px;
}
main
> section[role="text-editor"]
> div[role="text-editor-control"]
> button:nth-child(10) {
border-radius: 0 0 3px;
}
main section[role="text-editor"] div[role="edit-post-wrapper"] #edit,
main section[role="text-editor"] div[role="edit-post-wrapper"] #highlight {
font-size: 0.8em;
}
}

View file

@ -1,275 +0,0 @@
article[role="settings"] {
margin: 100px auto;
width: 100%;
max-width: 900px;
transition: all 0.8s linear;
}
article[role="settings"] h1 {
color: var(--white);
}
article[role="settings"] label {
color: var(--secondary);
margin-bottom: 10px;
display: inline-block;
font-weight: 400;
}
section[role="member-settings"] {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-auto-columns: auto;
gap: 15px;
width: 100%;
max-width: 900px;
margin: 10px auto;
}
section[role="member-settings"] > div:nth-child(1) {
grid-column: 1/2;
grid-row: 1/3;
}
section[role="member-settings"] > div:nth-child(2) {
grid-column: 2/4;
grid-row: 1/3;
}
section[role="member-settings"] > div:nth-child(3) {
grid-row: 1/3;
}
section[role="member-settings"] > div:nth-child(4) {
color: var(--white);
}
section[role="member-settings"] > div:nth-child(4) a {
font-weight: bold;
text-decoration: underline;
color: var(--tertiary);
}
section[role="member-settings"] > div:nth-child(5) {
grid-column: 2/4;
}
section[role="member-settings"] > div:nth-child(6) {
grid-column: 1/3;
}
section[role="member-settings"] > div:nth-child(7) {
grid-column: 3/5;
min-height: 325px;
}
section[role="member-settings"] > div:nth-child(8) {
grid-column: 1/4;
color: var(--white);
word-wrap: break-word;
}
section[role="member-settings"] > div[role="member-avatar"] div,
section[role="member-settings"] > div[role="site-background"] div {
height: 100%;
border-radius: 3px;
}
section[role="member-settings"] div input[type="file"] {
display: none;
visibility: hidden;
}
section[role="member-settings"] div input[type="text"] {
width: 98.4%;
height: 40px;
margin-bottom: 10px;
}
section[role="member-settings"] div textarea {
width: 98.4%;
height: 63%;
}
article[role="settings"] button {
width: 100%;
text-align: left;
height: 50px;
margin-bottom: 5px;
}
article[role="settings"] button > span {
font-size: 0.8em;
display: inline;
top: -10px;
position: relative;
}
section[role="member-settings"]
> div[role="features"]
button[data-enabled="true"] {
color: var(--white);
}
section[role="member-settings"]
> div[role="features"]
button[data-enabled="false"] {
color: var(--primary);
background: var(--secondary);
}
section[role="member-settings"]
> div[role="theme"]
button[data-enabled="true"] {
color: var(--white);
background: var(--highlight);
display: block;
border-radius: 3px;
padding: 3px;
}
section[role="member-settings"]
> div[role="theme"]
button[data-enabled="false"] {
color: var(--primary);
background: var(--secondary);
display: block;
border-radius: 3px;
padding: 3px;
}
section[role="member-settings"] > div[role="mail"] a {
margin-right: 3px;
color: var(--secondary);
display: inline-block;
height: 40px;
padding: 15px 0 0;
border-top: var(--primary) 1px solid;
}
section[role="member-settings"] > div[role="mail"] a[data-enabled="true"] {
color: var(--tertiary);
font-weight: bold;
border-top: var(--highlight) 1px solid;
}
section[role="member-settings"] > div[role="mail"] div[data-enabled="false"] {
visibility: hidden;
display: none;
}
section[role="member-settings"] > div[role="mail"] input {
width: 98.4%;
height: 40px;
padding-left: 5px;
margin-bottom: 10px;
}
section[role="data-settings"] {
color: var(--white);
}
@media only screen and (max-width: 900px) {
main > article[role="settings"] {
width: 97%;
}
}
@media only screen and (max-width: 650px) {
section[role="member-settings"] div input[type="text"] {
width: 99.3%;
height: 40px;
margin-bottom: 10px;
}
section[role="member-settings"] {
grid-template-columns: 1fr 1fr;
}
section[role="member-settings"] > div[role="mail"] input {
width: 97.7%;
height: 40px;
padding-left: 5px;
margin-bottom: 10px;
}
section[role="member-settings"] div textarea {
height: 80px;
width: 99.3%;
}
section[role="member-settings"] > div:nth-child(1) {
grid-column: 1/2;
grid-row: 1/3;
height: 200px;
}
section[role="member-settings"] > div:nth-child(2) {
grid-column: 2/3;
grid-row: 1/3;
}
section[role="member-settings"] > div:nth-child(3) {
grid-column: 1/3;
grid-row: 3/5;
}
section[role="member-settings"] > div:nth-child(4) {
grid-column: 1/2;
}
section[role="member-settings"] > div:nth-child(5) {
grid-column: 2/3;
}
section[role="member-settings"] > div:nth-child(6) {
grid-column: 1/2;
}
section[role="member-settings"] > div:nth-child(7) {
grid-column: 2/3;
min-height: 325px;
}
section[role="member-settings"] > div:nth-child(8) {
grid-column: 1/3;
}
}
@media only screen and (max-width: 530px) {
section[role="member-settings"] > div[role="mail"] input {
width: 98.5%;
}
section[role="member-settings"] {
grid-template-columns: 100%;
}
section[role="member-settings"] div textarea {
height: 80px;
}
section[role="member-settings"] > div:nth-child(1) {
grid-row: 1/3;
height: 200px;
}
section[role="member-settings"] > div:nth-child(2) {
grid-row: 3/5;
grid-column: 1;
height: 200px;
}
section[role="member-settings"] > div:nth-child(3) {
grid-column: 1;
grid-row: 5/7;
}
section[role="member-settings"] > div:nth-child(4),
section[role="member-settings"] > div:nth-child(5),
section[role="member-settings"] > div:nth-child(6),
section[role="member-settings"] > div:nth-child(7),
section[role="member-settings"] > div:nth-child(8) {
grid-column: 1;
}
}

View file

@ -1,13 +0,0 @@
@import url("colors.css");
@import url("forms.css");
@import url("typography.css");
@import url("frame.css");
@import url("icons.css");
@import url("notifications.css");
@import url("init.css");
@import url("index.css");
@import url("book.css");
@import url("page-editor.css");
@import url("page-editor-highlights.css");
@import url("settings.css");
@import url("navigation.css");

View file

@ -1,29 +0,0 @@
:root {
--base-type: helvetica, arial, sans-serif;
--mono-type: "Lucida Console", monaco, monospace;
}
h1,
h2,
h3 {
color: var(--white);
}
h1 {
font-size: 2em;
font-weight: 700;
}
h2 {
font-size: 1.6em;
font-weight: 600;
}
h3 {
font-size: 1.3em;
font-weight: 500;
}
main > article > h1 {
color: var(--primary);
}

View file

@ -1,33 +1,33 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 462 462" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> <svg width="100%" height="100%" viewBox="0 0 486 678" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1.58717,0,0,1.58717,-403.964,-376.506)"> <g id="Logo" transform="matrix(1.36867,0,0,1.36867,-351.696,-71.9183)">
<g transform="matrix(1,0,0,1,200.753,94.1743)"> <g transform="matrix(2.31599,0,0,2.31599,218.53,-99.4797)">
<circle cx="92.268" cy="181.547" r="38.502" style="fill:rgb(252,99,153);"/> <path d="M93.67,140.92L93.67,140.921C105.569,140.921 115.216,150.567 115.216,162.467L115.216,172.724L115.216,172.724L115.216,182.262C115.216,194.161 105.569,203.808 93.669,203.808C81.976,203.217 74.12,195.969 72.237,184.474L72.282,182.737L72.282,162.467L72.205,160.847C72.775,149.587 82.728,141.121 93.67,140.92Z" style="fill:rgb(252,99,153);fill-rule:nonzero;"/>
</g> </g>
<g transform="matrix(1,0,0,1,200.753,201.192)"> <g transform="matrix(2.31599,0,0,2.31599,218.53,-437.697)">
<circle cx="92.268" cy="181.547" r="38.502" style="fill:rgb(252,99,153);"/> <path d="M93.67,211.678L93.67,211.678C105.569,211.678 115.216,221.324 115.216,233.224L115.216,243.481L115.216,243.481L115.216,253.019C115.216,264.919 105.569,274.565 93.669,274.565C81.976,273.975 74.12,266.726 72.237,255.232L72.282,253.495L72.282,233.224L72.205,231.604C72.775,220.344 82.728,211.878 93.67,211.678Z" style="fill:rgb(252,99,153);fill-rule:nonzero;"/>
</g> </g>
<g transform="matrix(1,0,0,1,307.732,201.192)"> <g transform="matrix(2.31599,0,0,2.31599,218.53,241.338)">
<circle cx="92.268" cy="181.547" r="38.502" style="fill:rgb(252,99,153);"/> <path d="M93.67,69.288L93.67,69.288C105.569,69.288 115.216,78.934 115.216,90.834L115.216,101.091L115.216,101.091L115.216,110.629C115.216,122.528 105.569,132.175 93.669,132.175C81.976,131.584 74.12,124.336 72.237,112.842L72.282,111.105L72.282,90.834L72.205,89.214C72.775,77.954 82.728,69.488 93.67,69.288Z" style="fill:rgb(171,183,183);fill-rule:nonzero;"/>
</g> </g>
<g transform="matrix(1,0,0,1,414.761,201.192)"> <g transform="matrix(2.31599,0,0,2.31599,218.53,-104.112)">
<circle cx="92.268" cy="181.547" r="38.502" style="fill:rgb(171,183,183);"/> <path d="M38.059,142.92L38.059,142.921C49.958,142.921 59.605,152.567 59.605,164.467L59.605,174.724L59.605,174.724L59.605,184.262C59.605,196.161 49.958,205.808 38.058,205.808C26.365,205.217 18.509,197.969 16.626,186.474L16.671,184.737L16.671,164.467L16.594,162.847C17.164,151.587 27.117,143.121 38.059,142.92Z" style="fill:rgb(252,99,153);fill-rule:nonzero;"/>
</g> </g>
<g transform="matrix(1,0,0,1,200.753,308.228)"> <g transform="matrix(2.31599,0,0,2.31599,218.53,-104.112)">
<circle cx="92.268" cy="181.547" r="38.502" style="fill:rgb(252,99,153);"/> <path d="M148.331,142.92L148.331,142.921C160.23,142.921 169.877,152.567 169.877,164.467L169.877,174.724L169.877,174.724L169.877,184.262C169.877,196.161 160.23,205.808 148.331,205.808C136.637,205.217 128.782,197.969 126.898,186.474L126.943,184.737L126.943,164.467L126.867,162.847C127.436,151.587 137.389,143.121 148.331,142.92Z" style="fill:rgb(171,183,183);fill-rule:nonzero;"/>
</g> </g>
<g transform="matrix(1,0,0,1,307.732,308.228)"> <g transform="matrix(2.31599,0,0,2.31599,218.53,-437.697)">
<circle cx="92.268" cy="181.547" r="38.502" style="fill:rgb(171,183,183);"/> <path d="M38.059,211.678L38.059,211.678C49.958,211.678 59.605,221.324 59.605,233.224L59.605,243.481L59.605,243.481L59.605,253.019C59.605,264.919 49.958,274.565 38.058,274.565C26.365,273.975 18.509,266.726 16.626,255.232L16.671,253.495L16.671,233.224L16.594,231.604C17.164,220.344 27.117,211.878 38.059,211.678Z" style="fill:rgb(252,99,153);fill-rule:nonzero;"/>
</g> </g>
<g transform="matrix(1,0,0,1,414.761,308.228)"> <g transform="matrix(2.31599,0,0,2.31599,218.53,-437.697)">
<circle cx="92.268" cy="181.547" r="38.502" style="fill:rgb(171,183,183);"/> <path d="M148.331,211.678L148.331,211.678C160.23,211.678 169.877,221.324 169.877,233.224L169.877,243.481L169.877,243.481L169.877,253.019C169.877,264.919 160.23,274.565 148.331,274.565C136.637,273.975 128.782,266.726 126.898,255.232L126.943,253.495L126.943,233.224L126.867,231.604C127.436,220.344 137.389,211.878 148.331,211.678Z" style="fill:rgb(252,99,153);fill-rule:nonzero;"/>
</g> </g>
<g transform="matrix(1,0,0,1,414.761,94.1743)"> <g transform="matrix(2.31599,0,0,2.31599,218.53,241.338)">
<circle cx="92.268" cy="181.547" r="38.502" style="fill:rgb(252,99,153);"/> <path d="M38.059,69.288L38.059,69.288C49.958,69.288 59.605,78.934 59.605,90.834L59.605,101.091L59.605,101.091L59.605,110.629C59.605,122.528 49.958,132.175 38.058,132.175C26.365,131.584 18.509,124.336 16.626,112.842L16.671,111.105L16.671,90.834L16.594,89.214C17.164,77.954 27.117,69.488 38.059,69.288Z" style="fill:rgb(252,99,153);fill-rule:nonzero;"/>
</g> </g>
<g transform="matrix(6.12323e-17,1,-1,6.12323e-17,581.547,183.453)"> <g transform="matrix(2.31599,0,0,2.31599,218.53,241.338)">
<circle cx="92.268" cy="181.547" r="38.502" style="fill:rgb(252,99,153);"/> <path d="M148.331,69.288L148.331,69.288C160.23,69.288 169.877,78.934 169.877,90.834L169.877,101.091L169.877,101.091L169.877,110.629C169.877,122.528 160.23,132.175 148.331,132.175C136.637,131.584 128.782,124.336 126.898,112.842L126.943,111.105L126.943,90.834L126.867,89.214C127.436,77.954 137.389,69.488 148.331,69.288Z" style="fill:rgb(171,183,183);fill-rule:nonzero;"/>
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -1,11 +1,7 @@
<?php <?php
//load Composer Classes require "../vendor/autoload.php";
require '../vendor/autoload.php';
//load Fipamo Classes
require '../brain/_loader.php';
use brain\init\App; use brain\init\App as App;
//start app
new App(); new App();

View file

@ -1,40 +1,40 @@
//** REQUEST TYPES **// //** REQUEST TYPES **//
export const REQUEST_TYPE_POST = 'POST'; export const REQUEST_TYPE_POST = "POST";
export const REQUEST_TYPE_GET = 'GET'; export const REQUEST_TYPE_GET = "GET";
export const REQUEST_TYPE_PUT = 'PUT'; export const REQUEST_TYPE_PUT = "PUT";
export const REQUEST_TYPE_DELETE = 'DELETE'; export const REQUEST_TYPE_DELETE = "DELETE";
//** POST CONTENT TYPES **// //** POST CONTENT TYPES **//
export const CONTENT_TYPE_JSON = 'json'; export const CONTENT_TYPE_JSON = "json";
export const CONTENT_TYPE_FORM = 'x-www-form-urlencoded'; export const CONTENT_TYPE_FORM = "x-www-form-urlencoded";
//** API URLS **// //** API URLS **//
export const API_STATUS = '/api/v1/status'; export const API_STATUS = "/api/v1/status";
export const API_GET_SETTINGS = '/api/v1/settings/site'; export const API_GET_SETTINGS = "/api/v1/settings/site";
export const API_GET_MEMBER_INFO = '/api/v1/settings/member'; export const API_GET_MEMBER_INFO = "/api/v1/settings/member";
export const API_NEW_PAGE = '/api/v1/page/create'; export const API_NEW_PAGE = "/api/v1/page/create";
export const API_EDIT_PAGE = '/api/v1/page/write'; export const API_EDIT_PAGE = "/api/v1/page/write";
export const API_DELETE_PAGE = '/api/v1/page/delete'; export const API_DELETE_PAGE = "/api/v1/page/delete";
export const API_SETTINGS_SYNC = '/api/v1/settings/sync'; export const API_SETTINGS_SYNC = "/api/v1/settings/sync";
export const API_PUBLISH_PAGES = '/api/v1/settings/publish'; export const API_PUBLISH_PAGES = "/api/v1/settings/publish";
export const API_NAV_SYNC = '/api/v1/settings/nav-sync'; export const API_NAV_SYNC = "/api/v1/settings/nav-sync";
export const API_REINDEX_PAGES = '/api/v1/settings/reindex'; export const API_REINDEX_PAGES = "/api/v1/settings/reindex";
export const API_SEND_MAIL = '/api/v1/mailer'; export const API_SEND_MAIL = "/api/v1/mailer";
export const API_LOGIN = '/api/v1/login'; export const API_LOGIN = "/api/v1/login";
//** API TASKS **// //** API TASKS **//
export const AUTH_STATUS = 'getAuthStatus'; export const AUTH_STATUS = "getAuthStatus";
export const TASK_SETTINGS_WRITE = 'writeSettings'; export const TASK_SETTINGS_WRITE = "writeSettings";
export const TASK_PUBLISH_SITE = 'publishSite'; export const TASK_PUBLISH_SITE = "publishSite";
export const TASK_PAGE_CREATE = 'createNewPage'; export const TASK_PAGE_CREATE = "createNewPage";
export const TASK_PAGE_EDIT = 'editPage'; export const TASK_PAGE_EDIT = "editPage";
export const TASK_PAGE_DELETE = 'deletePage'; export const TASK_PAGE_DELETE = "deletePage";
export const TASK_SEND_MAIL = 'sendMail'; export const TASK_SEND_MAIL = "sendMail";
export const TASK_REINDEX_PAGE = 'reIndexPages'; export const TASK_REINDEX_PAGE = "reIndexPages";
export const TASK_SYNC_SETTNIGS = 'syncSite'; export const TASK_SYNC_SETTNIGS = "syncSite";
export const TASK_SYNC_NAV = 'syncNav'; export const TASK_SYNC_NAV = "syncNav";
export const TASK_GET_SETTINGS = 'getSiteSettings'; export const TASK_GET_SETTINGS = "getSiteSettings";
export const TASK_GET_MEMBER_INFO = 'getMemberInfo'; export const TASK_GET_MEMBER_INFO = "getMemberInfo";
//** API STATUS **// //** API STATUS **//
export const API_ACCESS_GOOD = 'apiUseAuthorized'; export const API_ACCESS_GOOD = "apiUseAuthorized";
export const API_ACCESS_BAD = 'apiUseNotAuthorized'; export const API_ACCESS_BAD = "apiUseNotAuthorized";
/** /**
* A can of methods used to edit install settings, navigation pages and content pages * A can of methods used to edit install settings, navigation pages and content pages
@ -54,7 +54,7 @@ class FipamoAdminAPI {
if (baseURL) this.baseURL = baseURL; if (baseURL) this.baseURL = baseURL;
//asks server if a session is active //asks server if a session is active
this._request(this.baseURL ? this.baseURL + API_STATUS : API_STATUS).then( this._request(this.baseURL ? this.baseURL + API_STATUS : API_STATUS).then(
response => { (response) => {
if (response.type === API_ACCESS_GOOD) { if (response.type === API_ACCESS_GOOD) {
this.token = response.token; this.token = response.token;
} else { } else {
@ -93,10 +93,10 @@ class FipamoAdminAPI {
CONTENT_TYPE_JSON, CONTENT_TYPE_JSON,
data data
) )
.then(result => { .then((result) => {
resolve(result); resolve(result);
}) })
.catch(err => { .catch((err) => {
reject(err); reject(err);
}); });
}); });
@ -142,12 +142,12 @@ class FipamoAdminAPI {
*/ */
sync(task, data) { sync(task, data) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let url = ''; let url = "";
switch (task) { switch (task) {
case 'syncSite': case "syncSite":
url = API_SETTINGS_SYNC; url = API_SETTINGS_SYNC;
break; break;
case 'syncNav': case "syncNav":
url = API_NAV_SYNC; url = API_NAV_SYNC;
break; break;
} }
@ -158,10 +158,10 @@ class FipamoAdminAPI {
CONTENT_TYPE_JSON, CONTENT_TYPE_JSON,
data data
) )
.then(result => { .then((result) => {
resolve(result); resolve(result);
}) })
.catch(err => { .catch((err) => {
reject(err); reject(err);
}); });
}); });
@ -193,10 +193,10 @@ class FipamoAdminAPI {
CONTENT_TYPE_JSON, CONTENT_TYPE_JSON,
data data
) )
.then(result => { .then((result) => {
resolve(result); resolve(result);
}) })
.catch(err => { .catch((err) => {
reject(err); reject(err);
}); });
}); });
@ -239,18 +239,18 @@ class FipamoAdminAPI {
case TASK_PAGE_CREATE: case TASK_PAGE_CREATE:
url = API_NEW_PAGE; url = API_NEW_PAGE;
event = TASK_PAGE_CREATE; event = TASK_PAGE_CREATE;
content = CONTENT_TYPE_JSON; content = CONTENT_TYPE_FORM;
break; break;
case TASK_PAGE_EDIT: case TASK_PAGE_EDIT:
url = API_EDIT_PAGE; url = API_EDIT_PAGE;
event = TASK_PAGE_EDIT; event = TASK_PAGE_EDIT;
content = CONTENT_TYPE_JSON; content = CONTENT_TYPE_FORM;
break; break;
case TASK_PAGE_DELETE: case TASK_PAGE_DELETE:
url = API_DELETE_PAGE; url = API_DELETE_PAGE;
event = TASK_PAGE_DELETE; event = TASK_PAGE_DELETE;
content = CONTENT_TYPE_JSON; content = CONTENT_TYPE_FORM;
break; break;
default: default:
@ -272,10 +272,10 @@ class FipamoAdminAPI {
content, content,
data data
) )
.then(result => { .then((result) => {
resolve(result); resolve(result);
}) })
.catch(err => { .catch((err) => {
reject(err); reject(err);
}); });
}); });
@ -307,10 +307,10 @@ class FipamoAdminAPI {
CONTENT_TYPE_JSON, CONTENT_TYPE_JSON,
message message
) )
.then(result => { .then((result) => {
resolve(result); resolve(result);
}) })
.catch(err => { .catch((err) => {
reject(err); reject(err);
}); });
}); });
@ -338,7 +338,7 @@ class FipamoAdminAPI {
getInfo(type) { getInfo(type) {
let url, task; let url, task;
if (type == 'site') { if (type == "site") {
url = API_GET_SETTINGS; url = API_GET_SETTINGS;
task = TASK_GET_SETTINGS; task = TASK_GET_SETTINGS;
} else { } else {
@ -347,10 +347,10 @@ class FipamoAdminAPI {
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this._request(this.baseURL ? this.baseURL + url : url, task) this._request(this.baseURL ? this.baseURL + url : url, task)
.then(result => { .then((result) => {
resolve(result); resolve(result);
}) })
.catch(err => { .catch((err) => {
reject(err); reject(err);
}); });
}); });
@ -369,16 +369,16 @@ class FipamoAdminAPI {
var self = this; var self = this;
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
var request = new XMLHttpRequest(); var request = new XMLHttpRequest();
request.upload.addEventListener('progress', e => request.upload.addEventListener("progress", (e) =>
self.handleLoadProgress(e, self.progressBar) self.handleLoadProgress(e, self.progressBar)
); );
request.open(requestType, requestURL, true); request.open(requestType, requestURL, true);
request.onload = () => { request.onload = () => {
if (request.status == 200) { if (request.status == 200) {
let response = JSON.parse(request['response']); let response = JSON.parse(request["response"]);
resolve(response); resolve(response);
} else { } else {
let error = JSON.parse(request['response']); let error = JSON.parse(request["response"]);
reject(error); reject(error);
} }
}; };
@ -391,13 +391,13 @@ class FipamoAdminAPI {
eventType === TASK_PUBLISH_SITE || eventType === TASK_PUBLISH_SITE ||
eventType === TASK_REINDEX_PAGE eventType === TASK_REINDEX_PAGE
) )
request.setRequestHeader('fipamo-access-token', self.token); request.setRequestHeader("fipamo-access-token", self.token);
switch (contentType) { switch (contentType) {
case CONTENT_TYPE_JSON: case CONTENT_TYPE_JSON:
request.setRequestHeader( request.setRequestHeader(
'Content-type', "Content-type",
'application/' + contentType "application/" + contentType
); );
request.send(JSON.stringify(requestData)); request.send(JSON.stringify(requestData));
break; break;
@ -410,7 +410,7 @@ class FipamoAdminAPI {
eventType === TASK_GET_SETTINGS || eventType === TASK_GET_SETTINGS ||
eventType === TASK_GET_MEMBER_INFO eventType === TASK_GET_MEMBER_INFO
) { ) {
request.setRequestHeader('fipamo-access-token', self.token); request.setRequestHeader("fipamo-access-token", self.token);
} }
request.send(); request.send();
} }
@ -424,7 +424,7 @@ class FipamoAdminAPI {
let percent = Math.ceil((e.loaded / e.total) * 100); let percent = Math.ceil((e.loaded / e.total) * 100);
//if a progress bar element is present, talk to it //if a progress bar element is present, talk to it
if (progressBar != null) { if (progressBar != null) {
progressBar.style.width = percent + '%'; progressBar.style.width = percent + "%";
} }
} }
} }

View file

@ -1,43 +0,0 @@
@use "sass:color";
//CSS
//Bulma
@import "../../node_modules/bulma/sass/utilities/_all";
@import "../../node_modules/bulma/sass/grid/columns";
//Colors
@import "main/_colors";
//Mixins
@import "main/_mixins";
//Normalize
@import "main/_normalize";
//Typography
@import "main/_typography";
//Main Structure
@import "main/_structure";
//Index
@import "main/_index";
//Settings
@import "main/_settings";
//Error
@import "main/_error";
//Navigation
@import "main/_navigation";
//Forms
@import "main/_forms";
//Posts
@import "main/_posts";
//Editor
@import "main/_calendar";
@import "main/_editor";
@import "main/_editor-highlight";

View file

@ -1,327 +0,0 @@
.dp-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2000;
}
.dp {
position: relative;
background: $primary;
box-shadow: 2px 2px 16px rgba(#000, 0.25);
line-height: 1.4;
border-radius: 4px;
max-height: 400px;
z-index: 5000;
padding-top: 6px;
overflow: hidden;
-webkit-tap-highlight-color: transparent;
}
.dp::before {
content: ' ';
height: 6px;
position: absolute;
top: 0;
left: 0;
right: 0;
background: $highlight;
}
.dp-permanent .dp {
padding-top: 0;
border: 1px solid #eee;
box-shadow: none;
}
.dp-permanent .dp::before {
display: none;
}
.dp-cal {
min-height: 300px;
}
.dp-below {
position: absolute;
font-size: 0.8em;
width: 400px;
max-width: 90vw;
}
.dp-permanent {
position: relative;
font-size: 0.8em;
width: 400px;
max-width: 100vw;
}
.dp-permanent .dp {
z-index: 0;
}
.dp-modal .dp {
position: absolute;
top: 50%;
left: 50%;
max-width: 600px;
width: calc(100% - 4em);
transform: translate(-50%, -50%);
animation: slide-up 0.3s forwards;
}
.dp-months {
padding: 24px;
}
.dp-years {
box-sizing: border-box;
max-height: 400px;
padding: 8px 0;
/* HACK for Chrome on Android */
overflow: auto !important;
}
.dp-cal-month,
.dp-cal-year,
.dp-day,
.dp-month,
.dp-year {
box-sizing: border-box;
text-align: center;
text-decoration: none;
position: relative;
color: $white;
border-radius: 2px;
border: 0;
background: transparent;
}
.dp-cal-header {
position: relative;
text-align: center;
padding-bottom: 16px;
background: color.adjust($primary, $lightness: -10%);
}
.dp-next,
.dp-prev {
position: absolute;
width: 30px;
height: 30px;
overflow: hidden;
top: 14px;
color: color.adjust($primary, $lightness: -50%);
border-radius: 2px;
border: 0;
background: transparent;
}
.dp-prev {
left: 24px;
}
.dp-next {
right: 24px;
}
.dp-next:focus,
.dp-prev:focus,
.dp-next:hover,
.dp-prev:hover {
outline: none;
color: inherit;
}
.dp-prev::before,
.dp-next::before {
content: '';
border: 2px solid;
width: 10px;
height: 10px;
display: inline-block;
transform: rotate(-45deg);
transition: border-color 0.2s;
margin: 9px 0 40px 4px;
}
.dp-prev::before {
border-right: 0;
border-bottom: 0;
}
.dp-next::before {
border-left: 0;
border-top: 0;
margin-left: 0;
margin-right: 4px;
}
.dp-cal-month,
.dp-cal-year {
display: inline-block;
font-size: 1.4em;
padding: 16px 8px 8px;
outline: none;
}
.dp-cal-footer {
text-align: center;
background: color.adjust($primary, $lightness: -10%);
}
.dp-day-today::after {
content: '';
height: 0;
width: 0;
border: 7px solid $highlight;
border-bottom-color: transparent;
border-left-color: transparent;
position: absolute;
top: 0;
right: 0;
}
.dp-close,
.dp-clear,
.dp-today {
box-sizing: border-box;
display: inline-block;
width: 33%;
padding: 8px;
text-decoration: none;
color: color.adjust($primary, $lightness: -50%);
border: 0;
background: transparent;
}
.dp-permanent .dp-close,
.dp-permanent .dp-clear {
display: none;
}
.dp-close:active,
.dp-clear:active,
.dp-today:active,
.dp-next:active,
.dp-prev:active,
.dp-cal-month:active,
.dp-cal-year:active {
background: $highlight;
color: $white;
}
@media screen and (min-device-width: 1200px) {
.dp-close:hover,
.dp-close:focus,
.dp-clear:hover,
.dp-clear:focus,
.dp-today:hover,
.dp-today:focus,
.dp-next:hover,
.dp-next:focus,
.dp-prev:hover,
.dp-prev:focus,
.dp-cal-month:focus,
.dp-cal-month:hover,
.dp-cal-year:hover,
.dp-cal-year:focus {
background: $highlight;
color: $white;
}
}
.dp-col-header,
.dp-day {
width: 14.2857%;
display: inline-block;
padding: 8px;
text-align: center;
}
.dp-col-header {
color: #aaa;
text-transform: uppercase;
font-weight: 300;
font-size: 0.8em;
padding: 8px 0;
}
.dp-month {
width: 33%;
display: inline-block;
padding: 8px;
}
.dp-year {
display: block;
padding: 8px 40px;
width: 100%;
}
.dp-edge-day {
color: #aaa;
}
.dp-current,
.dp-day:hover,
.dp-month:hover,
.dp-year:hover,
.dp-current:focus,
.dp-day:focus,
.dp-month:focus,
.dp-year:focus {
outline: none;
background: color.adjust($primary, $lightness: -40%);
color: $white;
}
.dp-selected:hover,
.dp-selected:focus,
.dp-selected {
background: $highlight;
color: color.adjust($primary, $lightness: -60%);
}
.dp-day-disabled {
background: transparent;
color: #ddd;
}
.dp-day-disabled:focus,
.dp-day-disabled:hover {
background: #ddd;
}
.dp-focuser {
position: absolute;
z-index: 0;
top: 50%;
left: 50%;
}
// Responsive
@media (max-width: 480px), (max-height: 480px) {
.dp-modal .dp {
font-size: 0.9em;
width: auto;
width: 100%;
}
.dp-day-of-week,
.dp-day {
padding: 8px;
}
}
@keyframes slide-up {
0% {
transform: translate(-50%, 100%);
}
100% {
transform: translate(-50%, -50%);
}
} ;

View file

@ -1,16 +0,0 @@
$primary: #1d3040;
$secondary: #b2cce5;
$tertiary: #f5ab35;
$highlight: #fc6399;
$white: #efebe3;
$grey: #abb7b7;
$black: #32302f;
// editor colors
$event-cool: #32cd32;
$event-lame: #f64747;
$editor-primary: #fde3a7;
$editor-secondary: #e7903c;
$editor-tertiary: #6bb9f0;
$editor-string: #dcc6e0;
$editor-tag: #e73c4e;

View file

@ -1,117 +0,0 @@
code[class*='language-'],
pre[class*='language-'] {
color: $editor-primary;
background: none;
text-shadow: 0 1px rgba(#000, 0.3);
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
tab-size: 4;
hyphens: none;
}
pre[class*='language-'] {
// padding: 1em
margin: 0.1em 0;
overflow: auto;
border-radius: 0.3em;
}
:not(pre) > code[class*='language-'],
pre[class*='language-'] {
background: $primary;
}
:not(pre) {
& > code[class*='language-'] {
padding: 0.1em;
border-radius: 0.3em;
white-space: normal;
}
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #8292a2;
}
.token {
&.punctuation {
color: $editor-secondary;
}
&.namespace {
opacity: 0.6;
}
&.keyword {
color: #66d9ef;
}
&.italic {
font-style: italic;
}
&.entity {
cursor: help;
}
&.content {
color: $editor-tertiary;
}
}
.token.property,
.token.tag,
.token.constant,
.token.symbol,
.token.deleted {
color: $editor-tag;
}
.token.boolean,
.token.number {
color: #ae81ff;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #a6e22e;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string,
.token.variable {
color: $editor-string;
}
.token.atrule,
.token.attr-value,
.token.function,
.token.class-name {
color: #e6db74;
}
.token.regex,
.token.important {
color: $editor-secondary;
}
.token.important,
.token.bold {
font-weight: bold;
}

View file

@ -1,120 +0,0 @@
#edit-control {
// margin 10px
top: 1px;
border-radius: 3px;
width: 100%;
max-width: 880px;
margin-top: 30px;
z-index: 2000;
button {
background: $secondary;
width: 10%;
height: 39px;
transition: all 0.3s linear;
margin: 0;
border-radius: 0;
display: inline-block;
vertical-align: top;
text-align: center;
svg.icons {
fill: $primary;
}
}
button:nth-child(1) {
border-radius: 3px 0 0 3px;
}
button:nth-child(10) {
border-radius: 0 3px 3px 0;
}
button:hover {
background: color.adjust($secondary, $lightness: -20%);
}
#option-update {
padding: 5px 5px 1px;
display: inline-block;
vertical-align: top;
text-align: center;
}
.icon-hide {
display: none;
visibility: hidden;
}
.submit-start {
background: $white;
svg {
fill: $event-cool !important;
}
}
.submit-cool {
background: $event-cool;
svg {
fill: $white;
}
}
.submit-delete {
background: $event-lame !important;
svg {
fill: $white !important;
}
}
#option-date {
height: 30px;
padding-top: 6px;
svg {
margin: -13px 5px 0 0;
display: inline-block;
vertical-align: top;
fill: $white;
}
}
.content-editor-btn-icon {
padding: 5px 5px 1px;
// border-radius 20px
color: $primary;
svg.edit-btn-icon {
fill: $primary;
}
}
.content-editor-btn-text {
padding: 5px;
// border-radius 20px
color: $primary;
}
#option-bold {
font-weight: bold;
text-decoration: none;
}
#option-italic {
font-weight: bold;
text-decoration: none;
font-style: italic;
}
#option-strikethrough {
font-weight: bold;
text-decoration: line-through;
font-style: italic;
}
}

View file

@ -1,27 +0,0 @@
#error-index {
width: 100%;
max-width: 900px;
margin: 0 auto;
padding: 10px;
height: 100%;
z-index: 10;
position: relative;
label#title {
font-size: 100px;
color: $highlight;
font-weight: 500;
}
label#message {
font-size: 50px;
color: $tertiary;
font-weight: 500;
}
label#error {
font-size: 25px;
color: $event-lame;
font-weight: 500;
}
}

View file

@ -1,71 +0,0 @@
form {
display: inline-block;
a {
color: $primary;
}
p {
background: $tertiary;
color: $primary;
padding: 5px;
display: block;
border-radius: 5px;
text-align: left;
}
}
input[type="email"],
input[type="password"],
input[type="text"] {
border: 0;
border-radius: 5px;
padding: 5px;
margin: 10px 5px 0 0;
font: 18px $basetype;
display: inline-block;
background: $primary;
color: $tertiary;
}
textarea {
border: 0;
border-radius: 3px;
color: $white;
font: 15px $basetype;
background: $primary;
}
button,
input[type="submit"] {
background: $highlight;
color: $primary;
font: 20px $basetype;
border-radius: 5px;
position: relative;
cursor: pointer;
border: 0;
padding: 10px 0 5px 0;
transition: all 0.3s linear;
}
select {
font: 14px $basetype;
border: 1px solid $secondary;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
color: $primary;
}
::-webkit-input-placeholder {
font: 25px $basetype;
color: $white;
}
:-moz-placeholder {
/* Firefox 18- */
font: 25px $basetype;
color: $white;
}
::-moz-placeholder {
/* Firefox 19+ */
font: 15px $basetype;
color: $white;
}
:-ms-input-placeholder {
font: 25px $basetype;
color: $white;
}

View file

@ -1,381 +0,0 @@
#dash-index-content {
width: 100%;
height: 100%;
margin: 0 auto;
#dash-index {
width: 100%;
height: 100%;
z-index: 10;
position: relative;
#dash-index-wrapper {
width: 100%;
height: 100%;
margin: 0 auto;
.dash-init,
.dash-restore {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: $primary;
form {
background: $white;
padding: 15px;
width: 300px;
border-radius: 5px;
text-align: center;
#the-logo {
width: 40px;
margin: 20px;
}
input {
width: 290px;
margin: 0 0 10px;
height: 30px;
}
button {
width: 300px;
}
div {
background: $primary;
color: $white;
border-radius: 3px;
padding: 5px;
label {
display: block;
padding: 5px;
color: $tertiary;
}
}
}
}
.dash-restore {
display: none;
visibility: hidden;
}
#dash-login {
width: 100%;
height: 100%;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
#dash-form,
#dash-reset {
width: 300px;
padding: 0.75em;
background: $white;
border-radius: 5px;
color: $white;
text-align: center;
#the-logo {
width: 40px;
margin: 20px;
}
input {
width: 290px;
margin: 0 0 10px;
height: 30px;
}
button {
width: 300px;
}
}
}
#dash-menu {
padding: 10px;
width: 90%;
max-width: 900px;
margin: 50px auto;
a {
display: inline-block;
vertical-align: top;
background: color.adjust($primary, $lightness: -60%);
width: 30%;
padding: 5px;
border-radius: 3px;
color: $white;
margin: 0 10px 10px 0;
&:hover {
background: color.adjust($primary, $lightness: -60%);
}
svg {
display: inline-block;
vertical-align: top;
fill: $white;
}
label {
display: inline-block;
margin-top: 5px;
width: 85%;
text-align: center;
cursor: pointer;
}
}
}
#dash-recent {
width: 100%;
max-width: 900px;
height: 100%;
padding: 5px 0 0;
margin: 0 auto;
#recent-list {
// padding: 5px
position: relative;
.recent-header {
height: 50px;
margin-top: 5px;
.index-header-left {
vertical-align: top;
display: inline-block;
width: 50%;
color: $white;
font-size: 3em;
}
.index-header-right {
width: 50%;
text-align: right;
vertical-align: top;
display: inline-block;
right: 10px;
color: $white;
a {
button {
border-radius: 3px;
margin-left: 10px;
svg {
transition: all 0.2s linear;
width: 40px;
height: 20px;
fill: $white;
}
}
}
}
}
a.post-link,
a.post-video-link {
font-size: 1.5em;
font-weight: 300;
display: inline-block;
border-radius: 3px;
vertical-align: top;
text-decoration: none;
position: relative;
overflow: hidden;
.post-video {
width: 100%;
height: 100%;
object-fit: cover;
position: absolute;
}
label {
font-size: 1.4em;
font-weight: 700;
color: $white;
padding: 5px;
vertical-align: top;
display: inline-block;
word-wrap: break-word;
width: 100%;
text-align: center;
position: relative;
top: 35%;
text-shadow: 2px 2px 0 rgba($black, 1);
}
div#options {
width: 100%;
position: absolute;
bottom: 0;
border-radius: 0 0 3px 3px;
background: linear-gradient(
to bottom,
rgba(#000, 0) 0%,
rgba(#000, 0.65) 100%
);
#option-left {
display: inline-block;
vertical-align: top;
width: 50%;
position: relative;
background: none;
button {
border-radius: 3px;
background: $primary;
margin: 0 0 10px 10px;
svg {
// @include object-transitions(0.1s)
width: 40px;
height: 20px;
fill: $secondary;
}
}
.item-options {
border-radius: 3px;
margin: 5px;
display: inline-block;
}
button[data-active='false'] {
background: $primary;
svg {
fill: $secondary;
}
}
button[data-active='true'] {
background: $tertiary;
svg {
fill: $primary;
}
}
}
#option-right {
display: inline-block;
width: 50%;
text-align: right;
span {
font-weight: bold;
display: block;
background: $white;
color: $primary;
border-radius: 3px;
font-size: 0.6em;
text-align: center;
position: relative;
padding: 5px;
float: right;
margin: 0 10px 0 0;
bottom: -15px;
}
}
}
}
a.recent-link:nth-child(3) {
width: 100%;
margin-bottom: 20px;
height: 500px;
}
a.recent-link:nth-child(4),
a.recent-link:nth-child(6) {
width: 48.6%;
height: 350px;
margin: 0 10px 20px 0;
}
a.recent-link:nth-child(5),
a.recent-link:nth-child(7) {
width: 48.6%;
height: 350px;
margin: 0 0 20px 10px;
}
}
}
}
}
}
@media only screen and (max-width: 768px) {
#dash-index-content {
#dash-index {
#dash-index-wrapper {
#dash-recent {
#recent-list {
a:nth-child(4),
a:nth-child(6) {
width: 48.9%;
}
}
}
}
}
}
}
@media only screen and (max-width: 640px) {
#dash-index-content {
#dash-index {
#dash-index-wrapper {
#dash-recent {
#recent-list {
a:nth-child(4),
a:nth-child(6) {
width: 48.5%;
}
}
}
}
}
}
}
@media only screen and (max-width: 480px) {
#dash-index-content {
#dash-index {
#dash-index-wrapper {
#dash-recent {
#recent-list {
.recent-header {
h3 {
width: 40%;
}
.index-menu {
width: 60%;
}
}
a.dash-link:nth-child(3),
a.dash-link:nth-child(4),
a.dash-link:nth-child(5),
a.dash-link:nth-child(6),
a.dash-link:nth-child(7) {
width: 100%;
margin: 15px 0 0;
height: 400px;
}
}
}
}
}
}
} ;

View file

@ -1,7 +0,0 @@
@mixin background-opacity($rgb_value, $opacity) {
background: rgba($rgb_value, $opacity);
}
@mixin custom-header($weight, $size, $line_height, $color) {
font: $weight $size/$line_height $bodyTypeSans;
color: $color;
}

View file

@ -1,93 +0,0 @@
#nav-index {
width: 100%;
max-width: 900px;
margin: 0 auto;
#nav-index-wrapper {
#nav-pages {
.nav-item {
display: block;
width: 98%;
background: $white;
border-radius: 3px;
color: $highlight;
height: 30px;
padding: 10px;
margin: 0 0 10px;
font-size: 1.5em;
cursor: move;
#item-arrows {
fill: $primary;
width: 40px;
height: 30px;
}
}
label {
display: inline-block;
vertical-align: middle;
padding: 0;
margin: -15px 0 0 10px;
cursor: move;
}
#nav-btns {
float: right;
top: -5px;
position: relative;
button {
color: $white;
border-radius: 3px;
width: 40px;
margin: 0 10px;
svg {
fill: $white;
width: 25px;
height: 20px;
}
}
}
}
}
}
@media only screen and (max-width: 375px) {
#nav-index {
#nav-index-wrapper {
#nav-pages {
.nav-item {
width: 94.5%;
font-size: 1em;
label {
width: 40%;
vertical-align: top;
margin-top: 0;
line-height: 1em;
}
}
}
}
}
}
@media only screen and (max-width: 320px) {
#nav-index {
#nav-index-wrapper {
#nav-pages {
.nav-item {
width: 94.5%;
font-size: 1em;
label {
width: 37%;
vertical-align: top;
margin-top: 0;
line-height: 1em;
}
}
}
}
}
} ;

View file

@ -1,351 +0,0 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
// -webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input {
/* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select {
/* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type='button'],
[type='reset'],
[type='submit'] {
// -webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type='button']::-moz-focus-inner,
[type='reset']::-moz-focus-inner,
[type='submit']::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type='button']:-moz-focusring,
[type='reset']:-moz-focusring,
[type='submit']:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type='checkbox'],
[type='radio'] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type='number']::-webkit-inner-spin-button,
[type='number']::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type='search'] {
// -webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type='search']::-webkit-search-decoration {
// -webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
// -webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}

View file

@ -1,701 +0,0 @@
#post-index {
width: 100%;
max-width: 900px;
margin: 0 auto;
#post-index-wrapper {
// padding: 0.75rem
overflow: hidden;
#post-index-header {
margin: 10px 0 0;
#post-index-header-left {
text-transform: capitalize;
display: inline-block;
width: 50%;
color: $white;
font-size: 3em;
}
#post-index-header-right {
text-align: right;
display: inline-block;
width: 50%;
a {
button {
color: $white;
border-radius: 3px;
margin-left: 10px;
width: 55px;
}
svg {
transition: all 0.1s linear;
width: 20px;
height: 17px;
fill: $white;
}
}
.current-filter {
color: $highlight;
text-decoration-color: $secondary;
}
}
}
#posts-list {
margin: 20px 0 0;
a.page-link {
background: $white;
display: inline-block;
vertical-align: top;
width: 100%;
text-decoration: none;
margin: 0 0 20px;
border-radius: 3px;
overflow: hidden;
color: color.adjust($primary, $lightness: -60%);
label {
font-size: 2em;
font-weight: 500;
padding: 10px;
display: inline-block;
vertical-align: top;
width: 100%;
}
div.page-bg,
div.page-video {
video {
width: 100%;
position: absolute;
}
width: 100%;
height: 350px;
background-color: $highlight;
position: relative;
label {
font-size: 2em;
font-weight: 700;
color: $white;
padding: 5px;
vertical-align: top;
display: inline-block;
word-wrap: break-word;
width: 100%;
text-align: center;
position: relative;
top: 35%;
text-shadow: 2px 2px 0 rgba($black, 1);
}
#meta {
width: 100%;
background: linear-gradient(
to bottom,
rgba(#000, 0%) 0%,
rgba(#000, 0.65%) 100%
);
border-radius: 3px;
margin: auto;
bottom: 0;
position: absolute;
padding: 0 0 20px;
#options {
width: 100%;
bottom: 0;
position: absolute;
#option-left {
display: inline-block;
vertical-align: top;
width: 50%;
position: relative;
background: none;
button {
border-radius: 3px;
background: $primary;
margin: 0 0 10px 10px;
}
svg {
transition: all 0.2s linear;
width: 40px;
height: 20px;
fill: $secondary;
}
.item-options {
border-radius: 3px;
margin: 5px;
display: inline-block;
}
button[data-active='false'] {
background: $primary;
svg {
fill: $secondary;
}
}
button[data-active='true'] {
background: $tertiary;
svg {
fill: $primary;
}
}
}
#option-right {
display: inline-block;
width: 50%;
text-align: right;
span {
font-weight: bold;
display: block;
background: $white;
color: $primary;
border-radius: 3px;
font-size: 0.6em;
text-align: center;
position: relative;
padding: 5px;
float: right;
margin: 0 10px 0 0;
bottom: -15px;
}
}
}
}
}
p {
padding: 5px 10px;
font-size: 1.2em;
font-weight: 400;
}
}
}
.paginate {
width: 260px;
display: block;
margin: 0 auto;
a.paginate-link {
display: inline-block;
vertical-align: top;
}
span.count {
text-align: center;
padding: 5px;
margin-top: -2px;
display: inline-block;
width: 190px;
font-size: 1.5em;
color: $tertiary;
}
}
}
}
#post-edit-index {
width: 100%;
overflow: hidden;
#post-edit-index-wrapper {
width: 100%;
#post-header {
// width 100%
background: $highlight;
#post-header-wrapper {
max-width: 900px;
margin: 0 auto;
padding: 0.75rem;
label {
color: $white;
font-size: 0.9em;
font-family: $basetype;
font-weight: 600;
}
span#post-span {
color: $primary;
font-size: 0.9em;
font-weight: 600;
text-transform: uppercase;
float: right;
}
#post-edit-title {
textarea#post-title-text {
background: $white;
font-family: $basetype;
width: 97.6%;
height: 80px;
font-size: 2em;
color: $primary;
padding: 5px;
margin: 0 0 5px;
}
#calendar-icon {
background: color.adjust($primary, $lightness: -15%);
border-radius: 3px 0 0 3px;
display: inline-block;
padding: 5.2px;
color: $secondary;
}
#layouts {
select {
background: $primary;
color: $secondary;
border-radius: 3px;
border-color: $primary;
margin: 0 0 10px;
width: 100%;
height: 45px;
padding: 5px;
font-size: 1.5em;
}
}
}
#post-meta {
#post-tags {
background: $white;
font-family: $basetype;
width: 97.6%;
height: 80px;
color: $primary;
padding: 5px;
margin: 0 0 5px;
}
#post-options {
display: inline-block;
vertical-align: top;
width: 100%;
padding: 0;
margin: 0 0 10px;
button.post-option-btn {
width: 25%;
height: 45px;
transition: all 0.3s linear;
margin: 0;
border-radius: 0;
display: inline-block;
vertical-align: top;
text-align: center;
}
button.post-option-btn:nth-child(1) {
border-radius: 3px 0 0 3px;
}
button.post-option-btn:nth-child(4) {
border-radius: 0 3px 3px 0;
}
a {
button.button-link {
border-radius: 0 3px 3px 0 !important;
}
}
button.post-option-btn[data-active='false'] {
background: $primary;
svg.svg-toggle {
fill: $secondary;
}
}
button.post-option-btn[data-active='true'] {
background: $tertiary;
svg.icons {
fill: $primary;
}
}
}
#page-files-upload,
#post-image-upload {
display: none;
}
}
}
}
#post-feature {
width: 100%;
#page-file-manager {
background: $tertiary;
width: 100%;
min-height: 300px;
#page-file-wrapper {
width: 100%;
max-width: 900px;
padding: 10px;
margin: 0 auto;
font-weight: bold;
color: $primary;
font-size: 1em;
#page-file-drop {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
min-height: 100px;
background: $white;
color: $primary;
vertical-align: middle;
border-radius: 5px;
margin: 0 0 10px;
label {
cursor: pointer;
font-weight: 600px;
text-transform: capitalize;
}
img {
width: 100%;
margin: 0;
padding: 0;
}
}
#page-images-list,
#page-files-list {
padding: 10px 0 0;
button.media-remove {
height: 35px;
width: 30px;
background: $event-lame;
color: $white;
float: right;
margin: 5px 5px 0;
}
.img-item {
height: 150px;
width: 23.8%;
border-radius: 3px;
margin: 0 10px 10px 0;
display: inline-block;
cursor: pointer;
}
.audio-item {
height: 150px;
width: 23.8%;
border-radius: 3px;
margin: 0 10px 10px 0;
display: inline-block;
cursor: pointer;
background: $primary;
background: url('/assets/images/global/upload-audio.png')
no-repeat center center / cover;
}
.video-item {
height: 150px;
width: 23.8%;
border-radius: 3px;
margin: 0 10px 10px 0;
display: inline-block;
cursor: pointer;
background: $primary;
background: url('/assets/images/global/upload-video.png')
no-repeat center center / cover;
}
.file-item {
height: 150px;
width: 23.8%;
border-radius: 3px;
margin: 0 10px 10px 0;
display: inline-block;
cursor: pointer;
background: $primary;
background: url('/assets/images/global/upload-doc.png')
no-repeat center center / cover;
}
}
}
}
}
#edit-post {
width: 100%;
max-width: 880px;
margin: 0 auto;
#edit-post-wrapper {
width: 100%;
max-width: 900px;
border-radius: 5px;
position: relative;
textarea:focus {
outline: none;
border-color: $highlight;
}
#edit,
#highlight {
border: 0;
width: 100%;
min-height: 300px;
height: auto;
position: absolute;
top: 0;
left: 0;
overflow: auto;
word-wrap: normal;
white-space: pre-wrap;
line-break: normal;
}
#highlight-content {
word-wrap: normal;
white-space: pre-wrap;
line-break: normal;
}
#edit,
#highlight,
#hightlight * {
font-size: 1.2em;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
line-height: 22pt;
}
#edit {
z-index: 1;
color: transparent;
background: transparent;
caret-color: $highlight;
}
#highlight {
z-index: 0;
pre {
margin: 0;
code {
font-family: $monotype;
padding: 5px;
border-radius: 5px;
line-height: 1.6em;
font-size: 1.25em;
color: $editor-primary;
word-wrap: normal;
white-space: pre-wrap;
line-break: normal;
-webkit-line-break: normal;
-o-line-break: normal;
-moz-line-break: normal;
display: inline-block;
width: 100%;
max-width: 900px;
min-height: 200px;
caret-color: $highlight;
}
}
}
}
}
}
}
@media only screen and (max-width: 800px) {
#post-edit-index {
#post-edit-index-wrapper {
#post-header {
#post-title {
#post-date {
width: 37.6%;
}
}
}
}
}
}
@media only screen and (max-width: 768px) {
#post-edit-index {
#post-edit-index-wrapper {
#post-header {
#post-title {
#post-date {
width: 43.1%;
}
}
#post-meta {
#edit-control {
max-width: 100%;
button {
width: 9.91%;
}
}
}
}
}
}
}
@media only screen and (max-width: 640px) {
#post-edit-index {
#post-edit-index-wrapper {
#post-header {
#post-title {
#post-date {
width: 42%;
}
}
}
}
}
}
@media only screen and (max-width: 480px) {
#post-index {
#post-index-wrapper {
#post-index-header {
#post-index-header-left {
font-size: 1.35em;
width: 30%;
}
#post-index-header-right {
width: 70%;
vertical-align: top;
}
}
#post-index-menu {
a {
font-size: 0.95em;
label {
display: none;
visibility: hidden;
}
}
}
}
}
#post-edit-index {
#post-edit-index-wrapper {
#post-header {
#post-title {
#post-options {
margin: 5px 0 0;
width: 100%;
padding: 0;
}
#post-date {
width: 89.2%;
}
}
#post-meta {
#edit-control {
button {
width: 9.91%;
}
}
}
}
}
}
}
@media only screen and (max-width: 320px) {
#post-index {
#post-index-wrapper {
#post-index-menu {
a {
font-size: 0.95em;
label {
display: none;
visibility: hidden;
}
}
}
}
}
#post-edit-index {
#post-edit-index-wrapper {
#post-header {
#post-title {
#post-title-text {
width: 96.4%;
}
#post-options {
margin: 5px 0 0;
width: 100%;
padding: 0;
}
#post-date {
width: 83.1%;
}
}
#post-meta {
#post-tags {
width: 96.4%;
}
#edit-control {
.content-editor-btn-icon {
svg.icons {
width: 20px;
}
}
.post-sumbit-btn {
svg.icons {
width: 20px;
}
}
button {
width: 10%;
}
}
}
}
}
}
} ;

View file

@ -1,383 +0,0 @@
#settings-actions {
position: fixed;
width: 40%;
margin-top: -85px;
left: 50%;
margin-left: -20%;
#buttons {
width: 185px;
margin: 28px auto;
text-align: center;
background: $white;
padding: 2px;
border-radius: 3px;
button {
color: $white;
border-radius: 3px;
width: 40px;
margin: 0 10px;
svg {
width: 25px;
height: 20px;
fill: $white;
}
}
button[data-render='false'] {
background: $secondary;
svg {
fill: $primary;
}
}
button[data-render='true'] {
background: $highlight;
svg {
fill: $white;
}
}
}
}
#settings-index {
width: 94%;
max-width: 900px;
margin: 0 auto;
overflow: hidden;
#settings-index-wrapper {
padding: 0;
button {
margin-top: 5px;
width: 100%;
height: 33px;
}
#member-settings,
#feature-settings,
#option-settings,
#token-settings,
#backup-settings {
background: $white;
padding: 0;
border-radius: 5px 0;
width: 100%;
margin: 20px auto;
label {
font-family: $basetype;
color: $primary;
font-weight: bold;
}
span {
color: $secondary;
}
input {
width: 95%;
margin: 0 5px 10px 0;
height: 30px;
padding: 10px;
}
input#backup-upload {
visibility: hidden;
display: none;
}
.backup-meta {
background: $primary;
color: $white;
padding: 8px;
border-radius: 3px;
margin: 5px 0 0;
text-align: center;
}
#member-images {
padding: 10px 15px 0;
#member-avatar-drop {
display: inline-block;
margin: 0 0 10px;
img {
width: 100%;
border-radius: 5px;
overflow: hidden;
cursor: pointer;
display: block;
margin-bottom: 2px;
}
input {
visibility: hidden;
display: none;
}
#privacy-toggle {
width: 50%;
}
#render-toggle {
width: 50%;
}
}
#site-background {
margin: 0 0 10px;
img {
width: 92.1%;
height: 292px;
border-radius: 3px;
overflow: hidden;
cursor: pointer;
}
input {
visibility: hidden;
display: none;
}
}
}
#member-meta {
padding: 10px 15px 0;
position: relative;
top: -30px;
}
#features {
padding: 10px 15px 0;
}
}
#mail-settings {
min-height: 240px;
/*
input {
margin: 0 5px 5px 0;
vertical-align: top;
}
*/
a.mail-option {
float: right;
font-family: $monotype;
font-size: 0.9em;
border-radius: 3px;
text-decoration: none;
margin: 0 0 0 5px;
}
a.mail-option[data-enabled='true'] {
color: $highlight;
}
a.mail-option[data-enabled='false'] {
color: $primary;
}
div[data-enabled='false'] {
display: none;
visibility: hidden;
}
#settings-api {
background: $primary;
border-radius: 3px;
padding: 10px;
span {
color: $white !important;
margin: -13px 0 0 5px;
position: relative;
vertical-align: middle;
display: inline-block;
font-weight: bold;
}
button {
color: $white;
border-radius: 3px;
width: 40px;
margin: 0;
svg {
width: 25px;
height: 20px;
fill: $white;
}
}
button[data-enabled='false'] {
background: $secondary;
svg {
fill: $primary;
}
}
button[data-enabled='true'] {
background: $highlight;
svg {
fill: $white;
}
}
}
}
textarea {
background: $primary;
width: 70%;
height: 89.5px;
color: $tertiary;
padding: 10px;
display: inline-block;
margin-bottom: 10px;
}
span#key {
color: $white;
background: $primary;
font-size: 0.9em;
border-radius: 3px;
padding: 5px;
display: block;
width: 95%;
overflow: hidden;
}
#feature-settings {
#feature-api,
#dynamic-api {
background: $white;
border-radius: 3px;
padding: 5px;
button {
color: $white;
border-radius: 3px;
width: 200px;
margin: 0;
height: 200px;
font-size: 1em;
svg.icons {
width: 100px;
height: 90px;
fill: $white;
position: relative;
display: block;
margin: 12px auto;
}
span {
color: $white;
margin: 6px 0 0 5px;
position: relative;
vertical-align: middle;
display: inline-block;
font-weight: bold;
}
}
button[data-enabled='false'] {
background: $secondary;
svg {
fill: $primary;
}
span {
color: $primary;
}
}
button[data-enabled='true'] {
background: $highlight;
svg {
fill: $white;
}
}
}
}
#token-settings {
#keys-tokens {
padding: 10px 15px 0;
#member-api-key,
#form-token {
background: $primary;
border-radius: 3px;
padding: 5px;
color: $white;
}
}
}
#option-settings {
#theme-settings {
a {
width: 95%;
margin: 0 5px 5px 0;
height: 15px;
padding: 10px;
display: inline-block;
}
a[data-enabled='false'] {
background: $white;
color: $primary;
border-radius: 3px;
font-weight: bold;
border-top: 1px $highlight solid;
border-bottom: 1px $highlight solid;
}
a[data-enabled='true'] {
background: $highlight;
color: $primary;
border-radius: 3px;
font-weight: bold;
border-top: 1px $primary solid;
border-bottom: 1px $primary solid;
svg {
fill: $primary;
display: inline-block;
float: right;
}
}
}
}
}
}
// Responsive for Settings
@media only screen and (max-width: 480px) {
#settings-actions {
margin-left: -42%;
#buttons {
width: 150px;
background: none;
button {
margin: 0 5px;
}
}
}
} ;

View file

@ -1,251 +0,0 @@
html,
body {
background: $primary
linear-gradient(
0deg,
rgba($primary, 1) 0%,
rgba(color.adjust($primary, $lightness: 10%), 1) 100%
)
no-repeat;
font: 400 1em $basetype;
height: 100%;
}
a {
font: 300 1em $basetype;
color: $secondary;
text-decoration: underline;
transition: all 0.2s linear;
}
svg.icons {
width: 25px;
fill: $secondary;
}
#notifications {
perspective: 1000px;
position: fixed;
z-index: 2000;
height: 55px;
width: 100%;
display: block;
align-items: center;
justify-content: center;
padding: 0;
margin-top: -55px;
#notify-message {
margin: 0 auto;
// ks-easing( "out-back" );
transition: all 0.6s cubic-bezier(0.83, 0.05, 0.28, 1);
// padding-top -125px
height: 50px;
width: 500px;
display: flex;
align-items: center;
justify-content: center;
opacity: 1;
transform-style: preserve-3d;
transform: rotateX(120deg);
transform-origin: 50% 0;
overflow: hidden;
#notify-good,
#notify-lame,
#notify-working {
display: block;
}
#notify-working-icon {
animation: spin 2s linear infinite;
@keyframes spin {
transform: rotate(360deg);
}
}
.notify-icon {
background: $black;
padding: 8px 5px 5px;
border-radius: 5px 0 0 5px;
height: 30px;
width: 30px;
text-align: center;
border: 2px solid $white;
}
#notify-text {
color: $white;
background: $black;
width: 400px;
height: 28px;
padding: 15px 0 0;
border-radius: 0 5px 5px 0;
border: 2px solid $white;
text-align: center;
overflow: hidden;
position: relative;
#notify-progress {
width: 0;
background: $highlight;
height: 43px;
position: absolute;
top: 0;
}
p {
top: -15px;
display: block;
position: relative;
}
}
.icons {
fill: $white;
}
}
}
.notify-close {
transform-style: preserve-3d;
transform: rotateX(-120deg);
}
.notify-open {
transform-style: preserve-3d;
transform: rotateX(0deg);
}
.blog-container {
width: 100%;
}
.main-container {
margin: 0 auto;
z-index: 10;
position: relative;
height: 100%;
section {
header {
width: 100%;
max-width: 900px;
margin: 10px auto;
background: $white;
height: 50px;
border-radius: 5px;
#wrapper {
padding: 5px;
#left,
#right {
width: 49.7%;
display: inline-block;
vertical-align: top;
min-height: 60px;
#the-logo {
width: 29px;
}
}
#right {
text-align: right;
color: $white;
// word-break: break-all;
#dash-menu {
text-align: right;
a {
button {
border-radius: 50px;
svg {
transition: all 0.2s linear;
width: 40px;
height: 20px;
fill: $white;
}
}
&:hover {
button {
background: $primary;
}
svg {
fill: $secondary;
}
}
}
}
}
}
}
}
} /* Mozilla based browsers */
::selection {
background-color: $highlight;
color: $white;
}
/* Works in Opera */
::-o-selection {
background-color: $highlight;
color: $white;
}
::-ms-selection {
background-color: $highlight;
color: $white;
}
/* Works in Internet Explorer */
::-webkit-selection {
background-color: $highlight;
color: $white;
}
// Responsive
@media only screen and (max-width: 901px) {
.main-container {
padding: 10px;
}
}
@media only screen and (max-width: 800px) {
.main-container {
section {
header {
#wrapper {
#left,
#right {
display: inline-block;
}
}
}
}
}
}
@media only screen and (max-width: 480px) {
.main-container {
section {
header {
#wrapper {
#left {
width: 30%;
}
#right {
width: 70%;
}
}
}
}
}
} ;

View file

@ -1,23 +0,0 @@
$basetype: helvetica, arial, sans-serif;
$monotype: 'Lucida Console', monaco, monospace;
h1,
h2,
h3 {
color: $white;
}
h1 {
font-size: 2em;
font-weight: 400;
}
h2 {
font-size: 1.75em;
font-weight: 400;
}
h3 {
font-size: 1.5em;
font-weight: 300;
}