Skip to content

Commit

Permalink
Merge pull request #31583 from colemanw/searchKitAddRow
Browse files Browse the repository at this point in the history
SearchKit - Add 'whole row' and 'add row' editable features
  • Loading branch information
colemanw authored Dec 31, 2024
2 parents 729a2b6 + 5046372 commit 12788aa
Show file tree
Hide file tree
Showing 25 changed files with 654 additions and 143 deletions.
17 changes: 17 additions & 0 deletions CRM/Utils/String.php
Original file line number Diff line number Diff line change
Expand Up @@ -1114,4 +1114,21 @@ public static function getSquareTokens(string $raw): array {
return $tokens;
}

public static function isQuotedString($value): bool {
return is_string($value) && strlen($value) > 1 && $value[0] === $value[-1] && in_array($value[0], ['"', "'"]);
}

public static function unquoteString(string $string): string {
// Strip the outer quotes if the string starts and ends with the same quote type
if (self::isQuotedString($string)) {
$string = substr($string, 1, -1);

// Replace escaped quotes with unescaped quotes, avoiding escaped backslashes
$string = preg_replace('/(?<!\\\\)\\\\\\"/', '"', $string);
$string = preg_replace('/(?<!\\\\)\\\\\\\'/', "'", $string);
}

return $string;
}

}
3 changes: 3 additions & 0 deletions ext/civicrm_admin_ui/ang/afsearchCustomFieldOptions.aff.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div af-fieldset="">
<crm-search-display-table search-name="Administer_Custom_Field_Options" display-name="Administer_Custom_Field_Options" filters="{option_group_id: routeParams.option_group_id}"></crm-search-display-table>
</div>
9 changes: 9 additions & 0 deletions ext/civicrm_admin_ui/ang/afsearchCustomFieldOptions.aff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
use CRM_CivicrmAdminUi_ExtensionUtil as E;

return [
'type' => 'search',
'title' => E::ts('Custom Field Options'),
'icon' => 'fa-list-ol',
'server_route' => 'civicrm/admin/custom/group/field/options',
];
37 changes: 37 additions & 0 deletions ext/civicrm_admin_ui/civicrm_admin_ui.civix.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,47 @@ public static function findClass($suffix) {
return self::CLASS_PREFIX . '_' . str_replace('\\', '_', $suffix);
}

/**
* @return \CiviMix\Schema\SchemaHelperInterface
*/
public static function schema() {
if (!isset($GLOBALS['CiviMixSchema'])) {
pathload()->loadPackage('civimix-schema@5', TRUE);
}
return $GLOBALS['CiviMixSchema']->getHelper(static::LONG_NAME);
}

}

use CRM_CivicrmAdminUi_ExtensionUtil as E;

($GLOBALS['_PathLoad'][0] ?? require __DIR__ . '/mixin/lib/pathload-0.php');
pathload()->addSearchDir(__DIR__ . '/mixin/lib');
spl_autoload_register('_civicrm_admin_ui_civix_class_loader', TRUE, TRUE);

function _civicrm_admin_ui_civix_class_loader($class) {
if ($class === 'CRM_CivicrmAdminUi_DAO_Base') {
if (version_compare(CRM_Utils_System::version(), '5.74.beta', '>=')) {
class_alias('CRM_Core_DAO_Base', 'CRM_CivicrmAdminUi_DAO_Base');
// ^^ Materialize concrete names -- encourage IDE's to pick up on this association.
}
else {
$realClass = 'CiviMix\\Schema\\CivicrmAdminUi\\DAO';
class_alias($realClass, $class);
// ^^ Abstract names -- discourage IDE's from picking up on this association.
}
return;
}

// This allows us to tap-in to the installation process (without incurring real file-reads on typical requests).
if (strpos($class, 'CiviMix\\Schema\\CivicrmAdminUi\\') === 0) {
// civimix-schema@5 is designed for backported use in download/activation workflows,
// where new revisions may become dynamically available.
pathload()->loadPackage('civimix-schema@5', TRUE);
CiviMix\Schema\loadClass($class);
}
}

