Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
2aed4ec2ed | |||
bd939cc078 | |||
1fb4d2eb57 | |||
e52ae78ed0 | |||
5e621883ff | |||
b5996dc7db | |||
bc33b4cac4 |
@ -18,7 +18,7 @@ I am working very hard to ensure the system is safe and reliable enough for me t
|
||||
## Find Us
|
||||
|
||||
* [DockerHub](https://hub.docker.com/repositories/thetempusproject)
|
||||
* [Packagist](https://packagist.org/users/joeyk4816/packages/)
|
||||
* [Packagist](https://packagist.org/packages/thetempusproject/)
|
||||
* [GitLab](https://git.thetempusproject.com/the-tempus-project/thetempusproject)
|
||||
|
||||
## Summary
|
||||
|
@ -73,7 +73,7 @@ class Config extends BedrockConfig {
|
||||
$html .= '<div class="mb-3 row">';
|
||||
$html .= '<h4 class="col-lg-3 col-form-label text-end">Current Image</h4>';
|
||||
$html .= '<div class="col-lg-6">';
|
||||
$html .= '<img alt="User Avatar" src="{ROOT_URL}' . $node['value'] . '" class="img-circle img-fluid p-2 avatar-125">';
|
||||
$html .= '<img alt="configured image" src="{ROOT_URL}' . $node['value'] . '" class="img-circle img-fluid p-2 avatar-125">';
|
||||
$html .= '</div>';
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
@ -121,7 +121,6 @@ class DatabaseModel extends BedrockDatabaseModel {
|
||||
$errors = [];
|
||||
foreach ( self::$installFlags as $flag_name ) {
|
||||
if ( empty( $options[$flag_name] ) ) {
|
||||
$module_data[ $flag_name ] = INSTALL_STATUS_SKIPPED;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -115,6 +115,8 @@ class Forms extends Check {
|
||||
self::addHandler( 'adminCreateToken', __CLASS__, 'adminCreateToken' );
|
||||
self::addHandler( 'apiLogin', __CLASS__, 'apiLogin' );
|
||||
self::addHandler( 'updatePreference', __CLASS__, 'updatePreference' );
|
||||
self::addHandler( 'renameIImage', __CLASS__, 'renameIImage' );
|
||||
self::addHandler( 'addImage', __CLASS__, 'addImage' );
|
||||
self::addHandler( 'installStart', __CLASS__, 'install', [ 'start' ] );
|
||||
self::addHandler( 'installAgreement', __CLASS__, 'install', [ 'agreement' ] );
|
||||
self::addHandler( 'installCheck', __CLASS__, 'install', [ 'check' ] );
|
||||
@ -663,4 +665,28 @@ class Forms extends Check {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function renameIImage() {
|
||||
if ( !Input::exists( 'filelocation' ) ) {
|
||||
self::addUserError( 'You must specify a location' );
|
||||
return false;
|
||||
}
|
||||
if ( !Input::exists( 'newname' ) ) {
|
||||
self::addUserError( 'You must specify a new name' );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function addImage() {
|
||||
if ( !Input::exists( 'folderSelect' ) ) {
|
||||
self::addUserError( 'You must specify a location' );
|
||||
return false;
|
||||
}
|
||||
if ( !Input::exists( 'uploadImage' ) ) {
|
||||
self::addUserError( 'You must include a file.' );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -158,6 +158,10 @@ class Installer {
|
||||
} else {
|
||||
self::$installJson['modules'][$name]['enabled_txt'] = '<span class="text-danger">No</span>';
|
||||
}
|
||||
// in this case only, we save an array to remove the objects later, so an array stored is a success.
|
||||
if ( ! empty( self::$installJson['modules'][$name]['resources_installed'] ) && is_array( self::$installJson['modules'][$name]['resources_installed'] ) ) {
|
||||
self::$installJson['modules'][$name]['resources_installed'] = INSTALL_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
return self::$installJson['modules'][$name];
|
||||
}
|
||||
@ -422,7 +426,7 @@ class Installer {
|
||||
}
|
||||
|
||||
// exclude any flags that have already been successfully installed
|
||||
if ( !empty( $module_data->$flag_type ) && $module_data->$flag_type == INSTALL_STATUS_SUCCESS ) {
|
||||
if ( ! empty( $module_data->$flag_type ) && $module_data->$flag_type == INSTALL_STATUS_SUCCESS ) {
|
||||
Debug::warn( "$flag_type has already been successfully installed" );
|
||||
$flags[ $flag_type ] = false;
|
||||
}
|
||||
@ -530,7 +534,7 @@ class Installer {
|
||||
}
|
||||
|
||||
foreach ( $flags as $flag_type ) {
|
||||
if ( ! in_array( $modelInfo[ $flag_type ], [ INSTALL_STATUS_SUCCESS, INSTALL_STATUS_NOT_REQUIRED ] ) ) {
|
||||
if ( empty( $modelInfo[ $flag_type ] ) || ! in_array( $modelInfo[ $flag_type ], [ INSTALL_STATUS_SUCCESS, INSTALL_STATUS_NOT_REQUIRED ] ) ) {
|
||||
$modelInfo['installStatus'] = INSTALL_STATUS_PARTIALLY_INSTALLED;
|
||||
break;
|
||||
}
|
||||
|
@ -245,7 +245,7 @@ class Permissions {
|
||||
|
||||
public static function getFieldEditHtml( $name, $default, $pretty ) {
|
||||
$fieldname = str_ireplace( '/', '-', $name );
|
||||
$fieldHtml = Forms::getSwitchHtml( $fieldname, [ 'true', 'false' ], $default );
|
||||
$fieldHtml = Forms::getSwitchHtml( $fieldname, $default );
|
||||
$html = '';
|
||||
$html .= '<div class="mb-3 row">';
|
||||
$html .= '<label for="' . $fieldname . '" class="col-lg-6 col-form-label text-end">' . $pretty . '</label>';
|
||||
|
@ -89,7 +89,7 @@ class Plugin {
|
||||
|
||||
foreach ( self::PLUGIN_FLAG_MAP as $flag_name => $function_name ) {
|
||||
if ( empty( $options[$flag_name] ) ) {
|
||||
$module_data[ $flag_name ] = INSTALL_STATUS_SKIPPED;
|
||||
// $module_data[ $flag_name ] = INSTALL_STATUS_SKIPPED;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -280,7 +280,7 @@ class Plugin {
|
||||
public function installResources( $options = '' ) {
|
||||
if ( empty( $this->resourceMatrix ) ) {
|
||||
Debug::log( 'resourceMatrix is empty' );
|
||||
return true;
|
||||
return INSTALL_STATUS_NOT_REQUIRED;
|
||||
}
|
||||
$ids = [];
|
||||
foreach( $this->resourceMatrix as $tableName => $entries ) {
|
||||
|
@ -268,15 +268,15 @@ class Preferences {
|
||||
}
|
||||
|
||||
$html .= '<div class="mb-3 row">';
|
||||
$html .= '<label for="' . $fieldname . '" class="col-lg-6 col-form-label text-end">' . $fieldTitle . '</label>';
|
||||
$html .= '<label for="' . $fieldname . '" class="col-lg-6 col-form-label text-start text-lg-end">' . $fieldTitle . '</label>';
|
||||
$html .= '<div class="col-lg-6">';
|
||||
$html .= $fieldHtml;
|
||||
$html .= '</div>';
|
||||
if ( 'file' === $type ) {
|
||||
$html .= '<div class="mb-3 row">';
|
||||
$html .= '<h4 class="col-lg-6 col-form-label text-end">Current Image</h4>';
|
||||
$html .= '<h4 class="col-lg-6 col-form-label text-start text-lg-end">Current Image</h4>';
|
||||
$html .= '<div class="col-lg-6">';
|
||||
$html .= '<img alt="User Avatar" src="{ROOT_URL}' . $defaultValue . '" class="img-circle img-fluid p-2 avatar-125">';
|
||||
$html .= '<img alt="preferred image" src="{ROOT_URL}' . $defaultValue . '" class="img-circle img-fluid p-2">';
|
||||
$html .= '</div>';
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
@ -39,7 +39,7 @@ if ( ! defined( 'CONFIG_DIRECTORY' ) ) {
|
||||
define( 'CANARY_SECURE_HASH', 'd73ed7591a30f0ca7d686a0e780f0d05' );
|
||||
# Tempus Project Core
|
||||
define( 'APP_NAME', 'The Tempus Project');
|
||||
define( 'TP_DEFAULT_LOGO', 'images/logo.png');
|
||||
define( 'TP_DEFAULT_LOGO', 'images/logoWhite.png');
|
||||
// Check
|
||||
define( 'MINIMUM_PHP_VERSION', 8.1);
|
||||
// Cookies
|
||||
|
@ -32,8 +32,6 @@ class Groups extends AdminController {
|
||||
self::$title = 'Admin - Groups';
|
||||
self::$group = new Group;
|
||||
self::$permissions = new Permissions;
|
||||
$view = Navigation::activePageSelect( 'nav.admin', '/admin/groups' );
|
||||
Components::set( 'ADMINNAV', $view );
|
||||
}
|
||||
|
||||
public function create( $data = null ) {
|
||||
|
@ -22,6 +22,7 @@ use TheTempusProject\Plugins\Comments as CommentPlugin;
|
||||
use TheTempusProject\Plugins\Blog as BlogPlugin;
|
||||
use TheTempusProject\Plugins\Contact as ContactPlugin;
|
||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
|
||||
class Home extends AdminController {
|
||||
public static $user;
|
||||
|
368
app/controllers/admin/images.php
Normal file
368
app/controllers/admin/images.php
Normal file
@ -0,0 +1,368 @@
|
||||
<?php
|
||||
/**
|
||||
* app/controllers/admin/tokens.php
|
||||
*
|
||||
* This is the admin app/user tokens controller.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers\Admin;
|
||||
|
||||
use TheTempusProject\Classes\Forms as TTPForms;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Houdini\Classes\Issues;
|
||||
use TheTempusProject\Houdini\Classes\Navigation;
|
||||
use TheTempusProject\Houdini\Classes\Components;
|
||||
use TheTempusProject\Houdini\Classes\Forms;
|
||||
use TheTempusProject\Classes\AdminController;
|
||||
use TheTempusProject\Models\Token;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Hermes\Functions\Redirect;
|
||||
use TheTempusProject\Bedrock\Functions\Session;
|
||||
use TheTempusProject\Hermes\Functions\Route as Routes;
|
||||
use TheTempusProject\Bedrock\Functions\Upload;
|
||||
use RecursiveIteratorIterator;
|
||||
use RecursiveDirectoryIterator;
|
||||
use FilesystemIterator;
|
||||
|
||||
class Images extends AdminController {
|
||||
private $directories = [
|
||||
APP_ROOT_DIRECTORY . 'images',
|
||||
APP_ROOT_DIRECTORY . 'app/images',
|
||||
APP_ROOT_DIRECTORY . 'app/plugins'
|
||||
];
|
||||
|
||||
private $excludedDirectories = [
|
||||
'.',
|
||||
'..',
|
||||
'vendor',
|
||||
'docker',
|
||||
'logs',
|
||||
'gitlab',
|
||||
'uploads',
|
||||
'config',
|
||||
];
|
||||
|
||||
public function upload() {
|
||||
if ( Input::exists( 'submit' ) ) {
|
||||
$route = '';
|
||||
$destination = '';
|
||||
if ( !TTPForms::check( 'addImage' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your image upload.' => Check::userErrors() ] );
|
||||
} else {
|
||||
$folder = Input::post( 'folderSelect' ) . DIRECTORY_SEPARATOR;
|
||||
// dv( $folder );
|
||||
$upload = Upload::image( 'uploadImage', $folder );
|
||||
if ( $upload ) {
|
||||
$route = str_replace( APP_ROOT_DIRECTORY, '', $folder );
|
||||
$destination = $route . Upload::last();
|
||||
Issues::add( 'success', 'Image uploaded.' );
|
||||
} else {
|
||||
Issues::add( 'error', [ 'There was an error with your image upload.' => Check::userErrors() ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$folders = $this->getDirectoriesRecursive( APP_ROOT_DIRECTORY );
|
||||
$folderHtml = $this->generateFolderHtml( $folders );
|
||||
Components::set( 'FOLDER_SELECT_ROOT', APP_ROOT_DIRECTORY );
|
||||
Components::set( 'FOLDER_SELECT', Views::simpleView( 'forms.folderSelect', $folderHtml ) );
|
||||
Views::view( 'admin.images.upload' );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private function getFolderObject( $folder, $subdirs = '' ) {
|
||||
$names = explode( DIRECTORY_SEPARATOR, $folder );
|
||||
$folderName = array_pop( $names );
|
||||
$out = [
|
||||
'folderName' => $folderName,
|
||||
'location' => $folder,
|
||||
'subdirs' => $subdirs,
|
||||
];
|
||||
if ( ! empty( $subdirs ) ) {
|
||||
$out['folderexpand'] = '<i class="fa-solid fa-caret-down justify-content-end"></i>';
|
||||
} else {
|
||||
$out['folderexpand'] = '';
|
||||
}
|
||||
return (object) $out;
|
||||
}
|
||||
|
||||
private function generateFolderHtml( $folders ) {
|
||||
$rows = [];
|
||||
foreach ( $folders as $top => $sub ) {
|
||||
$object = $this->getFolderObject( $top );
|
||||
if ( $top == $sub ) {
|
||||
$html = '';
|
||||
} else {
|
||||
$children = $this->generateFolderHtml( $sub );
|
||||
Components::set( 'parentfolderName', $object->folderName );
|
||||
$html = Views::simpleView( 'forms.folderSelectParent', $children );
|
||||
Components::set( 'parentfolderName', '' );
|
||||
}
|
||||
$rows[] = $this->getFolderObject( $top, $html );
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
private function getDirectoriesRecursive( $directory ) {
|
||||
$dirs = [];
|
||||
|
||||
$directory = rtrim( $directory, DIRECTORY_SEPARATOR );
|
||||
$directory = $directory. DIRECTORY_SEPARATOR;
|
||||
|
||||
$files = scandir( $directory );
|
||||
$filteredFiles = array_values( array_diff( $files, $this->excludedDirectories ) );
|
||||
|
||||
foreach ( $filteredFiles as $key => $filename ) {
|
||||
$long_name = $directory . $filename;
|
||||
$is_dir = ( ( strpos( $filename, '.' ) === false ) && ( is_dir( $long_name ) === true ) );
|
||||
if ( $is_dir ) {
|
||||
$recursive_dirs = $this->getDirectoriesRecursive( $long_name );
|
||||
if ( empty( $recursive_dirs ) ) {
|
||||
$recursive_dirs = $long_name;
|
||||
}
|
||||
$dirs[$long_name] = $recursive_dirs;
|
||||
}
|
||||
}
|
||||
|
||||
return $dirs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
self::$title = 'Admin - Images';
|
||||
}
|
||||
|
||||
public function create() {
|
||||
if ( Input::exists( 'submit' ) ) {
|
||||
if ( !TTPForms::check( 'addImage' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your image.' => Check::userErrors() ] );
|
||||
}
|
||||
|
||||
if ( Input::exists( 'folder' ) ) {
|
||||
$folder = Input::post('folder');
|
||||
} else {
|
||||
// IMAGE_DIRECTORY
|
||||
$folder = UPLOAD_DIRECTORY . App::$activeUser->username . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
$upload = Upload::image( 'upload', $folder );
|
||||
|
||||
if ( $upload ) {
|
||||
$route = str_replace( APP_ROOT_DIRECTORY, '', $folder );
|
||||
$out = $route . Upload::last();
|
||||
} else {
|
||||
Debug::error( 'There was an error with your upload.');
|
||||
Issues::add( 'error', [ 'There was an error with your upload.' => Check::userErrors() ] );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// if ( self::$token->create(
|
||||
// Input::post( 'name' ),
|
||||
// Input::post( 'notes' ),
|
||||
// Input::post( 'token_type' )
|
||||
// ) ) {
|
||||
// Session::flash( 'success', 'Token Created' );
|
||||
// Redirect::to( 'admin/images' );
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
Views::view( 'admin.images.create' );
|
||||
}
|
||||
|
||||
public function delete() {
|
||||
if ( self::$token->delete( [ $id ] ) ) {
|
||||
Session::flash( 'success', 'Token deleted.' );
|
||||
}
|
||||
Redirect::to( 'admin/images' );
|
||||
}
|
||||
|
||||
public function rename() {
|
||||
|
||||
if ( ! Input::exists( 'fileLocation' ) ) {
|
||||
Session::flash( 'warning', 'Unknown image.' );
|
||||
Redirect::to( 'admin/images' );
|
||||
}
|
||||
|
||||
Components::set( 'filelocation', Input::get( 'fileLocation' ) );
|
||||
|
||||
if ( Input::exists( 'submit' ) ) {
|
||||
if ( !TTPForms::check( 'renameIImage' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error renaming the image.' => Check::userErrors() ] );
|
||||
} else {
|
||||
$result = $this->renameFile( Input::post( 'filelocation' ), Input::post( 'newname' ) );
|
||||
|
||||
if ( ! empty( $result ) ) {
|
||||
Session::flash( 'success', 'Image has been renamed.' );
|
||||
Redirect::to( 'admin/images' );
|
||||
} else {
|
||||
Issues::add( 'error', [ 'There was an error with the install.' => $this->installer->getErrors() ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Views::view( 'admin.images.rename' );
|
||||
}
|
||||
|
||||
public function index() {
|
||||
return Views::view( 'admin.images.list.combined', $this->getAllImageDetails() );
|
||||
}
|
||||
|
||||
public function view() {
|
||||
if ( Input::exists( 'fileLocation' ) ) {
|
||||
return Views::view( 'admin.images.view', $this->getImageByLocation( Input::get( 'fileLocation' ) ) );
|
||||
}
|
||||
return $this->index();
|
||||
}
|
||||
|
||||
private function getAllImages() {
|
||||
$files = [];
|
||||
foreach ($this->directories as $dir) {
|
||||
if ($dir === 'app/plugins') {
|
||||
$pluginDirs = glob($dir . '/*', GLOB_ONLYDIR);
|
||||
foreach ($pluginDirs as $pluginDir) {
|
||||
$imageDir = $pluginDir . '/images';
|
||||
if (is_dir($imageDir)) {
|
||||
$files = array_merge($files, $this->scanDirectoryRecursively($imageDir));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$files = array_merge($files, $this->scanDirectory($dir));
|
||||
}
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
|
||||
private function scanDirectory($path) {
|
||||
return glob($path . '/*.{jpg,jpeg,png,gif,webp}', GLOB_BRACE) ?: [];
|
||||
}
|
||||
|
||||
private function scanDirectoryRecursively($path) {
|
||||
$files = [];
|
||||
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS));
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
if (preg_match('/\.(jpg|jpeg|png|gif|webp)$/i', $file->getFilename())) {
|
||||
$files[] = $file->getPathname();
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
private function getAllImageDetails() {
|
||||
$images = [];
|
||||
$files = $this->getAllImages();
|
||||
foreach ( $files as $file ) {
|
||||
$images[] = $this->getImageByLocation( $file );
|
||||
}
|
||||
return $images;
|
||||
}
|
||||
|
||||
private function getImageByLocation( $location ) {
|
||||
$realPath = realpath( $location );
|
||||
|
||||
return (object) [
|
||||
'filename' => basename( $location ),
|
||||
'extension' => pathinfo( $location , PATHINFO_EXTENSION),
|
||||
'fileSize' => $this->formatFileSize(filesize( $location )),
|
||||
'location' => $realPath,
|
||||
'locationSafe' => urlencode( $realPath ),
|
||||
'url' => Routes::getAddress() . str_replace( APP_ROOT_DIRECTORY, '', $realPath ),
|
||||
'folder' => dirname( $location )
|
||||
];
|
||||
}
|
||||
|
||||
private function formatFileSize($size) {
|
||||
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
$i = 0;
|
||||
while ($size >= 1024 && $i < count($units) - 1) {
|
||||
$size /= 1024;
|
||||
$i++;
|
||||
}
|
||||
return round($size, 2) . ' ' . $units[$i];
|
||||
}
|
||||
|
||||
private function renameFile( $currentLocation, $newFilename ) {
|
||||
// Ensure the file exists
|
||||
if (!file_exists($currentLocation)) {
|
||||
throw new \Exception("File does not exist: $currentLocation");
|
||||
}
|
||||
|
||||
// Extract directory and current extension
|
||||
$directory = dirname($currentLocation);
|
||||
$currentExtension = pathinfo($currentLocation, PATHINFO_EXTENSION);
|
||||
$newExtension = pathinfo($newFilename, PATHINFO_EXTENSION);
|
||||
|
||||
// Ensure the file extension has not changed
|
||||
if (strcasecmp($currentExtension, $newExtension) !== 0) {
|
||||
throw new \Exception("File extension cannot be changed.");
|
||||
}
|
||||
|
||||
// Construct the new file path
|
||||
$newLocation = $directory . DIRECTORY_SEPARATOR . $newFilename;
|
||||
|
||||
// Ensure the new file name does not already exist
|
||||
if (file_exists($newLocation)) {
|
||||
throw new \Exception("A file with the new name already exists: $newFilename");
|
||||
}
|
||||
|
||||
// Attempt to rename the file
|
||||
if (!rename($currentLocation, $newLocation)) {
|
||||
throw new \Exception("Failed to rename file.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -30,8 +30,6 @@ class Plugins extends AdminController {
|
||||
self::$title = 'Admin - Installed Plugins';
|
||||
$this->installer = new Installer;
|
||||
$this->plugins = $this->installer->getAvailablePlugins();
|
||||
$view = Navigation::activePageSelect( 'nav.admin', '/admin/plugins' );
|
||||
Components::set( 'ADMINNAV', $view );
|
||||
}
|
||||
|
||||
public function index() {
|
||||
|
@ -31,8 +31,6 @@ class Routes extends AdminController {
|
||||
parent::__construct();
|
||||
self::$title = 'Admin - Redirects';
|
||||
self::$routes = new RoutesClass;
|
||||
$view = Navigation::activePageSelect( 'nav.admin', '/admin/routes' );
|
||||
Components::set( 'ADMINNAV', $view );
|
||||
}
|
||||
|
||||
public function create() {
|
||||
|
@ -31,8 +31,6 @@ class Tokens extends AdminController {
|
||||
parent::__construct();
|
||||
self::$title = 'Admin - Tokens';
|
||||
self::$token = new Token;
|
||||
$view = Navigation::activePageSelect( 'nav.admin', '/admin/tokens' );
|
||||
Components::set( 'ADMINNAV', $view );
|
||||
}
|
||||
|
||||
public function create() {
|
||||
|
@ -27,6 +27,7 @@ use TheTempusProject\Models\User;
|
||||
use TheTempusProject\Models\Group;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Houdini\Classes\Template;
|
||||
use TheTempusProject\Bedrock\Functions\Upload;
|
||||
|
||||
class Users extends AdminController {
|
||||
public static $user;
|
||||
@ -37,8 +38,6 @@ class Users extends AdminController {
|
||||
self::$title = 'Admin - Users';
|
||||
self::$user = new User;
|
||||
self::$group = new Group;
|
||||
$view = Navigation::activePageSelect( 'nav.admin', '/admin/users' );
|
||||
Components::set( 'ADMINNAV', $view );
|
||||
}
|
||||
|
||||
public function create() {
|
||||
@ -106,7 +105,7 @@ class Users extends AdminController {
|
||||
}
|
||||
|
||||
if ( Input::exists( 'submit' ) ) {
|
||||
if ( !FormChecker::check( 'editUser' ) ) {
|
||||
if ( ! FormChecker::check( 'editUser' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your request.' => Check::userErrors() ] );
|
||||
} else {
|
||||
$fields = [
|
||||
@ -114,6 +113,25 @@ class Users extends AdminController {
|
||||
'email' => Input::post( 'email' ),
|
||||
'userGroup' => Input::post( 'groupSelect' ),
|
||||
];
|
||||
|
||||
if ( Input::exists( 'avatar' ) ) {
|
||||
$folder = UPLOAD_DIRECTORY . $userData->username . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR;
|
||||
$upload = Upload::image( 'avatar', $folder );
|
||||
if ( $upload ) {
|
||||
$route = str_replace( APP_ROOT_DIRECTORY, '', $folder );
|
||||
$prefs = [];
|
||||
$prefs['avatar'] = $route . Upload::last();
|
||||
|
||||
self::$user->updatePrefs( $prefs, $userData->ID );
|
||||
} else {
|
||||
Issues::add( 'error', [ 'There was an error with your avatar.' => Check::userErrors() ] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( Input::exists( 'password' ) ) {
|
||||
$fields['password'] = Hash::make( Input::post( 'password' ) );
|
||||
}
|
||||
|
||||
if ( Input::exists( 'confirmed' ) ) {
|
||||
$fields['confirmed'] = 1;
|
||||
} else {
|
||||
@ -121,6 +139,7 @@ class Users extends AdminController {
|
||||
$fields['confirmationCode'] = Code::genConfirmation();
|
||||
}
|
||||
}
|
||||
|
||||
if ( self::$user->update( $userData->ID, $fields ) ) {
|
||||
Issues::add( 'success', 'User Updated.' );
|
||||
return $this->index();
|
||||
|
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* app/controllers/alpha.php
|
||||
*
|
||||
* This is the friends and family alpha controller.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers;
|
||||
|
||||
use TheTempusProject\Classes\Controller;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
|
||||
class Alpha extends Controller {
|
||||
public function index() {
|
||||
self::$title = 'Friends and Family Alpha';
|
||||
self::$pageDescription = 'The Tempus Project friends and family alpha has begun. Please join me and take part in bringing a dream to reality.';
|
||||
Views::view( 'alpha.index' );
|
||||
}
|
||||
|
||||
public function crashcourse() {
|
||||
self::$title = 'Friends and Family Crash-Course';
|
||||
self::$pageDescription = 'The Tempus Project runs not only this site, but it can be used and deployed for any number of sites. This crash course is intended to give you all the knowledge you will need to start building your own applications powered by The Tempus Project.';
|
||||
Views::view( 'alpha.crashcourse' );
|
||||
}
|
||||
|
||||
public function certification() {
|
||||
self::$title = 'Friends and Family Certification';
|
||||
self::$pageDescription = 'The Tempus Project runs not only this site, but it can be used and deployed for any number of sites. This certification course is intended to give experienced users all the information they will need to start building your own applications powered by The Tempus Project.';
|
||||
Views::view( 'alpha.certification' );
|
||||
}
|
||||
}
|
@ -38,15 +38,15 @@ class Home extends Controller {
|
||||
return Issues::add( 'notice', 'You are already logged in. Please <a href="' . Routes::getAddress() . 'home/logout">click here</a> to log out.' );
|
||||
}
|
||||
if ( !Input::exists() ) {
|
||||
return Views::view( 'login' );
|
||||
return Views::view( 'auth.login' );
|
||||
}
|
||||
if ( !Forms::check( 'login' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your login.' => Check::userErrors() ] );
|
||||
return Views::view( 'login' );
|
||||
return Views::view( 'auth.login' );
|
||||
}
|
||||
if ( !self::$user->logIn( Input::post( 'username' ), Input::post( 'password' ), Input::post( 'remember' ) ) ) {
|
||||
Issues::add( 'error', 'Username or password was incorrect.' );
|
||||
return Views::view( 'login' );
|
||||
return Views::view( 'auth.login' );
|
||||
}
|
||||
Session::flash( 'success', 'You have been logged in.' );
|
||||
if ( Input::exists( 'rurl' ) ) {
|
||||
@ -79,13 +79,13 @@ class Home extends Controller {
|
||||
}
|
||||
self::$title = $user->username . '\'s Profile - {SITENAME}';
|
||||
self::$pageDescription = 'User Profile for ' . $user->username . ' - {SITENAME}';
|
||||
Views::view( 'profile', $user );
|
||||
Views::view( 'profilePage', $user );
|
||||
}
|
||||
|
||||
public function terms() {
|
||||
self::$title = 'Terms and Conditions - {SITENAME}';
|
||||
self::$pageDescription = '{SITENAME} Terms and Conditions of use. Please use {SITENAME} safely.';
|
||||
Components::set( 'TERMS', Views::simpleView( 'terms' ) );
|
||||
Components::set( 'TERMS', Views::simpleView( 'auth.terms' ) );
|
||||
Views::view( 'termsPage' );
|
||||
}
|
||||
|
||||
@ -98,8 +98,7 @@ class Home extends Controller {
|
||||
public function privacy() {
|
||||
self::$title = 'Privacy Policy - {SITENAME}';
|
||||
self::$pageDescription = 'At {SITENAME} you privacy is very important to us. On this page you can find a detailed outline of all the information we collect and how its used.';
|
||||
Components::set( 'PRIVACY', Views::simpleView( 'privacy' ) );
|
||||
Views::raw( '<div class="col-lg-8 mx-auto">{PRIVACY}</div>' );
|
||||
Views::view( 'privacy' );
|
||||
}
|
||||
|
||||
public function faq() {
|
||||
|
@ -1,3 +0,0 @@
|
||||
<?php
|
||||
// the idea is that this will be info pages for the plugin various/info
|
||||
?>
|
@ -31,14 +31,14 @@ class Register extends Controller {
|
||||
Template::noIndex();
|
||||
self::$title = 'Confirm Email';
|
||||
if ( !isset( $code ) && !Input::exists( 'confirmationCode' ) ) {
|
||||
return Views::view( 'confirmation' );
|
||||
return Views::view( 'auth.confirmation' );
|
||||
}
|
||||
if ( Forms::check( 'emailConfirmation' ) ) {
|
||||
$code = Input::post( 'confirmationCode' );
|
||||
}
|
||||
if ( !self::$user->confirm( $code ) ) {
|
||||
Issues::add( 'error', 'There was an error confirming your account, please try again.' );
|
||||
return Views::view( 'confirmation' );
|
||||
return Views::view( 'auth.confirmation' );
|
||||
}
|
||||
Session::flash( 'success', 'You have successfully confirmed your email address.' );
|
||||
Redirect::to( 'home/index' );
|
||||
@ -52,16 +52,16 @@ class Register extends Controller {
|
||||
return Issues::add( 'notice', 'The site administrator has disable the ability to register a new account.' );
|
||||
}
|
||||
|
||||
Components::set( 'TERMS', Views::simpleView( 'terms' ) );
|
||||
Components::set( 'TERMS', Views::simpleView( 'auth.terms' ) );
|
||||
if ( App::$isLoggedIn ) {
|
||||
return Issues::add( 'notice', 'You are currently logged in.' );
|
||||
}
|
||||
if ( !Input::exists() ) {
|
||||
return Views::view( 'register' );
|
||||
return Views::view( 'auth.register' );
|
||||
}
|
||||
if ( !Forms::check( 'register' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your registration.' => Check::userErrors() ] );
|
||||
return Views::view( 'register' );
|
||||
return Views::view( 'auth.register' );
|
||||
}
|
||||
self::$user->create( [
|
||||
'username' => Input::post( 'username' ),
|
||||
@ -80,7 +80,7 @@ class Register extends Controller {
|
||||
self::$title = 'Recover Account - {SITENAME}';
|
||||
Template::noIndex();
|
||||
if ( !Input::exists() ) {
|
||||
return Views::view( 'forgot' );
|
||||
return Views::view( 'auth.forgot' );
|
||||
}
|
||||
if ( Check::email( Input::post( 'entry' ) ) && self::$user->findByEmail( Input::post( 'entry' ) ) ) {
|
||||
$userData = self::$user->data();
|
||||
@ -96,7 +96,7 @@ class Register extends Controller {
|
||||
Redirect::to( 'home/login' );
|
||||
}
|
||||
Issues::add( 'error', 'User not found.' );
|
||||
Views::view( 'forgot' );
|
||||
Views::view( 'auth.forgot' );
|
||||
}
|
||||
|
||||
public function resend() {
|
||||
@ -109,7 +109,7 @@ class Register extends Controller {
|
||||
return Issues::add( 'notice', 'Your account has already been confirmed.' );
|
||||
}
|
||||
if ( !Forms::check( 'confirmationResend' ) ) {
|
||||
return Views::view( 'confirmation_resend' );
|
||||
return Views::view( 'auth.confirmation_resend' );
|
||||
}
|
||||
Email::send( App::$activeUser->email, 'confirmation', App::$activeUser->confirmationCode, [ 'template' => true ] );
|
||||
Session::flash( 'success', 'Your confirmation email has been sent to the email for your account.' );
|
||||
@ -121,7 +121,7 @@ class Register extends Controller {
|
||||
Template::noIndex();
|
||||
if ( !isset( $code ) && !Input::exists( 'resetCode' ) ) {
|
||||
Issues::add( 'info', 'Please provide a reset code.' );
|
||||
return Views::view( 'password_reset_code' );
|
||||
return Views::view( 'auth.password_reset_code' );
|
||||
}
|
||||
if ( Input::exists( 'resetCode' ) ) {
|
||||
if ( Forms::check( 'passwordResetCode' ) ) {
|
||||
@ -130,15 +130,15 @@ class Register extends Controller {
|
||||
}
|
||||
if ( ! self::$user->checkCode( $code ) ) {
|
||||
Issues::add( 'error', 'There was an error with your reset code. Please try again.' );
|
||||
return Views::view( 'password_reset_code' );
|
||||
return Views::view( 'auth.password_reset_code' );
|
||||
}
|
||||
Components::set( 'resetCode', $code );
|
||||
if ( ! Input::exists('password') ) {
|
||||
return Views::view( 'password_reset' );
|
||||
return Views::view( 'auth.password_reset' );
|
||||
}
|
||||
if ( ! Forms::check( 'passwordReset' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your request.' => Check::userErrors() ] );
|
||||
return Views::view( 'password_reset' );
|
||||
return Views::view( 'auth.password_reset' );
|
||||
}
|
||||
self::$user->changePassword( $code, Input::post( 'password' ) );
|
||||
Email::send( self::$user->data()->email, 'passwordChange', null, [ 'template' => true ] );
|
||||
|
@ -70,7 +70,7 @@ class Usercp extends Controller {
|
||||
self::$title = 'User Control Panel';
|
||||
$menu = Views::simpleView( 'nav.usercp', App::$userCPlinks );
|
||||
Navigation::activePageSelect( $menu, null, true, true );
|
||||
Views::view( 'profile', App::$activeUser );
|
||||
Views::view( 'user_cp.profile', App::$activeUser );
|
||||
}
|
||||
|
||||
public function password() {
|
||||
@ -104,6 +104,10 @@ class Usercp extends Controller {
|
||||
$userPrefs = App::$activePrefs;
|
||||
if ( Input::exists( 'submit' ) ) {
|
||||
$fields = $prefs->convertFormToArray( true, false );
|
||||
// @TODO now i may need to rework the form checker to work with this....
|
||||
// if (!Forms::check('userPrefs')) {
|
||||
// Issues::add( 'error', [ 'There was an error with your request.' => Check::userErrors() ] );
|
||||
// }
|
||||
self::$user->updatePrefs( $fields, App::$activeUser->ID );
|
||||
Issues::add( 'success', 'Your preferences have been updated.' );
|
||||
// if the image upload fails, need to fall back on original
|
||||
|
@ -9,36 +9,42 @@
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
|
||||
.context-main {
|
||||
color: #fff;
|
||||
}
|
||||
.context-second {
|
||||
color: #1e1e1e;
|
||||
.context-main-border {
|
||||
border-color: #f5f5f5!important;
|
||||
}
|
||||
|
||||
.context-main-bg {
|
||||
background-color: #2c2c2c;
|
||||
}
|
||||
.context-second-bg {
|
||||
background-color: #1e1e1e;
|
||||
background-color: #383838;
|
||||
}
|
||||
.context-third-bg {
|
||||
background-color: #3a3a3a;
|
||||
}
|
||||
.context-other-bg {
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
.context-main {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.bg-default {
|
||||
background-color: #2c2c2c;
|
||||
}
|
||||
|
||||
hr {
|
||||
color: #f5f5f5;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.bg-none,.bg-warning {
|
||||
color: #000 !important;
|
||||
}
|
||||
.context-other {
|
||||
color: #000;
|
||||
}
|
||||
.accordion-button:not(.collapsed) {
|
||||
color: #f5f5f5;
|
||||
background-color: var(--bs-accordion-dark-active-bg);
|
||||
@ -68,12 +74,6 @@ body {
|
||||
.install-terms strong {
|
||||
color: #ffffff;
|
||||
}
|
||||
.context-main {
|
||||
color: #ffffff;
|
||||
}
|
||||
.context-other {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terms Page
|
||||
|
@ -9,10 +9,28 @@
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
|
||||
.context-other-bg {
|
||||
background-color: #eaeaea;
|
||||
.context-main-border {
|
||||
border-color: #1e1e1e!important;
|
||||
}
|
||||
|
||||
.context-main-bg {
|
||||
background-color: #f7f7f7;
|
||||
/* background-color: #b1b; */
|
||||
}
|
||||
.context-second-bg {
|
||||
background-color: #eaeaea;
|
||||
/* background-color: #b1b; */
|
||||
}
|
||||
.context-third-bg {
|
||||
background-color: #ccc;
|
||||
/* background-color: #b1b; */
|
||||
}
|
||||
|
||||
.context-main {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
|
||||
.nav-link.active {
|
||||
font-weight: bold; /* Make the text bold */
|
||||
}
|
||||
@ -21,10 +39,6 @@ hr {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.context-main-bg {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
/* Base styles for the switch container */
|
||||
.material-switch {
|
||||
position: relative;
|
||||
@ -77,20 +91,6 @@ hr {
|
||||
transform: translateX(25px); /* Adjust based on switch width */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.context-main {
|
||||
color: #000;
|
||||
}
|
||||
.context-other {
|
||||
color: #fff;
|
||||
}
|
||||
html {
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
position: relative;
|
||||
@ -319,3 +319,4 @@ body {
|
||||
/* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
|
||||
background: linear-gradient(to right, #2c2c2c, #1e1e1e, #1e1e1e);
|
||||
}
|
||||
|
||||
|
@ -1,218 +0,0 @@
|
||||
/**
|
||||
* app/css/wysiwyg.css
|
||||
*
|
||||
* This file is for the wysiwyg editor's css.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-family: 'Helvetica Neue', 'Helvetica', arial, sans-serif;
|
||||
}
|
||||
|
||||
/* WYSIWYG Editor */
|
||||
.wp-webdeasy-comment-editor {
|
||||
width: 40rem;
|
||||
min-height: 18rem;
|
||||
box-shadow: 0 0 4px 1px rgba(0, 0, 0, 0.3);
|
||||
border-top: 6px solid #4a4a4a;
|
||||
border-radius: 3px;
|
||||
margin: 2rem 0;
|
||||
|
||||
.toolbar {
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
|
||||
|
||||
.line {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #e2e2e2;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.box {
|
||||
display: flex;
|
||||
border-left: 1px solid #e2e2e2;
|
||||
|
||||
.editor-btn {
|
||||
display: block;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
transition: .2s ease all;
|
||||
|
||||
&:hover, &.active {
|
||||
background-color: #e1e1e1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.icon img {
|
||||
width: 15px;
|
||||
padding: 9px;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
&.icon.smaller img {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
&.has-submenu {
|
||||
width: 20px;
|
||||
padding: 0 10px;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
position: absolute;
|
||||
background-image: url(https://img.icons8.com/ios-glyphs/30/000000/chevron-down.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
.submenu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 34px;
|
||||
left: -1px;
|
||||
z-index: 10;
|
||||
background-color: #FFF;
|
||||
border: 1px solid #b5b5b5;
|
||||
border-top: none;
|
||||
|
||||
.btn {
|
||||
width: 39px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .submenu {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-area {
|
||||
padding: 15px 12px;
|
||||
line-height: 1.5;
|
||||
|
||||
.visuell-view {
|
||||
outline: none;
|
||||
min-height: 12rem;
|
||||
|
||||
p {
|
||||
margin: 12px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.html-view {
|
||||
outline: none;
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
border: none;
|
||||
resize: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Modal */
|
||||
.modal {
|
||||
z-index: 40;
|
||||
display: none;
|
||||
|
||||
.modal-wrapper {
|
||||
background-color: #FFF;
|
||||
padding: 1rem;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 20rem;
|
||||
min-height: 10rem;
|
||||
z-index: 41;
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
flex-direction: column;
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
input {
|
||||
margin: 1rem 0;
|
||||
padding: .5rem;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
width: calc(100% - 1rem);
|
||||
}
|
||||
|
||||
.row {
|
||||
|
||||
label {
|
||||
margin-left: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #D2434F;
|
||||
border: 0;
|
||||
color: #FFF;
|
||||
padding: .5rem 1.2rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-bg {
|
||||
position: fixed;
|
||||
background-color: rgba(0, 0, 0, .3);
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Codepen Footer */
|
||||
footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
|
||||
p {
|
||||
margin: 0.5rem 1rem;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
}
|
@ -125,7 +125,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
if ( toggleButton ) {
|
||||
toggleButton.checked = true;
|
||||
}
|
||||
|
||||
|
||||
if ( enableButton ) {
|
||||
enableButton.innerText = 'Disable Now';
|
||||
}
|
||||
@ -158,21 +158,21 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
toggleButton.addEventListener('click', function () {
|
||||
if (darkModeStylesheet.disabled) {
|
||||
toggleDarkModePref( true );
|
||||
darkModeStylesheet.disabled = false;
|
||||
localStorage.setItem('darkMode', 'enabled');
|
||||
} else {
|
||||
toggleDarkModePref( false );
|
||||
darkModeStylesheet.disabled = true;
|
||||
localStorage.setItem('darkMode', 'disabled');
|
||||
}
|
||||
|
||||
document.querySelectorAll('.table-striped').forEach((table) => {
|
||||
if (localStorage.getItem('darkMode') === 'enabled') {
|
||||
table.classList.add('table-dark');
|
||||
table.classList.remove('table-light');
|
||||
darkModeStylesheet.disabled = false;
|
||||
localStorage.setItem('darkMode', 'enabled');
|
||||
} else {
|
||||
table.classList.add('table-light');
|
||||
table.classList.remove('table-dark');
|
||||
toggleDarkModePref( false );
|
||||
darkModeStylesheet.disabled = true;
|
||||
localStorage.setItem('darkMode', 'disabled');
|
||||
}
|
||||
|
||||
document.querySelectorAll('.table-striped').forEach((table) => {
|
||||
if (localStorage.getItem('darkMode') === 'enabled') {
|
||||
table.classList.add('table-dark');
|
||||
table.classList.remove('table-light');
|
||||
} else {
|
||||
table.classList.add('table-light');
|
||||
table.classList.remove('table-dark');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -1,233 +0,0 @@
|
||||
/**
|
||||
* app/js/wysiwyg.js
|
||||
*
|
||||
* This is css used in the debuging console.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
// define vars
|
||||
const editor = document.getElementsByClassName('wp-webdeasy-comment-editor')[0];
|
||||
const toolbar = editor.getElementsByClassName('toolbar')[0];
|
||||
const buttons = toolbar.querySelectorAll('.editor-btn:not(.has-submenu)');
|
||||
const contentArea = editor.getElementsByClassName('content-area')[0];
|
||||
const visuellView = contentArea.getElementsByClassName('visuell-view')[0];
|
||||
const htmlView = contentArea.getElementsByClassName('html-view')[0];
|
||||
const modal = document.getElementsByClassName('modal')[0];
|
||||
|
||||
// add active tag event
|
||||
document.addEventListener('selectionchange', selectionChange);
|
||||
|
||||
// add paste event
|
||||
visuellView.addEventListener('paste', pasteEvent);
|
||||
|
||||
// add paragraph tag on new line
|
||||
contentArea.addEventListener('keypress', addParagraphTag);
|
||||
|
||||
// add toolbar button actions
|
||||
for(let i = 0; i < buttons.length; i++) {
|
||||
let button = buttons[i];
|
||||
|
||||
button.addEventListener('click', function(e) {
|
||||
let action = this.dataset.action;
|
||||
|
||||
switch(action) {
|
||||
case 'toggle-view':
|
||||
execCodeAction(this, editor);
|
||||
break;
|
||||
case 'createLink':
|
||||
execLinkAction();
|
||||
break;
|
||||
default:
|
||||
execDefaultAction(action);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This function toggles between visual and html view
|
||||
*/
|
||||
function execCodeAction(button, editor) {
|
||||
|
||||
if(button.classList.contains('active')) { // show visuell view
|
||||
visuellView.innerHTML = htmlView.value;
|
||||
htmlView.style.display = 'none';
|
||||
visuellView.style.display = 'block';
|
||||
|
||||
button.classList.remove('active');
|
||||
} else { // show html view
|
||||
htmlView.innerText = visuellView.innerHTML;
|
||||
visuellView.style.display = 'none';
|
||||
htmlView.style.display = 'block';
|
||||
|
||||
button.classList.add('active');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function adds a link to the current selection
|
||||
*/
|
||||
function execLinkAction() {
|
||||
modal.style.display = 'block';
|
||||
let selection = saveSelection();
|
||||
|
||||
let submit = modal.querySelectorAll('button.done')[0];
|
||||
let close = modal.querySelectorAll('.close')[0];
|
||||
|
||||
// done button active => add link
|
||||
submit.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
let newTabCheckbox = modal.querySelectorAll('#new-tab')[0];
|
||||
let linkInput = modal.querySelectorAll('#linkValue')[0];
|
||||
let linkValue = linkInput.value;
|
||||
let newTab = newTabCheckbox.checked;
|
||||
|
||||
restoreSelection(selection);
|
||||
|
||||
if(window.getSelection().toString()) {
|
||||
let a = document.createElement('a');
|
||||
a.href = linkValue;
|
||||
if(newTab) a.target = '_blank';
|
||||
window.getSelection().getRangeAt(0).surroundContents(a);
|
||||
}
|
||||
|
||||
modal.style.display = 'none';
|
||||
linkInput.value = '';
|
||||
|
||||
// deregister modal events
|
||||
submit.removeEventListener('click', arguments.callee);
|
||||
close.removeEventListener('click', arguments.callee);
|
||||
});
|
||||
|
||||
// close modal on X click
|
||||
close.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
let linkInput = modal.querySelectorAll('#linkValue')[0];
|
||||
|
||||
modal.style.display = 'none';
|
||||
linkInput.value = '';
|
||||
|
||||
// deregister modal events
|
||||
submit.removeEventListener('click', arguments.callee);
|
||||
close.removeEventListener('click', arguments.callee);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This function executes all 'normal' actions
|
||||
*/
|
||||
function execDefaultAction(action) {
|
||||
document.execCommand(action, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current selection
|
||||
*/
|
||||
function saveSelection() {
|
||||
if(window.getSelection) {
|
||||
sel = window.getSelection();
|
||||
if(sel.getRangeAt && sel.rangeCount) {
|
||||
let ranges = [];
|
||||
for(var i = 0, len = sel.rangeCount; i < len; ++i) {
|
||||
ranges.push(sel.getRangeAt(i));
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
} else if (document.selection && document.selection.createRange) {
|
||||
return document.selection.createRange();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a saved selection
|
||||
*/
|
||||
function restoreSelection(savedSel) {
|
||||
if(savedSel) {
|
||||
if(window.getSelection) {
|
||||
sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
for(var i = 0, len = savedSel.length; i < len; ++i) {
|
||||
sel.addRange(savedSel[i]);
|
||||
}
|
||||
} else if(document.selection && savedSel.select) {
|
||||
savedSel.select();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current selected format buttons active/inactive
|
||||
*/
|
||||
function selectionChange(e) {
|
||||
|
||||
for(let i = 0; i < buttons.length; i++) {
|
||||
let button = buttons[i];
|
||||
|
||||
// don't remove active class on code toggle button
|
||||
if(button.dataset.action === 'toggle-view') continue;
|
||||
|
||||
button.classList.remove('active');
|
||||
}
|
||||
|
||||
if(!childOf(window.getSelection().anchorNode.parentNode, editor)) return false;
|
||||
|
||||
parentTagActive(window.getSelection().anchorNode.parentNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the passed child has the passed parent
|
||||
*/
|
||||
function childOf(child, parent) {
|
||||
return parent.contains(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tag active that is responsible for the current element
|
||||
*/
|
||||
function parentTagActive(elem) {
|
||||
if(!elem ||!elem.classList || elem.classList.contains('visuell-view')) return false;
|
||||
|
||||
let toolbarButton;
|
||||
|
||||
// active by tag names
|
||||
let tagName = elem.tagName.toLowerCase();
|
||||
toolbarButton = document.querySelectorAll(`.toolbar .editor-btn[data-tag-name="${tagName}"]`)[0];
|
||||
if(toolbarButton) {
|
||||
toolbarButton.classList.add('active');
|
||||
}
|
||||
|
||||
// active by text-align
|
||||
let textAlign = elem.style.textAlign;
|
||||
toolbarButton = document.querySelectorAll(`.toolbar .editor-btn[data-style="textAlign:${textAlign}"]`)[0];
|
||||
if(toolbarButton) {
|
||||
toolbarButton.classList.add('active');
|
||||
}
|
||||
|
||||
return parentTagActive(elem.parentNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the paste event and removes all HTML tags
|
||||
*/
|
||||
function pasteEvent(e) {
|
||||
e.preventDefault();
|
||||
|
||||
let text = (e.originalEvent || e).clipboardData.getData('text/plain');
|
||||
document.execCommand('insertHTML', false, text);
|
||||
}
|
||||
|
||||
/**
|
||||
* This functions adds a paragraph tag when the enter key is pressed
|
||||
*/
|
||||
function addParagraphTag(evt) {
|
||||
if (evt.keyCode == '13') {
|
||||
|
||||
// don't add a p tag on list item
|
||||
if(window.getSelection().anchorNode.parentNode.tagName === 'LI') return;
|
||||
document.execCommand('formatBlock', false, 'p');
|
||||
}
|
||||
}
|
@ -38,11 +38,22 @@ class Group extends DatabaseModel {
|
||||
[ 'name', 'varchar', '32' ],
|
||||
[ 'permissions', 'text', '' ],
|
||||
];
|
||||
public $searchFields = [
|
||||
'name',
|
||||
];
|
||||
public $permissionMatrix = [
|
||||
'adminAccess' => [
|
||||
'pretty' => 'Access Administrator Areas',
|
||||
'default' => false,
|
||||
],
|
||||
'uploadImages' => [
|
||||
'pretty' => 'Upload images (such as avatars)',
|
||||
'default' => false,
|
||||
],
|
||||
'maintenanceAccess' => [
|
||||
'pretty' => 'Upload images (such as avatars)',
|
||||
'default' => false,
|
||||
],
|
||||
];
|
||||
public $resourceMatrix = [
|
||||
[
|
||||
|
@ -46,6 +46,9 @@ class Log extends DatabaseModel {
|
||||
[ 'source', 'varchar', '64' ],
|
||||
[ 'action', 'text', '' ],
|
||||
];
|
||||
public $searchFields = [
|
||||
'source',
|
||||
];
|
||||
|
||||
/**
|
||||
* The model constructor.
|
||||
|
@ -24,6 +24,9 @@ class Routes extends DatabaseModel {
|
||||
[ 'original_url', 'varchar', '32' ],
|
||||
[ 'forwarded_url', 'text', '' ],
|
||||
];
|
||||
public $searchFields = [
|
||||
'nickname',
|
||||
];
|
||||
public $resourceMatrix = [
|
||||
[
|
||||
'original_url' => 'fb',
|
||||
|
@ -36,6 +36,9 @@ class Sessions extends DatabaseModel {
|
||||
[ 'username', 'varchar', '20' ],
|
||||
[ 'token', 'varchar', '120' ],
|
||||
];
|
||||
public $searchFields = [
|
||||
'username',
|
||||
];
|
||||
public static $activeSession = false;
|
||||
|
||||
/**
|
||||
|
@ -31,6 +31,10 @@ class Token extends DatabaseModel {
|
||||
[ 'createdBy', 'int', '10' ],
|
||||
[ 'expiresAt', 'int', '10' ],
|
||||
];
|
||||
public $searchFields = [
|
||||
'name',
|
||||
'token',
|
||||
];
|
||||
public $permissionMatrix = [
|
||||
'addAppToken' => [
|
||||
'pretty' => 'Add Application Tokens',
|
||||
|
@ -44,11 +44,8 @@ class User extends DatabaseModel {
|
||||
[ 'confirmationCode', 'varchar', '80' ],
|
||||
[ 'prefs', 'text', '' ],
|
||||
];
|
||||
public $permissionMatrix = [
|
||||
'uploadImages' => [
|
||||
'pretty' => 'Upload images (such as avatars)',
|
||||
'default' => false,
|
||||
],
|
||||
public $searchFields = [
|
||||
'username',
|
||||
];
|
||||
public $preferenceMatrix = [
|
||||
'gender' => [
|
||||
@ -428,7 +425,7 @@ class User extends DatabaseModel {
|
||||
if ( ! empty( $filter ) ) {
|
||||
switch ( $filter ) {
|
||||
case 'newsletter':
|
||||
$data = self::$db->search( $this->tableName, 'prefs', 'newsletter":"true' );
|
||||
$data = self::$db->searchColumn( $this->tableName, 'prefs', 'newsletter":"true' );
|
||||
break;
|
||||
default:
|
||||
$data = self::$db->get( $this->tableName, '*' );
|
||||
@ -546,6 +543,7 @@ class User extends DatabaseModel {
|
||||
$instance->prefs = json_decode( $instance->prefs, true );
|
||||
$instance->gender = $instance->prefs['gender'];
|
||||
$instance->avatar = $instance->prefs['avatar'];
|
||||
$instance->usernamePretty = \ucfirst( $instance->username );
|
||||
$out[] = $instance;
|
||||
if ( !empty( $end ) ) {
|
||||
$out = $out[0];
|
||||
@ -659,7 +657,7 @@ class User extends DatabaseModel {
|
||||
}
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'userUpdate' );
|
||||
Debug::error( "User: $id not updated: $fields" );
|
||||
Debug::error( "User: $id not updated: " . var_export( $fields, true ) );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -29,8 +29,6 @@ class Blog extends AdminController {
|
||||
parent::__construct();
|
||||
self::$posts = new Posts;
|
||||
self::$title = 'Admin - Blog';
|
||||
$view = Navigation::activePageSelect( 'nav.admin', '/admin/blog' );
|
||||
Components::set( 'ADMINNAV', $view );
|
||||
}
|
||||
|
||||
public function index( $data = null ) {
|
||||
|
@ -171,4 +171,16 @@ class Blog extends Controller {
|
||||
self::$pageDescription = '{SITENAME} blog posts easily and conveniently sorted by years.';
|
||||
Views::view( 'blog.list', self::$posts->byYear( $year ) );
|
||||
}
|
||||
|
||||
public function search() {
|
||||
$results = [];
|
||||
if ( Input::exists( 'submit' ) ) {
|
||||
$dbResults = self::$posts->search( Input::post('searchTerm') );
|
||||
if ( ! empty( $dbResults ) ) {
|
||||
$results = $dbResults;
|
||||
}
|
||||
}
|
||||
Components::set( 'searchResults', Views::simpleView( 'blog.list', $results ) );
|
||||
Views::view( 'blog.searchResults' );
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,11 @@ use TheTempusProject\Models\Comments;
|
||||
|
||||
class Posts extends DatabaseModel {
|
||||
public $tableName = 'posts';
|
||||
public $searchFields = [
|
||||
'title',
|
||||
'slug',
|
||||
'content',
|
||||
];
|
||||
public static $comments = false;
|
||||
|
||||
public $databaseMatrix = [
|
||||
|
@ -37,6 +37,7 @@ class Blog extends Plugin {
|
||||
'posts' => [
|
||||
[
|
||||
'title' => 'Welcome',
|
||||
'slug' => 'welcome',
|
||||
'content' => '<p>This is just a simple message to say thank you for installing The Tempus Project. If you have any questions you can find everything through our website <a href="https://TheTempusProject.com">here</a>.</p>',
|
||||
'author' => 1,
|
||||
'created' => '{time}',
|
||||
|
@ -26,9 +26,10 @@ class BlogLoader extends DefaultLoader {
|
||||
*/
|
||||
public function __construct() {
|
||||
$posts = new Posts;
|
||||
Components::set('SIDEBAR', Views::simpleView('blog.sidebar', $posts->recent(5)));
|
||||
Components::set('SIDEBAR2', Views::simpleView('blog.sidebar2', $posts->archive()));
|
||||
Components::set('SIDEBARABOUT', Views::simpleView('blog.about'));
|
||||
Components::set('SIDEBAR', Views::simpleView('blog.widgets.recent', $posts->recent(5)));
|
||||
Components::set('SIDEBAR2', Views::simpleView('blog.widgets.archive', $posts->archive()));
|
||||
Components::set('SIDEBARABOUT', Views::simpleView('blog.widgets.about'));
|
||||
Components::set('SIDEBARSEARCH', Views::simpleView('blog.widgets.search'));
|
||||
Components::set('BLOGFEATURES', '');
|
||||
Navigation::setCrumbComponent( 'BLOG_BREADCRUMBS', Input::get( 'url' ) );
|
||||
Components::set( 'BLOG_TEMPLATE_URL', Template::parse( '{ROOT_URL}app/plugins/comments/' ) );
|
||||
|
@ -39,25 +39,44 @@
|
||||
</head>
|
||||
<body>
|
||||
<!-- Navigation -->
|
||||
<header class="p-3 text-bg-dark">
|
||||
<div class="container">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
|
||||
<img src="{ROOT_URL}{LOGO}" class="bi me-2" width="40" height="32" role="img" aria-label="{SITENAME} Logo">
|
||||
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
|
||||
{SITENAME}
|
||||
</a>
|
||||
{topNavLeft}
|
||||
<div class="text-end d-flex align-items-center">
|
||||
{topNavRight}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<header class="p-3 text-bg-dark">
|
||||
<div class="container">
|
||||
<div class="d-flex align-items-center position-relative">
|
||||
<!-- Navbar Toggler (Left) -->
|
||||
|
||||
<!-- Centered Logo (Now inside normal document flow) -->
|
||||
<a href="/" class="align-items-center text-white text-decoration-none d-flex d-md-none">
|
||||
<img src="{ROOT_URL}{LOGO}" width="40" height="32" alt="{SITENAME} Logo" class="bi">
|
||||
</a>
|
||||
|
||||
<!-- Logo (Normal Position for Large Screens) -->
|
||||
<a href="/" class="align-items-center text-white text-decoration-none d-none d-md-flex">
|
||||
<img src="{ROOT_URL}{LOGO}" width="40" height="32" alt="{SITENAME} Logo" class="bi">
|
||||
</a>
|
||||
|
||||
<div class="navbar-expand-md flex-grow-1">
|
||||
<div class="collapse navbar-collapse d-md-flex" id="mainMenu">
|
||||
<!-- Centered Navigation -->
|
||||
<div class="d-none d-md-block d-flex justify-content-center position-absolute start-50 translate-middle-x">
|
||||
{topNavLeft}
|
||||
</div>
|
||||
<div class="d-flex justify-content-center flex-grow-1 d-md-none">
|
||||
{topNavLeft}
|
||||
</div>
|
||||
|
||||
<!-- Right-Side Content (Push to End) -->
|
||||
<div class="d-flex flex-row justify-content-center align-items-center mt-3 mt-md-0 ms-md-auto">
|
||||
{topNavRight}
|
||||
</div>
|
||||
</div> <!-- End Collapse -->
|
||||
</div> <!-- End Navbar Expand -->
|
||||
|
||||
<button class="me-3 d-md-none btn btn-md btn-outline-light" type="button" data-bs-toggle="collapse" data-bs-target="#mainMenu" aria-controls="mainMenu" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<i class="fa fa-bars"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="d-flex flex-column min-vh-100">
|
||||
<div class="flex-container flex-grow-1">
|
||||
@ -79,24 +98,27 @@
|
||||
|
||||
<div class="pt-4">
|
||||
<div class="container">
|
||||
<h3 class="pb-4 mb-4 fst-italic border-bottom">
|
||||
<h3 class="pb-4 mb-4 fst-italic border-bottom context-main-border">
|
||||
{SITENAME} Blog
|
||||
</h3>
|
||||
<div class="row g-5">
|
||||
<div class="d-md-flex g-5">
|
||||
<!-- Main Content -->
|
||||
<div class="col-md-8">
|
||||
<div class="col-12 col-md-8">
|
||||
{CONTENT}
|
||||
</div>
|
||||
<!-- Sidebar Content -->
|
||||
<div class="col-md-4">
|
||||
<div class="col-12 col-md-4">
|
||||
<div class="position-sticky" style="top: 2rem;">
|
||||
<div class="p-4">
|
||||
<div class="ps-md-2 ps-lg-5">
|
||||
{SIDEBARABOUT}
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<div class="ps-md-2 ps-lg-5">
|
||||
{SIDEBARSEARCH}
|
||||
</div>
|
||||
<div class="ps-md-2 ps-lg-5">
|
||||
{SIDEBAR}
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<div class="ps-md-2 ps-lg-5">
|
||||
{SIDEBAR2}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,6 +0,0 @@
|
||||
<div class="p-4 mb-3 rounded context-main-bg">
|
||||
<h4 class="fst-italic">About</h4>
|
||||
<p class="mb-0">
|
||||
The blog is mostly here to serve ass a simple way to link to long-form content on the site. There won't be any breaking news or tell-all stories here. Just good ole fashioned boring crap no one wants to read.
|
||||
</p>
|
||||
</div>
|
@ -2,7 +2,7 @@
|
||||
<legend class="text-center">Add Blog Post</legend>
|
||||
<hr>
|
||||
{ADMIN_BREADCRUMBS}
|
||||
<form action="" method="post">
|
||||
<form method="post">
|
||||
<fieldset>
|
||||
<!-- Title -->
|
||||
<div class="mb-3 row">
|
||||
|
@ -2,7 +2,7 @@
|
||||
<legend class="text-center">Edit Blog Post</legend>
|
||||
<hr>
|
||||
{ADMIN_BREADCRUMBS}
|
||||
<form action="" method="post">
|
||||
<form method="post">
|
||||
<fieldset>
|
||||
<!-- Title -->
|
||||
<div class="mb-3 row">
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div><!-- /.blog-post -->
|
||||
</div><!-- /.blog-main -->
|
||||
</div><!-- /.row -->
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<legend>New Blog Post</legend>
|
||||
<div class="form-group">
|
||||
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||
|
@ -1,5 +1,5 @@
|
||||
{LOOP}
|
||||
<article class="blog-post">
|
||||
<article class="blog-post context-main-bg p-2">
|
||||
<h2 class="blog-post-title mb-1">{title}</h2>
|
||||
<p class="blog-post-meta">{DTC date}{created}{/DTC} by <a href="{ROOT_URL}home/profile/{authorName}" class="text-decoration-none">{authorName}</a></p>
|
||||
<div class="well">
|
||||
@ -9,7 +9,7 @@
|
||||
<hr>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<article class="blog-post">
|
||||
<p class="blog-post-meta">No Posts Found.</p>
|
||||
</article>
|
||||
<div class="text-center">
|
||||
<p class="h5">No Posts Found</p>
|
||||
</div>
|
||||
{/ALT}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-sm-12 blog-main">
|
||||
<div class="blog-post">
|
||||
<div class="col-lg-12 col-sm-12 blog-main context-main-bg p-1 p-md-2 mb-2 rounded">
|
||||
<div class="blog-post mb-5 pb-5">
|
||||
<h2 class="blog-post-title">{title}</h2>
|
||||
<hr>
|
||||
<p class="blog-post-meta">{DTC date}{created}{/DTC} by <a href="{ROOT_URL}home/profile/{authorName}" class="text-decoration-none">{authorName}</a></p>
|
||||
|
@ -1,15 +0,0 @@
|
||||
<div class="card">
|
||||
<div class="card-header bg-info">
|
||||
<h3 class="card-title">Recent Posts</h3>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
{LOOP}
|
||||
<li class="list-group-item">
|
||||
<a href="{ROOT_URL}blog/post/{ID}">{title}</a>
|
||||
</li>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<li class="list-group-item">No Posts to show</li>
|
||||
{/ALT}
|
||||
</ul>
|
||||
</div>
|
3
app/plugins/blog/views/searchResults.html
Normal file
3
app/plugins/blog/views/searchResults.html
Normal file
@ -0,0 +1,3 @@
|
||||
<legend class="text-center my-2">Search Results</legend>
|
||||
<hr>
|
||||
{searchResults}
|
@ -1,18 +0,0 @@
|
||||
<div class="card context-main-bg">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Recent Posts</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ol class="list-unstyled">
|
||||
{LOOP}
|
||||
<li><a href="{ROOT_URL}blog/post/{ID}" class="text-decoration-none">{title}</a></li>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<li>No Posts to show</li>
|
||||
{/ALT}
|
||||
</ol>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="{ROOT_URL}blog" class="text-decoration-none">View All</a>
|
||||
</div>
|
||||
</div>
|
@ -1,15 +0,0 @@
|
||||
<div class="card context-main-bg">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Archives</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ol class="list-unstyled">
|
||||
{LOOP}
|
||||
<li>({count}) <a href="{ROOT_URL}blog/month/{month}/{year}" class="text-decoration-none">{monthText} {year}</a></li>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<li>None To Show</li>
|
||||
{/ALT}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
11
app/plugins/blog/views/widgets/about.html
Normal file
11
app/plugins/blog/views/widgets/about.html
Normal file
@ -0,0 +1,11 @@
|
||||
<div class="pb-2 pb-lg-3">
|
||||
<div class="card rounded context-main-bg">
|
||||
<div class="card-body">
|
||||
<h4 class="fst-italic">About</h4>
|
||||
<p class="mb-0">
|
||||
The blog is mostly here to serve ass a simple way to link to long-form content on the site.
|
||||
There won't be any breaking news or tell-all stories here. Just good ole fashioned boring crap no one wants to read.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
17
app/plugins/blog/views/widgets/archive.html
Normal file
17
app/plugins/blog/views/widgets/archive.html
Normal file
@ -0,0 +1,17 @@
|
||||
<div class="pb-2 pb-lg-3">
|
||||
<div class="card rounded context-main-bg">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Archives</h3>
|
||||
</div>
|
||||
<div class="card-body context-second-bg">
|
||||
<ol class="list-unstyled">
|
||||
{LOOP}
|
||||
<li>({count}) <a href="{ROOT_URL}blog/month/{month}/{year}" class="text-decoration-none">{monthText} {year}</a></li>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<li>None To Show</li>
|
||||
{/ALT}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
20
app/plugins/blog/views/widgets/recent.html
Normal file
20
app/plugins/blog/views/widgets/recent.html
Normal file
@ -0,0 +1,20 @@
|
||||
<div class="pb-2 pb-lg-3">
|
||||
<div class="card rounded context-main-bg">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Recent Posts</h3>
|
||||
</div>
|
||||
<div class="card-body context-second-bg">
|
||||
<ol class="list-unstyled">
|
||||
{LOOP}
|
||||
<li><a href="{ROOT_URL}blog/post/{ID}" class="text-decoration-none">{title}</a></li>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<li>No Posts to show</li>
|
||||
{/ALT}
|
||||
</ol>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="{ROOT_URL}blog" class="text-decoration-none">View All</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
18
app/plugins/blog/views/widgets/search.html
Normal file
18
app/plugins/blog/views/widgets/search.html
Normal file
@ -0,0 +1,18 @@
|
||||
<div class="pb-2 pb-lg-3">
|
||||
<div class="card rounded context-main-bg">
|
||||
<div class="card-body">
|
||||
<form method="post" action="/blog/search">
|
||||
<fieldset>
|
||||
<!-- Hidden Token -->
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
|
||||
<!-- Search -->
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" aria-label="Search Terms" name="searchTerm" id="searchTerm">
|
||||
<button type="submit" class="btn btn-secondary bg-primary" name="submit" value="submit">Search</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -44,14 +44,14 @@ class Bugreport extends Plugin {
|
||||
],
|
||||
];
|
||||
public $permissionMatrix = [
|
||||
'bugReport' => [
|
||||
'canSendBugReports' => [
|
||||
'pretty' => 'Can Submit Bug Reports',
|
||||
'default' => false,
|
||||
],
|
||||
];
|
||||
public $contact_footer_links = [
|
||||
[
|
||||
'text' => 'Bug Report',
|
||||
'text' => 'Report a Bug',
|
||||
'url' => '{ROOT_URL}bugreport',
|
||||
'filter' => 'loggedin',
|
||||
],
|
||||
|
@ -1,15 +1,20 @@
|
||||
<div class="col-8 mx-auto p-4 rounded shadow-sm mb-5 context-main-bg mt-4 container">
|
||||
<h2 class="text-center mb-4">Bug Report</h2>
|
||||
<div class="m-2 m-lg-4">
|
||||
<div class="col-12 mx-5 col-sm-10 col-lg-8 mx-auto p-4 rounded shadow-sm context-main-bg">
|
||||
<h2 class="text-center mb-4">Report a Bug</h2>
|
||||
<hr>
|
||||
<p>Thank you for visiting our bug reporting page. We value our users' input highly and in an effort to better serve your needs, please fill out the form below to help us address this issue.</p>
|
||||
<p>We read each and every bug report submitted, and by submitting this form you allow us to send you a follow-up email.</p>
|
||||
<form action="" method="post">
|
||||
<p class="text-center text-sm-start">
|
||||
Thank you for visiting our bug reporting page. We value our users' input highly and in an effort to better serve your needs, please fill out the form below to help us address this issue.
|
||||
</p>
|
||||
<p class="text-center text-sm-start">
|
||||
We read each and every bug report submitted, and by submitting this form you allow us to send you a follow-up email.
|
||||
</p>
|
||||
<form method="post">
|
||||
<!-- Page URL -->
|
||||
<div class="mb-3">
|
||||
<label for="url" class="form-label">Page you were trying to reach:</label>
|
||||
<input type="url" name="url" id="url" class="form-control" aria-describedby="urlHelp" required>
|
||||
<small id="urlHelp" class="form-text text-muted">
|
||||
What is the URL of the page you actually received the error on? (The URL is the website address. Example: {ROOT_URL}home)
|
||||
This is the URL of the page you actually received the error.
|
||||
</small>
|
||||
</div>
|
||||
|
||||
@ -18,7 +23,7 @@
|
||||
<label for="ourl" class="form-label">Page you were on:</label>
|
||||
<input type="url" name="ourl" id="ourl" class="form-control" aria-describedby="ourlHelp">
|
||||
<small id="ourlHelp" class="form-text text-muted">
|
||||
What is the URL of the page you were on before you received the error? (The URL is the website address. Example: {ROOT_URL}home/newhome)
|
||||
This is the URL of the page you were on before you received the error.
|
||||
</small>
|
||||
</div>
|
||||
|
||||
@ -37,8 +42,11 @@
|
||||
|
||||
<!-- Description -->
|
||||
<div class="mb-3">
|
||||
<label for="entry" class="form-label">Describe the problem/error as best as you can: (max: 2000 characters)</label>
|
||||
<textarea class="form-control" name="entry" id="entry" rows="6" maxlength="2000" required></textarea>
|
||||
<label for="entry" class="form-label">Describe the error you received: </label>
|
||||
<textarea class="form-control" name="entry" id="entry" rows="6" maxlength="2000" aria-describedby="descHelp" required></textarea>
|
||||
<small id="descHelp" class="form-text text-muted">
|
||||
(max: 2000 characters)
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- Hidden Token -->
|
||||
@ -49,4 +57,5 @@
|
||||
<button type="submit" name="submit" value="submit" class="btn btn-primary btn-lg">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
@ -3,7 +3,7 @@
|
||||
<legend class="text-center">Edit Comment</legend>
|
||||
<hr>
|
||||
{ADMIN_BREADCRUMBS}
|
||||
<form action="" method="post" class="container py-4">
|
||||
<form method="post" class="container py-4">
|
||||
<fieldset>
|
||||
<div class="mb-3 row">
|
||||
<label for="comment" class="col-lg-5 col-form-label text-end">Comment:</label>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<form action="" method="post" class="text-center mx-auto mt-4" style="max-width: 600px;">
|
||||
<form method="post" class="text-center mx-auto mt-4" style="max-width: 600px;">
|
||||
<div class="mb-3">
|
||||
<textarea
|
||||
class="form-control"
|
||||
|
@ -1,14 +1,14 @@
|
||||
<div class="card">
|
||||
<div class="card-header d-flex align-items-center justify-content-between context-second-bg context-main">
|
||||
<div class="card-header d-flex align-items-center justify-content-between context-main-bg context-main">
|
||||
<h3 class="card-title mb-0">
|
||||
<i class="fa fa-fw fa-comment"></i> Comments
|
||||
</h3>
|
||||
<span class="badge bg-primary">{count}</span>
|
||||
</div>
|
||||
<div class="card-body context-main-bg context-main">
|
||||
<div class="card-body context-second-bg">
|
||||
<ul class="list-group list-group-flush">
|
||||
{LOOP}
|
||||
<li class="list-group-item context-second-bg context-main mb-2">
|
||||
<li class="list-group-item context-main-bg context-main mb-2">
|
||||
<div class="d-flex align-items-start">
|
||||
<div class="me-3">
|
||||
<img src="{ROOT_URL}{avatar}" class="rounded-circle" alt="User Avatar" style="width: 50px; height: 50px;">
|
||||
@ -28,7 +28,7 @@
|
||||
</li>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<li class="list-group-item context-second-bg context-main mb-2">
|
||||
<li class="list-group-item context-main-bg mb-2">
|
||||
<div class="text-center">
|
||||
<p class="mb-0">Be the first to comment.</p>
|
||||
</div>
|
||||
|
@ -27,8 +27,6 @@ class Contact extends AdminController {
|
||||
parent::__construct();
|
||||
self::$title = 'Admin - Contact';
|
||||
self::$contact = new ContactModel;
|
||||
$view = Navigation::activePageSelect( 'nav.admin', '/admin/contact' );
|
||||
Components::set( 'ADMINNAV', $view );
|
||||
}
|
||||
|
||||
public function view( $id = null ) {
|
||||
|
@ -40,7 +40,7 @@ class Contact extends Plugin {
|
||||
],
|
||||
];
|
||||
public $permissionMatrix = [
|
||||
'contact' => [
|
||||
'canUseContactForm' => [
|
||||
'pretty' => 'Can Submit Contact',
|
||||
'default' => true,
|
||||
],
|
||||
|
@ -1,45 +1,47 @@
|
||||
<div class="context-main-bg container py-4 my-4">
|
||||
<h2 class="text-center mb-4">Contact Us</h2>
|
||||
<div class="col-lg-6 offset-md-3">
|
||||
<p>
|
||||
Here at <strong>{SITENAME}</strong>, we highly value your feedback. We constantly strive to provide our users with the highest level of quality in everything we do.
|
||||
</p>
|
||||
<p>
|
||||
If you would like to provide any suggestions or comments on our service, we ask that you please fill out the quick form below and let us know what's on your mind.
|
||||
</p>
|
||||
<div class="m-2 m-lg-4">
|
||||
<div class="context-main-bg container py-2 my-2 py-lg-4 my-lg-4">
|
||||
<h2 class="text-center mb-4">Contact Us</h2>
|
||||
<div class="col-12 col-lg-6 offset-lg-3">
|
||||
<p class="text-center text-lg-start">
|
||||
Here at <strong>{SITENAME}</strong>, we highly value your feedback. We constantly strive to provide our users with the highest level of quality in everything we do.
|
||||
</p>
|
||||
<p class="text-center text-lg-start">
|
||||
If you would like to provide any suggestions or comments on our service, we ask that you please fill out the quick form below and let us know what's on your mind.
|
||||
</p>
|
||||
</div>
|
||||
<form method="post">
|
||||
<!-- Name -->
|
||||
<div class="mb-3 row">
|
||||
<label for="name" class="col-lg-3 col-form-label text-lg-end">Name:</label>
|
||||
<div class="col-lg-6">
|
||||
<input type="text" class="form-control" name="name" id="name" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Email (Optional) -->
|
||||
<div class="mb-3 row">
|
||||
<label for="contactEmail" class="col-lg-3 col-form-label text-lg-end">E-mail: (optional)</label>
|
||||
<div class="col-lg-6">
|
||||
<input type="email" class="form-control" name="contactEmail" id="contactEmail">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feedback -->
|
||||
<div class="mb-3 row">
|
||||
<label for="entry" class="col-lg-3 col-form-label text-lg-end">Feedback:</label>
|
||||
<div class="col-lg-6">
|
||||
<textarea class="form-control" name="entry" id="entry" rows="6" maxlength="2000" required></textarea>
|
||||
<small class="form-text text-muted">Max: 2000 characters</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hidden Token -->
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="text-center">
|
||||
<button type="submit" name="submit" value="submit" class="btn btn-primary btn-lg">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<form action="" method="post">
|
||||
<!-- Name -->
|
||||
<div class="mb-3 row">
|
||||
<label for="name" class="col-lg-3 col-form-label text-end">Name:</label>
|
||||
<div class="col-lg-6">
|
||||
<input type="text" class="form-control" name="name" id="name" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Email (Optional) -->
|
||||
<div class="mb-3 row">
|
||||
<label for="contactEmail" class="col-lg-3 col-form-label text-end">E-mail: (optional)</label>
|
||||
<div class="col-lg-6">
|
||||
<input type="email" class="form-control" name="contactEmail" id="contactEmail">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feedback -->
|
||||
<div class="mb-3 row">
|
||||
<label for="entry" class="col-lg-3 col-form-label text-end">Feedback:</label>
|
||||
<div class="col-lg-6">
|
||||
<textarea class="form-control" name="entry" id="entry" rows="6" maxlength="2000" required></textarea>
|
||||
<small class="form-text text-muted">Max: 2000 characters</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hidden Token -->
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="text-center">
|
||||
<button type="submit" name="submit" value="submit" class="btn btn-primary btn-lg">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
@ -259,7 +259,9 @@ class Message extends DatabaseModel {
|
||||
}
|
||||
$messageOut['fromAvatar'] = self::$user->getAvatar( $message->userFrom );
|
||||
$messageOut['userTo'] = self::$user->getUsername( $message->userTo );
|
||||
$messageOut['userToPretty'] = \ucfirst( $messageOut['userTo'] );
|
||||
$messageOut['userFrom'] = self::$user->getUsername( $message->userFrom );
|
||||
$messageOut['userFromPretty'] = \ucfirst( $messageOut['userFrom'] );
|
||||
$out[] = (object) $messageOut;
|
||||
if ( !empty( $end ) ) {
|
||||
$out = $out[0];
|
||||
|
@ -1,57 +1,73 @@
|
||||
<div class="container py-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-4">
|
||||
<form action="" method="post" class="needs-validation">
|
||||
<legend class="mb-4">New Message</legend>
|
||||
<fieldset>
|
||||
<!-- To User Field -->
|
||||
<div class="mb-3 row">
|
||||
<label for="toUser" class="col-sm-6 col-form-label">To:</label>
|
||||
<div class="col-sm-6">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="toUser"
|
||||
id="toUser"
|
||||
value="{prepopuser}"
|
||||
required>
|
||||
<div class="m-2 m-lg-4">
|
||||
<div class="col-12 mx-5 col-sm-10 col-lg-8 mx-auto p-4 rounded shadow-sm context-main-bg">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{ROOT_URL}messages" class="text-decoration-none">
|
||||
Messages
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active" aria-current="page">
|
||||
Create
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-lg-6">
|
||||
<form method="post" class="needs-validation">
|
||||
<legend class="mb-3">New Message</legend>
|
||||
<fieldset>
|
||||
<!-- To User Field -->
|
||||
<div class="mb-3 row">
|
||||
<label for="toUser" class="col-sm-6 col-form-label">To:</label>
|
||||
<div class="col-sm-6">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="toUser"
|
||||
id="toUser"
|
||||
value="{prepopuser}"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Subject Field -->
|
||||
<div class="mb-3 row">
|
||||
<label for="subject" class="col-sm-6 col-form-label">Subject:</label>
|
||||
<div class="col-sm-6">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="subject"
|
||||
id="subject"
|
||||
required>
|
||||
|
||||
<!-- Subject Field -->
|
||||
<div class="mb-3 row">
|
||||
<label for="subject" class="col-sm-6 col-form-label">Subject:</label>
|
||||
<div class="col-sm-6">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="subject"
|
||||
id="subject"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Message Field -->
|
||||
<div class="mb-3">
|
||||
<label for="message" class="form-label">Message:</label>
|
||||
<textarea
|
||||
class="form-control"
|
||||
name="message"
|
||||
id="message"
|
||||
rows="6"
|
||||
maxlength="2000"
|
||||
required></textarea>
|
||||
</div>
|
||||
</fieldset>
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<div class="text-center text-md-start">
|
||||
<button
|
||||
type="submit"
|
||||
name="submit"
|
||||
value="submit"
|
||||
class="btn btn-primary btn-lg">
|
||||
Send
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Message Field -->
|
||||
<div class="mb-3">
|
||||
<label for="message" class="form-label">Message:</label>
|
||||
<textarea
|
||||
class="form-control"
|
||||
name="message"
|
||||
id="message"
|
||||
rows="6"
|
||||
maxlength="2000"
|
||||
required></textarea>
|
||||
</div>
|
||||
</fieldset>
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<button
|
||||
type="submit"
|
||||
name="submit"
|
||||
value="submit"
|
||||
class="btn btn-primary btn-lg">
|
||||
Send
|
||||
</button>
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,14 +1,14 @@
|
||||
<h2>Inbox</h2>
|
||||
<form action="{ROOT_URL}messages/delete" method="post">
|
||||
<table class="table table-striped">
|
||||
<table class="table table-striped text-center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20%">From</th>
|
||||
<th style="width: 25%">Subject</th>
|
||||
<th style="width: 15%">Last Reply</th>
|
||||
<th style="width: 20%"></th>
|
||||
<th style="width: 15%">From</th>
|
||||
<th style="width: 40%">Subject</th>
|
||||
<th style="width: 20%">Last Reply</th>
|
||||
<th style="width: 10%"></th>
|
||||
<th style="width: 10%">
|
||||
<th style="width: 10%"></th>
|
||||
<th style="width: 5%">
|
||||
<INPUT type="checkbox" onchange="checkAll(this)" name="check.t" value="T_[]"/>
|
||||
</th>
|
||||
</tr>
|
||||
@ -16,11 +16,11 @@
|
||||
<tbody>
|
||||
{LOOP}
|
||||
<tr {unreadBadge}>
|
||||
<td><a href="{ROOT_URL}home/profile/{userFrom}">{userFrom}</a></td>
|
||||
<td><a href="{ROOT_URL}messages/view/{ID}">{subject}</a></td>
|
||||
<td>{DTC}{lastReply}{/DTC}</td>
|
||||
<td><a href="{ROOT_URL}messages/read/{ID}">Mark as read</a></td>
|
||||
<td><a href="{ROOT_URL}messages/delete/{ID}">Delete</a></td>
|
||||
<td><a href="{ROOT_URL}home/profile/{userFrom}" class="text-decoration-none">{userFromPretty}</a></td>
|
||||
<td><a href="{ROOT_URL}messages/view/{ID}" class="text-decoration-none">{subject}</a></td>
|
||||
<td>{DTC date}{lastReply}{/DTC}</td>
|
||||
<td><a href="{ROOT_URL}messages/read/{ID}" class="btn btn-sm btn-info"><i class="fa-solid fa-envelope-open"></i></a></td>
|
||||
<td><a href="{ROOT_URL}messages/delete/{ID}" class="btn btn-sm btn-danger"><i class="fa fa-fw fa-trash"></i></a></td>
|
||||
<td>
|
||||
<input type="checkbox" value="{ID}" name="T_[]">
|
||||
</td>
|
||||
@ -35,5 +35,6 @@
|
||||
{/ALT}
|
||||
</tbody>
|
||||
</table>
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-sm btn-danger">Delete</button> <a href="{ROOT_URL}messages/create" class="btn btn-sm btn-primary">New message</a>
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-sm btn-danger"><i class="fa fa-fw fa-trash"></i></button>
|
||||
<a href="{ROOT_URL}messages/create" class="btn btn-sm btn-primary">New message</a>
|
||||
</form>
|
||||
|
@ -1,8 +1,10 @@
|
||||
<div class="context-main context-main-bg col-10 offset-1 my-3 p-3">
|
||||
<div class="my-3 p-3">
|
||||
{message_inbox}
|
||||
</div>
|
||||
<div class="my-3 p-3">
|
||||
{message_outbox}
|
||||
<div class="m-2 m-lg-4">
|
||||
<div class="col-12 col-sm-10 col-lg-8 mx-auto p-md-2 p-lg-4 rounded shadow-sm context-main-bg context-main">
|
||||
<div class="my-3 p-3">
|
||||
{message_inbox}
|
||||
</div>
|
||||
<div class="my-3 p-3">
|
||||
{message_outbox}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,43 +0,0 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-6 col-lg-6 col-sm-offset-0 col-md-offset-3 col-lg-offset-3 top-pad" >
|
||||
<div class="card panel-primary">
|
||||
{LOOP}
|
||||
{SINGLE}
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">{subject}</h3>
|
||||
</div>
|
||||
{/SINGLE}
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-lg-3 " align="center">
|
||||
<a href="{ROOT_URL}home/profile/{userFrom}">{userFrom}</a><br>
|
||||
<img alt="User Pic" src="{ROOT_URL}{fromAvatar}" class="img-circle img-responsive">
|
||||
</div>
|
||||
<div class=" col-md-9 col-lg-9 ">
|
||||
<table class="table table-user-information">
|
||||
<tbody>
|
||||
<td>{message}</td>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
{ADMIN}
|
||||
{ID}
|
||||
<span class="float-right">
|
||||
{DTC}{sent}{/DTC}
|
||||
</span>
|
||||
{/ADMIN}
|
||||
</div>
|
||||
{/LOOP}
|
||||
</div>
|
||||
<form action="{ROOT_URL}messages/reply" method="post">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<input type="hidden" name="messageID" value="{PID}">
|
||||
<button name="submit" value="reply" type="submit" class="btn btn-sm btn-primary">Reply</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,37 +1,53 @@
|
||||
<div class="context-main context-main-bg col-8 offset-2 my-3 p-3">
|
||||
<div class="col-sm-12 col-md-6 col-lg-6 col-sm-offset-0 col-md-offset-3 col-lg-offset-3 top-pad" >
|
||||
<div class="card panel-primary">
|
||||
{LOOP}
|
||||
{SINGLE}
|
||||
<div class="card-header context-main-bg">
|
||||
<h5 class="card-title context-main">{subject}</h5>
|
||||
<div class="m-2 m-lg-4">
|
||||
<div class="col-12 mx-5 col-sm-10 col-lg-8 mx-auto p-4 rounded shadow-sm context-main-bg context-main">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{ROOT_URL}messages" class="text-decoration-none">
|
||||
Messages
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active" aria-current="page">
|
||||
View
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<div class="card panel-primary col-lg-8 mx-auto text-center">
|
||||
{LOOP}
|
||||
{SINGLE}
|
||||
<div class="card-header context-second-bg">
|
||||
<p class="card-title context-main text-center h3">{subject}</p>
|
||||
</div>
|
||||
{/SINGLE}
|
||||
<div class="card-body context-other-bg">
|
||||
<div class="row">
|
||||
<div class="col-4 col-lg-3 text-center">
|
||||
<a href="{ROOT_URL}home/profile/{userFrom}" class="text-decoration-none">{userFromPretty}</a><br>
|
||||
<img alt="User Pic" src="{ROOT_URL}{fromAvatar}" class="img-circle img-fluid mt-2">
|
||||
</div>
|
||||
{/SINGLE}
|
||||
<div class="card-body context-second-bg">
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-lg-3 text-center">
|
||||
<a href="{ROOT_URL}home/profile/{userFrom}">{userFrom}</a><br>
|
||||
<img alt="User Pic" src="{ROOT_URL}{fromAvatar}" class="img-circle img-fluid">
|
||||
</div>
|
||||
<div class=" col-md-9 col-lg-9 context-main">
|
||||
{message}
|
||||
</div>
|
||||
<div class="col-8 col-lg-9 text-start">
|
||||
{message}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer context-main-bg">
|
||||
{ADMIN}
|
||||
{ID}
|
||||
<span class="float-right">
|
||||
</div>
|
||||
<div class="card-footer context-second-bg">
|
||||
{ADMIN}
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="">
|
||||
{ID}
|
||||
</div>
|
||||
<div class="">
|
||||
{DTC}{sent}{/DTC}
|
||||
</span>
|
||||
{/ADMIN}
|
||||
</div>
|
||||
{/LOOP}
|
||||
</div>
|
||||
<form action="{ROOT_URL}messages/reply" method="post">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<input type="hidden" name="messageID" value="{PID}">
|
||||
<button name="submit" value="reply" type="submit" class="btn btn-md btn-primary my-4">Reply</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{/ADMIN}
|
||||
</div>
|
||||
{/LOOP}
|
||||
</div>
|
||||
<form action="{ROOT_URL}messages/reply" method="post">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<input type="hidden" name="messageID" value="{PID}">
|
||||
<button name="submit" value="reply" type="submit" class="btn btn-md btn-primary my-4">Reply</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
@ -1,4 +1,4 @@
|
||||
<div class="dropdown nav-item mx-2">
|
||||
<div class="dropdown nav-item mx-2 my-2 my-lg-0">
|
||||
<a
|
||||
href="#"
|
||||
class="d-flex align-items-center text-white text-decoration-none dropdown-toggle"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<h2>Outbox</h2>
|
||||
<form action="{ROOT_URL}messages/delete" method="post">
|
||||
<table class="table table-striped">
|
||||
<table class="table table-striped text-center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20%">To</th>
|
||||
@ -15,10 +15,10 @@
|
||||
<tbody>
|
||||
{LOOP}
|
||||
<tr>
|
||||
<td><a href="{ROOT_URL}home/profile/{userTo}">{userTo}</a></td>
|
||||
<td><a href="{ROOT_URL}messages/view/{ID}">{subject}</a></td>
|
||||
<td><a href="{ROOT_URL}home/profile/{userTo}" class="text-decoration-none">{userToPretty}</a></td>
|
||||
<td><a href="{ROOT_URL}messages/view/{ID}" class="text-decoration-none">{subject}</a></td>
|
||||
<td>{DTC date}{sent}{/DTC}</td>
|
||||
<td><a href="{ROOT_URL}messages/delete/{ID}">Delete</a></td>
|
||||
<td><a href="{ROOT_URL}messages/delete/{ID}" class="btn btn-sm btn-danger"><i class="fa fa-fw fa-trash"></i></a></td>
|
||||
<td>
|
||||
<input type="checkbox" value="{ID}" name="F_[]">
|
||||
</td>
|
||||
@ -33,5 +33,5 @@
|
||||
{/ALT}
|
||||
</tbody>
|
||||
</table>
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-sm btn-danger">Delete</button>
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-sm btn-danger"><i class="fa fa-fw fa-trash"></i></button>
|
||||
</form>
|
@ -1,5 +1,5 @@
|
||||
<div class="context-main context-main-bg col-8 offset-2 my-3 p-3">
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
<form method="post">
|
||||
<legend class="text-center">Reply</legend>
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
|
@ -2,8 +2,7 @@
|
||||
<legend class="text-center">Send Notification</legend>
|
||||
<hr>
|
||||
{ADMIN_BREADCRUMBS}
|
||||
|
||||
<form action="" method="post" enctype="multipart/form-data">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<fieldset>
|
||||
<!-- Group -->
|
||||
<div class="mb-3 row">
|
||||
|
@ -1,4 +1,6 @@
|
||||
<div class="col-8 mx-auto p-4 rounded shadow-sm context-main-bg my-4">
|
||||
|
||||
<div class="m-2 m-lg-4">
|
||||
<div class="col-12 mx-5 col-sm-10 col-lg-8 mx-auto p-4 rounded shadow-sm context-main-bg">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<legend class="text-center">Notifications</legend>
|
||||
@ -26,7 +28,7 @@
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<tr>
|
||||
<td colspan="7" class=" context-main">
|
||||
<td colspan="3" class="text-center context-main">
|
||||
No Notifications
|
||||
</td>
|
||||
</tr>
|
||||
@ -35,4 +37,5 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,5 +1,5 @@
|
||||
<!-- Notifications Dropdown -->
|
||||
<div class="dropdown nav-item mx-2">
|
||||
<div class="dropdown nav-item mx-2 my-2 my-lg-0">
|
||||
<a
|
||||
href="#"
|
||||
class="d-flex align-items-center text-white text-decoration-none dropdown-toggle"
|
||||
|
@ -2,7 +2,7 @@
|
||||
<legend class="text-center">Add Subscriber</legend>
|
||||
<hr>
|
||||
{ADMIN_BREADCRUMBS}
|
||||
<form action="" method="post">
|
||||
<form method="post">
|
||||
<fieldset>
|
||||
<!-- Subject -->
|
||||
<div class="mb-3 row">
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="col-md-5 offset-md-1 mb-3 text-center">
|
||||
<div class="col-12 col-sm-6 col-md-3 offset-0 offset-lg-2 mb-3 text-center">
|
||||
<h5 class="">Subscribe</h5>
|
||||
<div class="d-flex flex-column flex-sm-row gap-2 justify-content-center mx-auto">
|
||||
<form action="{ROOT_URL}subscribe/home" method="post" class="form-horizontal">
|
||||
<div class="d-flex flex-column w-75 w-sm-100 gap-2 justify-content-center mx-auto">
|
||||
<form action="{ROOT_URL}subscribe/home" method="post">
|
||||
<label for="email" class="visually-hidden">Email address</label>
|
||||
<input name="email" id="email" type="email" class="form-control my-2" placeholder="Email address" autocomplete="email">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
|
@ -1,4 +1,4 @@
|
||||
<form action="{ROOT_URL}subscribe/home" method="post" class="form-horizontal">
|
||||
<form action="{ROOT_URL}subscribe/home" method="post">
|
||||
<input type="email" placeholder="Email" id="email" name="email" autocomplete="email">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Submit</button><br>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<form action="{ROOT_URL}home/unsubscribe" method="post" class="form-horizontal">
|
||||
<form action="{ROOT_URL}home/unsubscribe" method="post">
|
||||
<input type="email" placeholder="Email" id="email" name="email">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Submit</button><br>
|
||||
|
@ -44,6 +44,11 @@ class AdminLoader extends DefaultLoader {
|
||||
$menu = Views::simpleView( 'nav.admin', $links );
|
||||
$activeMenu = Navigation::activePageSelect( $menu, Input::get( 'url' ), false, true );
|
||||
Components::set( 'ADMIN_LINKS', $activeMenu );
|
||||
|
||||
$menu = Views::simpleView( 'nav.adminTop', Navigation::getMenuLinks( App::MAIN_MENU_NAME ) );
|
||||
$activeMenu = Navigation::activePageSelect( $menu, Input::get( 'url' ), false, true );
|
||||
Components::set( 'topNavLeft', $activeMenu );
|
||||
|
||||
Navigation::setCrumbComponent( 'ADMIN_BREADCRUMBS', Input::get( 'url' ) );
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@
|
||||
<!-- Center Element -->
|
||||
<div class="flex-grow-1 d-flex flex-column">
|
||||
<!-- Top Navigation Bar -->
|
||||
<div class="p-3 text-bg-dark">
|
||||
<div class="p-2 text-bg-dark">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
|
||||
{topNavLeft}
|
||||
</div>
|
||||
|
@ -73,9 +73,11 @@ class DefaultLoader extends Loader {
|
||||
$this->addCss( '<link rel="stylesheet" href="{ROOT_URL}app/css/main-dark.css" id="dark-mode-stylesheet" disabled>' );
|
||||
}
|
||||
Components::set( 'topNavRight', Template::parse( App::$topNavRight . '{STATUS}' ) );
|
||||
|
||||
$menu = Views::simpleView( 'nav.main', Navigation::getMenuLinks( App::MAIN_MENU_NAME ) );
|
||||
$activeMenu = Navigation::activePageSelect( $menu, Input::get( 'url' ), false, true );
|
||||
Components::set( 'topNavLeft', $activeMenu );
|
||||
|
||||
Components::set( 'colorSelect', Views::simpleView( 'forms.colorSelect' ) );
|
||||
Components::set( 'iconSelect', Views::simpleView( 'forms.iconSelect' ) );
|
||||
Navigation::setCrumbComponent( 'BREADCRUMB', Input::get( 'url' ) );
|
||||
|
@ -39,20 +39,45 @@
|
||||
</head>
|
||||
<body>
|
||||
<!-- Navigation -->
|
||||
<header class="p-3 text-bg-dark">
|
||||
<div class="container">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
|
||||
<img src="{ROOT_URL}{LOGO}" class="bi me-2" width="40" height="32" alt="{SITENAME} Logo" aria-label="{SITENAME} Logo">
|
||||
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
|
||||
{SITENAME}
|
||||
</a>
|
||||
{topNavLeft}
|
||||
<div class="text-end d-flex align-items-center">
|
||||
{topNavRight}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<header class="p-3 text-bg-dark">
|
||||
<div class="container">
|
||||
<div class="d-flex align-items-center position-relative">
|
||||
<!-- Navbar Toggler (Left) -->
|
||||
|
||||
<!-- Centered Logo (Now inside normal document flow) -->
|
||||
<a href="/" class="align-items-center text-white text-decoration-none d-flex d-md-none">
|
||||
<img src="{ROOT_URL}{LOGO}" width="40" height="32" alt="{SITENAME} Logo" class="bi">
|
||||
</a>
|
||||
|
||||
<!-- Logo (Normal Position for Large Screens) -->
|
||||
<a href="/" class="align-items-center text-white text-decoration-none d-none d-md-flex">
|
||||
<img src="{ROOT_URL}{LOGO}" width="40" height="32" alt="{SITENAME} Logo" class="bi">
|
||||
</a>
|
||||
|
||||
<div class="navbar-expand-md flex-grow-1">
|
||||
<div class="collapse navbar-collapse d-md-flex" id="mainMenu">
|
||||
<!-- Centered Navigation -->
|
||||
<div class="d-none d-md-block d-flex justify-content-center position-absolute start-50 translate-middle-x">
|
||||
{topNavLeft}
|
||||
</div>
|
||||
<div class="d-flex justify-content-center flex-grow-1 d-md-none">
|
||||
{topNavLeft}
|
||||
</div>
|
||||
|
||||
<!-- Right-Side Content (Push to End) -->
|
||||
<div class="d-flex flex-row justify-content-center align-items-center mt-3 mt-md-0 ms-md-auto">
|
||||
{topNavRight}
|
||||
</div>
|
||||
</div> <!-- End Collapse -->
|
||||
</div> <!-- End Navbar Expand -->
|
||||
|
||||
<button class="me-3 d-md-none btn btn-md btn-outline-light" type="button" data-bs-toggle="collapse" data-bs-target="#mainMenu" aria-controls="mainMenu" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<i class="fa fa-bars"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="d-flex flex-column min-vh-100">
|
||||
<div class="flex-container flex-grow-1">
|
||||
<!-- Issues -->
|
||||
|
@ -1,16 +1,27 @@
|
||||
<div class="col-8 mx-auto p-4 rounded shadow-sm context-main-bg my-4">
|
||||
<h2 class="text-center mb-4">About {SITENAME}</h2>
|
||||
<p class="lead">
|
||||
{SITENAME} was built out of a need to create and manage my own web applications.
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
Right now, this entire system was built and managed by myself. As stated, I have used my own version of this for years, but translating it to a publicly available product is not a 1-to-1 job. There may be bugs or issues encountered while you use the product. I can't guarantee a fix for every need in every case immediately, but I do actively keep track of bugs and work hard to ensure everyone has a great experience using the app.
|
||||
</p>
|
||||
<p>
|
||||
If you encounter any bugs, feel free to report them <a href="/bugreport" class="text-decoration-none">here</a>. Likewise, there are forms for feedback, reviews, suggestions, and a general contact form. Thanks for taking the time to check out the product!
|
||||
</p>
|
||||
<div class="text-center mt-4 pb-4">
|
||||
{loggedin}<a href="/bugreport" class="btn btn-primary btn-lg px-5">Report a Bug</a>{/loggedin}
|
||||
<a href="/contact" class="btn btn-outline-secondary btn-lg px-5 ms-3">Contact Us</a>
|
||||
<div class="m-2 m-lg-4">
|
||||
<div class="col-12 mx-5 col-sm-10 col-lg-8 mx-auto p-4 rounded shadow-sm context-main-bg">
|
||||
<h2 class="text-center mb-4">About {SITENAME}</h2>
|
||||
<p class="lead text-center text-lg-start">
|
||||
{SITENAME} was built out of a need to create and manage web applications.
|
||||
At the time, I had used wordpress but I didn't want or even need any of the blog functionality.
|
||||
No matter what plugins you add, no matter how you customize layout, wordpress is still a blog at its core.
|
||||
There is nothing inherently wrong with a blog, but when you start from a blog, everything is a post, or a plugin.
|
||||
Under the hood, wordpress is going to run how wordpress wants, as a web interface for accessing text records.
|
||||
</p>
|
||||
<p class="text-center text-lg-start">
|
||||
The Tempus Project was always intended to be a web application, not a blog.
|
||||
</p>
|
||||
<p class="text-muted text-center text-lg-start">
|
||||
Right now, this entire system was built and managed by myself. As stated, I have used my own version of this for years, but translating it to a publicly available product is not a 1-to-1 job. There may be bugs or issues encountered while you use the product. I can't guarantee a fix for every need in every case immediately, but I do actively keep track of bugs and work hard to ensure everyone has a great experience using the app.
|
||||
</p>
|
||||
<p class="text-center text-lg-start">
|
||||
If you encounter any bugs, feel free to report them <a href="/bugreport" class="text-decoration-none">here</a>. Likewise, there are forms for feedback, reviews, suggestions, and a general contact form. Thanks for taking the time to check out the product!
|
||||
</p>
|
||||
<div class="text-center mt-4 pb-4">
|
||||
{loggedin}
|
||||
<a href="/bugreport" class="btn btn-primary px-3 btn-lg m-2">Report a Bug</a>
|
||||
{/loggedin}
|
||||
<a href="/contact" class="btn btn-outline-primary px-3 m-2 btn-lg">Contact Us</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -7,7 +7,7 @@
|
||||
Please be very careful with this feature. This form allows you to send an email (formatted within the default site email template) to registered emails from various sources including newsletter subscribers, call to action subscribers, and all registered user accounts.
|
||||
</p>
|
||||
</div>
|
||||
<form action="" method="post">
|
||||
<form method="post">
|
||||
<fieldset>
|
||||
<!-- Subject -->
|
||||
<div class="mb-3 row">
|
||||
|
30
app/views/admin/images/list/combined.html
Normal file
30
app/views/admin/images/list/combined.html
Normal file
@ -0,0 +1,30 @@
|
||||
<div class="container py-5 context-main-bg">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
{ADMIN_BREADCRUMBS}
|
||||
<a href="{ROOT_URL}admin/images/upload" class="btn btn-sm btn-primary">Create</a>
|
||||
</div>
|
||||
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
|
||||
{LOOP}
|
||||
<div class="col">
|
||||
<div class="card h-100 shadow-sm context-other-bg">
|
||||
<div class="d-flex justify-content-center align-items-center context-other-bg" style="height: 250px;">
|
||||
<img src="{url}" class="img-fluid p-2" style="max-width: 100%; max-height: 100%; object-fit: contain;">
|
||||
</div>
|
||||
<div class="card-body context-third-bg d-flex flex-column">
|
||||
<div class="flex-grow-1">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="">
|
||||
<a href="{ROOT_URL}admin/images/view?fileLocation={locationSafe}" class="btn btn-sm btn-outline-primary">View</a>
|
||||
<a href="{url}" class="btn btn-sm btn-outline-primary" target="_blank">Open</a>
|
||||
<a href="{ROOT_URL}admin/images/rename?fileLocation={locationSafe}" class="btn btn-sm btn-outline-warning">Rename</a>
|
||||
<a href="{ROOT_URL}admin/images/delete?fileLocation={locationSafe}" class="btn btn-sm btn-outline-danger">Delete</a>
|
||||
</div>
|
||||
<small class="text-muted">{filename}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/LOOP}
|
||||
</div>
|
||||
</div>
|
35
app/views/admin/images/rename.html
Normal file
35
app/views/admin/images/rename.html
Normal file
@ -0,0 +1,35 @@
|
||||
<div class="context-main-bg context-main p-3">
|
||||
<legend class="text-center">Rename Image</legend>
|
||||
<hr>
|
||||
{ADMIN_BREADCRUMBS}
|
||||
<form method="post">
|
||||
<fieldset>
|
||||
<!-- Name -->
|
||||
<div class="mb-3 row">
|
||||
<label for="nickname" class="col-lg-6 col-form-label text-end">Location:</label>
|
||||
<div class="col-lg-2">
|
||||
<input type="hidden" class="form-control" name="filelocation" id="filelocation" value="{filelocation}">
|
||||
<strong>
|
||||
{filelocation}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Forward URL -->
|
||||
<div class="mb-3 row">
|
||||
<label for="newname" class="col-lg-6 col-form-label text-end">New filename ( Extensions cannot be modified ):</label>
|
||||
<div class="col-lg-2">
|
||||
<input type="text" class="form-control" name="newname" id="newname" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hidden Token -->
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="text-center">
|
||||
<button type="submit" name="submit" value="submit" class="btn btn-primary btn-lg">Save</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
29
app/views/admin/images/upload.html
Normal file
29
app/views/admin/images/upload.html
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
|
||||
|
||||
<div class="container p-4 context-main-bg mb-4 text-center">
|
||||
<h3 class="mb-4">Image Upload</h3>
|
||||
<hr>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<fieldset>
|
||||
<div class="mb-3 row">
|
||||
<label for="avatar" class="h4 col-lg-6 col-form-label text-start text-lg-end">Image</label>
|
||||
<div class="col-lg-6">
|
||||
<input type="file" class="form-control" name="uploadImage" id="uploadImage">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<span class="h4 col-lg-6 col-form-label text-start text-lg-end">Destination Folder</span>
|
||||
<div class="col-lg-6">
|
||||
{FOLDER_SELECT}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Update</button><br>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
66
app/views/admin/images/view.html
Normal file
66
app/views/admin/images/view.html
Normal file
@ -0,0 +1,66 @@
|
||||
<div class="container py-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
{ADMIN_BREADCRUMBS}
|
||||
<div class="card shadow">
|
||||
<!-- Card Header -->
|
||||
<div class="card-header text-center bg-dark text-white">
|
||||
<h3 class="card-title mb-0">{filename}</h3>
|
||||
</div>
|
||||
|
||||
<!-- Card Body -->
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<!-- User Image -->
|
||||
<div class="col-md-4 text-center">
|
||||
<img src="{url}" alt="User Pic" class="img-fluid" style="max-width: 150px;">
|
||||
</div>
|
||||
|
||||
<!-- User Details -->
|
||||
<div class="col-md-8">
|
||||
<table class="table table-borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">filename</th>
|
||||
<td>{filename}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">extension</th>
|
||||
<td>{extension}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">fileSize</th>
|
||||
<td>{fileSize}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">location</th>
|
||||
<td>{location}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">url</th>
|
||||
<td>{url}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">folder</th>
|
||||
<td>{folder}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Admin Controls -->
|
||||
<div class="card-footer text-center">
|
||||
{ADMIN}
|
||||
<a href="{ROOT_URL}admin/images/rename?fileLocation={locationSafe}" class="btn btn-warning btn-sm me-2" data-bs-toggle="tooltip" title="Rename image">
|
||||
<i class="fa fa-fw fa-pencil"></i>
|
||||
</a>
|
||||
<a href="{ROOT_URL}admin/images/delete?fileLocation={locationSafe}" class="btn btn-danger btn-sm" data-bs-toggle="tooltip" title="Delete image">
|
||||
<i class="fa fa-fw fa-trash"></i>
|
||||
</a>
|
||||
{/ADMIN}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -2,7 +2,7 @@
|
||||
<legend class="text-center">Settings</legend>
|
||||
<hr>
|
||||
{ADMIN_BREADCRUMBS}
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<fieldset>
|
||||
{configForm}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
<legend class="text-center">Create Token</legend>
|
||||
<hr>
|
||||
{ADMIN_BREADCRUMBS}
|
||||
<form action="" method="post" class="container py-4">
|
||||
<form method="post" class="container py-4">
|
||||
<fieldset>
|
||||
<div class="mb-3 row">
|
||||
<label for="name" class="col-lg-5 col-form-label text-end">Name</label>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<legend class="text-center">Edit Token</legend>
|
||||
<hr>
|
||||
{ADMIN_BREADCRUMBS}
|
||||
<form action="" method="post" class="container py-4">
|
||||
<form method="post" class="container py-4">
|
||||
<fieldset>
|
||||
<div class="mb-3 row">
|
||||
<label for="name" class="col-lg-5 col-form-label text-end">Name</label>
|
||||
|
@ -34,7 +34,7 @@
|
||||
<div class="mb-3 row">
|
||||
<label for="password" class="col-lg-6 col-form-label text-end">Password:</label>
|
||||
<div class="col-lg-2">
|
||||
<input type="password" class="form-control" name="password" id="password" value="" required>
|
||||
<input type="password" class="form-control" name="password" id="password" value="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
<div class="mb-3 row">
|
||||
<label for="password2" class="col-lg-6 col-form-label text-end">Re-Enter Password:</label>
|
||||
<div class="col-lg-2">
|
||||
<input type="password" class="form-control" name="password2" id="password2" value="" required>
|
||||
<input type="password" class="form-control" name="password2" id="password2" value="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
{LOOP}
|
||||
<tr>
|
||||
<td align="center">{ID}</td>
|
||||
<td><a href='{ROOT_URL}admin/users/view/{ID}' class="text-decoration-none">{username}</a></td>
|
||||
<td><a href='{ROOT_URL}admin/users/view/{ID}' class="text-decoration-none">{usernamePretty}</a></td>
|
||||
<td>{DTC date}{registered}{/DTC}</td>
|
||||
<td><a href="{ROOT_URL}admin/users/edit/{ID}" class="btn btn-sm btn-warning"><i class="fa fa-fw fa-pencil"></i></a></td>
|
||||
<td><a href="{ROOT_URL}admin/users/delete/{ID}" class="btn btn-sm btn-danger"><i class="fa fa-fw fa-trash"></i></a></td>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<div class="card shadow">
|
||||
<!-- Card Header -->
|
||||
<div class="card-header text-center bg-dark text-white">
|
||||
<h3 class="card-title mb-0">{username}</h3>
|
||||
<h3 class="card-title mb-0">{usernamePretty}</h3>
|
||||
</div>
|
||||
|
||||
<!-- Card Body -->
|
||||
@ -27,7 +27,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Group:</th>
|
||||
<td><a href="{ROOT_URL}admin/groups/view/{userGroup}">{groupName}</a></td>
|
||||
<td><a href="{ROOT_URL}admin/groups/view/{userGroup}" class="text-decoration-none">{groupName}</a></td>
|
||||
</tr>
|
||||
{/ADMIN}
|
||||
<tr>
|
||||
@ -45,7 +45,7 @@
|
||||
{ADMIN}
|
||||
<tr>
|
||||
<th scope="row">Email:</th>
|
||||
<td><a href="mailto:{email}">{email}</a></td>
|
||||
<td><a href="mailto:{email}" class="text-decoration-none">{email}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">User ID:</th>
|
||||
|
@ -1,30 +0,0 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-9 col-md-9 col-sm-12 col-centered">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<h2>Welcome to The Tempus-Project Friends and Family Alpha.</h2>
|
||||
<hr>
|
||||
<p>This project is now entering its third official version and nearly its tenth year of development. What a long journey it has been to get here.</p>
|
||||
<p>With that being said, I won't waste your time with a journey down memory road. If you have been sent this page, clearly I trust you, or one of our mutual friends is an asshole. Both equally possible... The main purpose of inviting you was to ask for your help.</p>
|
||||
<h2>What I need</h2>
|
||||
<p>With any application, there are bugs. The best developers I have had the pleasure of working with make mundane every day mistakes just like everyone else. This obviously includes myself. With any project you spend years working on, you will develop blind spots, or places where even if something was broken, you would skip right past it and never notice.</p>
|
||||
<p>I would like your help in identifying these such blind spots.</p>
|
||||
<h2>What you can do to help.</h2>
|
||||
<p>Currently there is a bug-report form at the bottom, usable by anyone with a registered account. I have also built an administrator system that allows me to track progress of these bugs and ensure they get fixed. In addition to tracking bugs, there is a public suggestions system and a publicly viewable to-do list.</p>
|
||||
<p>I will need some users to help test very specific things like permissions for various groups. I will need some trusted users to act as administrators and test features. I will also just need some people to use and interact with the site to ensure they aren't encountering any bugs.</p>
|
||||
<p>There are a ton of things you can do to help!</p>
|
||||
<ul>
|
||||
<li>Report any bugs!!! ( there is a bug-report link at the bottom of every page )</li>
|
||||
<li>Register an account</li>
|
||||
<li>Subscribe to the mailing list</li>
|
||||
<li>Browse blog posts</li>
|
||||
<li>Make suggestions for improvements or new features</li>
|
||||
<li>Leave comments on the blog and other features.</li>
|
||||
<li>Keep an eye out for email or messages requesting specific help.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -3,7 +3,7 @@
|
||||
<h1 class="mb-4">Email Confirmation</h1>
|
||||
<hr>
|
||||
<p>Please enter the confirmation code you received in your email.</p>
|
||||
<form action="" method="post" class="">
|
||||
<form method="post">
|
||||
<fieldset>
|
||||
<div data-mdb-input-init class="form-outline mb-4 col-2 offset-5">
|
||||
<input class="form-control" type="text" name="confirmationCode" id="confirmationCode" placeholder="Confirmation Code">
|
||||
@ -12,4 +12,4 @@
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Submit</button><br>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
@ -2,7 +2,7 @@
|
||||
<h1 class="mb-4">Re-Send Confirmation</h1>
|
||||
<hr>
|
||||
<p>Please click the resend button to resend your email confirmation. Don't forget to check the spam folder!</p>
|
||||
<form action="" method="post" class="">
|
||||
<form method="post">
|
||||
<input type="hidden" name="resendConfirmation" value="true">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Resend Confirmation</button><br>
|
@ -1,5 +1,5 @@
|
||||
<div class="col-8 mx-auto p-4 rounded shadow-sm mb-5 context-main-bg mt-4 text-center">
|
||||
<form action="" method="post">
|
||||
<form method="post">
|
||||
<legend class=" my-2">Lost and Found</legend>
|
||||
<p class="col-8 offset-2">You can begin the process of recovering your account here. Provide your username, or email address and instructions for ressetting your password will be mailed to you shortly.</p>
|
||||
<fieldset>
|
@ -2,7 +2,7 @@
|
||||
<h1 class="mb-4">Change Password</h1>
|
||||
<hr>
|
||||
<p>Please enter the confirmation code you received in your email.</p>
|
||||
<form action="" method="post" class="">
|
||||
<form method="post">
|
||||
<fieldset>
|
||||
<div data-mdb-input-init class="form-outline mb-4 col-2 offset-5">
|
||||
<input class="form-control" type="password" name="password" id="password" placeholder="New Password">
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user