wip from prod

This commit is contained in:
Joey Kimsey
2025-01-03 15:06:34 -05:00
parent 1ef85c6c2c
commit 7170cb20a0
22 changed files with 219 additions and 487 deletions

View File

@ -37,9 +37,14 @@ class Routes extends AdminController {
public function create() { public function create() {
if ( Input::exists( 'redirect_type' ) ) { if ( Input::exists( 'redirect_type' ) ) {
return Views::view( 'admin.routes.create' );
}
if ( !TTPForms::check( 'createRoute' ) ) { if ( !TTPForms::check( 'createRoute' ) ) {
Issues::add( 'error', [ 'There was an error with your route.' => Check::userErrors() ] ); Issues::add( 'error', [ 'There was an error with your route.' => Check::userErrors() ] );
return Views::view( 'admin.routes.create' );
} }
if ( self::$routes->create( if ( self::$routes->create(
Input::post( 'original_url' ), Input::post( 'original_url' ),
Input::post( 'forwarded_url' ), Input::post( 'forwarded_url' ),
@ -49,7 +54,8 @@ class Routes extends AdminController {
Session::flash( 'success', 'Route Created' ); Session::flash( 'success', 'Route Created' );
Redirect::to( 'admin/routes' ); Redirect::to( 'admin/routes' );
} }
}
Issues::add( 'error', 'There was an unknown error saving your redirect.' );
Views::view( 'admin.routes.create' ); Views::view( 'admin.routes.create' );
} }

View File

@ -27,7 +27,7 @@ use TheTempusProject\TheTempusProject as App;
class Home extends Controller { class Home extends Controller {
public function index() { public function index() {
self::$title = '{SITENAME}'; self::$title = '{SITENAME}';
self::$pageDescription = 'AllTheBookmarks.com is here to provide you a better, faster, and easier way - to manage bookmarks across multiple browser and multiple devices seamlessly.'; self::$pageDescription = 'AllTheBookmarks.com is here to provide you a better, faster, and easier - way to manage bookmarks across multiple browsers and devices seamlessly.';
if ( App::$isLoggedIn ) { if ( App::$isLoggedIn ) {
return Views::view( 'bookmarks.introduction' ); return Views::view( 'bookmarks.introduction' );
} }

View File

@ -72,7 +72,7 @@ class Routes extends DatabaseModel {
return false; return false;
} }
if ( !Check::simpleName( $nickname ) ) { if ( !Check::simpleName( $nickname ) ) {
Debug::warn( 'Invalid route nickname: ' . $name ); Debug::warn( 'Invalid route nickname: ' . $nickname );
return false; return false;
} }
if ( 'external' == $type && !Check::url( $forwarded_url ) ) { if ( 'external' == $type && !Check::url( $forwarded_url ) ) {

View File

@ -142,11 +142,11 @@ class Posts extends DatabaseModel {
$contentSummary = $spaceSummary; $contentSummary = $spaceSummary;
if ( count( $wordsArray, 1 ) >= 100 ) { if ( count( $wordsArray, 1 ) >= 100 ) {
$contentSummaryNoLink = $contentSummary; $contentSummaryNoLink = $contentSummary;
$contentSummary .= '... <a href="{ROOT_URL}blog/post/' . $instance->ID . '">Read More</a>'; $contentSummary .= '... <a href="{ROOT_URL}blog/post/' . $instance->ID . '" class="text-decoration-none atb-green">Read More</a>';
} }
} else { } else {
$contentSummaryNoLink = $lineSummary; $contentSummaryNoLink = $lineSummary;
$contentSummary = $lineSummary . '... <a href="{ROOT_URL}blog/post/' . $instance->ID . '">Read More</a>'; $contentSummary = $lineSummary . '... <a href="{ROOT_URL}blog/post/' . $instance->ID . '" class="text-decoration-none atb-green">Read More</a>';
} }
$instance->contentSummaryNoLink = $contentSummaryNoLink; $instance->contentSummaryNoLink = $contentSummaryNoLink;
$instance->contentSummary = $contentSummary; $instance->contentSummary = $contentSummary;

View File

@ -1,7 +1,7 @@
{LOOP} {LOOP}
<article class="blog-post"> <article class="blog-post">
<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}">{authorName}</a></p> <p class="blog-post-meta">{DTC date}{created}{/DTC} by <a href="{ROOT_URL}home/profile/{author}" class="text-decoration-none atb-green">{authorName}</a></p>
<div class="well"> <div class="well">
{contentSummary} {contentSummary}
</div> </div>

View File

@ -3,7 +3,7 @@
<div class="blog-post"> <div class="blog-post">
<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}">{authorName}</a></p> <p class="blog-post-meta">{DTC date}{created}{/DTC} by <a href="{ROOT_URL}home/profile/{author}" class="text-decoration-none atb-green">{authorName}</a></p>
{content} {content}
{ADMIN} {ADMIN}
<hr> <hr>

View File

@ -569,7 +569,7 @@ class Bookmarks extends Controller {
self::$title = 'Bookmark Dashboards - {SITENAME}'; self::$title = 'Bookmark Dashboards - {SITENAME}';
if ( !App::$isMember ) { if ( !App::$isMember ) {
Issues::add( 'notice', 'You will need an active subscription to start creating dashboards. You can check our <a href="/member/join">Pricing</a> page for more details.' ); Issues::add( 'notice', 'You will need an active subscription to start creating dashboards. You can check our <a href="/member/join" class="text-decoration-none">Pricing</a> page for more details.' );
return Views::view( 'bookmarks.dashboardExplainer' ); return Views::view( 'bookmarks.dashboardExplainer' );
} }
$dashboards = self::$dashboards->byUser(); $dashboards = self::$dashboards->byUser();
@ -691,7 +691,7 @@ class Bookmarks extends Controller {
public function import() { public function import() {
self::$title = 'Bookmark Import - {SITENAME}'; self::$title = 'Bookmark Import - {SITENAME}';
if ( !App::$isMember ) { if ( !App::$isMember ) {
Issues::add( 'notice', 'You will need an active subscription to start importing bookmarks. You can check our <a href="/member/join">Pricing</a> page for more details.' ); Issues::add( 'notice', 'You will need an active subscription to start importing bookmarks. You can check our <a href="/member/join" class="text-decoration-none">Pricing</a> page for more details.' );
return Views::view( 'bookmarks.importExplainer' ); return Views::view( 'bookmarks.importExplainer' );
} }
@ -743,7 +743,7 @@ class Bookmarks extends Controller {
public function export() { public function export() {
self::$title = 'Bookmark Export - {SITENAME}'; self::$title = 'Bookmark Export - {SITENAME}';
if ( !App::$isMember ) { if ( !App::$isMember ) {
Issues::add( 'notice', 'You will need an active subscription to start exporting bookmarks. You can check our <a href="/member/join">Pricing</a> page for more details.' ); Issues::add( 'notice', 'You will need an active subscription to start exporting bookmarks. You can check our <a href="/member/join" class="text-decoration-none">Pricing</a> page for more details.' );
return Views::view( 'bookmarks.exportExplainer' ); return Views::view( 'bookmarks.exportExplainer' );
} }
@ -806,7 +806,7 @@ class Bookmarks extends Controller {
} }
} }
public function share( $id = '' ) { public function share() {
$panelArray = []; $panelArray = [];
$folders = self::$folders->byUser(); $folders = self::$folders->byUser();
if ( empty( $folders ) ) { if ( empty( $folders ) ) {

View File

@ -232,4 +232,3 @@ function loadDashLinkOrder() {
bookmarkSort.innerHTML = ""; // Remove all children bookmarkSort.innerHTML = ""; // Remove all children
orderedElements.forEach(element => bookmarkSort.appendChild(element)); // Append in order orderedElements.forEach(element => bookmarkSort.appendChild(element)); // Append in order
} }

View File

@ -30,7 +30,7 @@
<div class="mb-3 row"> <div class="mb-3 row">
<label for="title" class="col-lg-5 col-form-label text-end">Privacy</label> <label for="title" class="col-lg-5 col-form-label text-end">Privacy</label>
<div class="col-lg-3"> <div class="col-lg-3">
<select id="privacy" name="privacy" class="form-select" value="{privacy}"> <select id="privacy" name="privacy" class="form-control" value="{privacy}">
<option value="private">Private</option> <option value="private">Private</option>
<option value="public">Public</option> <option value="public">Public</option>
</select> </select>

View File

@ -1,7 +1,7 @@
{LOOP} {LOOP}
<li class="list-group-item context-main-bg bg-{color}"> <li class="list-group-item context-main-bg bg-{color}">
<a href="{ROOT_URL}bookmarks/bookmark/{ID}" class="context-main">{iconHtml}</a> <a href="{ROOT_URL}bookmarks/bookmark/{ID}" class="context-main">{iconHtml}</a>
<a href="{url}"> {title}</a> <a href="{url}" class="text-decoration-none atb-green"> {title}</a>
<span class="float-end"> <span class="float-end">
<a class="btn btn-sm atb-green-bg" data-bs-toggle="modal" data-bs-target="#linkShare{ID}"> <a class="btn btn-sm atb-green-bg" data-bs-toggle="modal" data-bs-target="#linkShare{ID}">
<i class="fa fa-fw fa-share"></i> <i class="fa fa-fw fa-share"></i>

View File

@ -1,8 +1,7 @@
{LOOP} {LOOP}
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 bookmark-card"> <div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 bookmark-card" id="folderCard{ID}">
<div class="card m-3 accordion"> <div class="card m-3 accordion">
<div class="accordion-item"> <div class="accordion-item">
<div class="card-header accordion-header bg-{color} context-main"> <div class="card-header accordion-header bg-{color} context-main">
<div class="d-flex justify-content-between align-items-center w-100"> <div class="d-flex justify-content-between align-items-center w-100">
<span data-bs-target="#Collapse{ID}" data-bs-toggle="collapse" aria-expanded="true" aria-controls="Collapse{ID}"> <span data-bs-target="#Collapse{ID}" data-bs-toggle="collapse" aria-expanded="true" aria-controls="Collapse{ID}">

View File

@ -55,7 +55,7 @@
<!-- Call to Action --> <!-- Call to Action -->
<div class="text-center mt-5"> <div class="text-center mt-5">
<a href="#" class="btn atb-green-bg btn-lg"> <a href="/edge" class="btn atb-green-bg btn-lg">
<i class="fas fa-download me-2"></i>Get the Addon for Edge <i class="fas fa-download me-2"></i>Get the Addon for Edge
</a> </a>
</div> </div>

View File

@ -20,7 +20,7 @@
<div class="mb-3 row"> <div class="mb-3 row">
<label for="title" class="col-lg-5 col-form-label text-end">Privacy</label> <label for="title" class="col-lg-5 col-form-label text-end">Privacy</label>
<div class="col-lg-3"> <div class="col-lg-3">
<select id="privacy" name="privacy" class="form-select" value="{privacy}"> <select id="privacy" name="privacy" class="form-control" value="{privacy}">
<option value="private">Private</option> <option value="private">Private</option>
<option value="public">Public</option> <option value="public">Public</option>
</select> </select>

View File

@ -6,7 +6,7 @@
<hr> <hr>
<div class="alert alert-success w-100 text-center" role="alert"> <div class="alert alert-success w-100 text-center" role="alert">
If you have not already installed the AllTheBookmarks Edge extension, you can find it in the If you have not already installed the AllTheBookmarks Edge extension, you can find it in the
<a href="#" class="text-decoration-none text-primary" target="_blank">Microsoft Store</a>. <a href="/edge" class="text-decoration-none text-primary" target="_blank">Microsoft Store</a>.
</div> </div>
<p class="card-text"> <p class="card-text">
Once installed, you can add the extension to your Edge toolbar with just a few easy steps. Once installed, you can add the extension to your Edge toolbar with just a few easy steps.

View File

@ -6,7 +6,7 @@
<hr> <hr>
<div class="alert alert-success w-100 text-center" role="alert"> <div class="alert alert-success w-100 text-center" role="alert">
If you have not already installed the AllTheBookmarks Edge extension, you can find it in the If you have not already installed the AllTheBookmarks Edge extension, you can find it in the
<a href="#" class="text-decoration-none text-primary" target="_blank">Microsoft Store</a>. <a href="/edge" class="text-decoration-none text-primary" target="_blank">Microsoft Store</a>.
</div> </div>
<p class="card-text"> <p class="card-text">
With Edge, accessing the extension settings couldn't be easier. With Edge, accessing the extension settings couldn't be easier.

View File

@ -26,7 +26,7 @@
<!-- Submit Button --> <!-- Submit Button -->
<div class="text-center"> <div class="text-center">
<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-lg atb-green-bg">Submit</button>
</div> </div>
</form> </form>
</div> </div>

View File

@ -1,5 +1,5 @@
<div class="context-main-bg context-main p-3"> <div class="context-main-bg context-main p-3">
<legend class="text-center">Edit Route: {nickname}</legend> <legend class="text-center">Create Route</legend>
<hr> <hr>
{ADMIN_BREADCRUMBS} {ADMIN_BREADCRUMBS}
<form method="post"> <form method="post">

View File

@ -14,7 +14,7 @@
<div class="mb-3 row"> <div class="mb-3 row">
<label for="token_type" class="col-lg-5 col-form-label text-end">Token Type</label> <label for="token_type" class="col-lg-5 col-form-label text-end">Token Type</label>
<div class="col-lg-3"> <div class="col-lg-3">
<select id="token_type" name="token_type" class="form-select"> <select id="token_type" name="token_type" class="form-control">
<option value='app' selected>Application</option> <option value='app' selected>Application</option>
<option value='user'>User</option> <option value='user'>User</option>
</select> </select>

View File

@ -14,7 +14,7 @@
<div class="mb-3 row"> <div class="mb-3 row">
<label for="token_type" class="col-lg-5 col-form-label text-end">Token Type</label> <label for="token_type" class="col-lg-5 col-form-label text-end">Token Type</label>
<div class="col-lg-3"> <div class="col-lg-3">
<select id="token_type" name="token_type" class="form-select"> <select id="token_type" name="token_type" class="form-control">
{OPTION=token_type} {OPTION=token_type}
<option value='app' selected>Application</option> <option value='app' selected>Application</option>
<option value='user'>User</option> <option value='user'>User</option>

View File

@ -3,63 +3,217 @@
<hr> <hr>
<!-- Table of Contents --> <!-- Table of Contents -->
<div class="mb-5"> <div class="mb-4">
<h2 class="h4 atb-green">Table of Contents</h2> <h2 class="h4 atb-green">General Questions</h2>
<ul class="list-unstyled"> <ul class="list-unstyled">
<li><a href="#question1" class="text-decoration-none context-main">Does this work on mobile?</a></li> <li><a href="#generalHeading1" class="text-decoration-none context-main">Does this work on mobile?</a></li>
<li><a href="#question2" class="text-decoration-none context-main">Does this work on Mac/PC/Linux?</a></li> <li><a href="#generalHeading2" class="text-decoration-none context-main">Does this work on Mac / PC / Linux?</a></li>
<li><a href="#question3" class="text-decoration-none context-main">How do I use the extension on my mobile device?</a></li> <li><a href="#generalHeading3" class="text-decoration-none context-main">I have a ton of bookmarks, how can I add them all to allthebookmarks?</a></li>
<li><a href="#question4" class="text-decoration-none context-main">How do I add this to my phone like an app?</a></li> <li><a href="#generalHeading4" class="text-decoration-none context-main">I have everything organized now, how do I add the bookmarks back?</a></li>
</ul> </ul>
</div> </div>
<!-- Accordion for Questions --> <!-- Accordion for General Questions -->
<div class="accordion" id="faqAccordion"> <div class="accordion mb-5" id="generalAccordion">
<div class="accordion-item"> <div class="accordion-item">
<h2 class="accordion-header context-second-bg" id="heading1"> <h2 class="accordion-header context-second-bg" id="generalHeading1">
<button class="accordion-button context-main context-main-bg" type="button" data-bs-toggle="collapse" data-bs-target="#collapse1" aria-expanded="true" aria-controls="collapse1"> <button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse1" aria-expanded="false" aria-controls="collapse1">
Does this work on mobile? Does this work on mobile?
</button> </button>
</h2> </h2>
<div id="collapse1" class="accordion-collapse collapse show" aria-labelledby="heading1" data-bs-parent="#faqAccordion"> <div id="collapse1" class="accordion-collapse collapse" aria-labelledby="generalHeading1" data-bs-parent="#generalAccordion">
<div class="ml-5 accordion-body context-main context-main-bg" id="question1"> <div class="ml-5 accordion-body context-main context-main-bg" id="general1">
<span class="atb-green">Yes, this works seamlessly on mobile devices.</span> <span class="atb-green">
Yes, the web app works seamlessly on mobile devices. At this time, the app is being optimized for even better mobile friendly use.
While our browser extensions cannot be used on mobile, users are given the ability to use our bookmarklet.
The Bookmarklet is similar to a small app you can save in your mobile browser. More information can be found on our extensions page.
</span>
</div> </div>
</div> </div>
</div> </div>
<div class="accordion-item"> <div class="accordion-item">
<h2 class="accordion-header context-main context-second-bg" id="heading2"> <h2 class="accordion-header context-main context-second-bg" id="generalHeading2">
<button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse2" aria-expanded="false" aria-controls="collapse2"> <button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse2" aria-expanded="false" aria-controls="collapse2">
Does this work on Mac/PC/Linux? Does this work on Mac/PC/Linux?
</button> </button>
</h2> </h2>
<div id="collapse2" class="accordion-collapse collapse" aria-labelledby="heading2" data-bs-parent="#faqAccordion"> <div id="collapse2" class="accordion-collapse collapse" aria-labelledby="generalHeading2" data-bs-parent="#generalAccordion">
<div class="accordion-body context-main context-main-bg" id="question2"> <div class="accordion-body context-main context-main-bg" id="general2">
<span class="atb-green">Yes, it is compatible with Mac, PC, and Linux platforms.</span> <span class="atb-green">
Yes, the web app is compatible with Mac, PC, and Linux platforms.
At this time, there is no extension support directly for safari, but you can use one of the other available browsers on a Mac computer to achieve similar results.
</span>
</div> </div>
</div> </div>
</div> </div>
<div class="accordion-item"> <div class="accordion-item">
<h2 class="accordion-header context-main context-second-bg" id="heading3"> <h2 class="accordion-header context-main context-second-bg" id="generalHeading3">
<button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse3" aria-expanded="false" aria-controls="collapse3"> <button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse3" aria-expanded="false" aria-controls="collapse3">
I have a ton of bookmarks, how can I add them all to allthebookmarks?
</button>
</h2>
<div id="collapse3" class="accordion-collapse collapse" aria-labelledby="generalHeading3" data-bs-parent="#generalAccordion">
<div class="accordion-body context-main context-main-bg" id="general3">
<span class="atb-green">
All major browsers have a method for exporting bookmarks to a file.
Conveniently, you can find a tutorial on this process for your browser, on our tutorials page.
Our members can access the bookmark imports feature which will allow you to take that file and upload all the bookmarks to your dashboard.
</span>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header context-main context-second-bg" id="generalHeading4">
<button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse4" aria-expanded="false" aria-controls="collapse4">
I have everything organized now, how do I add the bookmarks back?
</button>
</h2>
<div id="collapse4" class="accordion-collapse collapse" aria-labelledby="generalHeading4" data-bs-parent="#generalAccordion">
<div class="accordion-body context-main context-main-bg" id="general4">
<span class="atb-green">
All major browsers have a method for importing bookmarks from a file.
Conveniently, you can find a tutorial on this process for your browser, on our tutorials page.
Our members can access the bookmark export feature which will allow you to generate a file from any number of folders and bookmarks on the site.
This file can be used to import all those bookmarks right into your browser of choice.
</span>
</div>
</div>
</div>
</div>
<div class="mb-4">
<h2 class="h4 atb-green">Mobile Device Questions</h2>
<ul class="list-unstyled">
<li><a href="#mobileHeading1" class="text-decoration-none context-main">How do I add bookmarks on my mobile device?</a></li>
<li><a href="#mobileHeading2" class="text-decoration-none context-main">How do I use the extension on my mobile device?</a></li>
<li><a href="#mobileHeading3" class="text-decoration-none context-main">How do I add this to my phone like an app?</a></li>
</ul>
</div>
<!-- Accordion for Mobile Questions -->
<div class="accordion mb-5" id="mobileAccordion">
<div class="accordion-item">
<h2 class="accordion-header context-second-bg" id="mobileHeading1">
<button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse5" aria-expanded="false" aria-controls="collapse5">
How do I add bookmarks on my mobile device?
</button>
</h2>
<div id="collapse5" class="accordion-collapse collapse" aria-labelledby="mobileHeading1" data-bs-parent="#mobileAccordion">
<div class="ml-5 accordion-body context-main context-main-bg" id="mobile1">
<span class="atb-green">
Adding bookmarks from your mobile device is incredibly easy with our bookmarklet, available for use on all mobile devices with supported web-browsing.
In addition to the bookmarklet, you always have the ability to add a bookmark directly from the web app here.
</span>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header context-main context-second-bg" id="mobileHeading2">
<button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse6" aria-expanded="false" aria-controls="collapse6">
How do I use the extension on my mobile device? How do I use the extension on my mobile device?
</button> </button>
</h2> </h2>
<div id="collapse3" class="accordion-collapse collapse" aria-labelledby="heading3" data-bs-parent="#faqAccordion"> <div id="collapse6" class="accordion-collapse collapse" aria-labelledby="mobileHeading2" data-bs-parent="#mobileAccordion">
<div class="accordion-body context-main context-main-bg" id="question3"> <div class="accordion-body context-main context-main-bg" id="mobile2">
<span class="atb-green">To use the extension on mobile, open your browser, install the extension, and follow the setup instructions.</span> <span class="atb-green">
At this time, none of our browser extensions are directly supported on mobile. You can still utilize the web-app or mobile-bookmarklet from any device.
This is more of an industry choice than a design decision as most mobile browsers have no support at all for mobile extensions.
</span>
</div> </div>
</div> </div>
</div> </div>
<div class="accordion-item"> <div class="accordion-item">
<h2 class="accordion-header context-main context-second-bg" id="heading4"> <h2 class="accordion-header context-main context-second-bg" id="mobileHeading3">
<button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse4" aria-expanded="false" aria-controls="collapse4"> <button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse7" aria-expanded="false" aria-controls="collapse7">
How do I add this to my phone like an app? How do I add this to my phone like an app?
</button> </button>
</h2> </h2>
<div id="collapse4" class="accordion-collapse collapse" aria-labelledby="heading4" data-bs-parent="#faqAccordion"> <div id="collapse7" class="accordion-collapse collapse" aria-labelledby="mobileHeading3" data-bs-parent="#mobileAccordion">
<div class="accordion-body context-main context-main-bg" id="question4"> <div class="accordion-body context-main context-main-bg" id="mobile3">
<span class="atb-green">You can add it to your phone by installing the app or creating a shortcut from your browser to your home screen.</span> <span class="atb-green">
While there isn't currently and Android or iPhone app available, you can add shortcut to your phone's home-screen for easy access to our web-app.
We have tutorials on how to do this available for both iPhone and Android devices.
</span>
</div>
</div>
</div>
</div>
<div class="mb-4">
<h2 class="h4 atb-green">Extension Questions</h2>
<ul class="list-unstyled">
<li><a href="#extensionHeading1" class="text-decoration-none context-main">Why isn't the extension in dark mode?</a></li>
<li><a href="#extensionHeading2" class="text-decoration-none context-main">How do I switch-accounts or sign-out of the extension?</a></li>
<li><a href="#extensionHeading3" class="text-decoration-none context-main">Folders in the extension don't match the folders on the site, what do I do?</a></li>
<li><a href="#extensionHeading4" class="text-decoration-none context-main">I use the same Folder / Privacy / Color frequently, do i need to change it every time I bookmark something?</a></li>
</ul>
</div>
<!-- Accordion for Extension Questions -->
<div class="accordion mb-3" id="extensionAccordion">
<div class="accordion-item">
<h2 class="accordion-header context-second-bg" id="extensionHeading1">
<button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse8" aria-expanded="false" aria-controls="collapse8">
Why isn't the extension in dark mode?
</button>
</h2>
<div id="collapse8" class="accordion-collapse collapse" aria-labelledby="extensionHeading1" data-bs-parent="#extensionAccordion">
<div class="ml-5 accordion-body context-main context-main-bg" id="extension1">
<span class="atb-green">
While the site and extension both support Dark-Mode, they aren't sharing that setting between them both.
If you would like to change DarkMode in the web app, you can find the toggle in your profile settings.
If you would like to change DarkMode in the extension, you can find the toggle in your settings.
If you need more info on finding the extension settings, we have tutorials available that can help.
</span>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header context-main context-second-bg" id="extensionHeading2">
<button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse9" aria-expanded="false" aria-controls="collapse9">
How do I switch-accounts or sign-out of the extension?
</button>
</h2>
<div id="collapse9" class="accordion-collapse collapse" aria-labelledby="extensionHeading2" data-bs-parent="#extensionAccordion">
<div class="accordion-body context-main context-main-bg" id="extension2">
<span class="atb-green">
To Sign out, simply open the extension settings page and there should be a log-out button in grey, at the top-right of the page.
If you need more info on finding the extension settings, we have tutorials available that can help.
</span>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header context-main context-second-bg" id="extensionHeading3">
<button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse10" aria-expanded="false" aria-controls="collapse10">
Folders in the extension don't match the folders on the site, what do I do?
</button>
</h2>
<div id="collapse10" class="accordion-collapse collapse" aria-labelledby="extensionHeading3" data-bs-parent="#extensionAccordion">
<div class="accordion-body context-main context-main-bg" id="extension3">
<span class="atb-green">
Unfortunately, as part of our commitment to your privacy, the extension works in a fairly one-sided manner.
This means the app is never pushing new data to your extension, instead the extension must request the list from the web-app.
In some cases this can lead to a miss-match between what you have saved in the app vs what you have available in the extension.
To fix this, simply open the extension settings page. This should sync your folders with the web-app.
If you need more info on finding the extension settings, we have tutorials available that can help.
</span>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header context-main context-second-bg" id="extensionHeading4">
<button class="accordion-button context-main context-main-bg collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse11" aria-expanded="false" aria-controls="collapse11">
I use the same Folder / Privacy / Color frequently, do i need to change it every time I bookmark something?
</button>
</h2>
<div id="collapse11" class="accordion-collapse collapse" aria-labelledby="extensionHeading4" data-bs-parent="#extensionAccordion">
<div class="accordion-body context-main context-main-bg" id="extension4">
<span class="atb-green">
The extension settings page provides a convenient way to change your default settings when adding folders or bookmarks.
You can select the Folder, color, and privacy defaults all from a single page.
If you need more info on finding the extension settings, we have tutorials available that can help.
</span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -19,9 +19,4 @@
<span class="fa-brands fa-fw fa-youtube"></span> <span class="fa-brands fa-fw fa-youtube"></span>
</a> </a>
</li> </li>
<li class="ms-3">
<a class=" atb-green" href="{ROOT_URL}git">
<span class="fa-brands fa-fw fa-github"></span>
</a>
</li>
</ul> </ul>

View File

@ -1,421 +0,0 @@
<?php
/**
* install.php
*
* This is the install controller for the application.
* After completion: YOU SHOULD DELETE THIS FILE.
*
* @version 3.0
* @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/
namespace TheTempusProject\Controllers;
require_once 'bin/autoload.php';
use TheTempusProject\TheTempusProject;
use TheTempusProject\Classes\Controller;
use TheTempusProject\Classes\Plugin;
use TheTempusProject\Classes\Installer;
use TheTempusProject\Classes\Forms;
use TheTempusProject\Models\User;
use TheTempusProject\Classes\Email;
use TheTempusProject\Bedrock\Functions\Code;
use TheTempusProject\Bedrock\Functions\Check;
use TheTempusProject\Bedrock\Functions\Cookie;
use TheTempusProject\Bedrock\Functions\Input;
use TheTempusProject\Bedrock\Functions\Upload;
use TheTempusProject\Bedrock\Functions\Hash;
use TheTempusProject\Bedrock\Functions\Session;
use TheTempusProject\Houdini\Classes\Issues;
use TheTempusProject\Houdini\Classes\Views;
use TheTempusProject\Houdini\Classes\Components;
use TheTempusProject\Houdini\Classes\Template;
use TheTempusProject\Hermes\Functions\Redirect;
use TheTempusProject\Hermes\Functions\Route;
use TheTempusProject\Canary\Bin\Canary as Debug;
class Install extends Controller {
private $installer;
private $location = false;
private $steps = [
'Welcome',
'Terms',
'Verify',
'Configure',
'Routing',
'Models',
'Plugins',
'Install',
'Resources',
'User',
'Complete',
];
/**
* This is the main builder for the rest of the controller. It mostly handle template variables used on all pages.
*/
public function __construct() {
parent::__construct();
self::$title = 'TP Installer';
self::$pageDescription = 'This is the install script for The Tempus Project.';
$this->installer = new Installer();
Template::noIndex();
Template::noFollow();
foreach ( $this->steps as $step ) {
Components::set( 'menu-' . $step, 'disabled' );
}
if ( $this->checkSession() !== false ) {
$this->location = $this->getStep();
Components::set( 'menu-' . ucfirst( $this->location ), 'active' );
} else {
Components::set( 'menu-Welcome', 'active' );
}
Components::set( 'installer-nav', Views::simpleView( 'install.nav' ) );
}
/**
* This method will reset the install hash, set the saved install step, update the session and cookie, and refresh if required.
*
* @param string $page
* @param boolean $redirect
* @return void
*/
public function nextStep( $page, $redirect = false ) {
$newHash = Code::genInstall();
$this->installer->setNode( 'installHash', $newHash, true );
$this->installer->setNode( 'installStep', $page, true );
Session::put( 'installHash', $newHash );
Cookie::put( 'installHash', $newHash );
if ( $redirect === true ) {
Redirect::reload();
}
return true;
}
public function checkSession() {
if ( empty( $this->installer->getNode('installHash') ) ) {
Debug::error( 'install hash not found on file.' );
return false;
}
$session = Session::get( 'installHash' );
$cookie = Cookie::get( 'installHash' );
$file = $this->installer->getNode('installHash');
if ( ! $session && ! $cookie ) {
Debug::error( 'install hash not found in session or cookie.' );
return false;
}
if ( $cookie && ! $session ) {
if ( $cookie !== $file ) {
Debug::error( 'install cookie did not match install file.' );
Cookie::delete( 'installHash' );
return false;
}
Debug::error( 'cookie matches file, using as session' );
Session::put( 'installHash', $cookie );
return true;
}
if ( $session !== $file ) {
Debug::error( 'session did not match file, deleting session' );
Session::delete( 'installHash' );
return false;
}
return true;
}
public function getStep() {
if ( !empty( $this->installer->getNode('installStep') ) ) {
return $this->installer->getNode('installStep');
}
Debug::error( 'install status not found.' );
return false;
}
/**
* The index method is called on the first request and all requests thereafter and is responsible for routing
* the current request to the appropriate installer step/method.
*/
public function index() {
if ( false === $this->location ) {
return $this->welcome();
}
// this seems dumb, i could probably do this better
$location = $this->location;
return $this->$location();
}
/**
* The welcome method is is just a page to submit a form and save the install.json for the first time.
*/
public function welcome() {
if ( Forms::Check( 'installStart' ) ) {
return $this->nextStep( 'terms', true );
}
if ( Input::exists( 'submit' ) ) {
Issues::add( 'error', ['There was an error with the Installation.' => Check::userErrors()] );
}
Views::view( 'install.start' );
}
/**
* The terms step is pretty straight forward. You simply need to continue to the next step, understanding
* that you agree to these terms when you continue the installation.
*/
public function terms() {
if ( Forms::Check( 'installAgreement' ) ) {
return $this->nextStep( 'verify', true );
}
if ( Input::exists( 'submit' ) ) {
Issues::add( 'error', [ 'There was an error with the Installation.' => Check::userErrors() ] );
}
Components::set( 'TERMS', Views::simpleView( 'terms' ) );
Views::view( 'install.agreement' );
}
/**
* There is a small list a of requirements for the application to run properly. These are things like sessions, emails, cookies, etc.
* This step verifies that all of these features are working as expected.
*/
public function verify() {
if ( Forms::Check( 'installCheck' ) ) {
return $this->nextStep( 'configure', true );
}
if ( Input::exists( 'submit' ) ) {
Issues::add( 'error', ['There was an error with the Installation.' => array_merge( Check::userErrors(), Check::systemErrors() )] );
}
Views::view( 'install.check' );
}
/**
* One of the most important steps for installation, is the configuration. In this step, we will define some very core settings
* for the app including the app's name and database credentials.
*/
public function configure() {
if ( Forms::Check( 'installConfigure' ) ) {
$logo = 'images/logo180.png';
if ( Input::exists( 'logo' ) && Upload::image( 'logo', 'System' ) ) {
$logo = 'Uploads/Images/System/' . Upload::last();
}
TheTempusProject::$activeConfig->load( BEDROCK_CONFIG_JSON );
$baseConfig = TheTempusProject::$configMatrix;
$baseConfig['main']['logo']['value'] = $logo;
$baseConfig['main']['name']['value'] = Input::postNull( 'siteName' );
$baseConfig['main']['template']['value'] = $baseConfig['main']['template']['default'];
$baseConfig['main']['tokenEnabled']['value'] = $baseConfig['main']['tokenEnabled']['default'];
$baseConfig['main']['loginLimit']['value'] = $baseConfig['main']['loginLimit']['default'];
$baseConfig['database']['dbEnabled']['value'] = $baseConfig['database']['dbEnabled']['default'];
$baseConfig['database']['dbHost']['value'] = Input::postNull( 'dbHost' );
$baseConfig['database']['dbMaxQuery']['value'] = $baseConfig['database']['dbMaxQuery']['default'];
$baseConfig['database']['dbName']['value'] = Input::postNull( 'dbName' );
$baseConfig['database']['dbPassword']['value'] = Input::postNull( 'dbPassword' );
$baseConfig['database']['dbPrefix']['value'] = Input::postNull( 'dbPrefix' );
$baseConfig['database']['dbUsername']['value'] = Input::postNull( 'dbUsername' );
if ( ! TheTempusProject::$activeConfig->generate( CONFIG_JSON, $baseConfig ) ) {
return Issues::add( 'error', 'Config file already exists so the installer has been halted. If there was an error with installation, please delete app/config/config.json manually and try again. The installer should automatically bring you back to this step.' );
}
Session::flash( 'success', 'Config saved successfully.' );
return $this->nextStep( 'routing', true );
}
if ( Input::exists( 'submit' ) ) {
Issues::add( 'error', ['There was an error with your form.' => Check::userErrors()] );
}
Views::view( 'install.configure' );
}
/**
* For the application to function properly on nginx or apache, the web servers must be configured correctly.
* Depending on which server you use, this step will help you set up and test the routing required for the
* application to function as expected.
*/
public function routing() {
if ( Input::exists( 'submit' ) && Forms::Check( 'installRouting' ) ) {
// if its Apache, attempt to generate the htaccess file before testing
if ( Check::isApache() ) {
if ( !$this->installer->checkHtaccess() ) {
if ( !$this->installer->saveHtaccess() ) {
Issues::add( 'error', 'There was an unexpected error when generating your htaccess file. Please see the error logs for more information.' );
}
}
}
// Apache should have the htaccess now, and Nginx should have been configured this way out of the box
if ( Route::testRouting() ) {
Session::flash( 'success', 'Routing is working as expected.' );
return $this->nextStep( 'models', true );
} else {
Issues::add( 'error', 'Could not verify url routing' );
}
// routing is busted, if its Apache, we already have the error from htaccess generation
// so Nginx is the only one that needs more info
if ( Check::isNginx() ) {
Issues::add( 'error', 'There appears to be an issue with your configuration. Certain urls are not being routed as expected.' );
}
} elseif ( Input::exists( 'submit' ) ) {
Issues::add( 'error', ['There was an error with your form.' => Check::userErrors()] );
}
Views::view( 'install.routing' );
}
/**
* Since models are required for the proper function of the app, this step is required and has no selection to make.
* This step will install all the required models excluding resources.
*/
public function models() {
$errors = [];
$options = [ 'installResources' => false ];
$models = $this->installer->getModelList( MODEL_DIRECTORY );
if ( Input::exists( 'submit' ) && Forms::Check( 'installModels' ) ) {
$error = false;
foreach ( $models as $model ) {
$result = $this->installer->installModel( $model, $options );
if ( $result === false ) {
$error = true;
continue;
}
}
if ( $error ) {
Issues::add( 'error', [ 'There was an error with the Installation.' => $this->installer->getErrors() ] );
} else {
Session::flash( 'success', [ 'Models Have been installed successfully.' => $this->installer->getErrors() ] );
return $this->nextStep( 'plugins', true );
}
} elseif ( Input::exists( 'submit' ) ) {
Issues::add( 'error', [ 'There was an error with your form.' => Check::userErrors() ] );
}
Views::view( 'install.models', $models );
}
/**
* This step will allow the user to install any plugins currently available for installing excluding resources.
*/
public function plugins() {
$errors = [];
$options = [ 'resources_installed' => false ];
$plugins = $this->installer->getAvailablePlugins();
$selected_plugins = Input::post( 'P_' );
if ( Input::exists( 'submit' ) && Forms::Check( 'installPlugins' ) ) {
$error = false;
foreach ( $plugins as $plugin ) {
if ( ! in_array( $plugin->name, $selected_plugins ) ) {
continue;
}
$result = $this->installer->installPlugin( $plugin, $options );
if ( !$result ) {
$error = true;
continue;
}
Plugin::enable( $plugin->name, true );
}
if ( $error ) {
Issues::add( 'error', ['There was an error with the Installation.' => $this->installer->getErrors()] );
} else {
Session::flash( 'success', [ 'Plugins Have been installed successfully.' => $this->installer->getErrors() ] );
return $this->nextStep( 'resources', true );
}
} elseif ( Input::exists( 'submit' ) ) {
Issues::add( 'error', ['There was an error with your form.' => Check::userErrors()] );
}
Views::view( 'install.plugins', $plugins );
}
/**
* The resource step will cycle through the partially installed models and install any missing resources.
*/
public function resources() {
$errors = [];
if ( Input::exists( 'submit' ) && Forms::Check( 'installResources' ) ) {
$error = false;
$allModules = $this->installer->getModules(true);
foreach ( $allModules as $name => $module ) {
if ( empty( $module ) || 'unknown' === $name || empty( $name ) || empty( $module['installedVersion'] ) ) {
continue;
}
if ( 'plugin' == $module['type'] ) {
$installResult = $this->installer->installPlugin( (object) $module, [ 'resources_installed' => true ], false );
} else {
$installResult = $this->installer->installModel( (object) $module, [ 'installResources' => true ], false );
}
if ( !$installResult ) {
$error = true;
}
}
if ( $error ) {
Issues::add( 'error', ['There was an error with the Installation.' => $this->installer->getErrors()] );
} else {
Session::flash( 'success', ['Resources have been installed successfully.' => $this->installer->getErrors()] );
return $this->nextStep( 'user', true );
}
} elseif ( Input::exists( 'submit' ) ) {
Issues::add( 'error', ['There was an error with your form.' => Check::userErrors()] );
}
Views::view( 'install.resources' );
}
/**
* This is the registration step; allowing the installer to create the super admin account.
*/
public function user() {
if ( Input::exists( 'submit' ) && Forms::Check( 'installAdminUser' ) ) {
$user = new User();
if ( !$user->create( [
'username' => Input::post( 'newUsername' ),
'password' => Hash::make( Input::post( 'userPassword' ) ),
'email' => Input::post( 'userEmail' ),
'lastLogin' => time(),
'registered' => time(),
'confirmed' => 1,
'terms' => 1,
'userGroup' => 1,
] ) ) {
Issues::add( 'error', 'There was an error creating the admin user.' );
return;
}
$this->nextStep( 'complete' );
return $this->complete( true );
} elseif ( Input::exists( 'submit' ) ) {
Issues::add( 'error', ['There was an error with your form.' => Check::userErrors()] );
}
Views::view( 'install.adminUser' );
}
/**
* This is the final step of installation. On first load it will send an email and show the final view.
* It will then redirect to the index controller and prompt the user to delete this file on any subsequent loads.
*
* @param bool $sendEmail
*/
public function complete( $sendEmail = false ) {
if ( $sendEmail ) {
Issues::add( 'success', 'The Tempus Project has been installed successfully.' );
Email::send( Input::post( 'email' ), 'install', null, [ 'template' => true ] );
return Views::view( 'install.complete' );
}
Session::flash( 'notice', 'Installation has been completed. Updates and installation can be managed in the admin panel. Please delete the install.php file.' );
Redirect::to( 'home/index' );
}
}
$app = new TheTempusProject();
if ( CANARY_ENABLED ) {
// ini_set( 'display_errors', '1' );
// ini_set( 'display_startup_errors', '1' );
// error_reporting( E_ALL );
// $app->printDebug();
}
$app->setUrl( 'install/index' );
$app->load();
if ( CANARY_DEBUG_TO_CONSOLE ) {
Components::set( 'DEBUGGING_LOG', Debug::dump() );
register_shutdown_function( [ $app::class, 'handle_shutdown' ] );
}
exit;