/**
* (Delegated) Implements hook_civicrm_config().
*
Expand Down
4 changes: 2 additions & 2 deletions ext/civicrm_admin_ui/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
<civix>
<namespace>CRM/CivicrmAdminUi</namespace>
<angularModule>crmCivicrmAdminUi</angularModule>
<format>23.02.1</format>
<format>24.09.1</format>
</civix>
<mixins>
<mixin>[email protected]</mixin>
<mixin>[email protected]</mixin>
</mixins>
<upgrader>CRM_CivicrmAdminUi_Upgrader</upgrader>
<upgrader>CiviMix\Schema\CivicrmAdminUi\AutomaticUpgrader</upgrader>
</extension>
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php
use CRM_CivicrmAdminUi_ExtensionUtil as E;

return [
[
'name' => 'SavedSearch_Administer_Custom_Field_Options',
'entity' => 'SavedSearch',
'cleanup' => 'unused',
'update' => 'unmodified',
'params' => [
'version' => 4,
'values' => [
'name' => 'Administer_Custom_Field_Options',
'label' => E::ts('Administer Custom Field Options'),
'api_entity' => 'OptionValue',
'api_params' => [
'version' => 4,
'select' => [
'label',
'value',
'description',
'option_group_id:label',
],
'orderBy' => [],
'where' => [],
'groupBy' => [],
'join' => [],
'having' => [],
],
],
'match' => ['name'],
],
],
[
'name' => 'SavedSearch_Administer_Custom_Field_Options_SearchDisplay_Administer_Custom_Field_Options',
'entity' => 'SearchDisplay',
'cleanup' => 'unused',
'update' => 'unmodified',
'params' => [
'version' => 4,
'values' => [
'name' => 'Administer_Custom_Field_Options',
'label' => E::ts('Administer Custom Field Options'),
'saved_search_id.name' => 'Administer_Custom_Field_Options',
'type' => 'table',
'settings' => [
'description' => E::ts(''),
'sort' => [],
'limit' => 50,
'pager' => [
'show_count' => TRUE,
'expose_limit' => TRUE,
'hide_single' => TRUE,
],
'placeholder' => 5,
'cssRules' => [
[
'disabled',
'is_active',
'=',
FALSE,
],
],
'columns' => [
[
'type' => 'field',
'key' => 'label',
'dataType' => 'String',
'label' => E::ts('Option Label'),
'sortable' => TRUE,
'editable' => TRUE,
],
[
'type' => 'field',
'key' => 'value',
'dataType' => 'String',
'label' => E::ts('Option Value'),
'sortable' => TRUE,
],
[
'type' => 'field',
'key' => 'description',
'dataType' => 'Text',
'label' => E::ts('Option Description'),
'sortable' => TRUE,
'show_linebreaks' => FALSE,
'editable' => TRUE,
],
[
'text' => '',
'style' => 'default',
'size' => 'btn-xs',
'icon' => 'fa-bars',
'links' => [
[
'entity' => 'OptionValue',
'action' => 'update',
'join' => '',
'target' => 'crm-popup',
'icon' => 'fa-pencil',
'text' => E::ts('Edit'),
'style' => 'default',
'path' => '',
'condition' => [],
],
[
'task' => 'enable',
'entity' => 'OptionValue',
'target' => 'crm-popup',
'icon' => 'fa-toggle-on',
'text' => E::ts('Enable'),
'style' => 'default',
'condition' => [],
],
[
'task' => 'disable',
'entity' => 'OptionValue',
'target' => 'crm-popup',
'icon' => 'fa-toggle-off',
'text' => E::ts('Disable'),
'style' => 'default',
'condition' => [],
],
[
'entity' => 'OptionValue',
'action' => 'delete',
'join' => '',
'target' => 'crm-popup',
'icon' => 'fa-trash',
'text' => E::ts('Delete'),
'style' => 'danger',
'path' => '',
'condition' => [],
],
],
'type' => 'menu',
'alignment' => 'text-right',
],
],
'actions' => FALSE,
'editableRow' => [
'create' => TRUE,
'createLabel' => E::ts('Add Option'),
],
'classes' => ['table', 'table-striped'],
'draggable' => 'weight',
],
],
'match' => [
'saved_search_id',
'name',
],
],
],
];
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@
'icon' => 'fa-list-ol',
'text' => E::ts('Multiple Choice Options'),
'style' => 'default',
'path' => 'civicrm/admin/custom/group/field/option?reset=1&action=browse&gid=[custom_group_id]&fid=[id]',
'path' => 'civicrm/admin/custom/group/field/options#?option_group_id=[option_group_id]',
'condition' => [
'option_group_id:label',
'option_group_id:name',
'IS NOT EMPTY',
],
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ protected function formatResult(iterable $result): array {
$data[$key] = $this->getValue($key, $record, $index);
}
foreach ($this->display['settings']['columns'] as $column) {
$columns[] = $this->formatColumn($column, $data);
$columns[] = $this->formatColumn($column, $data, $this->display['settings']);
}
$row = [
'data' => $data,
Expand Down Expand Up @@ -232,9 +232,10 @@ private function generateFileUrl($fileID) {
/**
* @param array $column
* @param array $data
* @param array $settings
* @return array{val: mixed, links: array, edit: array, label: string, title: string, image: array, cssClass: string}
*/
private function formatColumn($column, $data) {
private function formatColumn(array $column, array $data, array $settings) {
$column += ['rewrite' => NULL, 'label' => NULL, 'key' => ''];
$out = [];
switch ($column['type']) {
Expand Down Expand Up @@ -262,11 +263,11 @@ private function formatColumn($column, $data) {
$out['links'] = $links;
}
}
elseif (!empty($column['editable']) && !$column['rewrite']) {
elseif (!empty($column['editable']) && !$column['rewrite'] && empty($settings['editableRow']['disable'])) {
$edit = $this->formatEditableColumn($column, $data);
if ($edit) {
// When internally processing an inline-edit, get all metadata
if (isset($this->colKey) && $this->colKey === $column['key']) {
if (isset($this->rowKey) && isset($this->values) && array_key_exists($column['key'], $this->values)) {
$out['edit'] = $edit;
}
// Otherwise, the client only needs a boolean
Expand Down Expand Up @@ -1840,4 +1841,34 @@ protected function getIdKeyName(?string $entityName) {
return CoreUtil::getIdFieldName($entityName);
}

/**
* Get data from the where/having clauses, useful for inferring values to create a new entity
*
* If $this->applyFilters has already run, it will include data from filters
*
* @return array
* @throws \CRM_Core_Exception
*/
public function getQueryData(): array {
// First pass: gather raw data from the where & having clauses
$data = [];
foreach (array_merge($this->_apiParams['where'], $this->_apiParams['having'] ?? []) as $clause) {
if ($clause[1] === '=' || $clause[1] === 'IN') {
$data[$clause[0]] = $clause[2];
}
}
// Second pass: format values (because data from first pass could be useful to FormattingUtil)
foreach ($this->_apiParams['where'] as $clause) {
if ($clause[1] === '=' || $clause[1] === 'IN') {
[$fieldPath] = explode(':', $clause[0]);
$fieldSpec = $this->getField($fieldPath);
$data[$fieldPath] = $clause[2];
if ($fieldSpec) {
FormattingUtil::formatInputValue($data[$fieldPath], $clause[0], $fieldSpec, $data, $clause[1]);
}
}
}
return $data;
}

}
Loading

0 comments on commit 12788aa

Please sign in to comment.