Implement canCommitTemplate and canResetTemplate checks, added UX for commit / reset buttons (load indicator & success flash messages)
This commit is contained in:
parent
f730fc85e1
commit
7ebd8b9ffc
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use Cache;
|
use Cache;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use October\Rain\Halcyon\Model;
|
||||||
use October\Rain\Halcyon\Processors\Processor;
|
use October\Rain\Halcyon\Processors\Processor;
|
||||||
use October\Rain\Halcyon\Datasource\Datasource;
|
use October\Rain\Halcyon\Datasource\Datasource;
|
||||||
use October\Rain\Halcyon\Exception\DeleteFileException;
|
use October\Rain\Halcyon\Exception\DeleteFileException;
|
||||||
|
|
@ -33,7 +34,7 @@ class AutoDatasource extends Datasource implements DatasourceInterface
|
||||||
/**
|
/**
|
||||||
* Create a new datasource instance.
|
* 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
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct($datasources)
|
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");
|
throw new Exception("$path is deleted");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$datasourceIndex = array_keys($this->datasources)[$datasourceIndex];
|
||||||
|
|
||||||
return $this->datasources[$datasourceIndex];
|
return $this->datasources[$datasourceIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,6 +190,17 @@ class AutoDatasource extends Datasource implements DatasourceInterface
|
||||||
return $dirName . '/' . $fileName . '.' . $extension;
|
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.
|
* Returns a single template.
|
||||||
*
|
*
|
||||||
|
|
@ -249,7 +284,8 @@ class AutoDatasource extends Datasource implements DatasourceInterface
|
||||||
*/
|
*/
|
||||||
public function insert($dirName, $fileName, $extension, $content)
|
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
|
// Refresh the cache
|
||||||
$this->populateCache(true);
|
$this->populateCache(true);
|
||||||
|
|
@ -281,10 +317,12 @@ class AutoDatasource extends Datasource implements DatasourceInterface
|
||||||
$this->allowCacheRefreshes = true;
|
$this->allowCacheRefreshes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($this->datasources[0]->selectOne($dirName, $searchFileName, $searchExt))) {
|
$datasource = $this->getFirstDatasource();
|
||||||
$result = $this->datasources[0]->update($dirName, $fileName, $extension, $content, $oldFileName, $oldExtension);
|
|
||||||
|
if (!empty($datasource->selectOne($dirName, $searchFileName, $searchExt))) {
|
||||||
|
$result = $datasource->update($dirName, $fileName, $extension, $content, $oldFileName, $oldExtension);
|
||||||
} else {
|
} else {
|
||||||
$result = $this->datasources[0]->insert($dirName, $fileName, $extension, $content);
|
$result = $datasource->insert($dirName, $fileName, $extension, $content);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh the cache
|
// Refresh the cache
|
||||||
|
|
@ -305,7 +343,7 @@ class AutoDatasource extends Datasource implements DatasourceInterface
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// Delete from only the first datasource
|
// Delete from only the first datasource
|
||||||
$this->datasources[0]->delete($dirName, $fileName, $extension);
|
$this->getFirstDatasource()->delete($dirName, $fileName, $extension);
|
||||||
}
|
}
|
||||||
catch (Exception $ex) {
|
catch (Exception $ex) {
|
||||||
// Check to see if this is a valid path to delete
|
// Check to see if this is a valid path to delete
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ use Cms\Models\ThemeData;
|
||||||
use System\Models\Parameter;
|
use System\Models\Parameter;
|
||||||
use October\Rain\Halcyon\Datasource\DbDatasource;
|
use October\Rain\Halcyon\Datasource\DbDatasource;
|
||||||
use October\Rain\Halcyon\Datasource\FileDatasource;
|
use October\Rain\Halcyon\Datasource\FileDatasource;
|
||||||
|
use October\Rain\Halcyon\Datasource\DatasourceInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents the CMS theme.
|
* This class represents the CMS theme.
|
||||||
|
|
@ -514,14 +515,14 @@ class Theme
|
||||||
{
|
{
|
||||||
$enableDbLayer = Config::get('cms.enableDatabaseLayer', false);
|
$enableDbLayer = Config::get('cms.enableDatabaseLayer', false);
|
||||||
if (is_null($enableDbLayer)) {
|
if (is_null($enableDbLayer)) {
|
||||||
$enableDbLayer = !Config::get('app.debug');
|
$enableDbLayer = !Config::get('app.debug', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $enableDbLayer && App::hasDatabase();
|
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
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function registerHalyconDatasource()
|
public function registerHalyconDatasource()
|
||||||
|
|
@ -531,8 +532,8 @@ class Theme
|
||||||
if (!$resolver->hasDatasource($this->dirName)) {
|
if (!$resolver->hasDatasource($this->dirName)) {
|
||||||
if (static::databaseLayerEnabled()) {
|
if (static::databaseLayerEnabled()) {
|
||||||
$datasource = new AutoDatasource([
|
$datasource = new AutoDatasource([
|
||||||
new DbDatasource($this->dirName, 'cms_theme_contents'),
|
'database' => new DbDatasource($this->dirName, 'cms_theme_contents'),
|
||||||
new FileDatasource($this->getPath(), App::make('files')),
|
'filesystem' => new FileDatasource($this->getPath(), App::make('files')),
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
$datasource = new FileDatasource($this->getPath(), App::make('files'));
|
$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.
|
* Implements the getter functionality.
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ use Cms\Classes\Router;
|
||||||
use Cms\Classes\Layout;
|
use Cms\Classes\Layout;
|
||||||
use Cms\Classes\Partial;
|
use Cms\Classes\Partial;
|
||||||
use Cms\Classes\Content;
|
use Cms\Classes\Content;
|
||||||
|
use Cms\Classes\CmsObject;
|
||||||
use Cms\Classes\CmsCompoundObject;
|
use Cms\Classes\CmsCompoundObject;
|
||||||
use Cms\Classes\ComponentManager;
|
use Cms\Classes\ComponentManager;
|
||||||
use Cms\Classes\ComponentPartial;
|
use Cms\Classes\ComponentPartial;
|
||||||
|
|
@ -391,7 +392,7 @@ class Index extends Controller
|
||||||
/**
|
/**
|
||||||
* Commits the DB changes of a template to the filesystem
|
* Commits the DB changes of a template to the filesystem
|
||||||
*
|
*
|
||||||
* @return void
|
* @return array $response
|
||||||
*/
|
*/
|
||||||
public function onCommit()
|
public function onCommit()
|
||||||
{
|
{
|
||||||
|
|
@ -400,7 +401,9 @@ class Index extends Controller
|
||||||
$template = $this->loadTemplate($type, trim(Request::input('templatePath')));
|
$template = $this->loadTemplate($type, trim(Request::input('templatePath')));
|
||||||
|
|
||||||
if ($this->canCommitTemplate($template)) {
|
if ($this->canCommitTemplate($template)) {
|
||||||
|
// @TODO: Implement commit logic
|
||||||
|
|
||||||
|
Flash::success(Lang::get('cms::lang.editor.commit_success', ['type' => $type]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->getUpdateResponse($template, $type);
|
return $this->getUpdateResponse($template, $type);
|
||||||
|
|
@ -409,7 +412,7 @@ class Index extends Controller
|
||||||
/**
|
/**
|
||||||
* Resets a template to the version on the filesystem
|
* Resets a template to the version on the filesystem
|
||||||
*
|
*
|
||||||
* @return void
|
* @return array $response
|
||||||
*/
|
*/
|
||||||
public function onReset()
|
public function onReset()
|
||||||
{
|
{
|
||||||
|
|
@ -418,7 +421,9 @@ class Index extends Controller
|
||||||
$template = $this->loadTemplate($type, trim(Request::input('templatePath')));
|
$template = $this->loadTemplate($type, trim(Request::input('templatePath')));
|
||||||
|
|
||||||
if ($this->canResetTemplate($template)) {
|
if ($this->canResetTemplate($template)) {
|
||||||
|
// @TODO: Implement reset logic
|
||||||
|
|
||||||
|
Flash::success(Lang::get('cms::lang.editor.reset_success', ['type' => $type]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->getUpdateResponse($template, $type);
|
return $this->getUpdateResponse($template, $type);
|
||||||
|
|
@ -435,7 +440,7 @@ class Index extends Controller
|
||||||
* @param string $type The type of template being affected
|
* @param string $type The type of template being affected
|
||||||
* @return array $result;
|
* @return array $result;
|
||||||
*/
|
*/
|
||||||
protected function getUpdateResponse($template, $type)
|
protected function getUpdateResponse(CmsObject $template, string $type)
|
||||||
{
|
{
|
||||||
$result = [
|
$result = [
|
||||||
'templatePath' => $template->fileName,
|
'templatePath' => $template->fileName,
|
||||||
|
|
@ -458,16 +463,20 @@ class Index extends Controller
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if the provided template can be committed
|
* 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
|
* @param CmsObject $template
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
protected function canCommitTemplate($template)
|
protected function canCommitTemplate(CmsObject $template)
|
||||||
{
|
{
|
||||||
$result = true; // will set to false by default
|
$result = false;
|
||||||
|
|
||||||
if (Theme::databaseLayerEnabled()) {
|
|
||||||
|
|
||||||
|
if (Config::get('app.debug', false) &&
|
||||||
|
Theme::databaseLayerEnabled() &&
|
||||||
|
Theme::getActiveTheme()->getDatasource()->sourceHasModel('database', $template)
|
||||||
|
) {
|
||||||
|
$result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
|
@ -475,16 +484,18 @@ class Index extends Controller
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if the provided template can be reset
|
* 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
|
* @param CmsObject $template
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
protected function canResetTemplate($template)
|
protected function canResetTemplate(CmsObject $template)
|
||||||
{
|
{
|
||||||
$result = true; // will set to false by default
|
$result = false;
|
||||||
|
|
||||||
if (Theme::databaseLayerEnabled()) {
|
if (Theme::databaseLayerEnabled()) {
|
||||||
|
$datasource = Theme::getActiveTheme()->getDatasource();
|
||||||
|
$result = $datasource->sourceHasModel('database', $template) && $datasource->sourceHasModel('filesystem', $template);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
class="btn btn-danger oc-icon-download <?php if (!$canCommit): ?>hide<?php endif ?>"
|
class="btn btn-danger oc-icon-download <?php if (!$canCommit): ?>hide<?php endif ?>"
|
||||||
data-request="onCommit"
|
data-request="onCommit"
|
||||||
data-request-confirm="<?= e(trans('cms::lang.editor.commit_confirm')) ?>"
|
data-request-confirm="<?= e(trans('cms::lang.editor.commit_confirm')) ?>"
|
||||||
|
data-load-indicator="<?= e(trans('cms::lang.editor.committing')) ?>"
|
||||||
data-control="commit-button">
|
data-control="commit-button">
|
||||||
<?= e(trans('cms::lang.editor.commit')) ?>
|
<?= e(trans('cms::lang.editor.commit')) ?>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -12,6 +13,7 @@
|
||||||
class="btn btn-danger oc-icon-bomb <?php if (!$canReset): ?>hide<?php endif ?>"
|
class="btn btn-danger oc-icon-bomb <?php if (!$canReset): ?>hide<?php endif ?>"
|
||||||
data-request="onReset"
|
data-request="onReset"
|
||||||
data-request-confirm="<?= e(trans('cms::lang.editor.reset_confirm')) ?>"
|
data-request-confirm="<?= e(trans('cms::lang.editor.reset_confirm')) ?>"
|
||||||
|
data-load-indicator="<?= e(trans('cms::lang.editor.resetting')) ?>"
|
||||||
data-control="reset-button">
|
data-control="reset-button">
|
||||||
<?= e(trans('cms::lang.editor.reset')) ?>
|
<?= e(trans('cms::lang.editor.reset')) ?>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -186,10 +186,14 @@ return [
|
||||||
'close_searchbox' => 'Close Search box',
|
'close_searchbox' => 'Close Search box',
|
||||||
'open_replacebox' => 'Open Replace box',
|
'open_replacebox' => 'Open Replace box',
|
||||||
'close_replacebox' => 'Close Replace box',
|
'close_replacebox' => 'Close Replace box',
|
||||||
'reset' => 'Reset',
|
|
||||||
'commit' => 'Commit',
|
'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',
|
'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' => [
|
'asset' => [
|
||||||
'menu_label' => 'Assets',
|
'menu_label' => 'Assets',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue