Initial commit
This commit is contained in:
42
app/plugins/timers/controllers/api/timers.php
Normal file
42
app/plugins/timers/controllers/api/timers.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* app/controllers/api/users.php
|
||||
*
|
||||
* This is the users' api 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\Api;
|
||||
|
||||
use TheTempusProject\Models\User;
|
||||
use TheTempusProject\Classes\ApiController;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Classes\Forms;
|
||||
use TheTempusProject\Houdini\Classes\Template;
|
||||
use TheTempusProject\Models\Timers as Timer;
|
||||
|
||||
class Timers extends ApiController {
|
||||
public static $timers;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
self::$timers = new Timer;
|
||||
Template::setTemplate( 'api' );
|
||||
}
|
||||
|
||||
public function create() {
|
||||
$name = Input::exists('name') ? Input::post('name') : '';
|
||||
$type = Input::exists('type') ? Input::post('type') : 'stopwatch';
|
||||
$currentSeconds = Input::exists('currentSeconds') ? Input::post('currentSeconds') : 0;
|
||||
$pausedAt = 0;
|
||||
$hours = Input::exists('hours') ? Input::post('hour') : '00';
|
||||
$minutes = Input::exists('minutes') ? Input::post('minute') : '00';
|
||||
$seconds = Input::exists('seconds') ? Input::post('seconds') : '00';
|
||||
$response = self::$timers->create( $name, $currentSeconds, $type, $pausedAt, $hours, $minutes, $seconds);
|
||||
Views::view( 'api.response', ['response' => json_encode( [ 'data' => $response ], true )]);
|
||||
}
|
||||
}
|
113
app/plugins/timers/controllers/timers.php
Normal file
113
app/plugins/timers/controllers/timers.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/timers/controllers/timers.php
|
||||
*
|
||||
* This is the home controller for the timers plugin.
|
||||
*
|
||||
* @package TP Timers
|
||||
* @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\Houdini\Classes\Views;
|
||||
use TheTempusProject\Classes\Controller;
|
||||
use TheTempusProject\Models\Timers as Timer;
|
||||
use TheTempusProject\Houdini\Classes\Components;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Bedrock\Functions\Session;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Houdini\Classes\Issues;
|
||||
use TheTempusProject\Classes\Forms;
|
||||
use TheTempusProject\Houdini\Classes\Template;
|
||||
use TheTempusProject\Bedrock\Bedrock;
|
||||
|
||||
class Timers extends Controller {
|
||||
protected static $timers;
|
||||
|
||||
public function __construct() {
|
||||
self::$title = 'Timers - {SITENAME}';
|
||||
self::$pageDescription = 'This is for tracking any number of things using timers.';
|
||||
self::$timers = new Timer;
|
||||
if ( ! App::$isLoggedIn ) {
|
||||
Issues::add( 'info', 'If you register an account and log in, you can save your timers for reuse.' );
|
||||
Components::set( 'timers', '' );
|
||||
Components::set( 'stopWatches', '' );
|
||||
} else {
|
||||
$timers = self::$timers->userTimers();
|
||||
$timerView = Views::simpleView( 'timers.timerElement', $timers );
|
||||
Components::set( 'timers', $timerView );
|
||||
$stopwatches = self::$timers->userStopWatches();
|
||||
$stopWatcheView = Views::simpleView( 'timers.stopwatchElement', $stopwatches );
|
||||
Components::set( 'stopWatches', $stopWatcheView );
|
||||
}
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function index() {
|
||||
Views::view( 'timers.index' );
|
||||
}
|
||||
|
||||
public function save() {
|
||||
Template::setTemplate( 'api' );
|
||||
$name = Input::post('name') ? Input::post('name') : 'unnamed';
|
||||
$type = Input::post('type') ? Input::post('type') : 'stopwatch';
|
||||
$currentSeconds = Input::post('currentSeconds') ? Input::post('currentSeconds') : 0;
|
||||
$pausedAt = 0;
|
||||
$hours = Input::post('hours') ? Input::post('hours') : '00';
|
||||
$minutes = Input::post('minutes') ? Input::post('minutes') : '00';
|
||||
$seconds = Input::post('seconds') ? Input::post('seconds') : '00';
|
||||
$response = self::$timers->create( $name, $currentSeconds, $type, $pausedAt, $hours, $minutes, $seconds );
|
||||
$out = [
|
||||
'id' => $response,
|
||||
];
|
||||
Views::view( 'api.response', ['response' => json_encode( [ 'data' => $out ], true )]);
|
||||
}
|
||||
|
||||
public function update( $id = null ) {
|
||||
if ( empty( $id ) ) {
|
||||
$id = Input::postNull('id');
|
||||
}
|
||||
Template::setTemplate( 'api' );
|
||||
$timer = self::$timers->findById( $id );
|
||||
if ( $timer == false || $timer->createdBy != App::$activeUser->ID ) {
|
||||
$response = $id;
|
||||
} else {
|
||||
if ( Input::post('paused') ) {
|
||||
$pausedAt = time();
|
||||
} else {
|
||||
$pausedAt = 0;
|
||||
}
|
||||
$response = self::$timers->update( $id, Input::post('currentSeconds'), $pausedAt );
|
||||
}
|
||||
Views::view( 'api.response', ['response' => json_encode( [ 'data' => $response ], true )]);
|
||||
}
|
||||
|
||||
public function remove( $id = null ) {
|
||||
if ( empty( $id ) ) {
|
||||
$id = Input::postNull('id');
|
||||
}
|
||||
Template::setTemplate( 'api' );
|
||||
$timer = self::$timers->findById( $id );
|
||||
if ( $timer == false || $timer->createdBy != App::$activeUser->ID ) {
|
||||
$response = $id;
|
||||
} else {
|
||||
$response = self::$timers->delete( $id );
|
||||
}
|
||||
Views::view( 'api.response', ['response' => json_encode( [ 'data' => $response ], true )]);
|
||||
}
|
||||
|
||||
public function resume() {
|
||||
$this->index();
|
||||
}
|
||||
|
||||
public function pause() {
|
||||
$this->index();
|
||||
}
|
||||
|
||||
public function archive() {
|
||||
$this->index();
|
||||
}
|
||||
}
|
8
app/plugins/timers/css/timers.css
Normal file
8
app/plugins/timers/css/timers.css
Normal file
@ -0,0 +1,8 @@
|
||||
.panel-footer .btn {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.panel {
|
||||
margin-bottom: 10px;
|
||||
}
|
38
app/plugins/timers/forms.php
Normal file
38
app/plugins/timers/forms.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/timers/forms.php
|
||||
*
|
||||
* This houses all of the form checking functions for this plugin.
|
||||
*
|
||||
* @package TP Timers
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Plugins\Suggestions;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Classes\Forms;
|
||||
|
||||
class TimerForms extends Forms {
|
||||
/**
|
||||
* Adds these functions to the form list.
|
||||
*/
|
||||
public function __construct() {
|
||||
self::addHandler( 'saveTimer', __CLASS__, 'saveTimer' );
|
||||
self::addHandler( 'pauseTimer', __CLASS__, 'pauseTimer' );
|
||||
self::addHandler( 'resumeTimer', __CLASS__, 'resumeTimer' );
|
||||
}
|
||||
public static function saveTimer() {
|
||||
return true;
|
||||
}
|
||||
public static function pauseTimer() {
|
||||
return true;
|
||||
}
|
||||
public static function resumeTimer() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
new TimerForms;
|
356
app/plugins/timers/js/timers.js
Normal file
356
app/plugins/timers/js/timers.js
Normal file
@ -0,0 +1,356 @@
|
||||
$(document).ready(function() {
|
||||
function createStopwatch(name, id, currentTime = 0, pausedAt = 0) {
|
||||
if (!id) {
|
||||
id = 'stopwatch' + ($('#stopWatches').children().length + 1);
|
||||
}
|
||||
var panelHtml = generatePanelHtml( name, id, 'glyphicon-time', 'stopwatch', 0, currentTime, pausedAt );
|
||||
$('#stopWatches').append(panelHtml);
|
||||
|
||||
setupStopwatch( id, currentTime, pausedAt );
|
||||
}
|
||||
|
||||
function createTimer( name, id, totalTime = 0, currentTime = 0, pausedAt = 0 ) {
|
||||
if (!id) {
|
||||
id = 'timer' + ($('#timers').children().length + 1);
|
||||
}
|
||||
var panelHtml = generatePanelHtml( name, id, 'glyphicon-hourglass', 'timer', totalTime, currentTime, pausedAt );
|
||||
$('#timers').append(panelHtml);
|
||||
|
||||
setupTimer( id, totalTime, currentTime, pausedAt );
|
||||
}
|
||||
|
||||
function generatePanelHtml(name, id, iconClass, type, totalSeconds, currentSeconds = 0, pausedAt = 0) {
|
||||
var panelColor, readout, defaultTime, resumeButtons;
|
||||
if (type === 'timer') {
|
||||
panelColor = 'primary';
|
||||
defaultTime = `<b>Default Time:</b>
|
||||
<span class="pull-right">
|
||||
${formatTime(totalSeconds)}
|
||||
</span>
|
||||
<br />`;
|
||||
readout = `<p id="${id}">Time left: ${formatTime(currentSeconds)}</p>`;
|
||||
} else {
|
||||
panelColor = 'info';
|
||||
defaultTime = '';
|
||||
readout = `<p id="${id}">Time elapsed: ${formatTime(currentSeconds)}</p>`;
|
||||
}
|
||||
|
||||
if ( 0 != pausedAt ) {
|
||||
resumeButtons = `<button id="Resume${id}" class="btn btn-sm btn-success"><i class="glyphicon glyphicon-play"></i></button>
|
||||
<button id="Pause${id}" class="btn btn-sm btn-default" style="display:none"><i class="glyphicon glyphicon-pause"></i></button>`;
|
||||
} else {
|
||||
resumeButtons = `<button id="Resume${id}" class="btn btn-sm btn-success" style="display:none"><i class="glyphicon glyphicon-play"></i></button>
|
||||
<button id="Pause${id}" class="btn btn-sm btn-default"><i class="glyphicon glyphicon-pause"></i></button>`;
|
||||
}
|
||||
return `
|
||||
<span class="col-lg-4" id="Panel${id}">
|
||||
<div class="panel panel-${panelColor}" role="tab">
|
||||
<div class="pull-left panel-heading">
|
||||
<button type="button" class="btn btn-default btn-sm" data-target="#Collapse${id}" data-toggle="collapse" aria-expanded="true" aria-controls="#Collapse${id}">
|
||||
<i class="glyphicon ${iconClass}"></i> ${name}
|
||||
</button>
|
||||
</div>
|
||||
<div class="panel-heading text-center">
|
||||
${resumeButtons}
|
||||
<span class="pull-right">${readout}</span>
|
||||
</div>
|
||||
<div id="Collapse${id}" class="panel-collapse collapse in" style="width:100%; position: relative;" role="tabpanel" aria-expanded="true">
|
||||
<div class="panel-body">
|
||||
<b>Name:</b>
|
||||
<span class="pull-right timer-name">
|
||||
${name}
|
||||
</span>
|
||||
<br />
|
||||
${defaultTime}
|
||||
<b>Created At:</b>
|
||||
<span class="pull-right">
|
||||
${getFormattedDate()}
|
||||
</span>
|
||||
<br />
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
${generateButtons(id, type)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>`;
|
||||
}
|
||||
|
||||
function generateButtons(id, type) {
|
||||
var duplicate = '';
|
||||
if (type === 'timer') {
|
||||
duplicate = `<button id="Duplicate${id}" class="btn btn-sm btn-info"><i class="glyphicon glyphicon-copy"></i></button>`;
|
||||
}
|
||||
return `
|
||||
<button id="Reset${id}" class="btn btn-sm btn-primary"><i class="glyphicon glyphicon-refresh"></i></button>
|
||||
<span class="pull-right">
|
||||
${duplicate}
|
||||
<button id="Remove${id}" class="btn btn-sm btn-danger"><i class="glyphicon glyphicon-trash"></i></button>
|
||||
<button id="Save${id}" class="btn btn-sm btn-success" onclick="saveTimer('${id}')"><i class="glyphicon glyphicon-save"></i></button>
|
||||
</span>
|
||||
`;
|
||||
}
|
||||
|
||||
function setupStopwatch(id, currentTime, pausedAt) {
|
||||
var interval;
|
||||
if ( 0 == pausedAt ) {
|
||||
interval = setInterval(() => updateDisplay(id, ++currentTime), 1000);
|
||||
} else {
|
||||
updateDisplay( id, currentTime );
|
||||
}
|
||||
setData(id, interval, currentTime);
|
||||
|
||||
setupControlButtons(id, 'stopwatch', () => updateDisplay(id, ++currentTime));
|
||||
}
|
||||
|
||||
function setupTimer( id, totalTime, currentTime, pausedAt = 0 ) {
|
||||
var interval;
|
||||
if ( 0 == pausedAt ) {
|
||||
interval = setInterval(() => {
|
||||
if (currentTime <= 0) {
|
||||
clearInterval(interval);
|
||||
$('#' + id).html("Time's up!");
|
||||
} else {
|
||||
updateDisplay(id, --currentTime);
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
updateDisplay( id, currentTime );
|
||||
}
|
||||
|
||||
setData( id, interval, currentTime, totalTime );
|
||||
|
||||
setupControlButtons(id, 'timer', () => {
|
||||
if (currentTime <= 0) {
|
||||
clearInterval(interval);
|
||||
$('#' + id).html("Time's up!");
|
||||
} else {
|
||||
updateDisplay(id, --currentTime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setData( id, interval, elapsed, original = 0 ) {
|
||||
$('#' + id).data({ 'interval': interval, 'elapsed': elapsed, 'original': original });
|
||||
}
|
||||
|
||||
function updateDisplay(id, time) {
|
||||
$('#' + id).html(`Time: ${formatTime(time)}`);
|
||||
$('#' + id).data({ 'elapsed': time });
|
||||
}
|
||||
|
||||
function setupControlButtons(id, type, updateFn) {
|
||||
var $pause = $(`#Pause${id}`);
|
||||
var $resume = $(`#Resume${id}`);
|
||||
var $remove = $(`#Remove${id}`);
|
||||
var $reset = $(`#Reset${id}`);
|
||||
var $duplicate = $(`#Duplicate${id}`);
|
||||
|
||||
if (type === 'timer') {
|
||||
$duplicate.click(function() {
|
||||
var element = $( '#Panel' + id );
|
||||
var name = element.find('.timer-name').text();
|
||||
createTimer( name + ' Copy', 0, $('#' + id).data('original'), $('#' + id).data('original'), true );
|
||||
});
|
||||
}
|
||||
|
||||
$pause.click(function() {
|
||||
clearInterval($('#' + id).data('interval'));
|
||||
$pause.hide();
|
||||
$resume.show();
|
||||
});
|
||||
|
||||
$resume.click(function() {
|
||||
var element = $( '#' + id );
|
||||
var elapsedTime = element.data('elapsed') || 0;
|
||||
if ( type === 'timer') {
|
||||
var newInterval = setInterval( function() {
|
||||
elapsedTime--;
|
||||
updateDisplay( id, elapsedTime );
|
||||
element.data('elapsed', elapsedTime );
|
||||
}, 1000);
|
||||
} else {
|
||||
var newInterval = setInterval(function() {
|
||||
elapsedTime++;
|
||||
updateDisplay( id, elapsedTime );
|
||||
element.data( 'elapsed', elapsedTime );
|
||||
}, 1000);
|
||||
}
|
||||
element.data( 'interval', newInterval );
|
||||
$resume.hide();
|
||||
$pause.show();
|
||||
});
|
||||
|
||||
$remove.click(function() {
|
||||
clearInterval($('#' + id).data('interval'));
|
||||
$.post('/timers/remove', {
|
||||
id: id,
|
||||
}).done(function(response) {
|
||||
$('#' + id).closest('.panel').remove();
|
||||
alert('Timer removed successfully!');
|
||||
}).fail(function() {
|
||||
alert('Error removing timer.');
|
||||
});
|
||||
});
|
||||
|
||||
$reset.click(function() {
|
||||
var element = $( '#' + id ); // get the element we are working with
|
||||
var originalTime = $( '#' + id ).data('original') || 0; // get the original time
|
||||
clearInterval( element.data('interval') ); //stop the countdown
|
||||
if ( type === 'timer') {
|
||||
element.data( 'elapsed', originalTime ); // set time remaining to original time
|
||||
updateDisplay( id, originalTime ); // let the display know things have changed
|
||||
|
||||
// if its currently ticking, make it keep ticking
|
||||
if ( ! $resume.is(":visible") ) {
|
||||
var newInterval = setInterval( function() {
|
||||
if ( originalTime <= 0 ) {
|
||||
clearInterval( newInterval );
|
||||
} else {
|
||||
originalTime--;
|
||||
element.data('elapsed', originalTime );
|
||||
}
|
||||
updateDisplay( id, originalTime );
|
||||
}, 1000);
|
||||
element.data( 'interval', newInterval );
|
||||
}
|
||||
} else {
|
||||
var elapsedTime = 0;
|
||||
element.data( 'elapsed', elapsedTime );
|
||||
updateDisplay( id, elapsedTime );
|
||||
var newInterval = setInterval(function() {
|
||||
elapsedTime++;
|
||||
updateDisplay( id, elapsedTime );
|
||||
element.data( 'elapsed', elapsedTime );
|
||||
}, 1000);
|
||||
element.data( 'interval', newInterval );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getFormattedDate() {
|
||||
var date = new Date();
|
||||
var options = { year: 'numeric', month: 'long', day: 'numeric' };
|
||||
return date.toLocaleDateString('en-US', options);
|
||||
}
|
||||
|
||||
function changeId( currentID, newID ) {
|
||||
$(`#${currentID}`).attr('id', newID);
|
||||
$(`#Resume${currentID}`).attr('id', `Resume${newID}`);
|
||||
$(`#Pause${currentID}`).attr('id', `Pause${newID}`);
|
||||
$(`#Panel${currentID}`).attr('id', `Panel${newID}`);
|
||||
$(`#Collapse${currentID}`).attr('id', `Collapse${newID}`);
|
||||
$(`#Save${currentID}`).attr('id', `Save${newID}`).attr('onclick', `saveTimer('${newID}')`);
|
||||
$(`#Remove${currentID}`).attr('id', `Remove${newID}`);
|
||||
$(`#Reset${currentID}`).attr('id', `Reset${newID}`);
|
||||
$(`#Duplicate${currentID}`).attr('id', `Duplicate${newID}`);
|
||||
$(`button[data-target="#Collapse${currentID}"]`).attr('data-target', `#Collapse${newID}`);
|
||||
$(`button[aria-controls="#Collapse${currentID}"]`).attr('aria-controls', `#Collapse${newID}`)
|
||||
}
|
||||
|
||||
function formatTime(seconds) {
|
||||
var hrs = Math.floor(seconds / 3600);
|
||||
var mins = Math.floor((seconds % 3600) / 60);
|
||||
var secs = seconds % 60;
|
||||
return `${hrs > 0 ? hrs + 'h ' : ''}${mins > 0 ? mins + 'm ' : ''}${secs}s`;
|
||||
}
|
||||
|
||||
$('#addStopwatch').click(function() {
|
||||
createStopwatch($('#stopwatchName').val());
|
||||
});
|
||||
|
||||
$('#addTimer').click(function() {
|
||||
var name = $('#name').val();
|
||||
var hours = parseInt($('#hours').val()) || 0;
|
||||
var minutes = parseInt($('#minutes').val()) || 0;
|
||||
var seconds = parseInt($('#seconds').val()) || 0;
|
||||
var totalTime = hours * 3600 + minutes * 60 + seconds;
|
||||
|
||||
if ( totalTime > 0 ) {
|
||||
createTimer( name, '', totalTime, totalTime ); // for new timers, it starts at max time
|
||||
} else {
|
||||
alert( 'Please enter a valid number of hours, minutes, or seconds.' );
|
||||
}
|
||||
});
|
||||
|
||||
$('.timer-row').each( function() {
|
||||
var $row = $(this);
|
||||
var name = $row.find('.timer-name').text();
|
||||
var currentSeconds = parseInt($row.find('.timer-current').text(), 10);
|
||||
var pausedAt = $row.find('.timer-paused').text();
|
||||
var hours = parseInt($row.find('.timer-hours').text(), 10);
|
||||
var minutes = parseInt($row.find('.timer-minutes').text(), 10);
|
||||
var seconds = parseInt($row.find('.timer-seconds').text(), 10);
|
||||
var id = $row.find('.timer-id').text();
|
||||
var totalTime = hours * 3600 + minutes * 60 + seconds;
|
||||
var createdAt = $row.find('.timer-created').text();
|
||||
|
||||
createTimer( name, id, totalTime, currentSeconds, pausedAt );
|
||||
|
||||
$row.remove();
|
||||
});
|
||||
|
||||
$('.stopwatch-row').each( function() {
|
||||
var $row = $(this);
|
||||
var name = $row.find('.timer-name').text();
|
||||
var currentSeconds = parseInt($row.find('.timer-current').text(), 10);
|
||||
var pausedAt = $row.find('.timer-paused').text();
|
||||
var id = $row.find('.timer-id').text();
|
||||
var createdAt = $row.find('.timer-created').text();
|
||||
|
||||
createStopwatch( name, id, currentSeconds, pausedAt );
|
||||
|
||||
$row.remove();
|
||||
});
|
||||
|
||||
window.saveTimer = function( elementId ) {
|
||||
var type;
|
||||
if ( elementId.includes('timer') ) {
|
||||
type = 'timer';
|
||||
} else if ( elementId.includes('stopwatch') ) {
|
||||
type = 'stopwatch';
|
||||
} else {
|
||||
return updateTimer( elementId );
|
||||
}
|
||||
var element = $( '#Panel' + elementId );
|
||||
var name = element.find('.timer-name').text();
|
||||
var originalTime = $('#' + elementId).data('original') || 0;
|
||||
var totalSeconds = $('#' + elementId).data('elapsed') || 0;
|
||||
var hours = Math.floor(originalTime / 3600);
|
||||
var minutes = Math.floor((originalTime % 3600) / 60);
|
||||
var seconds = originalTime % 60;
|
||||
|
||||
$.post('/timers/save', {
|
||||
name: name.trim(),
|
||||
type: type,
|
||||
hours: hours,
|
||||
minutes: minutes,
|
||||
seconds: seconds,
|
||||
currentSeconds: totalSeconds,
|
||||
}).done(function(response) {
|
||||
var responseData = JSON.parse(response);
|
||||
var timerId = responseData.data.id;
|
||||
alert('Timer saved successfully! ID: ' + timerId);
|
||||
}).fail(function() {
|
||||
alert('Error saving timer.');
|
||||
});
|
||||
};
|
||||
|
||||
function updateTimer( elementId ) {
|
||||
var $resume = $(`#Resume${elementId}`);
|
||||
var totalSeconds = $('#' + elementId).data('elapsed') || 0;
|
||||
var fields = {};
|
||||
|
||||
if ( $resume.is(":visible") ) {
|
||||
fields.paused = true;
|
||||
}
|
||||
|
||||
fields.currentSeconds = totalSeconds;
|
||||
|
||||
$.post( '/timers/update/' + elementId, fields ).done(function(response) {
|
||||
alert('Timer updated successfully!');
|
||||
}).fail(function() {
|
||||
alert('Error saving timer.');
|
||||
});
|
||||
}
|
||||
});
|
176
app/plugins/timers/models/timers.php
Normal file
176
app/plugins/timers/models/timers.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/suggestions/models/suggestions.php
|
||||
*
|
||||
* This class is used for the manipulation of the suggestions database table.
|
||||
*
|
||||
* @package TP Suggest
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Models;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Bedrock\Classes\Config;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||
use TheTempusProject\Classes\DatabaseModel;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
|
||||
class Timers extends DatabaseModel {
|
||||
public $tableName = 'timers';
|
||||
public $databaseMatrix = [
|
||||
[ 'name', 'varchar', '86' ],
|
||||
[ 'type', 'varchar', '24' ],
|
||||
[ 'currentSeconds', 'int', '10' ],
|
||||
[ 'hours', 'int', '10' ],
|
||||
[ 'minutes', 'int', '10' ],
|
||||
[ 'seconds', 'int', '10' ],
|
||||
[ 'createdBy', 'int', '11' ],
|
||||
[ 'createdAt', 'int', '11' ],
|
||||
[ 'updatedAt', 'int', '11' ],
|
||||
[ 'pausedAt', 'int', '11' ],
|
||||
];
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function filter( $data, $params = [] ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function listByUser( $limit = 0 ) {
|
||||
$where = [ 'createdBy', '=', App::$activeUser->ID ];
|
||||
if ( empty( $limit ) ) {
|
||||
$timers = self::$db->getPaginated( $this->tableName, $where, 'createdAt', 'DESC' );
|
||||
} else {
|
||||
$timers = self::$db->get( $this->tableName, $where, 'createdAt', 'DESC', [ 0, $limit ] );
|
||||
}
|
||||
if ( ! $timers->count() ) {
|
||||
Debug::info( 'No timers found.' );
|
||||
return [];
|
||||
}
|
||||
return $this->filter( $timers->results() );
|
||||
}
|
||||
|
||||
public function userTimers( $limit = 0 ) {
|
||||
$where = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'type', '=', 'timer' ];
|
||||
if ( empty( $limit ) ) {
|
||||
$timers = self::$db->getPaginated( $this->tableName, $where, 'createdAt', 'DESC' );
|
||||
} else {
|
||||
$timers = self::$db->get( $this->tableName, $where, 'createdAt', 'DESC', [ 0, $limit ] );
|
||||
}
|
||||
if ( ! $timers->count() ) {
|
||||
Debug::info( 'No timers found.' );
|
||||
return [];
|
||||
}
|
||||
return $this->filter( $timers->results() );
|
||||
}
|
||||
|
||||
public function userStopWatches( $limit = 0 ) {
|
||||
$where = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'type', '=', 'stopwatch' ];
|
||||
if ( empty( $limit ) ) {
|
||||
$timers = self::$db->getPaginated( $this->tableName, $where, 'createdAt', 'DESC' );
|
||||
} else {
|
||||
$timers = self::$db->get( $this->tableName, $where, 'createdAt', 'DESC', [ 0, $limit ] );
|
||||
}
|
||||
if ( ! $timers->count() ) {
|
||||
Debug::info( 'No timers found.' );
|
||||
return [];
|
||||
}
|
||||
return $this->filter( $timers->results() );
|
||||
}
|
||||
|
||||
public function create( $name, $currentSeconds, $type = 'stopwatch', $pausedAt = 0, $hours = 0, $minutes = 0, $seconds = 0 ) {
|
||||
$fields = [
|
||||
'name' => $name,
|
||||
'currentSeconds' => $currentSeconds,
|
||||
'type' => $type,
|
||||
'pausedAt' => $pausedAt,
|
||||
'hours' => $hours,
|
||||
'minutes' => $minutes,
|
||||
'seconds' => $seconds,
|
||||
'createdBy' => App::$activeUser->ID,
|
||||
'createdAt' => time(),
|
||||
];
|
||||
if ( !self::$db->insert( $this->tableName, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
return false;
|
||||
}
|
||||
return self::$db->lastId();
|
||||
}
|
||||
|
||||
public function update( $ID, $currentSeconds, $pausedAt = 0 ) {
|
||||
if ( !Check::id( $ID ) ) {
|
||||
Debug::info( 'timer: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
if ( !Check::id( $pausedAt ) ) {
|
||||
Debug::info( 'timer: illegal pausedAt.' );
|
||||
return false;
|
||||
}
|
||||
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'ID', '=', $ID ];
|
||||
$timer = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( ! $timer->count() ) {
|
||||
Debug::info( "Timer: Doesn't exist or user doesn't have access" );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'pausedAt' => $pausedAt,
|
||||
'currentSeconds' => $currentSeconds,
|
||||
'updatedAt' => time(),
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $ID, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function pause( $ID, $currentSeconds ) {
|
||||
if ( !Check::id( $ID ) ) {
|
||||
Debug::info( 'Timer: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'ID', '=', $ID ];
|
||||
$timer = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( ! $timer->count() ) {
|
||||
Debug::info( "Timer: Doesn't exist or user doesn't have access" );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'pausedAt' => time(),
|
||||
'currentSeconds' => $currentSeconds,
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $ID, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function resume( $I, $currentSecondsD ) {
|
||||
if ( !Check::id( $ID ) ) {
|
||||
Debug::info( 'Timer: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'ID', '=', $ID ];
|
||||
$timer = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( ! $timer->count() ) {
|
||||
Debug::info( "Timer: Doesn't exist or user doesn't have access" );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'pausedAt' => '',
|
||||
'currentSeconds' => $currentSeconds,
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $ID, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
44
app/plugins/timers/plugin.php
Normal file
44
app/plugins/timers/plugin.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/timers/plugin.php
|
||||
*
|
||||
* This houses all of the main plugin info and functionality.
|
||||
*
|
||||
* @package TP Timers
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Plugins;
|
||||
|
||||
use TheTempusProject\Classes\Plugin;
|
||||
|
||||
class Timers extends Plugin {
|
||||
public $pluginName = 'TP Timers';
|
||||
public $pluginAuthor = 'JoeyK';
|
||||
public $pluginWebsite = 'https://TheTempusProject.com';
|
||||
public $modelVersion = '1.0';
|
||||
public $pluginVersion = '3.0';
|
||||
public $pluginDescription = 'A simple plugin which adds various timers for tabletop gaming.';
|
||||
public $configName = 'timers';
|
||||
public $configMatrix = [
|
||||
'enabled' => [
|
||||
'type' => 'radio',
|
||||
'pretty' => 'Enable timer usage.',
|
||||
'default' => true,
|
||||
],
|
||||
];
|
||||
public $permissionMatrix = [
|
||||
'timers' => [
|
||||
'pretty' => 'Can use timers',
|
||||
'default' => true,
|
||||
],
|
||||
];
|
||||
public $main_links = [
|
||||
[
|
||||
'text' => 'Timers',
|
||||
'url' => '{ROOT_URL}timers/index',
|
||||
],
|
||||
];
|
||||
}
|
29
app/plugins/timers/views/index.html
Normal file
29
app/plugins/timers/views/index.html
Normal file
@ -0,0 +1,29 @@
|
||||
<link rel="stylesheet" href="{ROOT_URL}app/plugins/timers/css/timers.css" crossorigin="anonymous">
|
||||
<script src="{ROOT_URL}app/plugins/timers/js/timers.js" type="module" defer></script>
|
||||
|
||||
<h1 class="text-center">Timers</h1>
|
||||
<div class="container">
|
||||
<h2>Timers</h2>
|
||||
<div class="form-inline">
|
||||
<div class="form-group">
|
||||
<input type="text" id="name" class="form-control" placeholder="Name">
|
||||
<input type="text" id="hours" class="form-control" placeholder="Hours">
|
||||
<input type="text" id="minutes" class="form-control" placeholder="Minutes">
|
||||
<input type="text" id="seconds" class="form-control" placeholder="Seconds">
|
||||
<button id="addTimer" class="btn btn-primary">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
<h2>StopWatch</h2>
|
||||
<div class="form-inline">
|
||||
<div class="form-group">
|
||||
<input type="text" id="stopwatchName" class="form-control" placeholder="Name">
|
||||
<button id="addStopwatch" class="btn btn-primary">Start</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="timers" class="" style="margin-top: 20px;" role="tablist" aria-multiselectable="true">
|
||||
{timers}
|
||||
</div>
|
||||
<div id="stopWatches" class="" style="margin-top: 20px;" role="tablist" aria-multiselectable="true">
|
||||
{stopWatches}
|
||||
</div>
|
15
app/plugins/timers/views/stopwatchElement.html
Normal file
15
app/plugins/timers/views/stopwatchElement.html
Normal file
@ -0,0 +1,15 @@
|
||||
{LOOP}
|
||||
<div class="stopwatch-row">
|
||||
<span class="timer-name">{name}</span>
|
||||
<span class="timer-current">{currentSeconds}</span>
|
||||
<span class="timer-paused">{pausedAt}</span>
|
||||
<span class="timer-hours">{hours}</span>
|
||||
<span class="timer-minutes">{minutes}</span>
|
||||
<span class="timer-seconds">{seconds}</span>
|
||||
<span class="timer-id">{ID}</span>
|
||||
<span class="timer-created">{DTC}{createdAt}{/DTC}</span>
|
||||
</div>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<span class=""></span>
|
||||
{/ALT}
|
15
app/plugins/timers/views/timerElement.html
Normal file
15
app/plugins/timers/views/timerElement.html
Normal file
@ -0,0 +1,15 @@
|
||||
{LOOP}
|
||||
<div class="timer-row">
|
||||
<span class="timer-name">{name}</span>
|
||||
<span class="timer-current">{currentSeconds}</span>
|
||||
<span class="timer-paused">{pausedAt}</span>
|
||||
<span class="timer-hours">{hours}</span>
|
||||
<span class="timer-minutes">{minutes}</span>
|
||||
<span class="timer-seconds">{seconds}</span>
|
||||
<span class="timer-id">{ID}</span>
|
||||
<span class="timer-created">{DTC}{createdAt}{/DTC}</span>
|
||||
</div>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<span class=""></span>
|
||||
{/ALT}
|
Reference in New Issue
Block a user