Implement canCommitTemplate and canResetTemplate checks, added UX for commit / reset buttons (load indicator & success flash messages)

This commit is contained in:
Luke Towers 2018-11-23 11:07:36 -06:00
parent f730fc85e1
commit 7ebd8b9ffc
5 changed files with 93 additions and 26 deletions

View File

@ -2,6 +2,7 @@
use Cache;
use Exception;
use October\Rain\Halcyon\Model;
use October\Rain\Halcyon\Processors\Processor;
use October\Rain\Halcyon\Datasource\Datasource;
use October\Rain\Halcyon\Exception\DeleteFileException;
@ -33,7 +34,7 @@ class AutoDatasource extends Datasource implements DatasourceInterface
/**
* Create a new datasource instance.
*
* @param array $datasources Array of datasources to utilize. Lower indexes = higher priority
* @param array $datasources Array of datasources to utilize. Lower indexes = higher priority ['datasourceName' => $datasource]
* @return void
*/
public function __construct($datasources)
@ -69,13 +70,34 @@ class AutoDatasource extends Datasource implements DatasourceInterface
}
/**
* Returns the datasource instances being used internally
* Check to see if the specified datasource has the provided Halcyon Model
*
* @return array
* @param string $source The string key of the datasource to check
* @param Model $model The Halcyon Model to check for
* @return boolean
*/
public function getDatasources()
public function sourceHasModel(string $source, Model $model)
{
return $this->datasources;
$result = false;
$keys = array_keys($this->datasources);
if (in_array($source, $keys)) {
// Get the datasource's cache index key
$cacheIndex = array_search($source, $keys);
// Generate the path
list($name, $extension) = $model->getFileNameParts();
$path = $this->makeFilePath($model->getObjectTypeDirName(), $name, $extension);
// Deleted paths are included as being handled by a datasource
// The functionality built on this will need to make sure they
// include deleted records when actually performing sycning actions
if (isset($this->pathCache[$cacheIndex][$path])) {
$result = true;
}
}
return $result;
}
/**
@ -107,6 +129,8 @@ class AutoDatasource extends Datasource implements DatasourceInterface
throw new Exception("$path is deleted");
}
$datasourceIndex = array_keys($this->datasources)[$datasourceIndex];
return $this->datasources[$datasourceIndex];
}
@ -166,6 +190,17 @@ class AutoDatasource extends Datasource implements DatasourceInterface
return $dirName . '/' . $fileName . '.' . $extension;
}
/**
* Get the first datasource for use with CRUD operations
*
* @return DatasourceInterface
*/
protected function getFirstDatasource()
{
$keys = array_keys($this->datasources);
return $this->datasources[$keys[0]];
}
/**
* Returns a single template.
*
@ -249,7 +284,8 @@ class AutoDatasource extends Datasource implements DatasourceInterface
*/
public function insert($dirName, $fileName, $extension, $content)
{
$result = $this->datasources[0]->insert($dirName, $fileName, $extension, $content);
// Insert only on the first datasource
$result = $this->getFirstDatasource()->insert($dirName, $fileName, $extension, $content);
// Refresh the cache
$this->populateCache(true);
@ -281,10 +317,12 @@ class AutoDatasource extends Datasource implements DatasourceInterface
$this->allowCacheRefreshes = true;
}
if (!empty($this->datasources[0]->selectOne($dirName, $searchFileName, $searchExt))) {
$result = $this->datasources[0]->update($dirName, $fileName, $extension, $content, $oldFileName, $oldExtension);
$datasource = $this->getFirstDatasource();
if (!empty($datasource->selectOne($dirName, $searchFileName, $searchExt))) {
$result = $datasource->update($dirName, $fileName, $extension, $content, $oldFileName, $oldExtension);
} else {
$result = $this->datasources[0]->insert($dirName, $fileName, $extension, $content);
$result = $datasource->insert($dirName, $fileName, $extension, $content);
}
// Refresh the cache
@ -305,7 +343,7 @@ class AutoDatasource extends Datasource implements DatasourceInterface
{
try {
// Delete from only the first datasource
$this->datasources[0]->delete($dirName, $fileName, $extension);
$this->getFirstDatasource()->delete($dirName, $fileName, $extension);
}
catch (Exception $ex) {
// Check to see if this is a valid path to delete

View File

@ -16,6 +16,7 @@ use Cms\Models\ThemeData;
use System\Models\Parameter;
use October\Rain\Halcyon\Datasource\DbDatasource;
use October\Rain\Halcyon\Datasource\FileDatasource;
use October\Rain\Halcyon\Datasource\DatasourceInterface;
/**
* This class represents the CMS theme.
@ -514,14 +515,14 @@ class Theme
{
$enableDbLayer = Config::get('cms.enableDatabaseLayer', false);
if (is_null($enableDbLayer)) {
$enableDbLayer = !Config::get('app.debug');
$enableDbLayer = !Config::get('app.debug', false);
}
return $enableDbLayer && App::hasDatabase();
}
/**
* Ensures this theme is registered as a Halcyon them datasource.
* Ensures this theme is registered as a Halcyon datasource.
* @return void
*/
public function registerHalyconDatasource()
@ -531,8 +532,8 @@ class Theme
if (!$resolver->hasDatasource($this->dirName)) {
if (static::databaseLayerEnabled()) {
$datasource = new AutoDatasource([
new DbDatasource($this->dirName, 'cms_theme_contents'),
new FileDatasource($this->getPath(), App::make('files')),
'database' => new DbDatasource($this->dirName, 'cms_theme_contents'),
'filesystem' => new FileDatasource($this->getPath(), App::make('files')),
]);
} else {
$datasource = new FileDatasource($this->getPath(), App::make('files'));
@ -542,6 +543,17 @@ class Theme
}
}
/**
* Get the theme's datasource
*
* @return DatasourceInterface
*/
public function getDatasource()
{
$resolver = App::make('halcyon');
return $resolver->datasource($this->getDirName());
}
/**
* Implements the getter functionality.
* @param string $name

View File

@ -16,6 +16,7 @@ use Cms\Classes\Router;
use Cms\Classes\Layout;
use Cms\Classes\Partial;
use Cms\Classes\Content;
use Cms\Classes\CmsObject;
use Cms\Classes\CmsCompoundObject;
use Cms\Classes\ComponentManager;
use Cms\Classes\ComponentPartial;
@ -391,7 +392,7 @@ class Index extends Controller
/**
* Commits the DB changes of a template to the filesystem
*
* @return void
* @return array $response
*/
public function onCommit()
{
@ -400,7 +401,9 @@ class Index extends Controller
$template = $this->loadTemplate($type, trim(Request::input('templatePath')));
if ($this->canCommitTemplate($template)) {
// @TODO: Implement commit logic
Flash::success(Lang::get('cms::lang.editor.commit_success', ['type' => $type]));
}
return $this->getUpdateResponse($template, $type);
@ -409,7 +412,7 @@ class Index extends Controller
/**
* Resets a template to the version on the filesystem
*
* @return void
* @return array $response
*/
public function onReset()
{
@ -418,7 +421,9 @@ class Index extends Controller
$template = $this->loadTemplate($type, trim(Request::input('templatePath')));
if ($this->canResetTemplate($template)) {
// @TODO: Implement reset logic
Flash::success(Lang::get('cms::lang.editor.reset_success', ['type' => $type]));
}
return $this->getUpdateResponse($template, $type);
@ -435,7 +440,7 @@ class Index extends Controller
* @param string $type The type of template being affected
* @return array $result;
*/
protected function getUpdateResponse($template, $type)
protected function getUpdateResponse(CmsObject $template, string $type)
{
$result = [
'templatePath' => $template->fileName,
@ -458,16 +463,20 @@ class Index extends Controller
/**
* Check to see if the provided template can be committed
* Only available in debug mode, the DB layer must be enabled, and the template must exist in the database
*
* @param CmsObject $template
* @return boolean
*/
protected function canCommitTemplate($template)
protected function canCommitTemplate(CmsObject $template)
{
$result = true; // will set to false by default
if (Theme::databaseLayerEnabled()) {
$result = false;
if (Config::get('app.debug', false) &&
Theme::databaseLayerEnabled() &&
Theme::getActiveTheme()->getDatasource()->sourceHasModel('database', $template)
) {
$result = true;
}
return $result;
@ -475,16 +484,18 @@ class Index extends Controller
/**
* Check to see if the provided template can be reset
* Only available when the DB layer is enabled and the template exists in both the DB & Filesystem
*
* @param CmsObject $template
* @return boolean
*/
protected function canResetTemplate($template)
protected function canResetTemplate(CmsObject $template)
{
$result = true; // will set to false by default
$result = false;
if (Theme::databaseLayerEnabled()) {
$datasource = Theme::getActiveTheme()->getDatasource();
$result = $datasource->sourceHasModel('database', $template) && $datasource->sourceHasModel('filesystem', $template);
}
return $result;

View File

@ -3,6 +3,7 @@
class="btn btn-danger oc-icon-download <?php if (!$canCommit): ?>hide<?php endif ?>"
data-request="onCommit"
data-request-confirm="<?= e(trans('cms::lang.editor.commit_confirm')) ?>"
data-load-indicator="<?= e(trans('cms::lang.editor.committing')) ?>"
data-control="commit-button">
<?= e(trans('cms::lang.editor.commit')) ?>
</button>
@ -12,6 +13,7 @@
class="btn btn-danger oc-icon-bomb <?php if (!$canReset): ?>hide<?php endif ?>"
data-request="onReset"
data-request-confirm="<?= e(trans('cms::lang.editor.reset_confirm')) ?>"
data-load-indicator="<?= e(trans('cms::lang.editor.resetting')) ?>"
data-control="reset-button">
<?= e(trans('cms::lang.editor.reset')) ?>
</button>

View File

@ -186,10 +186,14 @@ return [
'close_searchbox' => 'Close Search box',
'open_replacebox' => 'Open Replace box',
'close_replacebox' => 'Close Replace box',
'reset' => 'Reset',
'commit' => 'Commit',
'reset_confirm' => 'Are you sure you want to reset this file to the copy that is on the filesystem? This will completely replace it with the file that is on the filesystem',
'reset' => 'Reset',
'commit_confirm' => 'Are you sure you want to commit your changes to this file to the filesystem? This will overwrite the existing file on the filesystem',
'reset_confirm' => 'Are you sure you want to reset this file to the copy that is on the filesystem? This will completely replace it with the file that is on the filesystem',
'committing' => 'Committing',
'resetting' => 'Resetting',
'commit_success' => 'The :type has been committed to the filesystem',
'reset_success' => 'The :type has been reset to the filesystem version',
],
'asset' => [
'menu_label' => 'Assets',