Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More control of CRUD interface elements #669

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/ngrest/base/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* Base Controller for all NgRest Controllers.
*
* @property NgRestModel $model The model based from the modelClass instance
* @property string $description A text descirption for the CRUD which is display below the CRUD title
* @property string $description A text description for the CRUD which is display below the CRUD title
*
* @author Basil Suter <basil@nadar.io>
* @since 1.0.0
Expand Down Expand Up @@ -175,7 +175,7 @@ public function getModel()

return $this->_model;
}

/**
* Render the ngrest default index template.
*
Expand All @@ -184,10 +184,11 @@ public function getModel()
* @param string $arrayIndex
* @param string $modelClass
* @param string $modelSelection
* @param string|bool|array $interfaceSettings
* @throws Exception
* @return string
*/
public function actionIndex($inline = false, $relation = false, $arrayIndex = false, $modelClass = false, $modelSelection = false)
public function actionIndex($inline = false, $relation = false, $arrayIndex = false, $modelClass = false, $modelSelection = false, $interfaceSettings = true)
{
$apiEndpoint = $this->model->ngRestApiEndpoint();

Expand All @@ -211,6 +212,7 @@ public function actionIndex($inline = false, $relation = false, $arrayIndex = fa
// generate crud renderer
$crud = Yii::createObject($this->renderCrud);
$crud->description = $this->description;
$crud->setInterfaceSettings($interfaceSettings);
$crud->setModel($this->model);
$crud->setSettingButtonDefinitions($this->globalButtons);
$crud->setIsInline($inline);
Expand Down
137 changes: 137 additions & 0 deletions src/ngrest/render/RenderCrud.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,47 @@ class RenderCrud extends Render implements ViewContextInterface, RenderCrudInter

const TYPE_UPDATE = 'update';


/**
* Interface constants
*/

/**
* @const string Name of the parameter responsible for displaying CRUD Title.
*/
const INTERFACE_TITLE = 'title';

/**
* @const string Name of the parameter responsible for displaying CRUD Description.
*/
const INTERFACE_DESCRIPTION = 'description';

/**
* @const string Name of the parameter responsible for displaying CRUD Global Buttons.
*/
const INTERFACE_GLOBALBUTTONS = 'globalbuttons';

/**
* @const string Name of the parameter responsible for displaying CRUD Search input field.
*/
const INTERFACE_SEARCH = 'search';

/**
* @const string Name of the parameter responsible for displaying CRUD Group dropdown field.
*/
const INTERFACE_GROUP = 'group';

/**
* @const string Name of the parameter responsible for displaying CRUD Filter dropdown field.
*/
const INTERFACE_FILTER = 'filter';

/**
* @const string Name of the parameter responsible for displaying CRUD Items counter.
*/
const INTERFACE_COUNTER = 'counter';


/**
* @var string A description for the CRUD Title which is display below the title.
* @since 3.2.0
Expand Down Expand Up @@ -261,6 +302,102 @@ public function setSettingButtonDefinitions(array $buttons)
$this->_settingButtonDefinitions= $elements;
}


/**
* @var array
*/
private $_interfaceSettings = true;

/**
* @inheritdoc
*/
public function getInterfaceSettings()
{
return $this->_interfaceSettings;
}

/**
* Setter method for CRUD interface settings.
*
* Can accept boolean, string or array.
*
* Boolean:
* `true` - show everything, `false` - hide everything (except CRUD data itself)
*
* String:
* `minimal` - Only table title and items counter are shown.
* `modest` - Title, description, search & filter inputs, and items counter are shown.
* Any other string (include empty string) - show everything.
*
* Array:
* Shows only those interface elements, the names of which are specified in the array as keys, and the values are true (or similar).
* Accordingly, for an empty array, all elements will be hidden.
*
* @param bool|array|string $interfaceSettings
* @since 5.0.0
*/
public function setInterfaceSettings($interfaceSettings)
{
$noInterface = [
self::INTERFACE_TITLE => false,
self::INTERFACE_DESCRIPTION => false,
self::INTERFACE_GLOBALBUTTONS => false,
self::INTERFACE_SEARCH => false,
self::INTERFACE_GROUP => false,
self::INTERFACE_FILTER => false,
self::INTERFACE_COUNTER => false
];

$fullInterface = [
self::INTERFACE_TITLE => true,
self::INTERFACE_DESCRIPTION => true,
self::INTERFACE_GLOBALBUTTONS => true,
self::INTERFACE_SEARCH => true,
self::INTERFACE_GROUP => true,
self::INTERFACE_FILTER => true,
self::INTERFACE_COUNTER => true
];

if (is_array($interfaceSettings)) {
// Array input
$outputSettings = array_merge($noInterface, array_intersect_key($interfaceSettings, $noInterface));
} else {
if (is_string($interfaceSettings)) {
$outputSettings = $noInterface;
switch ($interfaceSettings) {
case 'minimal':
$outputSettings[self::INTERFACE_TITLE] = true;
$outputSettings[self::INTERFACE_COUNTER] = true;
break;
case 'modest':
$outputSettings[self::INTERFACE_TITLE] = true;
$outputSettings[self::INTERFACE_DESCRIPTION] = true;
$outputSettings[self::INTERFACE_SEARCH] = true;
$outputSettings[self::INTERFACE_FILTER] = true;
$outputSettings[self::INTERFACE_COUNTER] = true;
break;

default:
$outputSettings = $fullInterface;
break;
}
} else {
if ($interfaceSettings) {
// All on
$outputSettings = $fullInterface;
} else {
// All off
$outputSettings = $noInterface;
}

}
}

$this->_interfaceSettings = $outputSettings;
}



/**
* Indicates whether the current plugin config is sortable or not.
*
Expand Down
20 changes: 19 additions & 1 deletion src/ngrest/render/RenderCrudInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,22 @@ public function canDelete();
* @since 2.0.0
*/
public function getActivePoolConfig();
}


/**
* Returns the configuration of CRUD interface.
*
* @return array Determine what parts of CRUD interface will be displayed.
* @since 5.0.0
*/
public function getInterfaceSettings();

/**
* Setter method for CRUD interface settings
*
* @param bool|array|string $interfaceSettings
* @since 5.0.0
*/
public function setInterfaceSettings($interfaceSettings);

}
6 changes: 5 additions & 1 deletion src/resources/dist/main.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/resources/scss/components/_crud.scss
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
}

