Compare commits

...

20 Commits
4.0.3 ... main

Author SHA1 Message Date
a1f786876e bugfix 2025-06-21 02:29:57 -04:00
46390c2447 wip 2025-02-25 14:03:12 -05:00
c40b29e812 Apple PWA fixes 2025-02-07 16:14:00 -05:00
4dd66c6f56 share display fix 2025-02-06 04:50:54 -05:00
2ac64e5c49 image update 2025-02-05 22:46:24 -05:00
5590592ebe composer bump 2025-02-05 22:05:19 -05:00
b65dda1328 composer changes 2025-02-05 20:56:39 -05:00
f928e87141 bugfixes 2025-02-05 20:45:41 -05:00
a6b241c7f0 add qr-codes, share button, and pwa config toggle 2025-02-05 19:39:54 -05:00
a38d132e61 rename comments 2025-02-05 06:36:53 -05:00
d7e8b586d7 various updates
remove dependence on jQuery
add image delete
Admin ui fix for mobile
image updates to new style
update comments
2025-02-05 06:36:29 -05:00
ea120e09bc add missing webmanifest parts 2025-02-05 05:30:23 -05:00
2aed4ec2ed composer bump 2025-02-04 21:34:36 -05:00
bd939cc078 composer bump 2025-02-03 12:47:23 -05:00
1fb4d2eb57 wip 2025-02-03 10:29:09 -05:00
e52ae78ed0 composer bump 2025-02-02 18:44:53 -05:00
5e621883ff Various changes
mobile-friendly ui updates
admin user-edit bugfix
file cleanup
added searchFields
add blog search
remove unused code
add maintenance mode config
2025-02-02 02:16:43 -05:00
b5996dc7db remove unused code 2025-02-02 01:55:15 -05:00
bc33b4cac4 cleanup and added admin images control 2025-02-02 01:55:15 -05:00
ca850bb46b UI fixes and composer bump 2025-01-27 00:26:43 -05:00
233 changed files with 2917 additions and 2168 deletions

1
.gitignore vendored
View File

@ -65,3 +65,4 @@ vendor/canary/logs/*
components/* components/*
mailhog.log mailhog.log
uploads/* uploads/*
images/qr-codes/

View File

@ -35,7 +35,7 @@ New classes must be prefaced with a doc-block following this style:
* *
* This is the admin controller. * This is the admin controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -18,7 +18,7 @@ I am working very hard to ensure the system is safe and reliable enough for me t
## Find Us ## Find Us
* [DockerHub](https://hub.docker.com/repositories/thetempusproject) * [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) * [GitLab](https://git.thetempusproject.com/the-tempus-project/thetempusproject)
## Summary ## Summary

View File

@ -5,7 +5,7 @@
* This is the base admin controller. Every other admin controller should * This is the base admin controller. Every other admin controller should
* extend this class. * extend this class.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -5,7 +5,7 @@
* This is the base api controller. Every other api controller should * This is the base api controller. Every other api controller should
* extend this class. * extend this class.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This class handles all the hard-coded configurations. * This class handles all the hard-coded configurations.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -69,14 +69,21 @@ class Config extends BedrockConfig {
$html .= '<div class="col-lg-6">'; $html .= '<div class="col-lg-6">';
$html .= $fieldHtml; $html .= $fieldHtml;
$html .= '</div>'; $html .= '</div>';
$html .= '</div>';
if ( 'file' === $node['type'] ) { if ( 'file' === $node['type'] ) {
$html .= '<div class="mb-3 row">'; $html .= '<div class="mb-3 row">';
$html .= '<h4 class="col-lg-3 col-form-label text-end">Current Image</h4>'; $html .= '<h4 class="col-lg-3 col-form-label text-end">Current Value</h4>';
$html .= '<div class="col-lg-6">'; $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 .= '<input type="text" class="form-control" name="'.$fieldname.'Text" value="'.$node['value'] . '">';
$html .= '</div>';
$html .= '</div>';
$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 d-flex justify-content-center">';
$html .= '<img alt="configured image" src="{ROOT_URL}' . $node['value'] . '" class="img-circle img-fluid p-2 avatar-125">';
$html .= '</div>';
$html .= '</div>'; $html .= '</div>';
} }
$html .= '</div>';
return Template::parse( $html ); return Template::parse( $html );
} }

View File

@ -4,7 +4,7 @@
* *
* This is the main controller class. * This is the main controller class.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the main TempusProject database model. * This is the main TempusProject database model.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -121,7 +121,6 @@ class DatabaseModel extends BedrockDatabaseModel {
$errors = []; $errors = [];
foreach ( self::$installFlags as $flag_name ) { foreach ( self::$installFlags as $flag_name ) {
if ( empty( $options[$flag_name] ) ) { if ( empty( $options[$flag_name] ) ) {
$module_data[ $flag_name ] = INSTALL_STATUS_SKIPPED;
continue; continue;
} }

View File

@ -4,7 +4,7 @@
* *
* This is our class for constructing and sending various kinds of emails. * This is our class for constructing and sending various kinds of emails.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -164,7 +164,7 @@ class Email {
} }
} }
$data->MAIL_FOOT = Views::simpleView( 'email.foot' ); $data->MAIL_FOOT = Views::simpleView( 'email.foot' );
$data->MAIL_TITLE = self::$title; $data->MAIL_TITLE = Template::parse( self::$title );
$data->MAIL_BODY = Template::parse( self::$message, $data ); $data->MAIL_BODY = Template::parse( self::$message, $data );
$subject = Template::parse( self::$subject, $data ); $subject = Template::parse( self::$subject, $data );
$body = Views::simpleView( 'email.template', $data ); $body = Views::simpleView( 'email.template', $data );

View File

@ -7,7 +7,7 @@
* error reporting to easily define exactly what feedback you * error reporting to easily define exactly what feedback you
* would like to give. * would like to give.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -115,6 +115,8 @@ class Forms extends Check {
self::addHandler( 'adminCreateToken', __CLASS__, 'adminCreateToken' ); self::addHandler( 'adminCreateToken', __CLASS__, 'adminCreateToken' );
self::addHandler( 'apiLogin', __CLASS__, 'apiLogin' ); self::addHandler( 'apiLogin', __CLASS__, 'apiLogin' );
self::addHandler( 'updatePreference', __CLASS__, 'updatePreference' ); self::addHandler( 'updatePreference', __CLASS__, 'updatePreference' );
self::addHandler( 'renameIImage', __CLASS__, 'renameIImage' );
self::addHandler( 'addImage', __CLASS__, 'addImage' );
self::addHandler( 'installStart', __CLASS__, 'install', [ 'start' ] ); self::addHandler( 'installStart', __CLASS__, 'install', [ 'start' ] );
self::addHandler( 'installAgreement', __CLASS__, 'install', [ 'agreement' ] ); self::addHandler( 'installAgreement', __CLASS__, 'install', [ 'agreement' ] );
self::addHandler( 'installCheck', __CLASS__, 'install', [ 'check' ] ); self::addHandler( 'installCheck', __CLASS__, 'install', [ 'check' ] );
@ -356,6 +358,10 @@ class Forms extends Check {
self::addUserError( 'Invalid Email.' ); self::addUserError( 'Invalid Email.' );
return false; return false;
} }
if ( $user->usernameExists( Input::post( 'username' ) ) ) {
self::addUserError( 'A user with that username is already registered.' );
return false;
}
if ( !$user->noEmailExists( Input::post( 'email' ) ) ) { if ( !$user->noEmailExists( Input::post( 'email' ) ) ) {
self::addUserError( 'A user with that email is already registered.' ); self::addUserError( 'A user with that email is already registered.' );
return false; return false;
@ -372,7 +378,7 @@ class Forms extends Check {
self::addUserError( 'You must agree to the terms of service.' ); self::addUserError( 'You must agree to the terms of service.' );
return false; return false;
} }
if ( !self::token() ) { if ( ! self::token() ) {
return false; return false;
} }
return true; return true;
@ -663,4 +669,28 @@ class Forms extends Check {
} }
return true; 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;
}
} }

View File

@ -6,7 +6,7 @@
* the application. It handles installing the application, installing and updating * the application. It handles installing the application, installing and updating
* models as well as the database, and generating and checking the htaccess file. * models as well as the database, and generating and checking the htaccess file.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -158,6 +158,10 @@ class Installer {
} else { } else {
self::$installJson['modules'][$name]['enabled_txt'] = '<span class="text-danger">No</span>'; 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]; return self::$installJson['modules'][$name];
} }
@ -422,7 +426,7 @@ class Installer {
} }
// exclude any flags that have already been successfully installed // 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" ); Debug::warn( "$flag_type has already been successfully installed" );
$flags[ $flag_type ] = false; $flags[ $flag_type ] = false;
} }
@ -530,7 +534,7 @@ class Installer {
} }
foreach ( $flags as $flag_type ) { 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; $modelInfo['installStatus'] = INSTALL_STATUS_PARTIALLY_INSTALLED;
break; break;
} }

View File

@ -4,7 +4,7 @@
* *
* This class handles all the hard-coded permissions. * This class handles all the hard-coded permissions.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -245,7 +245,7 @@ class Permissions {
public static function getFieldEditHtml( $name, $default, $pretty ) { public static function getFieldEditHtml( $name, $default, $pretty ) {
$fieldname = str_ireplace( '/', '-', $name ); $fieldname = str_ireplace( '/', '-', $name );
$fieldHtml = Forms::getSwitchHtml( $fieldname, [ 'true', 'false' ], $default ); $fieldHtml = Forms::getSwitchHtml( $fieldname, $default );
$html = ''; $html = '';
$html .= '<div class="mb-3 row">'; $html .= '<div class="mb-3 row">';
$html .= '<label for="' . $fieldname . '" class="col-lg-6 col-form-label text-end">' . $pretty . '</label>'; $html .= '<label for="' . $fieldname . '" class="col-lg-6 col-form-label text-end">' . $pretty . '</label>';

View File

@ -4,7 +4,7 @@
* *
* This class is used as a foundation for all plugins to build from. * This class is used as a foundation for all plugins to build from.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -89,7 +89,7 @@ class Plugin {
foreach ( self::PLUGIN_FLAG_MAP as $flag_name => $function_name ) { foreach ( self::PLUGIN_FLAG_MAP as $flag_name => $function_name ) {
if ( empty( $options[$flag_name] ) ) { if ( empty( $options[$flag_name] ) ) {
$module_data[ $flag_name ] = INSTALL_STATUS_SKIPPED; // $module_data[ $flag_name ] = INSTALL_STATUS_SKIPPED;
continue; continue;
} }
@ -280,7 +280,7 @@ class Plugin {
public function installResources( $options = '' ) { public function installResources( $options = '' ) {
if ( empty( $this->resourceMatrix ) ) { if ( empty( $this->resourceMatrix ) ) {
Debug::log( 'resourceMatrix is empty' ); Debug::log( 'resourceMatrix is empty' );
return true; return INSTALL_STATUS_NOT_REQUIRED;
} }
$ids = []; $ids = [];
foreach( $this->resourceMatrix as $tableName => $entries ) { foreach( $this->resourceMatrix as $tableName => $entries ) {

View File

@ -4,7 +4,7 @@
* *
* This class handles all the hard-coded preferences. * This class handles all the hard-coded preferences.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -268,15 +268,15 @@ class Preferences {
} }
$html .= '<div class="mb-3 row">'; $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 .= '<div class="col-lg-6">';
$html .= $fieldHtml; $html .= $fieldHtml;
$html .= '</div>'; $html .= '</div>';
if ( 'file' === $type ) { if ( 'file' === $type ) {
$html .= '<div class="mb-3 row">'; $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 .= '<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>';
} }
$html .= '</div>'; $html .= '</div>';

View File

@ -39,7 +39,7 @@ if ( ! defined( 'CONFIG_DIRECTORY' ) ) {
define( 'CANARY_SECURE_HASH', 'd73ed7591a30f0ca7d686a0e780f0d05' ); define( 'CANARY_SECURE_HASH', 'd73ed7591a30f0ca7d686a0e780f0d05' );
# Tempus Project Core # Tempus Project Core
define( 'APP_NAME', 'The Tempus Project'); define( 'APP_NAME', 'The Tempus Project');
define( 'TP_DEFAULT_LOGO', 'images/logo.png'); define( 'TP_DEFAULT_LOGO', 'images/logoWhite.png');
// Check // Check
define( 'MINIMUM_PHP_VERSION', 8.1); define( 'MINIMUM_PHP_VERSION', 8.1);
// Cookies // Cookies

View File

@ -4,7 +4,7 @@
* *
* This is the admin log controller. * This is the admin log controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the composer controller. Its only very effective when using composer for autoloading. * This is the composer controller. Its only very effective when using composer for autoloading.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the error logs controller. * This is the error logs controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the groups admin controller. * This is the groups admin controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -32,8 +32,6 @@ class Groups extends AdminController {
self::$title = 'Admin - Groups'; self::$title = 'Admin - Groups';
self::$group = new Group; self::$group = new Group;
self::$permissions = new Permissions; self::$permissions = new Permissions;
$view = Navigation::activePageSelect( 'nav.admin', '/admin/groups' );
Components::set( 'ADMINNAV', $view );
} }
public function create( $data = null ) { public function create( $data = null ) {

View File

@ -4,7 +4,7 @@
* *
* This is the admin dashboard controller. * This is the admin dashboard controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -17,9 +17,12 @@ use TheTempusProject\Classes\AdminController;
use TheTempusProject\Models\User; use TheTempusProject\Models\User;
use TheTempusProject\Models\Comments; use TheTempusProject\Models\Comments;
use TheTempusProject\Models\Posts; use TheTempusProject\Models\Posts;
use TheTempusProject\Models\Contact;
use TheTempusProject\Plugins\Comments as CommentPlugin; use TheTempusProject\Plugins\Comments as CommentPlugin;
use TheTempusProject\Plugins\Blog as BlogPlugin; use TheTempusProject\Plugins\Blog as BlogPlugin;
use TheTempusProject\Plugins\Contact as ContactPlugin;
use TheTempusProject\Canary\Bin\Canary as Debug; use TheTempusProject\Canary\Bin\Canary as Debug;
use TheTempusProject\Bedrock\Functions\Input;
class Home extends AdminController { class Home extends AdminController {
public static $user; public static $user;
@ -58,6 +61,19 @@ class Home extends AdminController {
} }
} }
if ( class_exists( 'TheTempusProject\Plugins\Contact' ) ) {
$plugin = new ContactPlugin;
if ( ! $plugin->checkEnabled() ) {
Debug::info( 'Contact Plugin is disabled in the control panel.' );
Components::set( 'contactDash', '' );
} else {
$posts = new Contact;
$postsList = Views::simpleView( 'contact.admin.dashboard', $posts->listPaginated( 5 ) );
Components::set( 'contactDash', $postsList );
}
}
self::$user = new User; self::$user = new User;
$users = Views::simpleView( 'admin.dashboard.users', self::$user->recent( 5 ) ); $users = Views::simpleView( 'admin.dashboard.users', self::$user->recent( 5 ) );
Components::set( 'userDash', $users ); Components::set( 'userDash', $users );

View File

@ -0,0 +1,337 @@
<?php
/**
* app/controllers/admin/tokens.php
*
* This is the admin app/user tokens controller.
*
* @version 5.0.1
* @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 $spacer = [];
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 = [
'spacer' => implode( '', $this->spacer ),
'folderName' => $folderName,
'location' => $folder,
'subdirs' => $subdirs,
];
if ( ! empty( $subdirs ) ) {
$out['folderexpand'] = '<i class="fa fa-caret-down"></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 {
$this->spacer[] = '-> ';
$children = $this->generateFolderHtml( $sub );
array_pop( $this->spacer );
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() ] );
}
}
Views::view( 'admin.images.create' );
}
public function delete() {
if ( ! Input::exists( 'fileLocation' ) ) {
Session::flash( 'warning', 'Unknown image.' );
Redirect::to( 'admin/images' );
}
$fileLocation = Input::get('fileLocation');
// Ensure the file exists
if ( ! file_exists( $fileLocation ) ) {
Session::flash('error', 'File does not exist.');
Redirect::to('admin/images');
}
// Check if the file is an image
$validMimeTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
$fileMimeType = mime_content_type( $fileLocation );
if ( ! in_array( $fileMimeType, $validMimeTypes ) ) {
Session::flash('error', 'Invalid file type. Only images can be deleted.');
Redirect::to('admin/images');
}
// Attempt to delete the file
if (@unlink($fileLocation)) {
Session::flash('success', 'Image deleted.');
} else {
Session::flash('error', 'Failed to delete the image.');
}
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;
}
}

View File

@ -4,7 +4,7 @@
* *
* This is the login logs controller. * This is the login logs controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the generic logs controller. * This is the generic logs controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the installed plugins controller. * This is the installed plugins controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -30,8 +30,6 @@ class Plugins extends AdminController {
self::$title = 'Admin - Installed Plugins'; self::$title = 'Admin - Installed Plugins';
$this->installer = new Installer; $this->installer = new Installer;
$this->plugins = $this->installer->getAvailablePlugins(); $this->plugins = $this->installer->getAvailablePlugins();
$view = Navigation::activePageSelect( 'nav.admin', '/admin/plugins' );
Components::set( 'ADMINNAV', $view );
} }
public function index() { public function index() {

View File

@ -4,7 +4,7 @@
* *
* This is the admin routes/redirects controller. * This is the admin routes/redirects controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -31,8 +31,6 @@ class Routes extends AdminController {
parent::__construct(); parent::__construct();
self::$title = 'Admin - Redirects'; self::$title = 'Admin - Redirects';
self::$routes = new RoutesClass; self::$routes = new RoutesClass;
$view = Navigation::activePageSelect( 'nav.admin', '/admin/routes' );
Components::set( 'ADMINNAV', $view );
} }
public function create() { public function create() {

View File

@ -4,7 +4,7 @@
* *
* This is the admin email controller. The only real use is to send out emails to the various lists. * This is the admin email controller. The only real use is to send out emails to the various lists.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the configuration and settings controller. * This is the configuration and settings controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the admin app/user tokens controller. * This is the admin app/user tokens controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -31,8 +31,6 @@ class Tokens extends AdminController {
parent::__construct(); parent::__construct();
self::$title = 'Admin - Tokens'; self::$title = 'Admin - Tokens';
self::$token = new Token; self::$token = new Token;
$view = Navigation::activePageSelect( 'nav.admin', '/admin/tokens' );
Components::set( 'ADMINNAV', $view );
} }
public function create() { public function create() {

View File

@ -4,7 +4,7 @@
* *
* This is the users admin controller. * This is the users admin controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -27,6 +27,7 @@ use TheTempusProject\Models\User;
use TheTempusProject\Models\Group; use TheTempusProject\Models\Group;
use TheTempusProject\TheTempusProject as App; use TheTempusProject\TheTempusProject as App;
use TheTempusProject\Houdini\Classes\Template; use TheTempusProject\Houdini\Classes\Template;
use TheTempusProject\Bedrock\Functions\Upload;
class Users extends AdminController { class Users extends AdminController {
public static $user; public static $user;
@ -37,8 +38,6 @@ class Users extends AdminController {
self::$title = 'Admin - Users'; self::$title = 'Admin - Users';
self::$user = new User; self::$user = new User;
self::$group = new Group; self::$group = new Group;
$view = Navigation::activePageSelect( 'nav.admin', '/admin/users' );
Components::set( 'ADMINNAV', $view );
} }
public function create() { public function create() {
@ -106,7 +105,7 @@ class Users extends AdminController {
} }
if ( Input::exists( 'submit' ) ) { if ( Input::exists( 'submit' ) ) {
if ( !FormChecker::check( 'editUser' ) ) { if ( ! FormChecker::check( 'editUser' ) ) {
Issues::add( 'error', [ 'There was an error with your request.' => Check::userErrors() ] ); Issues::add( 'error', [ 'There was an error with your request.' => Check::userErrors() ] );
} else { } else {
$fields = [ $fields = [
@ -114,6 +113,25 @@ class Users extends AdminController {
'email' => Input::post( 'email' ), 'email' => Input::post( 'email' ),
'userGroup' => Input::post( 'groupSelect' ), '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' ) ) { if ( Input::exists( 'confirmed' ) ) {
$fields['confirmed'] = 1; $fields['confirmed'] = 1;
} else { } else {
@ -121,6 +139,7 @@ class Users extends AdminController {
$fields['confirmationCode'] = Code::genConfirmation(); $fields['confirmationCode'] = Code::genConfirmation();
} }
} }
if ( self::$user->update( $userData->ID, $fields ) ) { if ( self::$user->update( $userData->ID, $fields ) ) {
Issues::add( 'success', 'User Updated.' ); Issues::add( 'success', 'User Updated.' );
return $this->index(); return $this->index();

View File

@ -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' );
}
}

View File

@ -4,7 +4,7 @@
* *
* This is the api authentication controller. * This is the api authentication controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the api authentication controller. * This is the api authentication controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the users' api controller. * This is the users' api controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the error controller. * This is the error controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the home or 'index' controller. * This is the home or 'index' controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -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.' ); 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() ) { if ( !Input::exists() ) {
return Views::view( 'login' ); return Views::view( 'auth.login' );
} }
if ( !Forms::check( 'login' ) ) { if ( !Forms::check( 'login' ) ) {
Issues::add( 'error', [ 'There was an error with your login.' => Check::userErrors() ] ); 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' ) ) ) { if ( !self::$user->logIn( Input::post( 'username' ), Input::post( 'password' ), Input::post( 'remember' ) ) ) {
Issues::add( 'error', 'Username or password was incorrect.' ); 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.' ); Session::flash( 'success', 'You have been logged in.' );
if ( Input::exists( 'rurl' ) ) { if ( Input::exists( 'rurl' ) ) {
@ -79,13 +79,13 @@ class Home extends Controller {
} }
self::$title = $user->username . '\'s Profile - {SITENAME}'; self::$title = $user->username . '\'s Profile - {SITENAME}';
self::$pageDescription = 'User Profile for ' . $user->username . ' - {SITENAME}'; self::$pageDescription = 'User Profile for ' . $user->username . ' - {SITENAME}';
Views::view( 'profile', $user ); Views::view( 'profilePage', $user );
} }
public function terms() { public function terms() {
self::$title = 'Terms and Conditions - {SITENAME}'; self::$title = 'Terms and Conditions - {SITENAME}';
self::$pageDescription = '{SITENAME} Terms and Conditions of use. Please use {SITENAME} safely.'; 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' ); Views::view( 'termsPage' );
} }
@ -98,8 +98,7 @@ class Home extends Controller {
public function privacy() { public function privacy() {
self::$title = 'Privacy Policy - {SITENAME}'; 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.'; 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::view( 'privacy' );
Views::raw( '<div class="col-lg-8 mx-auto">{PRIVACY}</div>' );
} }
public function faq() { public function faq() {

View File

@ -1,3 +0,0 @@
<?php
// the idea is that this will be info pages for the plugin various/info
?>

View File

@ -4,7 +4,7 @@
* *
* This is the user registration controller. * This is the user registration controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -25,20 +25,21 @@ use TheTempusProject\TheTempusProject as App;
use TheTempusProject\Classes\Controller; use TheTempusProject\Classes\Controller;
use TheTempusProject\Classes\Forms; use TheTempusProject\Classes\Forms;
use TheTempusProject\Bedrock\Classes\Config; use TheTempusProject\Bedrock\Classes\Config;
use TheTempusProject\Plugins\Turnstile;
class Register extends Controller { class Register extends Controller {
public function confirm( $code = null ) { public function confirm( $code = null ) {
Template::noIndex(); Template::noIndex();
self::$title = 'Confirm Email'; self::$title = 'Confirm Email';
if ( !isset( $code ) && !Input::exists( 'confirmationCode' ) ) { if ( !isset( $code ) && !Input::exists( 'confirmationCode' ) ) {
return Views::view( 'confirmation' ); return Views::view( 'auth.confirmation' );
} }
if ( Forms::check( 'emailConfirmation' ) ) { if ( Forms::check( 'emailConfirmation' ) ) {
$code = Input::post( 'confirmationCode' ); $code = Input::post( 'confirmationCode' );
} }
if ( !self::$user->confirm( $code ) ) { if ( !self::$user->confirm( $code ) ) {
Issues::add( 'error', 'There was an error confirming your account, please try again.' ); 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.' ); Session::flash( 'success', 'You have successfully confirmed your email address.' );
Redirect::to( 'home/index' ); Redirect::to( 'home/index' );
@ -47,21 +48,39 @@ class Register extends Controller {
public function index() { public function index() {
self::$title = '{SITENAME} Sign Up'; self::$title = '{SITENAME} Sign Up';
self::$pageDescription = 'Many features of {SITENAME} are disabled or hidden from unregistered users. On this page you can sign up for an account to access all the app has to offer.'; self::$pageDescription = 'Many features of {SITENAME} are disabled or hidden from unregistered users. On this page you can sign up for an account to access all the app has to offer.';
if ( ! Config::getValue( 'main/registrationEnabled' ) ) { if ( ! Config::getValue( 'main/registrationEnabled' ) ) {
return Issues::add( 'notice', 'The site administrator has disable the ability to register a new account.' ); return Issues::add( 'notice', 'The site administrator has disable the ability to register a new account.' );
} }
$turnstile = '';
Components::set( 'TERMS', Views::simpleView( 'terms' ) ); if ( class_exists( 'TheTempusProject\Plugins\Turnstile' ) ) {
$turnstile = new Turnstile;
if ( ! $turnstile->checkEnabled() ) {
Components::set( 'TURNSTILE_WIDGET', '' );
$turnstile = '';
}
} else {
Components::set( 'TURNSTILE_WIDGET', '' );
}
Components::set( 'TERMS', Views::simpleView( 'auth.terms' ) );
if ( App::$isLoggedIn ) { if ( App::$isLoggedIn ) {
return Issues::add( 'notice', 'You are currently logged in.' ); return Issues::add( 'notice', 'You are currently logged in.' );
} }
if ( !Input::exists() ) { if ( ! Input::exists() ) {
return Views::view( 'register' ); return Views::view( 'auth.register' );
} }
if ( !Forms::check( 'register' ) ) { if ( Input::exists( 'userEmail' ) ) {
// for the really bad AI / headless bots
Session::flash( 'success', 'Thank you for registering! Please check your email to confirm your account.' );
Redirect::to( 'home/index' );
}
if ( ! Forms::check( 'register' ) ) {
Issues::add( 'error', [ 'There was an error with your registration.' => Check::userErrors() ] ); Issues::add( 'error', [ 'There was an error with your registration.' => Check::userErrors() ] );
return Views::view( 'register' ); return Views::view( 'auth.register' );
}
if ( ! empty( $turnstile ) ) {
if ( empty( $turnstile->verify() ) ) {
return Views::view( 'auth.register' );
}
} }
self::$user->create( [ self::$user->create( [
'username' => Input::post( 'username' ), 'username' => Input::post( 'username' ),
@ -80,7 +99,7 @@ class Register extends Controller {
self::$title = 'Recover Account - {SITENAME}'; self::$title = 'Recover Account - {SITENAME}';
Template::noIndex(); Template::noIndex();
if ( !Input::exists() ) { if ( !Input::exists() ) {
return Views::view( 'forgot' ); return Views::view( 'auth.forgot' );
} }
if ( Check::email( Input::post( 'entry' ) ) && self::$user->findByEmail( Input::post( 'entry' ) ) ) { if ( Check::email( Input::post( 'entry' ) ) && self::$user->findByEmail( Input::post( 'entry' ) ) ) {
$userData = self::$user->data(); $userData = self::$user->data();
@ -96,7 +115,7 @@ class Register extends Controller {
Redirect::to( 'home/login' ); Redirect::to( 'home/login' );
} }
Issues::add( 'error', 'User not found.' ); Issues::add( 'error', 'User not found.' );
Views::view( 'forgot' ); Views::view( 'auth.forgot' );
} }
public function resend() { public function resend() {
@ -109,7 +128,7 @@ class Register extends Controller {
return Issues::add( 'notice', 'Your account has already been confirmed.' ); return Issues::add( 'notice', 'Your account has already been confirmed.' );
} }
if ( !Forms::check( 'confirmationResend' ) ) { 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 ] ); 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.' ); Session::flash( 'success', 'Your confirmation email has been sent to the email for your account.' );
@ -121,7 +140,7 @@ class Register extends Controller {
Template::noIndex(); Template::noIndex();
if ( !isset( $code ) && !Input::exists( 'resetCode' ) ) { if ( !isset( $code ) && !Input::exists( 'resetCode' ) ) {
Issues::add( 'info', 'Please provide a reset code.' ); 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 ( Input::exists( 'resetCode' ) ) {
if ( Forms::check( 'passwordResetCode' ) ) { if ( Forms::check( 'passwordResetCode' ) ) {
@ -130,15 +149,15 @@ class Register extends Controller {
} }
if ( ! self::$user->checkCode( $code ) ) { if ( ! self::$user->checkCode( $code ) ) {
Issues::add( 'error', 'There was an error with your reset code. Please try again.' ); 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 ); Components::set( 'resetCode', $code );
if ( ! Input::exists('password') ) { if ( ! Input::exists('password') ) {
return Views::view( 'password_reset' ); return Views::view( 'auth.password_reset' );
} }
if ( ! Forms::check( 'passwordReset' ) ) { if ( ! Forms::check( 'passwordReset' ) ) {
Issues::add( 'error', [ 'There was an error with your request.' => Check::userErrors() ] ); 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' ) ); self::$user->changePassword( $code, Input::post( 'password' ) );
Email::send( self::$user->data()->email, 'passwordChange', null, [ 'template' => true ] ); Email::send( self::$user->data()->email, 'passwordChange', null, [ 'template' => true ] );

View File

@ -4,7 +4,7 @@
* *
* This is the user control panel controller. * This is the user control panel controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -31,7 +31,7 @@ use TheTempusProject\Bedrock\Functions\Session;
class Usercp extends Controller { class Usercp extends Controller {
public function __construct() { public function __construct() {
parent::__construct(); parent::__construct();
if ( !App::$isLoggedIn ) { if ( ! App::$isLoggedIn ) {
Session::flash( 'notice', 'You must be logged in to view this page!' ); Session::flash( 'notice', 'You must be logged in to view this page!' );
Redirect::home(); Redirect::home();
} }
@ -70,7 +70,7 @@ class Usercp extends Controller {
self::$title = 'User Control Panel'; self::$title = 'User Control Panel';
$menu = Views::simpleView( 'nav.usercp', App::$userCPlinks ); $menu = Views::simpleView( 'nav.usercp', App::$userCPlinks );
Navigation::activePageSelect( $menu, null, true, true ); Navigation::activePageSelect( $menu, null, true, true );
Views::view( 'profile', App::$activeUser ); Views::view( 'user_cp.profile', App::$activeUser );
} }
public function password() { public function password() {
@ -104,6 +104,10 @@ class Usercp extends Controller {
$userPrefs = App::$activePrefs; $userPrefs = App::$activePrefs;
if ( Input::exists( 'submit' ) ) { if ( Input::exists( 'submit' ) ) {
$fields = $prefs->convertFormToArray( true, false ); $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 ); self::$user->updatePrefs( $fields, App::$activeUser->ID );
Issues::add( 'success', 'Your preferences have been updated.' ); Issues::add( 'success', 'Your preferences have been updated.' );
// if the image upload fails, need to fall back on original // if the image upload fails, need to fall back on original

View File

@ -3,7 +3,7 @@
* *
* This is css used in the debuging console. * This is css used in the debuging console.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -3,38 +3,60 @@
* *
* This file provides dark mode styles to override existing Bootstrap 5 base styles. * This file provides dark mode styles to override existing Bootstrap 5 base styles.
* *
* @version 3.0-dark * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/ */
.context-main { .context-popover {
color: #fff; background-color: #383838;
color: white;
} }
.context-second {
color: #1e1e1e; .context-popover .popover-header {
background-color: #2c2c2c;
} }
.context-main-border {
border-color: #f5f5f5!important;
}
.context-main-border-other {
border-color: #1e1e1e!important;
}
.context-main-bg { .context-main-bg {
background-color: #2c2c2c; background-color: #2c2c2c;
} }
.context-second-bg { .context-second-bg {
background-color: #1e1e1e; background-color: #383838;
} }
.context-third-bg { .context-third-bg {
background-color: #3a3a3a; background-color: #3a3a3a;
} }
.context-other-bg {
background-color: #1e1e1e;
}
.context-main {
color: #fff;
}
.bg-default { .bg-default {
background-color: #2c2c2c; background-color: #2c2c2c;
} }
hr {
color: #f5f5f5;
}
.bg-none,.bg-warning { .bg-none,.bg-warning {
color: #000 !important; color: #000 !important;
} }
.context-other {
color: #000;
}
.accordion-button:not(.collapsed) { .accordion-button:not(.collapsed) {
color: #f5f5f5; color: #f5f5f5;
background-color: var(--bs-accordion-dark-active-bg); background-color: var(--bs-accordion-dark-active-bg);
@ -64,12 +86,6 @@ body {
.install-terms strong { .install-terms strong {
color: #ffffff; color: #ffffff;
} }
.context-main {
color: #ffffff;
}
.context-other {
color: #ffffff;
}
/** /**
* Terms Page * Terms Page
@ -145,6 +161,7 @@ body {
background-color: #1f1f1f; background-color: #1f1f1f;
color: #e0e0e0; color: #e0e0e0;
} }
.form-control:focus { .form-control:focus {
color: #e0e0e0; color: #e0e0e0;
border-color: #1e90ff; border-color: #1e90ff;

View File

@ -3,19 +3,77 @@
* *
* This file is for any css that should be applied site wide. * This file is for any css that should be applied site wide.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/ */
.facebook {
border-color: #1877F2 !important; /* Facebook Blue */
color: #1877F2 !important;
}
.context-other-bg { .x-black {
background-color: #eaeaea; border-color: #000000 !important; /* X (formerly Twitter) Black */
color: #000000 !important;
}
.reddit {
border-color: #FF4500 !important; /* Reddit Orange */
color: #FF4500 !important;
}
.opera {
border-color: #FF1B2D !important; /* Opera Red */
color: #FF1B2D !important;
}
.firefox {
border-color: #FF7139 !important; /* Firefox Orange */
color: #FF7139 !important;
}
.edge {
border-color: #0078D7 !important; /* Microsoft Edge Blue */
color: #0078D7 !important;
}
.safari {
border-color: #0B78E3 !important; /* Safari Blue */
color: #0B78E3 !important;
}
.context-main-border {
border-color: #1e1e1e!important;
}
.context-main-border-other {
border-color: #f5f5f5!important;
} }
.context-main-bg { .context-main-bg {
background-color: #f7f7f7; 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 */
}
hr {
color: #000;
} }
/* Base styles for the switch container */ /* Base styles for the switch container */
@ -57,7 +115,7 @@
bottom: 2.5px; bottom: 2.5px;
left: 5px; left: 5px;
transition: transform 0.3s ease-in-out; transition: transform 0.3s ease-in-out;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 2px 4px #00000033;
} }
/* Change background color when checked */ /* Change background color when checked */
@ -70,20 +128,6 @@
transform: translateX(25px); /* Adjust based on switch width */ transform: translateX(25px); /* Adjust based on switch width */
} }
.context-main {
color: #000;
}
.context-other {
color: #fff;
}
html { html {
font-family: 'Open Sans', sans-serif; font-family: 'Open Sans', sans-serif;
position: relative; position: relative;
@ -312,3 +356,4 @@ body {
/* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
background: linear-gradient(to right, #2c2c2c, #1e1e1e, #1e1e1e); background: linear-gradient(to right, #2c2c2c, #1e1e1e, #1e1e1e);
} }

View File

@ -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;
}
}

View File

@ -2,7 +2,7 @@
/** /**
* app/functions/common.php * app/functions/common.php
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

BIN
app/images/ttp-gitlab.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -3,11 +3,101 @@
* *
* This file is for 'access anywhere' javascript. * This file is for 'access anywhere' javascript.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/ */
/**
* Progressive Web-App
**/
let deferredPrompt;
const installPrompt = document.getElementById("install-prompt");
const chromeMessage = document.getElementById("chrome-install-message");
const iosMessage = document.getElementById("ios-install-message");
const installButton = document.getElementById("install-button");
const dismissButton = document.querySelector("#install-prompt .btn-close");
// Check if the user previously dismissed the prompt
if ( ! localStorage.getItem("pwaInstallDismissed") ) {
window.addEventListener("beforeinstallprompt", (event) => {
event.preventDefault();
deferredPrompt = event;
installPrompt.classList.remove("d-none");
installPrompt.classList.add("d-block"); // Show the alert
if ( chromeMessage ) {
chromeMessage.classList.remove("d-none");
chromeMessage.classList.add("d-block"); // Show the prompt
}
});
if ( isIos() && ! isInStandaloneMode() ) {
installPrompt.classList.remove("d-none");
installPrompt.classList.add("d-block"); // Show the alert
if ( iosMessage ) {
iosMessage.classList.remove("d-none");
iosMessage.classList.add("d-block"); // Show the prompt
}
}
}
// ios REQUIRES a service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/app/js/sw.js')
.then(() => console.log('Service Worker Registered'));
}
// Handle Install Button Click
if ( installButton ) {
installButton.addEventListener("click", async () => {
if ( deferredPrompt ) {
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
if (outcome === "dismissed") {
setInstallDismissed(); // Store that the user dismissed the prompt
}
deferredPrompt = null; // Reset prompt
installPrompt.classList.remove("d-block");
installPrompt.classList.add("d-none");
}
});
}
// Handle Close Button Click
if ( dismissButton ) {
dismissButton.addEventListener("click", () => {
setInstallDismissed(); // Store that the user dismissed the prompt
});
}
// Function to remember user choice for 7 days
function setInstallDismissed() {
localStorage.setItem("pwaInstallDismissed", Date.now() + 7 * 24 * 60 * 60 * 1000);
installPrompt.classList.remove("d-block"); // Hide the prompt
installPrompt.classList.add("d-none");
}
// Check if the 7-day period has passed
if (localStorage.getItem("pwaInstallDismissed")) {
const dismissUntil = parseInt(localStorage.getItem("pwaInstallDismissed"), 10);
if (Date.now() < dismissUntil) {
//
} else {
localStorage.removeItem("pwaInstallDismissed"); // Reset after 7 days
}
}
function isIos() {
return /iphone|ipad|ipod/i.test(navigator.userAgent);
}
function isInStandaloneMode() {
return window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone;
}
/** /**
* Automatically selects/de-selects all check boxes associated with that field * Automatically selects/de-selects all check boxes associated with that field
**/ **/
@ -80,14 +170,14 @@ function copyElementText( id ) {
} }
} }
$(document).ready(function() { document.addEventListener("DOMContentLoaded", function () {
$('select').each(function() { document.querySelectorAll("select").forEach(function (select) {
var selectedValue = $(this).attr('value'); var selectedValue = select.getAttribute("value");
if (selectedValue) { if (selectedValue) {
$(this).removeAttr('value'); select.removeAttribute("value");
$(this).find('option').each(function() { select.querySelectorAll("option").forEach(function (option) {
if ($(this).attr('value') === selectedValue) { if (option.getAttribute("value") === selectedValue) {
$(this).prop('selected', true); option.selected = true;
} }
}); });
} }
@ -178,12 +268,46 @@ document.addEventListener('DOMContentLoaded', function () {
}); });
} }
function toggleDarkModePref( value ) { function toggleDarkModePref(value) {
var fields = {}; var fields = new URLSearchParams();
fields.prefName = 'darkMode'; fields.append("prefName", "darkMode");
fields.prefValue = value; fields.append("prefValue", value);
$.post( '/usercp/updatePref', fields ).done(function(response) {
// alert('Timer updated successfully!'); fetch("/usercp/updatePref", {
}); method: "POST",
body: fields,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
})
// .then(response => response.text()) // Handle response if needed
.catch(error => console.error("Error:", error));
} }
}); });
// this reverses the carets for the folderSelect
document.querySelectorAll('[data-bs-toggle="collapse"]').forEach(button => {
button.addEventListener('click', () => {
setTimeout(() => {
const icon = button.querySelector('i');
// Only proceed if the icon already has one of the relevant classes
if (icon && (icon.classList.contains('fa-caret-down') || icon.classList.contains('fa-caret-up'))) {
icon.classList.toggle('fa-caret-down', button.classList.contains('collapsed'));
icon.classList.toggle('fa-caret-up', !button.classList.contains('collapsed'));
}
}, 150);
});
});
// this should load all popovers
document.addEventListener("DOMContentLoaded", function () {
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'));
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
return new bootstrap.Popover(popoverTriggerEl, {
customClass: 'context-popover',
});
});
});

