diff --git a/app/src/View/Helper/MenuHelper.php b/app/src/View/Helper/MenuHelper.php index 580cecbb3..57ca4035c 100644 --- a/app/src/View/Helper/MenuHelper.php +++ b/app/src/View/Helper/MenuHelper.php @@ -53,6 +53,7 @@ public function getMenuOrder($action) { 'Edit' => 10, // edit 'Duplicate' => 15, // content_copy 'Default' => 20, // link - default starting order for arbitrary action menu items + 'Add' => 80, // add 'Delete' => 100 // delete ); @@ -73,6 +74,7 @@ public function getMenuIcon($action) { } $icon = array( + 'Add' => 'add_circle', 'View' => 'visibility', 'Edit' => 'edit', 'Duplicate' => 'content_copy', diff --git a/app/templates/AttributeMappings/columns.inc b/app/templates/AttributeMappings/columns.inc index 0b65c5327..648857d6e 100644 --- a/app/templates/AttributeMappings/columns.inc +++ b/app/templates/AttributeMappings/columns.inc @@ -40,14 +40,10 @@ $indexColumns = [ $topLinks = [ [ - 'label' => ' ' . - __('match.op.AttributeMappings.install.nicknames.en'), - 'link' => [ - 'action' => 'install', - '?' => [ - 'mapping' => 'nicknames.en' - ] - ], - 'class' => 'buildbutton' + 'action' => 'install', + 'query' => ['?' => ['mapping' => 'nicknames.en']], + 'class' => 'buildbutton', + 'icon' => 'file_download', + 'label' => __('match.op.AttributeMappings.install.nicknames.en') ] ]; \ No newline at end of file diff --git a/app/templates/Standard/add-edit-view.php b/app/templates/Standard/add-edit-view.php index 64fb5d644..69176818a 100644 --- a/app/templates/Standard/add-edit-view.php +++ b/app/templates/Standard/add-edit-view.php @@ -37,6 +37,147 @@

+ + + id; + $linkArgs = [$vv_obj->id]; + + // $linkFilter is used for models that belong to a specific parent model (eg: co_id) + $linkFilter = []; + + + if(!empty($vv_primary_link) && !empty($this->request->getQuery($vv_primary_link))) { + $linkFilter = ['?' => [$vv_primary_link => $this->request->getQuery($vv_primary_link)]]; + $linkArgs = array_merge_recursive($linkArgs, $linkFilter); + } + + // Insert additional actions as per the .inc file + if(!empty($topLinks)) { + if(!isset($entity->status) || $entity->status == StatusEnum::Active) { + $actionOrderDefault = $this->Menu->getMenuOrder('Default'); + foreach($topLinks as $a) { + if($vv_permissions[ $a['action'] ]) { + $actionOrder = !empty($a['order']) ? $a['order'] : $actionOrderDefault++; + $actionIcon = !empty($a['icon']) ? $a['icon'] : $this->Menu->getMenuIcon('Default'); + $actionClass = !empty($a['class']) ? $a['class'] : ''; + $actionUrl = ''; + $actionLabel = ''; + $actionOnClick = []; // used for confirmation dialog + + // Generate the link text and urls: + + // If we have a .confirm text, we need to generate a confirm dialog box + $confirmKey = 'match.op.'.$a['action'].'.confirm'; + $confirmTxt = __($confirmKey); + + if($confirmTxt != $confirmKey) { + // We found the localized string + $actionPostBtnArray = array_merge_recursive(['action' => $a['action']], $linkArgs); + $actionUrl = $this->Url->build(array_merge_recursive(['action' => $a['action']], $linkArgs)); + // XXX should be configurable which field we put in, maybe displayField? + $action_args['vv_actions'][] = array( + 'order' => $actionOrder, + 'icon' => $actionIcon, + 'url' => 'javascript:void(0);', + 'label' => __('match.op.' . $a['action']), + 'class' => !empty($actionClass) ? $actionClass . ' nospin' : 'nospin', + 'onclick' => array( + 'dg_bd_txt' => __($confirmKey, [$entity->id]), // dialog body text + 'dg_post_btn_array' => $actionPostBtnArray, // postButton array for building the postButton + 'dg_url' => $actionUrl, // action url for building a unique ID + 'dg_conf_btn' => __('match.op.confirm'), // dialog confirm button text + 'dg_cancel_btn' => __('match.op.cancel'), // dialog cancel button text + 'dg_title' => __('match.op.confirm'), // dialog box title + 'dg_bd_txt_repl_str' => '' // dialog body text replacement strings + ), + ); + } elseif(!empty($a['controller'])) { + // We're linking into a related controller + $queryParams = [ $tableFK => $entity->id ]; + + if(!empty($a['query']) && is_callable($a['query'])) { + $queryParams = $a['query']($vv_cur_mg->id, $entity); + } + + $actionLabel = __('match.ct.' . Inflector::camelize(Inflector::pluralize($a['controller'])), [99]); + $actionUrl = $this->Url->build([ + 'controller' => $a['controller'], + 'action' => $a['action'], + '?' => $queryParams + ]); + } else { + $actionLabel = __('match.op.' . $a['action']); + $actionUrl = $this->Url->build( + array_merge_recursive(['action' => $a['action']], $linkArgs) + ); + } + + // If a specific label is sent in the config, use it instead + if(!empty($a['label'])) { + $actionLabel = $a['label']; + } + + // Set the action link configuration + $action_args['vv_actions'][] = array( + 'order' => $actionOrder, + 'icon' => $actionIcon, + 'url' => $actionUrl, + 'label' => $actionLabel, + 'class' => $actionClass, + 'onclick' => $actionOnClick + ); + } + } + } + } + + // Duplicate + if(isset($vv_permissions['duplicate']) && $vv_permissions['duplicate']) { + $action_args['vv_actions'][] = array( + 'order' => $this->Menu->getMenuOrder('Duplicate'), + 'icon' => $this->Menu->getMenuIcon('Duplicate'), + 'url' => $this->Url->build(array_merge_recursive(['action' => 'duplicate'], $linkArgs)), + 'label' => __('match.op.duplicate') + ); + } + + // Delete + if($vv_permissions['delete']) { + $actionPostBtnArray = array_merge_recursive(['action' => 'delete'], $linkArgs); + $actionUrl = $this->Url->build(array_merge_recursive(['action' => 'delete'], $linkArgs)); + $action_args['vv_actions'][] = array( + 'order' => $this->Menu->getMenuOrder('Delete'), + 'icon' => $this->Menu->getMenuIcon('Delete'), + 'url' => 'javascript:void(0);', + 'label' => __('match.op.delete'), + 'class' => 'deletebutton nospin', + 'onclick' => array( + 'dg_bd_txt' => __('match.op.delete.confirm', [$vv_obj->id]), + 'dg_post_btn_array' => $actionPostBtnArray, + 'dg_url' => $actionUrl, + 'dg_conf_btn' => __('match.op.remove'), + 'dg_cancel_btn' => __('match.op.cancel'), + 'dg_title' => __('match.op.remove'), + 'dg_bd_txt_repl_str' => '' + ), + ); + } + + if(!empty($action_args['vv_actions'])) { + print ''; + } + ?> + - + } + } + + // Add + $addLink = array_merge($linkFilter, ['action' => 'add']); + + // Allow model-specific overrides of the add link. If false, + // the override doesn't want the add link to render. + if(isset($addLinkFilter) && is_callable($addLinkFilter)) { + $addLink = $addLinkFilter($addLink, $this->request); + } + + $action_args['vv_actions'][] = array( + 'order' => $this->Menu->getMenuOrder('Add'), + 'icon' => $this->Menu->getMenuIcon('Add'), + 'url' => $this->Url->build($addLink), + 'label' => __('match.op.add.a', __('match.ct.'.$vv_modelname, [1])) + ); + + // Output the topLinks + if(!empty($action_args['vv_actions'])) { + print ''; + } + ?> diff --git a/app/webroot/css/co-base.css b/app/webroot/css/co-base.css index 8c6b8f862..5d7063372 100644 --- a/app/webroot/css/co-base.css +++ b/app/webroot/css/co-base.css @@ -477,13 +477,12 @@ body.logged-in #top-menu { #topLinks { margin: 1.5em 0 -1.5em 0; padding: 0; - font-size: 0.9em; } #topLinks li { list-style: none; display: inline-block; - margin: 0.5em; - padding: 0 0.5em; + margin: 0.5em 0; + padding: 0; } #topLinks a { text-decoration: none; @@ -498,6 +497,9 @@ body.logged-in #top-menu { #main #topLinks a:hover { text-decoration: underline; } +#topLinks a.dropdown-item.deletebutton { + color: var(--cmg-color-red-002); +} /* INNER CONTENT - for non-table-based layouts */ #content { padding: 1em 1.5em; diff --git a/app/webroot/css/co-responsive.css b/app/webroot/css/co-responsive.css index 4fc32f4c8..2e4da7c18 100644 --- a/app/webroot/css/co-responsive.css +++ b/app/webroot/css/co-responsive.css @@ -216,6 +216,7 @@ .field-actions .dropdown-menu { position: static; display: inline-block; + min-width: 0; font-size: 0.9em; border: none; background-color: transparent;