.crud-toolbar {
margin-left: auto;
.btn-group {
.btn {
border-radius: $border-radius !important;
Expand Down
82 changes: 53 additions & 29 deletions src/views/ngrest/crud.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
}
$filters = ArrayHelper::combine(array_keys($config->getFilters()));
$filters = Angular::optionsArrayInput($filters);

$interface = $this->context->getInterfaceSettings();
?>
<?php $this->registerAngularControllerScript(); ?>
<div ng-controller="<?= $config->hash; ?>" class="crud">
Expand All @@ -33,7 +35,9 @@
<?php if (!$relationCall): ?>
<?php if (!$isInline): ?>
<div class="crud-header">
<?php if ($interface[RenderCrud::INTERFACE_TITLE]): ?>
<h1 class="crud-title"><?= $currentMenu['alias']; ?></h1>
<?php endif; ?>
<modal is-modal-hidden="isExportModalHidden" modal-title="<?= Module::t('crud_exportdata_btn'); ?>">
<div ng-if="!isExportModalHidden">
<?php if (!empty($filters)): ?>
Expand All @@ -46,32 +50,34 @@
<button ng-show="exportResponse" type="button" class="btn btn-icon btn-download" ng-click="downloadExport()"><?= Module::t('crud_exportdata_btn_downloadexport'); ?></button>
</div>
</modal>
<div class="crud-toolbar">
<div class="btn-group" ng-class="{'show': isSettingsVisible}">
<button class="btn btn-toolbar" type="button" ng-click="toggleSettingsMenu()">
<i class="material-icons">more_vert</i>
</button>
<div class="dropdown-menu dropdown-menu-right" ng-class="{'show': isSettingsVisible}">
<a class="dropdown-item" ng-click="toggleExportModal()">
<i class="material-icons">get_app</i><span><?= Module::t('crud_exportdata_btn'); ?></span>
</a>
<a class="dropdown-item" ng-click="toggleNotificationMute()">
<span ng-show="serviceResponse._notifcation_mute_state">
<i class="material-icons">visibility</i><span><?= Module::t('crud_notification_enable'); ?></span>
</span>
<span ng-show="!serviceResponse._notifcation_mute_state">
<i class="material-icons">visibility_off</i><span><?= Module::t('crud_notification_disable'); ?></span>
</span>
</a>
<?php foreach ($this->context->getSettingButtonDefinitions() as $button): ?>
<?= $button; ?>
<?php endforeach; ?>
<?php if ($interface[RenderCrud::INTERFACE_GLOBALBUTTONS]): ?>
<div class="crud-toolbar">
<div class="btn-group" ng-class="{'show': isSettingsVisible}">
<button class="btn btn-toolbar" type="button" ng-click="toggleSettingsMenu()">
<i class="material-icons">more_vert</i>
</button>
<div class="dropdown-menu dropdown-menu-right" ng-class="{'show': isSettingsVisible}">
<a class="dropdown-item" ng-click="toggleExportModal()">
<i class="material-icons">get_app</i><span><?= Module::t('crud_exportdata_btn'); ?></span>
</a>
<a class="dropdown-item" ng-click="toggleNotificationMute()">
<span ng-show="serviceResponse._notifcation_mute_state">
<i class="material-icons">visibility</i><span><?= Module::t('crud_notification_enable'); ?></span>
</span>
<span ng-show="!serviceResponse._notifcation_mute_state">
<i class="material-icons">visibility_off</i><span><?= Module::t('crud_notification_disable'); ?></span>
</span>
</a>
<?php foreach ($this->context->getSettingButtonDefinitions() as $button): ?>
<?= $button; ?>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
<?php endif; ?>
</div>
<?php if ($this->context->description): ?>
<p class="text-muted"><?= Markdown::processParagraph($this->context->description); ?></p>
<?php if ($interface[RenderCrud::INTERFACE_DESCRIPTION] && $this->context->description): ?>
<p class="text-muted"><?= Markdown::processParagraph($this->context->description); ?></p>
<?php endif; ?>
<?php endif; ?>
<ul class="nav nav-tabs nav-tabs-mobile-icons">
Expand Down Expand Up @@ -123,8 +129,20 @@
<div class="tab-pane" ng-if="crudSwitchType==0" ng-class="{'active' : crudSwitchType==0}">
<div class="tab-padded">
<div class="row mt-2">
<div class="col-md-4 col-lg-6 col-xl-6 col-xxxl-8">
<div class="input-group input-group--append-clickable mb-2 mr-sm-2 mb-sm-0">
<?php
// Variable width of search field and group & filter selects
$_gfBasicWidth = 3 - (int)$interface[RenderCrud::INTERFACE_GROUP] - (int) ($interface[RenderCrud::INTERFACE_FILTER] && !empty($config->getFilters()));
$_gfw2 = 2*$_gfBasicWidth;
$_gfw3 = 3*$_gfBasicWidth;
$_gfw4 = 4*$_gfBasicWidth;
$_sew4 = ($_gfBasicWidth === 3 ? 12 : 4);
$_sew6 = ($_gfBasicWidth === 3 ? 12 : 6);
$_sew8 = ($_gfBasicWidth === 3 ? 12 : 8);
?>

<div class="col-md-<?=$_sew4?> col-lg-<?=$_sew6?> col-xl-<?=$_sew6?> col-xxxl-<?=$_sew8?>">
<?php if ($interface[RenderCrud::INTERFACE_SEARCH]): ?>
<div class="input-group input-group--append-clickable mb-2 mr-sm-2 mb-md-0">
<div class="input-group-prepend">
<div class="input-group-text">
<i class="material-icons">search</i>
Expand All @@ -137,12 +155,16 @@
</div>
</span>
</div>
<?php endif; ?>
</div>
<div class="col-md-4 col-lg-3 col-xl-3 col-xxxl-2">

<?php if ($interface[RenderCrud::INTERFACE_GROUP]): ?>
<div class="col-md-<?=$_gfw4?> col-lg-<?=$_gfw3?> col-xl-<?=$_gfw3?> col-xxxl-<?=$_gfw2?> mb-2 mb-md-0">
<luya-select ng-model="config.groupByField" initvalue="0" ng-change="changeGroupByField()" options='<?= Json::htmlEncode(Angular::optionsArrayInput($groups)); ?>'></luya-select>
</div>
<?php if (!empty($config->getFilters())): ?>
<div class="col-md-4 col-lg-3 col-xl-3 col-xxxl-2">
<?php endif; ?>
<?php if ($interface[RenderCrud::INTERFACE_FILTER] && !empty($config->getFilters())): ?>
<div class="col-md-<?=$_gfw4?> col-lg-<?=$_gfw3?> col-xl-<?=$_gfw3?> col-xxxl-<?=$_gfw2?>">
<luya-select ng-model="config.filter" initvalue="0" ng-change="changeNgRestFilter()" options='<?= Json::htmlEncode($filters); ?>'></luya-select>
</div>
<?php endif; ?>
Expand All @@ -160,8 +182,10 @@
<span><?= Module::t('ngrest_crud_btn_add'); ?></span>
</button>
<?php endif; ?>
<?php if ($interface[RenderCrud::INTERFACE_COUNTER]): ?>
<small class="crud-counter"><?= Module::t('ngrest_crud_total_count'); ?></small>
<div class="table-responsive">
<?php endif; ?>
<div class="table-responsive <?=$interface[RenderCrud::INTERFACE_COUNTER] ? '' : 'mt-4'?>">
<table class="table table-hover table-align-middle table-striped table-crud">
<thead class="thead-default">
<tr>
Expand Down
Loading