1
app/js/sw.js Normal file
View File

@ -0,0 +1 @@
self.addEventListener('fetch', () => {});

View File

@ -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');
}
}

View File

@ -4,7 +4,7 @@
* *
* This class is used for the manipulation of the groups database table. * This class is used for the manipulation of the groups database table.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -38,11 +38,22 @@ class Group extends DatabaseModel {
[ 'name', 'varchar', '32' ], [ 'name', 'varchar', '32' ],
[ 'permissions', 'text', '' ], [ 'permissions', 'text', '' ],
]; ];
public $searchFields = [
'name',
];
public $permissionMatrix = [ public $permissionMatrix = [
'adminAccess' => [ 'adminAccess' => [
'pretty' => 'Access Administrator Areas', 'pretty' => 'Access Administrator Areas',
'default' => false, 'default' => false,
], ],
'uploadImages' => [
'pretty' => 'Upload images (such as avatars)',
'default' => false,
],
'maintenanceAccess' => [
'pretty' => 'Upload images (such as avatars)',
'default' => false,
],
]; ];
public $resourceMatrix = [ public $resourceMatrix = [
[ [

View File

@ -4,7 +4,7 @@
* *
* Model for handling all logging. * Model for handling all logging.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -46,6 +46,9 @@ class Log extends DatabaseModel {
[ 'source', 'varchar', '64' ], [ 'source', 'varchar', '64' ],
[ 'action', 'text', '' ], [ 'action', 'text', '' ],
]; ];
public $searchFields = [
'source',
];
/** /**
* The model constructor. * The model constructor.

View File

@ -4,7 +4,7 @@
* *
* This class is used for the manipulation of the routes database table. * This class is used for the manipulation of the routes database table.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -24,6 +24,9 @@ class Routes extends DatabaseModel {
[ 'original_url', 'varchar', '32' ], [ 'original_url', 'varchar', '32' ],
[ 'forwarded_url', 'text', '' ], [ 'forwarded_url', 'text', '' ],
]; ];
public $searchFields = [
'nickname',
];
public $resourceMatrix = [ public $resourceMatrix = [
[ [
'original_url' => 'fb', 'original_url' => 'fb',

View File

@ -7,7 +7,7 @@
* Notes: After refactor, the sessions will use ID's for short term, and Cookies * Notes: After refactor, the sessions will use ID's for short term, and Cookies
* will use the token for long term storage * will use the token for long term storage
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -36,6 +36,9 @@ class Sessions extends DatabaseModel {
[ 'username', 'varchar', '20' ], [ 'username', 'varchar', '20' ],
[ 'token', 'varchar', '120' ], [ 'token', 'varchar', '120' ],
]; ];
public $searchFields = [
'username',
];
public static $activeSession = false; public static $activeSession = false;
/** /**
@ -56,7 +59,7 @@ class Sessions extends DatabaseModel {
public function checkSession( $sessionID ) { public function checkSession( $sessionID ) {
$user = new User; $user = new User;
// @todo lets put this on some sort of realistic checking regime other than check everything every time // @todo lets put this on some sort of realistic checking regime other than check everything every time
if ( $sessionID == false ) { if ( empty( $sessionID ) ) {
Debug::log( 'sessionID false' ); Debug::log( 'sessionID false' );
return false; return false;
} }

View File

@ -4,7 +4,7 @@
* *
* This class is used for the manipulation of the tokens database table. * This class is used for the manipulation of the tokens database table.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -31,6 +31,10 @@ class Token extends DatabaseModel {
[ 'createdBy', 'int', '10' ], [ 'createdBy', 'int', '10' ],
[ 'expiresAt', 'int', '10' ], [ 'expiresAt', 'int', '10' ],
]; ];
public $searchFields = [
'name',
'token',
];
public $permissionMatrix = [ public $permissionMatrix = [
'addAppToken' => [ 'addAppToken' => [
'pretty' => 'Add Application Tokens', 'pretty' => 'Add Application Tokens',

View File

@ -8,7 +8,7 @@
* @todo finish fixing the check functions that were migrated here * @todo finish fixing the check functions that were migrated here
* These could go in the Forms class? * These could go in the Forms class?
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -44,11 +44,8 @@ class User extends DatabaseModel {
[ 'confirmationCode', 'varchar', '80' ], [ 'confirmationCode', 'varchar', '80' ],
[ 'prefs', 'text', '' ], [ 'prefs', 'text', '' ],
]; ];
public $permissionMatrix = [ public $searchFields = [
'uploadImages' => [ 'username',
'pretty' => 'Upload images (such as avatars)',
'default' => false,
],
]; ];
public $preferenceMatrix = [ public $preferenceMatrix = [
'gender' => [ 'gender' => [
@ -428,7 +425,7 @@ class User extends DatabaseModel {
if ( ! empty( $filter ) ) { if ( ! empty( $filter ) ) {
switch ( $filter ) { switch ( $filter ) {
case 'newsletter': case 'newsletter':
$data = self::$db->search( $this->tableName, 'prefs', 'newsletter":"true' ); $data = self::$db->searchColumn( $this->tableName, 'prefs', 'newsletter":"true' );
break; break;
default: default:
$data = self::$db->get( $this->tableName, '*' ); $data = self::$db->get( $this->tableName, '*' );
@ -546,6 +543,7 @@ class User extends DatabaseModel {
$instance->prefs = json_decode( $instance->prefs, true ); $instance->prefs = json_decode( $instance->prefs, true );
$instance->gender = $instance->prefs['gender']; $instance->gender = $instance->prefs['gender'];
$instance->avatar = $instance->prefs['avatar']; $instance->avatar = $instance->prefs['avatar'];
$instance->usernamePretty = \ucfirst( $instance->username );
$out[] = $instance; $out[] = $instance;
if ( !empty( $end ) ) { if ( !empty( $end ) ) {
$out = $out[0]; $out = $out[0];
@ -643,7 +641,7 @@ class User extends DatabaseModel {
Debug::error( 'User not created.' ); Debug::error( 'User not created.' );
return false; return false;
} }
return true; return self::$db->lastId();
} }
/** /**
@ -659,7 +657,7 @@ class User extends DatabaseModel {
} }
if ( !self::$db->update( $this->tableName, $id, $fields ) ) { if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
new CustomException( 'userUpdate' ); new CustomException( 'userUpdate' );
Debug::error( "User: $id not updated: $fields" ); Debug::error( "User: $id not updated: " . var_export( $fields, true ) );
return false; return false;
} }
return true; return true;

View File

@ -5,7 +5,7 @@
* This is the Blog admin controller. * This is the Blog admin controller.
* *
* @package TP Blog * @package TP Blog
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -29,8 +29,6 @@ class Blog extends AdminController {
parent::__construct(); parent::__construct();
self::$posts = new Posts; self::$posts = new Posts;
self::$title = 'Admin - Blog'; self::$title = 'Admin - Blog';
$view = Navigation::activePageSelect( 'nav.admin', '/admin/blog' );
Components::set( 'ADMINNAV', $view );
} }
public function index( $data = null ) { public function index( $data = null ) {

View File

@ -5,7 +5,7 @@
* This is the blog controller. * This is the blog controller.
* *
* @package TP Blog * @package TP Blog
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -171,4 +171,16 @@ class Blog extends Controller {
self::$pageDescription = '{SITENAME} blog posts easily and conveniently sorted by years.'; self::$pageDescription = '{SITENAME} blog posts easily and conveniently sorted by years.';
Views::view( 'blog.list', self::$posts->byYear( $year ) ); 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' );
}
} }

View File

@ -5,7 +5,7 @@
* This houses all of the form checking functions for this plugin. * This houses all of the form checking functions for this plugin.
* *
* @package TP Blog * @package TP Blog
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -5,7 +5,7 @@
* This class is used for the manipulation of the blog database table. * This class is used for the manipulation of the blog database table.
* *
* @package TP Blog * @package TP Blog
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -24,6 +24,11 @@ use TheTempusProject\Models\Comments;
class Posts extends DatabaseModel { class Posts extends DatabaseModel {
public $tableName = 'posts'; public $tableName = 'posts';
public $searchFields = [
'title',
'slug',
'content',
];
public static $comments = false; public static $comments = false;
public $databaseMatrix = [ public $databaseMatrix = [
@ -168,9 +173,11 @@ class Posts extends DatabaseModel {
$draft = ' <b>Draft</b>'; $draft = ' <b>Draft</b>';
} }
$instance->isDraft = $draft; $instance->isDraft = $draft;
$instance->authorName = $authorName; $instance->authorName = \ucfirst( $authorName );
if ( self::$comments !== false ) { if ( self::$comments !== false ) {
$instance->commentCount = self::$comments->count( 'blog', $instance->ID ); $instance->commentCount = self::$comments->count( 'blog', $instance->ID );
} else {
$instance->commentCount = 0;
} }
$instance->content = Filters::applyOne( 'mentions.0', $instance->content, true ); $instance->content = Filters::applyOne( 'mentions.0', $instance->content, true );
$instance->content = Filters::applyOne( 'hashtags.0', $instance->content, true ); $instance->content = Filters::applyOne( 'hashtags.0', $instance->content, true );

View File

@ -5,7 +5,7 @@
* This houses all of the main plugin info and functionality. * This houses all of the main plugin info and functionality.
* *
* @package TP Blog * @package TP Blog
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -37,6 +37,7 @@ class Blog extends Plugin {
'posts' => [ 'posts' => [
[ [
'title' => 'Welcome', '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>', '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, 'author' => 1,
'created' => '{time}', 'created' => '{time}',

View File

@ -5,7 +5,7 @@
* This is the loader for the blog template. * This is the loader for the blog template.
* *
* @package TP Blog * @package TP Blog
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -26,9 +26,10 @@ class BlogLoader extends DefaultLoader {
*/ */
public function __construct() { public function __construct() {
$posts = new Posts; $posts = new Posts;
Components::set('SIDEBAR', Views::simpleView('blog.sidebar', $posts->recent(5))); Components::set('SIDEBAR', Views::simpleView('blog.widgets.recent', $posts->recent(5)));
Components::set('SIDEBAR2', Views::simpleView('blog.sidebar2', $posts->archive())); Components::set('SIDEBAR2', Views::simpleView('blog.widgets.archive', $posts->archive()));
Components::set('SIDEBARABOUT', Views::simpleView('blog.about')); Components::set('SIDEBARABOUT', Views::simpleView('blog.widgets.about'));
Components::set('SIDEBARSEARCH', Views::simpleView('blog.widgets.search'));
Components::set('BLOGFEATURES', ''); Components::set('BLOGFEATURES', '');
Navigation::setCrumbComponent( 'BLOG_BREADCRUMBS', Input::get( 'url' ) ); Navigation::setCrumbComponent( 'BLOG_BREADCRUMBS', Input::get( 'url' ) );
Components::set( 'BLOG_TEMPLATE_URL', Template::parse( '{ROOT_URL}app/plugins/comments/' ) ); Components::set( 'BLOG_TEMPLATE_URL', Template::parse( '{ROOT_URL}app/plugins/comments/' ) );

View File

@ -4,7 +4,7 @@
* app/plugins/blog/templates/blog.tpl * app/plugins/blog/templates/blog.tpl
* *
* @package TP Blog * @package TP Blog
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -41,24 +41,43 @@
<!-- Navigation --> <!-- Navigation -->
<header class="p-3 text-bg-dark"> <header class="p-3 text-bg-dark">
<div class="container"> <div class="container">
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start"> <div class="d-flex align-items-center position-relative">
<img src="{ROOT_URL}{LOGO}" class="bi me-2" width="40" height="32" role="img" aria-label="{SITENAME} Logo"> <!-- Navbar Toggler (Left) -->
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
{SITENAME} <!-- 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> </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} {topNavLeft}
<div class="text-end d-flex align-items-center"> </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} {topNavRight}
</div> </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>
</div> </div>
</header> </header>
<div class="d-flex flex-column min-vh-100"> <div class="d-flex flex-column min-vh-100">
<div class="flex-container flex-grow-1"> <div class="flex-container flex-grow-1">
{ISSUES} {ISSUES}
@ -79,24 +98,27 @@
<div class="pt-4"> <div class="pt-4">
<div class="container"> <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 {SITENAME} Blog
</h3> </h3>
<div class="row g-5"> <div class="d-md-flex g-5">
<!-- Main Content --> <!-- Main Content -->
<div class="col-md-8"> <div class="col-12 col-md-8">
{CONTENT} {CONTENT}
</div> </div>
<!-- Sidebar Content --> <!-- Sidebar Content -->
<div class="col-md-4"> <div class="col-12 col-md-4">
<div class="position-sticky" style="top: 2rem;"> <div class="position-sticky" style="top: 2rem;">
<div class="p-4"> <div class="ps-md-2 ps-lg-5">
{SIDEBARABOUT} {SIDEBARABOUT}
</div> </div>
<div class="p-4"> <div class="ps-md-2 ps-lg-5">
{SIDEBARSEARCH}
</div>
<div class="ps-md-2 ps-lg-5">
{SIDEBAR} {SIDEBAR}
</div> </div>
<div class="p-4"> <div class="ps-md-2 ps-lg-5">
{SIDEBAR2} {SIDEBAR2}
</div> </div>
</div> </div>
@ -108,7 +130,6 @@
{FOOT} {FOOT}
</div> </div>
<!-- Bootstrap core JavaScript and jquery --> <!-- Bootstrap core JavaScript and jquery -->
<script language="JavaScript" crossorigin="anonymous" type="text/javascript" src="{JQUERY_CDN}jquery.min.js"></script>
<script language="JavaScript" crossorigin="anonymous" type="text/javascript" src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script> <script language="JavaScript" crossorigin="anonymous" type="text/javascript" src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script language="JavaScript" crossorigin="anonymous" type="text/javascript" src="{BOOTSTRAP_CDN}js/bootstrap.min.js"></script> <script language="JavaScript" crossorigin="anonymous" type="text/javascript" src="{BOOTSTRAP_CDN}js/bootstrap.min.js"></script>
<!-- Custom javascript for this template --> <!-- Custom javascript for this template -->

View File

@ -5,7 +5,7 @@
* This is the loader for the rss template. * This is the loader for the rss template.
* *
* @package TP Blog * @package TP Blog
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -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>

View File

@ -2,7 +2,7 @@
<legend class="text-center">Add Blog Post</legend> <legend class="text-center">Add Blog Post</legend>
<hr> <hr>
{ADMIN_BREADCRUMBS} {ADMIN_BREADCRUMBS}
<form action="" method="post"> <form method="post">
<fieldset> <fieldset>
<!-- Title --> <!-- Title -->
<div class="mb-3 row"> <div class="mb-3 row">

View File

@ -2,7 +2,7 @@
<legend class="text-center">Edit Blog Post</legend> <legend class="text-center">Edit Blog Post</legend>
<hr> <hr>
{ADMIN_BREADCRUMBS} {ADMIN_BREADCRUMBS}
<form action="" method="post"> <form method="post">
<fieldset> <fieldset>
<!-- Title --> <!-- Title -->
<div class="mb-3 row"> <div class="mb-3 row">

View File

@ -21,7 +21,7 @@
<tbody> <tbody>
{LOOP} {LOOP}
<tr> <tr>
<td><a href="{ROOT_URL}admin/blog/view/{ID}">{title}</a>{isDraft}</td> <td><a href="{ROOT_URL}admin/blog/view/{ID}" class="text-decoration-none">{title}</a>{isDraft}</td>
<td>{authorName}</td> <td>{authorName}</td>
<td>{commentCount}</td> <td>{commentCount}</td>
<td>{DTC}{created}{/DTC}</td> <td>{DTC}{created}{/DTC}</td>

View File

@ -7,7 +7,7 @@
</div><!-- /.blog-post --> </div><!-- /.blog-post -->
</div><!-- /.blog-main --> </div><!-- /.blog-main -->
</div><!-- /.row --> </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> <legend>New Blog Post</legend>
<div class="form-group"> <div class="form-group">
<label for="title" class="col-lg-3 control-label">Title</label> <label for="title" class="col-lg-3 control-label">Title</label>

View File

@ -1,7 +1,7 @@
{LOOP} {LOOP}
<article class="blog-post"> <article class="blog-post context-main-bg p-2">
<h2 class="blog-post-title mb-1">{title}</h2> <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/{author}" class="text-decoration-none">{authorName}</a></p> <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"> <div class="well">
{contentSummary} {contentSummary}
</div> </div>
@ -9,7 +9,7 @@
<hr> <hr>
{/LOOP} {/LOOP}
{ALT} {ALT}
<article class="blog-post"> <div class="text-center">
<p class="blog-post-meta">No Posts Found.</p> <p class="h5">No Posts Found</p>
</article> </div>
{/ALT} {/ALT}

View File

@ -1,9 +1,9 @@
<div class="row"> <div class="row">
<div class="col-lg-12 col-sm-12 blog-main"> <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"> <div class="blog-post mb-5 pb-5">
<h2 class="blog-post-title">{title}</h2> <h2 class="blog-post-title">{title}</h2>
<hr> <hr>
<p class="blog-post-meta">{DTC date}{created}{/DTC} by <a href="{ROOT_URL}home/profile/{author}" class="text-decoration-none">{authorName}</a></p> <p class="blog-post-meta">{DTC date}{created}{/DTC} by <a href="{ROOT_URL}home/profile/{authorName}" class="text-decoration-none">{authorName}</a></p>
{content} {content}
{ADMIN} {ADMIN}
<hr> <hr>

View File

@ -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>

View File

@ -0,0 +1,3 @@
<legend class="text-center my-2">Search Results</legend>
<hr>
{searchResults}

View File

@ -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>

View File

@ -1,11 +0,0 @@
<div class="p-4">
<h4 class="fst-italic">Archives</h4>
<ul class="list-unstyled mb-0">
{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}
</ul>
</div>

View 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>

View 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>

View 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>

View 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>

View File

@ -5,7 +5,7 @@
* This is the bug report admin controller. * This is the bug report admin controller.
* *
* @package TP BugReports * @package TP BugReports
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -5,7 +5,7 @@
* This is the bug reports controller. * This is the bug reports controller.
* *
* @package TP BugReports * @package TP BugReports
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -5,7 +5,7 @@
* This houses all of the form checking functions for this plugin. * This houses all of the form checking functions for this plugin.
* *
* @package TP BugReports * @package TP BugReports
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -5,7 +5,7 @@
* This class is used for the manipulation of the bugreports database table. * This class is used for the manipulation of the bugreports database table.
* *
* @package TP BugReports * @package TP BugReports
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -5,7 +5,7 @@
* This houses all of the main plugin info and functionality. * This houses all of the main plugin info and functionality.
* *
* @package TP BugReports * @package TP BugReports
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -44,14 +44,14 @@ class Bugreport extends Plugin {
], ],
]; ];
public $permissionMatrix = [ public $permissionMatrix = [
'bugReport' => [ 'canSendBugReports' => [
'pretty' => 'Can Submit Bug Reports', 'pretty' => 'Can Submit Bug Reports',
'default' => false, 'default' => false,
], ],
]; ];
public $contact_footer_links = [ public $contact_footer_links = [
[ [
'text' => 'Bug Report', 'text' => 'Report a Bug',
'url' => '{ROOT_URL}bugreport', 'url' => '{ROOT_URL}bugreport',
'filter' => 'loggedin', 'filter' => 'loggedin',
], ],

View File

@ -1,15 +1,20 @@
<div class="col-8 mx-auto p-4 rounded shadow-sm mb-5 context-main-bg mt-4 container"> <div class="m-2 m-lg-4">
<h2 class="text-center mb-4">Bug Report</h2> <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> <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 class="text-center text-sm-start">
<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> 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.
<form action="" method="post"> </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 --> <!-- Page URL -->
<div class="mb-3"> <div class="mb-3">
<label for="url" class="form-label">Page you were trying to reach:</label> <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> <input type="url" name="url" id="url" class="form-control" aria-describedby="urlHelp" required>
<small id="urlHelp" class="form-text text-muted"> <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> </small>
</div> </div>
@ -18,7 +23,7 @@
<label for="ourl" class="form-label">Page you were on:</label> <label for="ourl" class="form-label">Page you were on:</label>
<input type="url" name="ourl" id="ourl" class="form-control" aria-describedby="ourlHelp"> <input type="url" name="ourl" id="ourl" class="form-control" aria-describedby="ourlHelp">
<small id="ourlHelp" class="form-text text-muted"> <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> </small>
</div> </div>
@ -37,8 +42,11 @@
<!-- Description --> <!-- Description -->
<div class="mb-3"> <div class="mb-3">
<label for="entry" class="form-label">Describe the problem/error as best as you can: (max: 2000 characters)</label> <label for="entry" class="form-label">Describe the error you received: </label>
<textarea class="form-control" name="entry" id="entry" rows="6" maxlength="2000" required></textarea> <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> </div>
<!-- Hidden Token --> <!-- Hidden Token -->
@ -50,3 +58,4 @@
</div> </div>
</form> </form>
</div> </div>
</div>

View File

@ -5,7 +5,7 @@
* This is the comments admin controller. * This is the comments admin controller.
* *
* @package TP Comments * @package TP Comments
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -4,7 +4,7 @@
* *
* This is the Moderator controller. * This is the Moderator controller.
* *
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -5,7 +5,7 @@
* This houses all of the form checking functions for this plugin. * This houses all of the form checking functions for this plugin.
* *
* @package TP Comments * @package TP Comments
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -6,7 +6,7 @@
* of the comments table. * of the comments table.
* *
* @package TP Comments * @package TP Comments
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -5,7 +5,7 @@
* This houses all of the main plugin info and functionality. * This houses all of the main plugin info and functionality.
* *
* @package TP Comments * @package TP Comments
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -65,7 +65,7 @@ class Comments extends Plugin {
public function __construct( $load = false ) { public function __construct( $load = false ) {
if ( !empty(App::$activePerms) ) { if ( !empty(App::$activePerms) ) {
App::$isMod = !empty(App::$activePerms['modAccess']); App::$isMod = ! empty( App::$activePerms['modAccess'] );
} else { } else {
App::$isMod = false; App::$isMod = false;
} }

View File

@ -3,7 +3,7 @@
<legend class="text-center">Edit Comment</legend> <legend class="text-center">Edit Comment</legend>
<hr> <hr>
{ADMIN_BREADCRUMBS} {ADMIN_BREADCRUMBS}
<form action="" method="post" class="container py-4"> <form method="post" class="container py-4">
<fieldset> <fieldset>
<div class="mb-3 row"> <div class="mb-3 row">
<label for="comment" class="col-lg-5 col-form-label text-end">Comment:</label> <label for="comment" class="col-lg-5 col-form-label text-end">Comment:</label>

View File

@ -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"> <div class="mb-3">
<textarea <textarea
class="form-control" class="form-control"

View File

@ -1,14 +1,14 @@
<div class="card"> <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"> <h3 class="card-title mb-0">
<i class="fa fa-fw fa-comment"></i> Comments <i class="fa fa-fw fa-comment"></i> Comments
</h3> </h3>
<span class="badge bg-primary">{count}</span> <span class="badge bg-primary">{count}</span>
</div> </div>
<div class="card-body context-main-bg context-main"> <div class="card-body context-second-bg">
<ul class="list-group list-group-flush"> <ul class="list-group list-group-flush">
{LOOP} {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="d-flex align-items-start">
<div class="me-3"> <div class="me-3">
<img src="{ROOT_URL}{avatar}" class="rounded-circle" alt="User Avatar" style="width: 50px; height: 50px;"> <img src="{ROOT_URL}{avatar}" class="rounded-circle" alt="User Avatar" style="width: 50px; height: 50px;">
@ -28,7 +28,7 @@
</li> </li>
{/LOOP} {/LOOP}
{ALT} {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"> <div class="text-center">
<p class="mb-0">Be the first to comment.</p> <p class="mb-0">Be the first to comment.</p>
</div> </div>

View File

@ -5,7 +5,7 @@
* This is the contact admin controller. * This is the contact admin controller.
* *
* @package TP Contact * @package TP Contact
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -27,8 +27,6 @@ class Contact extends AdminController {
parent::__construct(); parent::__construct();
self::$title = 'Admin - Contact'; self::$title = 'Admin - Contact';
self::$contact = new ContactModel; self::$contact = new ContactModel;
$view = Navigation::activePageSelect( 'nav.admin', '/admin/contact' );
Components::set( 'ADMINNAV', $view );
} }
public function view( $id = null ) { public function view( $id = null ) {

View File

@ -5,7 +5,7 @@
* This is the home controller for the contact plugin. * This is the home controller for the contact plugin.
* *
* @package TP Contact * @package TP Contact
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -21,6 +21,7 @@ use TheTempusProject\Bedrock\Functions\Input;
use TheTempusProject\Bedrock\Functions\Session; use TheTempusProject\Bedrock\Functions\Session;
use TheTempusProject\Hermes\Functions\Redirect; use TheTempusProject\Hermes\Functions\Redirect;
use TheTempusProject\Models\Contact as ContactModel; use TheTempusProject\Models\Contact as ContactModel;
use TheTempusProject\Plugins\Turnstile;
class Contact extends Controller { class Contact extends Controller {
protected static $contact; protected static $contact;
@ -29,13 +30,28 @@ class Contact extends Controller {
self::$contact = new ContactModel; self::$contact = new ContactModel;
self::$title = 'Contact - {SITENAME}'; self::$title = 'Contact - {SITENAME}';
self::$pageDescription = 'At {SITENAME}, we value our users\' input. You can provide any contact or suggestions using this form.'; self::$pageDescription = 'At {SITENAME}, we value our users\' input. You can provide any contact or suggestions using this form.';
if ( !Input::exists() ) { $turnstile = '';
if ( class_exists( 'TheTempusProject\Plugins\Turnstile' ) ) {
$turnstile = new Turnstile;
if ( ! $turnstile->checkEnabled() ) {
Components::set( 'TURNSTILE_WIDGET', '' );
$turnstile = '';
}
} else {
Components::set( 'TURNSTILE_WIDGET', '' );
}
if ( ! Input::exists() ) {
return Views::view( 'contact.create' ); return Views::view( 'contact.create' );
} }
if ( !Forms::check( 'contact' ) ) { if ( ! Forms::check( 'contact' ) ) {
Issues::add( 'error', [ 'There was an error with your form, please check your submission and try again.' => Check::userErrors() ] ); Issues::add( 'error', [ 'There was an error with your form, please check your submission and try again.' => Check::userErrors() ] );
return Views::view( 'contact.create' ); return Views::view( 'contact.create' );
} }
if ( ! empty( $turnstile ) ) {
if ( empty( $turnstile->verify() ) ) {
return Views::view( 'contact.create' );
}
}
$result = self::$contact->create( Input::post( 'name' ), Input::post( 'contactEmail' ), Input::post( 'entry' ) ); $result = self::$contact->create( Input::post( 'name' ), Input::post( 'contactEmail' ), Input::post( 'entry' ) );
if ( $result ) { if ( $result ) {
Session::flash( 'success', 'Thank you! Your contact has been received.' ); Session::flash( 'success', 'Thank you! Your contact has been received.' );

View File

@ -5,7 +5,7 @@
* This houses all of the form checking functions for this plugin. * This houses all of the form checking functions for this plugin.
* *
* @package TP Contact * @package TP Contact
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -7,7 +7,7 @@
* @todo make this send a confirmation email * @todo make this send a confirmation email
* *
* @package TP Contact * @package TP Contact
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]

View File

@ -5,7 +5,7 @@
* This houses all of the main plugin info and functionality. * This houses all of the main plugin info and functionality.
* *
* @package TP Contact * @package TP Contact
* @version 3.0 * @version 5.0.1
* @author Joey Kimsey <Joey@thetempusproject.com> * @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com * @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE] * @license https://opensource.org/licenses/MIT [MIT LICENSE]
@ -40,7 +40,7 @@ class Contact extends Plugin {
], ],
]; ];
public $permissionMatrix = [ public $permissionMatrix = [
'contact' => [ 'canUseContactForm' => [
'pretty' => 'Can Submit Contact', 'pretty' => 'Can Submit Contact',
'default' => true, 'default' => true,
], ],

View File

@ -0,0 +1,29 @@
<table class="table context-main">
<thead>
<tr>
<th style="width: 5%"></th>
<th style="width: 25%"></th>
<th style="width: 55%"></th>
<th style="width: 5%"></th>
<th style="width: 5%"></th>
</tr>
</thead>
<tbody>
{LOOP}
<tr>
<td>{ID}</td>
<td>{DTC}{time}{/DTC}</td>
<td>{feedback}</td>
<td><a href="{ROOT_URL}admin/contact/view/{ID}" class="btn btn-sm btn-primary"><i class="fa fa-fw fa-upload"></i></a></td>
<td><a href="{ROOT_URL}admin/contact/delete/{ID}" class="btn btn-sm btn-danger"><i class="fa fa-fw fa-trash"></i></a></td>
</tr>
{/LOOP}
{ALT}
<tr>
<td class="text-center" colspan="5">
No Contact forms to show.
</td>
</tr>
{/ALT}
</tbody>
</table>

View File

@ -1,17 +1,18 @@
<div class="context-main-bg container py-4 my-4"> <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> <h2 class="text-center mb-4">Contact Us</h2>
<div class="col-lg-6 offset-md-3"> <div class="col-12 col-lg-6 offset-lg-3">
<p> <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. 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>
<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. 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> </p>
</div> </div>
<form action="" method="post"> <form method="post">
<!-- Name --> <!-- Name -->
<div class="mb-3 row"> <div class="mb-3 row">
<label for="name" class="col-lg-3 col-form-label text-end">Name:</label> <label for="name" class="col-lg-3 col-form-label text-lg-end">Name:</label>
<div class="col-lg-6"> <div class="col-lg-6">
<input type="text" class="form-control" name="name" id="name" required> <input type="text" class="form-control" name="name" id="name" required>
</div> </div>
@ -19,7 +20,7 @@
<!-- Email (Optional) --> <!-- Email (Optional) -->
<div class="mb-3 row"> <div class="mb-3 row">
<label for="contactEmail" class="col-lg-3 col-form-label text-end">E-mail: (optional)</label> <label for="contactEmail" class="col-lg-3 col-form-label text-lg-end">E-mail: (optional)</label>
<div class="col-lg-6"> <div class="col-lg-6">
<input type="email" class="form-control" name="contactEmail" id="contactEmail"> <input type="email" class="form-control" name="contactEmail" id="contactEmail">
</div> </div>
@ -27,7 +28,7 @@
<!-- Feedback --> <!-- Feedback -->
<div class="mb-3 row"> <div class="mb-3 row">
<label for="entry" class="col-lg-3 col-form-label text-end">Feedback:</label> <label for="entry" class="col-lg-3 col-form-label text-lg-end">Feedback:</label>
<div class="col-lg-6"> <div class="col-lg-6">
<textarea class="form-control" name="entry" id="entry" rows="6" maxlength="2000" required></textarea> <textarea class="form-control" name="entry" id="entry" rows="6" maxlength="2000" required></textarea>
<small class="form-text text-muted">Max: 2000 characters</small> <small class="form-text text-muted">Max: 2000 characters</small>
@ -39,7 +40,9 @@
<!-- Submit Button --> <!-- Submit Button -->
<div class="text-center"> <div class="text-center">
{TURNSTILE_WIDGET}
<button type="submit" name="submit" value="submit" class="btn btn-primary btn-lg">Submit</button> <button type="submit" name="submit" value="submit" class="btn btn-primary btn-lg">Submit</button>
</div> </div>
</form> </form>
</div>
</div> </div>

Some files were not shown because too many files have changed in this diff Show More