diff --git a/app/resources/locales/en_US/information.po b/app/resources/locales/en_US/information.po
index 4cd7ed3a2..f129fe850 100644
--- a/app/resources/locales/en_US/information.po
+++ b/app/resources/locales/en_US/information.po
@@ -51,6 +51,12 @@ msgstr "Active, Cannot Be Disabled"
msgid "plugin.inactive"
msgstr "Inactive"
+msgid "global.attribute.modal"
+msgstr "Attribute Modal"
+
+msgid "global.attributes"
+msgstr "Attributes"
+
msgid "global.records.none"
msgstr "There are no records to display."
diff --git a/app/resources/locales/en_US/menu.po b/app/resources/locales/en_US/menu.po
index a875c0671..9fb8208b0 100644
--- a/app/resources/locales/en_US/menu.po
+++ b/app/resources/locales/en_US/menu.po
@@ -24,9 +24,6 @@
# Menu Messages
-msgid "co.Attributes"
-msgstr "Attributes"
-
msgid "co.configuration"
msgstr "Configuration"
diff --git a/app/src/Controller/StandardController.php b/app/src/Controller/StandardController.php
index e3490a4ad..360189cd3 100644
--- a/app/src/Controller/StandardController.php
+++ b/app/src/Controller/StandardController.php
@@ -166,6 +166,11 @@ public function beforeRender(\Cake\Event\EventInterface $event) {
}
$this->set('vv_template_path', $vv_template_path);
+
+ // Check to see if the model names a specific layout
+ if(method_exists($table, "getLayout")) {
+ $this->viewBuilder()->setLayout($table->getLayout());
+ }
return parent::beforeRender($event);
}
diff --git a/app/src/Model/Table/AdHocAttributesTable.php b/app/src/Model/Table/AdHocAttributesTable.php
index b7857f8d2..f88bc9179 100644
--- a/app/src/Model/Table/AdHocAttributesTable.php
+++ b/app/src/Model/Table/AdHocAttributesTable.php
@@ -42,6 +42,26 @@ class AdHocAttributesTable extends Table {
use \App\Lib\Traits\ValidationTrait;
use \App\Lib\Traits\SearchFilterTrait;
+ /**
+ * Provide the default layout
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getLayout(): string {
+ return "iframe";
+ }
+
+ /**
+ * Provide the default redirect goal
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getRedirectGoal(): string {
+ return "self";
+ }
+
/**
* Perform Cake Model initialization.
*
diff --git a/app/src/Model/Table/AddressesTable.php b/app/src/Model/Table/AddressesTable.php
index a149dd445..8ee0c64e0 100644
--- a/app/src/Model/Table/AddressesTable.php
+++ b/app/src/Model/Table/AddressesTable.php
@@ -57,6 +57,26 @@ class AddressesTable extends Table {
]
];
+ /**
+ * Provide the default layout
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getLayout(): string {
+ return "iframe";
+ }
+
+ /**
+ * Provide the default redirect goal
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getRedirectGoal(): string {
+ return "self";
+ }
+
/**
* Perform Cake Model initialization.
*
diff --git a/app/src/Model/Table/EmailAddressesTable.php b/app/src/Model/Table/EmailAddressesTable.php
index 7d48c5218..4a98b199b 100644
--- a/app/src/Model/Table/EmailAddressesTable.php
+++ b/app/src/Model/Table/EmailAddressesTable.php
@@ -58,6 +58,26 @@ class EmailAddressesTable extends Table {
]
];
+ /**
+ * Provide the default layout
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getLayout(): string {
+ return "iframe";
+ }
+
+ /**
+ * Provide the default redirect goal
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getRedirectGoal(): string {
+ return "self";
+ }
+
/**
* Perform Cake Model initialization.
*
diff --git a/app/src/Model/Table/ExternalIdentitiesTable.php b/app/src/Model/Table/ExternalIdentitiesTable.php
index 1694fd076..986300d14 100644
--- a/app/src/Model/Table/ExternalIdentitiesTable.php
+++ b/app/src/Model/Table/ExternalIdentitiesTable.php
@@ -110,14 +110,15 @@ public function initialize(array $config): void {
// XXX does some of this stuff really belong in the controller?
$this->setEditContains([
'PrimaryName',
-/* 'Addresses',
+ 'Addresses',
'AdHocAttributes',
'EmailAddresses',
'Identifiers',
'Names',
- 'PersonRoles',
+ //'ExternalIdentityRoles',
+ 'Pronouns',
'TelephoneNumbers',
- 'Urls'*/
+ 'Urls'
]);
$this->setIndexContains(['PrimaryName']);
diff --git a/app/src/Model/Table/IdentifiersTable.php b/app/src/Model/Table/IdentifiersTable.php
index 241eef6cb..1aabfd673 100644
--- a/app/src/Model/Table/IdentifiersTable.php
+++ b/app/src/Model/Table/IdentifiersTable.php
@@ -70,6 +70,26 @@ class IdentifiersTable extends Table {
]
];
+ /**
+ * Provide the default layout
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getLayout(): string {
+ return "iframe";
+ }
+
+ /**
+ * Provide the default redirect goal
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getRedirectGoal(): string {
+ return "self";
+ }
+
/**
* Perform Cake Model initialization.
*
diff --git a/app/src/Model/Table/NamesTable.php b/app/src/Model/Table/NamesTable.php
index a09777c64..d49d34eee 100644
--- a/app/src/Model/Table/NamesTable.php
+++ b/app/src/Model/Table/NamesTable.php
@@ -62,6 +62,26 @@ class NamesTable extends Table {
]
];
+ /**
+ * Provide the default layout
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getLayout(): string {
+ return "iframe";
+ }
+
+ /**
+ * Provide the default redirect goal
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getRedirectGoal(): string {
+ return "self";
+ }
+
/**
* Perform Cake Model initialization.
*
diff --git a/app/src/Model/Table/PeopleTable.php b/app/src/Model/Table/PeopleTable.php
index fd131ee95..55c448acd 100644
--- a/app/src/Model/Table/PeopleTable.php
+++ b/app/src/Model/Table/PeopleTable.php
@@ -129,7 +129,8 @@ public function initialize(array $config): void {
'EmailAddresses',
'Identifiers',
'Names',
- 'PersonRoles',
+ //'PersonRoles',
+ 'Pronouns',
'TelephoneNumbers',
'Urls'
]);
diff --git a/app/src/Model/Table/PronounsTable.php b/app/src/Model/Table/PronounsTable.php
index b7b1bc702..0149274d2 100644
--- a/app/src/Model/Table/PronounsTable.php
+++ b/app/src/Model/Table/PronounsTable.php
@@ -53,6 +53,26 @@ class PronounsTable extends Table {
]
];
+ /**
+ * Provide the default layout
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getLayout(): string {
+ return "iframe";
+ }
+
+ /**
+ * Provide the default redirect goal
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getRedirectGoal(): string {
+ return "self";
+ }
+
/**
* Perform Cake Model initialization.
*
diff --git a/app/src/Model/Table/TelephoneNumbersTable.php b/app/src/Model/Table/TelephoneNumbersTable.php
index 3044435ed..e1f6fe3ca 100644
--- a/app/src/Model/Table/TelephoneNumbersTable.php
+++ b/app/src/Model/Table/TelephoneNumbersTable.php
@@ -57,6 +57,26 @@ class TelephoneNumbersTable extends Table {
]
];
+ /**
+ * Provide the default layout
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getLayout(): string {
+ return "iframe";
+ }
+
+ /**
+ * Provide the default redirect goal
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getRedirectGoal(): string {
+ return "self";
+ }
+
/**
* Perform Cake Model initialization.
*
diff --git a/app/src/Model/Table/UrlsTable.php b/app/src/Model/Table/UrlsTable.php
index 914d051ee..af92b4d76 100644
--- a/app/src/Model/Table/UrlsTable.php
+++ b/app/src/Model/Table/UrlsTable.php
@@ -53,6 +53,26 @@ class UrlsTable extends Table {
]
];
+ /**
+ * Provide the default layout
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getLayout(): string {
+ return "iframe";
+ }
+
+ /**
+ * Provide the default redirect goal
+ *
+ * @since COmanage Registry v5.0.0
+ * @return string Type of redirect
+ */
+ public function getRedirectGoal(): string {
+ return "self";
+ }
+
/**
* Perform Cake Model initialization.
*
diff --git a/app/src/View/Helper/VueHelper.php b/app/src/View/Helper/VueHelper.php
index 7230ba524..37672e4f6 100644
--- a/app/src/View/Helper/VueHelper.php
+++ b/app/src/View/Helper/VueHelper.php
@@ -45,6 +45,9 @@ class VueHelper extends Helper {
'information' => [
'global.value.none',
'datepicker.hour'
+ ],
+ 'operation' => [
+ 'close'
]
];
diff --git a/app/templates/ExternalIdentities/fields-nav.inc b/app/templates/ExternalIdentities/fields-nav.inc
index 6ffd1566c..745e3b332 100644
--- a/app/templates/ExternalIdentities/fields-nav.inc
+++ b/app/templates/ExternalIdentities/fields-nav.inc
@@ -25,6 +25,22 @@
* @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
*/
+// List the MVEAs that may be shown on the mveaCanvas
+// When this array exists, the mveaCanvas.php element will render
+$mveas = [
+ 'names',
+ 'email_addresses',
+ 'identifiers',
+ 'ad_hoc_attributes',
+ 'addresses',
+ 'telephone_numbers',
+ 'urls',
+ 'pronouns'
+];
+
+// Name the MVEAs Entity Type
+$mveasEntityType = "external_identity";
+
// XXX: if CFM-218 (Make fields.inc configuration only) is accepted, move the contents of this file into fields.inc
$topLinks = [
[
@@ -42,6 +58,60 @@ $topLinks = [
]
];
+// $addMenuLinks is also given slightly different treatment from the typical $topLinks found in most views:
+// it is a page-global menu used for adding MVEAs and is given special treatment in element/mveaCanvas.php.
+$addMenuLinks = [
+ [
+ 'controller' => 'names',
+ 'action' => 'add',
+ 'icon' => 'account_box',
+ 'iconClass' => 'material-icons-outlined'
+ ],
+ [
+ 'controller' => 'email_addresses',
+ 'action' => 'add',
+ 'icon' => 'email',
+ 'iconClass' => 'material-icons-outlined'
+ ],
+ [
+ 'controller' => 'identifiers',
+ 'action' => 'add',
+ 'icon' => 'fingerprint'
+ ],
+ [
+ 'controller' => 'ad_hoc_attributes',
+ 'action' => 'add',
+ 'icon' => 'check_box',
+ 'iconClass' => 'material-icons-outlined'
+ ],
+ [
+ 'controller' => 'addresses',
+ 'action' => 'add',
+ 'icon' => 'contact_mail',
+ 'iconClass' => 'material-icons-outlined'
+ ],
+ [
+ 'controller' => 'history_records',
+ 'action' => 'add',
+ 'icon' => 'history'
+ ],
+ [
+ 'controller' => 'pronouns',
+ 'action' => 'add',
+ 'icon' => 'transgender'
+ ],
+ [
+ 'controller' => 'telephone_numbers',
+ 'action' => 'add',
+ 'icon' => 'phone'
+ ],
+ [
+ 'controller' => 'urls',
+ 'action' => 'add',
+ 'icon' => 'link'
+ ]
+];
+
$subnav = [
'name' => 'person',
'active' => 'external_identities',
diff --git a/app/templates/People/columns.inc b/app/templates/People/columns.inc
index e64a5f37b..c0c5b27e2 100644
--- a/app/templates/People/columns.inc
+++ b/app/templates/People/columns.inc
@@ -46,24 +46,6 @@ $topLinks = [];
// $rowActions appear as row-level menu items in the index view gear icon
$rowActions = [
- [
- 'controller' => 'names',
- 'action' => 'index',
- 'icon' => 'account_box',
- 'iconClass' => 'material-icons-outlined'
- ],
- [
- 'controller' => 'email_addresses',
- 'action' => 'index',
- 'icon' => 'email',
- 'iconClass' => 'material-icons-outlined'
- ],
- [
- 'controller' => 'identifiers',
- 'action' => 'index',
- 'icon' => 'fingerprint',
- 'class' => 'bottom-border'
- ],
[
'controller' => 'person_roles',
'action' => 'index',
@@ -75,32 +57,10 @@ $rowActions = [
'icon' => 'system_update_alt',
'class' => 'bottom-border'
],
- [
- 'controller' => 'ad_hoc_attributes',
- 'action' => 'index',
- 'icon' => 'check_box',
- 'iconClass' => 'material-icons-outlined'
- ],
- [
- 'controller' => 'addresses',
- 'action' => 'index',
- 'icon' => 'contact_mail',
- 'iconClass' => 'material-icons-outlined'
- ],
[
'controller' => 'history_records',
'action' => 'index',
'icon' => 'history'
- ],
- [
- 'controller' => 'telephone_numbers',
- 'action' => 'index',
- 'icon' => 'phone'
- ],
- [
- 'controller' => 'urls',
- 'action' => 'index',
- 'icon' => 'link'
]
];
diff --git a/app/templates/People/fields-nav.inc b/app/templates/People/fields-nav.inc
index 5ee314e2f..ec60b9eb8 100644
--- a/app/templates/People/fields-nav.inc
+++ b/app/templates/People/fields-nav.inc
@@ -25,9 +25,23 @@
* @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
*/
-// XXX: if CFM-218 (Make fields.inc configuration only) is accepted, move the contents of this file into fields.inc
+// List the MVEAs that may be shown on the mveaCanvas
+// When this array exists, the mveaCanvas.php element will render
+$mveas = [
+ 'names',
+ 'email_addresses',
+ 'identifiers',
+ 'ad_hoc_attributes',
+ 'addresses',
+ 'telephone_numbers',
+ 'urls',
+ 'pronouns'
+];
-// Output for $topLinks from this specific configuration is presented in the Person canvas "Actions" menu.
+// Name the MVEAs Entity Type
+$mveasEntityType = "person";
+
+// Output for $topLinks from this specific configuration is presented in the mveaCanvas.php "Actions" menu.
$topLinks = [
[
'icon' => 'history',
@@ -44,8 +58,7 @@ $topLinks = [
];
// $addMenuLinks is also given slightly different treatment from the typical $topLinks found in most views:
-// it is a page-global menu used for adding MVEAs to the person canvas and is given special treatment in
-// element/personCanvas.php.
+// it is a page-global menu used for adding MVEAs and is given special treatment in element/mveaCanvas.php.
$addMenuLinks = [
[
'controller' => 'names',
diff --git a/app/templates/PersonRoles/fields-nav.inc b/app/templates/PersonRoles/fields-nav.inc
index e306f822c..454647d2d 100644
--- a/app/templates/PersonRoles/fields-nav.inc
+++ b/app/templates/PersonRoles/fields-nav.inc
@@ -25,9 +25,42 @@
* @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
*/
+// List the MVEAs that may be shown on the mveaCanvas
+// When this array exists, the mveaCanvas.php element will render
+$mveas = [
+ 'ad_hoc_attributes',
+ 'addresses',
+ 'telephone_numbers'
+];
+
+// Name the MVEAs Entity Type
+$mveasEntityType = "person_role";
+
// XXX: if CFM-218 (Make fields.inc configuration only) is accepted, move the contents of this file into fields.inc
$topLinks = [];
+// $addMenuLinks is also given slightly different treatment from the typical $topLinks found in most views:
+// it is a page-global menu used for adding MVEAs and is given special treatment in element/mveaCanvas.php.
+$addMenuLinks = [
+ [
+ 'controller' => 'ad_hoc_attributes',
+ 'action' => 'add',
+ 'icon' => 'check_box',
+ 'iconClass' => 'material-icons-outlined'
+ ],
+ [
+ 'controller' => 'addresses',
+ 'action' => 'add',
+ 'icon' => 'contact_mail',
+ 'iconClass' => 'material-icons-outlined'
+ ],
+ [
+ 'controller' => 'telephone_numbers',
+ 'action' => 'add',
+ 'icon' => 'phone'
+ ]
+];
+
$subnav = [
'name' => 'person',
'active' => 'person_roles',
diff --git a/app/templates/Standard/add-edit-view.php b/app/templates/Standard/add-edit-view.php
index b1c2e2c3e..a98dee8a5 100644
--- a/app/templates/Standard/add-edit-view.php
+++ b/app/templates/Standard/add-edit-view.php
@@ -80,102 +80,83 @@
}
?>
-
-
+
+
+
+
= $vv_title; ?>
+
+ = $vv_title; ?>
+
+
element('personCanvas', ['vv_add_menu_links' => $addMenuLinks]);
- ?>
-
-
-
-
-
= $vv_title; ?>
-
- request->getParam('controller') == 'PersonRoles'
- || $this->request->getParam('controller') == 'ExternalIdentities'
- || $this->request->getParam('controller') == 'ExternalIdentityRoles'): ?>
- = $vv_title; ?>
-
- = $vv_title; ?>
-
-
-
- id;
-
- foreach(($topLinks ?? []) as $t) {
- $perm = false;
-
- if(!empty($t['link']['controller'])) {
- // We're linking into a related model
-
- $linkModel = \Cake\Utility\Inflector::camelize($t['link']['controller']);
-
- if(isset($vv_permissions[$linkModel][ $t['link']['action'] ])) {
- $perm = $vv_permissions[$linkModel][ $t['link']['action'] ];
- }
-
- // Inject a link to the current object ID
- $t['link']['?'][\App\Lib\Util\StringUtilities::entityToForeignKey($vv_obj)] = $vv_obj->id;
- } else {
- $perm = $vv_permissions[ $t['link']['action'] ];
-
- // We need to inject $linkFilter, but not overwrite any existing query params
- if(!empty($t['link']['?'])) {
- $t['link']['?'] = array_merge($t['link']['?'], $linkFilter);
- } else {
- $t['link']['?'] = $linkFilter;
- }
+ // Action list for top menu dropdown / button listing
+ $action_args = array();
+ $action_args['vv_attr_id'] = $vv_obj->id;
+
+ foreach(($topLinks ?? []) as $t) {
+ $perm = false;
+
+ if(!empty($t['link']['controller'])) {
+ // We're linking into a related model
+
+ $linkModel = \Cake\Utility\Inflector::camelize($t['link']['controller']);
+
+ if(isset($vv_permissions[$linkModel][ $t['link']['action'] ])) {
+ $perm = $vv_permissions[$linkModel][ $t['link']['action'] ];
}
- if($perm) {
- $action_args['vv_actions'][] = [
- 'order' => $this->Menu->getMenuOrder($t['order']),
- 'icon' => $this->Menu->getMenuIcon($t['icon']),
- 'url' => $this->Url->build($t['link']),
- 'label' => $t['label'],
- ];
+ // Inject a link to the current object ID
+ $t['link']['?'][\App\Lib\Util\StringUtilities::entityToForeignKey($vv_obj)] = $vv_obj->id;
+ } else {
+ $perm = $vv_permissions[ $t['link']['action'] ];
+
+ // We need to inject $linkFilter, but not overwrite any existing query params
+ if(!empty($t['link']['?'])) {
+ $t['link']['?'] = array_merge($t['link']['?'], $linkFilter);
+ } else {
+ $t['link']['?'] = $linkFilter;
}
}
-
- // Delete
- if($vv_action != 'add' && !empty($vv_obj->id) && $vv_permissions['delete']) {
- $actionPostBtnArray = ['action' => 'delete', $vv_obj->id];
- $actionUrl = $this->Url->build(['action' => 'delete', $vv_obj->id]);
- $action_args['vv_actions'][] = array(
- 'order' => $this->Menu->getMenuOrder('Delete'),
- 'icon' => $this->Menu->getMenuIcon('Delete'),
- 'url' => 'javascript:void(0);',
- 'label' => __d('operation', 'delete'),
- 'class' => 'deletebutton nospin',
- 'onclick' => array(
- 'dg_bd_txt' => __d('operation', 'delete.confirm', [$vv_obj->id]),
- 'dg_post_btn_array' => $actionPostBtnArray,
- 'dg_url' => $actionUrl,
- 'dg_conf_btn' => __d('operation', 'remove'),
- 'dg_cancel_btn' => __d('operation', 'cancel'),
- 'dg_title' => __d('operation', 'remove'),
- 'dg_bd_txt_repl_str' => ''
- )
- );
- }
-
- if(!empty($action_args['vv_actions'])) {
- print '
';
- print $this->element('menuAction', $action_args);
- print '
';
+
+ if($perm) {
+ $action_args['vv_actions'][] = [
+ 'order' => $this->Menu->getMenuOrder($t['order']),
+ 'icon' => $this->Menu->getMenuIcon($t['icon']),
+ 'url' => $this->Url->build($t['link']),
+ 'label' => $t['label'],
+ ];
}
- ?>
-
-
+ }
+
+ // Delete
+ if($vv_action != 'add' && !empty($vv_obj->id) && $vv_permissions['delete']) {
+ $actionPostBtnArray = ['action' => 'delete', $vv_obj->id];
+ $actionUrl = $this->Url->build(['action' => 'delete', $vv_obj->id]);
+ $action_args['vv_actions'][] = array(
+ 'order' => $this->Menu->getMenuOrder('Delete'),
+ 'icon' => $this->Menu->getMenuIcon('Delete'),
+ 'url' => 'javascript:void(0);',
+ 'label' => __d('operation', 'delete'),
+ 'class' => 'deletebutton nospin',
+ 'onclick' => array(
+ 'dg_bd_txt' => __d('operation', 'delete.confirm', [$vv_obj->id]),
+ 'dg_post_btn_array' => $actionPostBtnArray,
+ 'dg_url' => $actionUrl,
+ 'dg_conf_btn' => __d('operation', 'remove'),
+ 'dg_cancel_btn' => __d('operation', 'cancel'),
+ 'dg_title' => __d('operation', 'remove'),
+ 'dg_bd_txt_repl_str' => ''
+ )
+ );
+ }
+
+ if(!empty($action_args['vv_actions'])) {
+ print '
';
+ print $this->element('menuAction', $action_args);
+ print '
';
+ }
+ ?>
+
@@ -243,4 +224,15 @@
print $this->Field->endControlSet();
+/** MVEA Canvas output **/
+if($vv_action != 'add' && !empty($mveas)) {
+ // Pass along the $mveas and any $addMenuLinks defined in templates/.../fields-nav.inc config.
+ print $this->element('mveaCanvas',
+ [
+ 'vv_mveas' => $mveas,
+ 'vv_add_menu_links' => !empty($addMenuLinks) ? $addMenuLinks : '',
+ 'vv_entity_type' => $mveasEntityType
+ ]);
+}
+
// XXX insert changelog metadata (+nav? or maybe we should have a dedicate index view that shows all records in revision order?)
diff --git a/app/templates/Standard/index.php b/app/templates/Standard/index.php
index 7b7071c0d..f22db1363 100644
--- a/app/templates/Standard/index.php
+++ b/app/templates/Standard/index.php
@@ -83,15 +83,7 @@
= $vv_title; ?>
-
- = $vv_title; ?>
-
- = $vv_title; ?>
-
+ = $vv_title; ?>
diff --git a/app/templates/element/javascript.php b/app/templates/element/javascript.php
index 248eb605d..0933962e4 100644
--- a/app/templates/element/javascript.php
+++ b/app/templates/element/javascript.php
@@ -204,6 +204,17 @@
});
}
});
+
+ // Person canvas "Add" links
+ // Launch the MVEA modal window, load the Add url, and refresh the appropriate component when done.
+ $('#mvea-add-menu-container ul a').click(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ var title = $(this).find('.action-link-text').text();
+ var url = $(this).prop('href');
+ var componentRef = 'mvea' + $(this).data('cm-mveatype');
+ window.cmMveaModal.launch(title,url,componentRef);
+ });
// Bulk edit switch
$('#bulk-edit-switch').click(function() {
diff --git a/app/templates/element/menuAction.php b/app/templates/element/menuAction.php
index ee4549b6d..b712d81e9 100644
--- a/app/templates/element/menuAction.php
+++ b/app/templates/element/menuAction.php
@@ -61,10 +61,18 @@ class="= $actionsMenuClass; ?>">
?>
-
-
-
+
+
+
request->getQuery($vv_primary_link);
- if($isPersonRole || $isExternalId) {
- if($isExternalId && !empty($vv_ei_id)) {
- $curId = $vv_ei_id;
- }
- // We display the role or external identity name above the subnav to show the hierarchy.
- // We also use this structure to set the second-level $linkFilter
- print '';
- if(!empty($vv_ei_name)) {
- // We have an external identity name
- print $vv_ei_name->full_name;
- $linkFilter = ['external_identity_id' => $curId];
- } elseif(!empty($vv_person_role)) {
- // We have a person role
- print $vv_person_role;
- $linkFilter = ['person_role_id' => $curId];
- } elseif(!empty($vv_obj)) {
- // We are editing/viewing an object
- if(!empty($vv_obj->title)) {
- print $vv_obj->title;
- } elseif (!empty($vv_subtitle)) {
- print $vv_subtitle;
- } else {
- print print __d('information','global.title.none');
- }
- // Set up $linkFilter for edit/view on Roles and External Identities
- $curId = $vv_obj->id;
- if($curController == 'PersonRoles') {
- $linkFilter = ['person_role_id' => $curId];
- }
- if($curController == 'ExternalIdentities') {
- $linkFilter = ['external_identity_id' => $curId];
- }
- } else {
- // We shouldn't get here, but have a deafult in case.
- print __d('information','global.title.none');
- }
- print ' ';
- }
+ if(!empty($vv_ei_id)) {
+ $curId = $vv_ei_id;
+ $linkFilter = ['external_identity_id' => $curId];
+ } elseif(!empty($vv_obj)) {
+ $curId = $vv_obj->id;
+ $linkFilter = ['external_identity_id' => $curId];
+ }
?>
+
@@ -391,73 +363,13 @@
);
?>
-
-
- Html->link(
- __d('controller', 'Names', [99]),
- [ 'controller' => 'names',
- 'action' => 'index',
- '?' => $linkFilter
- ],
- ['class' => $linkClass]
- );
- ?>
-
-
- Html->link(
- __d('controller', 'EmailAddresses', [99]),
- [ 'controller' => 'email_addresses',
- 'action' => 'index',
- '?' => $linkFilter
- ],
- ['class' => $linkClass]
- );
- ?>
-
-
- Html->link(
- __d('controller', 'Identifiers', [99]),
- [ 'controller' => 'identifiers',
- 'action' => 'index',
- '?' => $linkFilter
- ],
- ['class' => $linkClass]
- );
- ?>
-
-
-
- Html->link(
- __d('controller', 'ExternalIdentityRoles', [99]),
- [ 'controller' => 'external_identity_roles',
- 'action' => 'index',
- '?' => $linkFilter
- ],
- ['class' => $linkClass]
- );
- ?>
-
-
-
Html->link(
- __d('controller', 'AdHocAttributes', [99]),
- [ 'controller' => 'ad_hoc_attributes',
+ __d('controller', 'ExternalIdentityRoles', [99]),
+ [ 'controller' => 'external_identity_roles',
'action' => 'index',
'?' => $linkFilter
],
@@ -465,63 +377,6 @@
);
?>
-
- Html->link(
- __d('controller', 'Addresses', [99]),
- [ 'controller' => 'addresses',
- 'action' => 'index',
- '?' => $linkFilter
- ],
- ['class' => $linkClass]
- );
- ?>
-
-
- Html->link(
- __d('controller', 'TelephoneNumbers', [99]),
- [ 'controller' => 'telephone_numbers',
- 'action' => 'index',
- '?' => $linkFilter
- ],
- ['class' => $linkClass]
- );
- ?>
-
-
-
- Html->link(
- __d('controller', 'Urls', [99]),
- [ 'controller' => 'urls',
- 'action' => 'index',
- '?' => $linkFilter
- ],
- ['class' => $linkClass]
- );
- ?>
-
-
- Html->link(
- __d('controller', 'Pronouns', [99]),
- [ 'controller' => 'pronouns',
- 'action' => 'index',
- '?' => $linkFilter
- ],
- ['class' => $linkClass]
- );
- ?>
-
@@ -613,7 +468,7 @@
-
-
+
+
\ No newline at end of file
diff --git a/app/templates/layout/iframe.php b/app/templates/layout/iframe.php
new file mode 100644
index 000000000..13aae2d7b
--- /dev/null
+++ b/app/templates/layout/iframe.php
@@ -0,0 +1,151 @@
+
+
+
+
+ = $this->Html->meta('viewport', 'width=device-width, initial-scale=1.0') . PHP_EOL ?>
+ = $this->Html->charset(); ?>
+
+ = (!empty($vv_title) ? $vv_title : __('registry.meta.registry')); ?>
+
+
+
+ = $this->Html->meta('favicon.ico', '/favicon.ico', array('type' => 'icon')) . PHP_EOL ?>
+
+
+ = $this->Html->css([
+ 'bootstrap/bootstrap.min',
+ 'select2/select2.min',
+ 'co-color',
+ 'co-base',
+ 'co-responsive'
+ ]) . PHP_EOL ?>
+
+
+ = $this->Html->script([
+ 'bootstrap/bootstrap.bundle.min.js',
+ 'jquery/jquery.min.js',
+ 'select2/select2.min.js'
+ ]) . PHP_EOL ?>
+
+
+ = $this->fetch('meta') ?>
+ = $this->fetch('css') ?>
+ = $this->fetch('script') ?>
+
+
+ request->getParam('controller')));
+ $action_stripped = preg_replace('/[^a-zA-Z0-9\-_]/', '', strtolower($this->request->getParam('action')));
+ $bodyClasses = $controller_stripped . ' ' . $action_stripped . ' in-iframe';
+ $isCoSelectView = $controller_stripped == 'cos' && $action_stripped == 'select';
+ $isDashboard = $controller_stripped == 'dashboards' && $action_stripped == 'dashboard';
+
+ // add further body classes as needed
+ if(!empty($vv_user)) {
+ $bodyClasses .= ' logged-in';
+ } else {
+ $bodyClasses .= ' logged-out';
+ }
+ ?>
+
+
+
+
+
+
+ = $this->fetch('content') ?>
+
+
+
+
+
+
+
+
+ = $this->element('dialog') ?>
+
+
+ = $this->Html->script('jstimezonedetect/jstz.min.js') ?>
+
+
+
+
+ = $this->Html->script([
+ 'vue/vue-3.2.31.global.prod.js',
+ 'js-cookie/js.cookie-2.1.3.min.js',
+ 'comanage/comanage.js'
+ ]) . PHP_EOL ?>
+
+
+ = $this->Html->script('duet-datepicker/duet/duet.esm.js',['type' => 'module']) ?>
+ = $this->Html->script('duet-datepicker/duet/duet.js',['nomodule' => '']) ?>
+
+
+ element('javascript'); ?>
+
+
+
+
+
+
diff --git a/app/webroot/css/co-base.css b/app/webroot/css/co-base.css
index b245c7fe2..ab88eef49 100644
--- a/app/webroot/css/co-base.css
+++ b/app/webroot/css/co-base.css
@@ -50,7 +50,7 @@ h1.loginMsg {
}
h2 {
font-size: 2em;
- line-height: 2.5em;
+ line-height: 2em;
margin: 0;
}
h3 {
@@ -628,6 +628,12 @@ ul.form-list li.alert-banner .co-alert {
#subnavigation nav {
padding: 0.5em 0;
}
+#cm-person-subnav-tabs {
+ margin-bottom: 1.5em;
+}
+#cm-person-subnav-links {
+ margin-top: -2em;
+}
.cm-subnav-tabs .nav-link {
text-transform: uppercase;
padding: 1em 1.5em;
@@ -1022,24 +1028,31 @@ table.index-table .form-check {
#person-actions .action-menu-toggle {
white-space: nowrap;
}
-.person-actions-add-menu-container {
+#mvea-add-menu-container {
float: right;
+ margin: 1em 0 0;
}
-#person-canvas {
+#mvea-canvas {
clear: both;
}
-#person-canvas-attributes,
-#person-canvas-attributes-js {
+#mvea-canvas-title-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin: 3em 0 -0.5em;
+}
+#mvea-canvas-attributes,
+#mvea-canvas-attributes-js {
margin-top: 0;
margin-bottom: 2em;
}
-#person-canvas-attributes-js .badge {
+#mvea-canvas-attributes-js .badge {
margin-right: 0.5em;
}
-#person-canvas-attributes-js .canvas-url-link {
+#mvea-canvas-attributes-js .canvas-url-link {
margin-left: 1em;
}
-#person-canvas-roles {
+#mvea-canvas-roles {
margin-bottom: 2em;
}
h2.card-title {
@@ -1338,6 +1351,36 @@ ul.form-list .cm-time-picker-vals li {
#dialog .modal-footer {
border-top: none;
}
+/* MVEA MODAL */
+.mvea-modal .modal-dialog {
+ max-width: 90vw;
+}
+.mvea-modal .modal-header {
+ padding: 0.5rem 1rem;
+ background-color: var(--cmg-color-lightgray-004);
+ border-bottom: none;
+}
+.mvea-modal .modal-content {
+ height: 80vh;
+}
+.mvea-modal .modal-body {
+ padding-top: 0;
+}
+.mvea-modal iframe {
+ width: 100%;
+ height: 100%;
+}
+#comanage-iframe-wrapper #subnavigation .supertitle-container,
+#comanage-iframe-wrapper #subnavigation #cm-person-subnav-tabs,
+#comanage-iframe-wrapper #subnavigation #cm-person-subnav-links {
+ display: none;
+}
+#comanage-iframe-wrapper #content {
+ padding: 1rem 2em 0;
+}
+#comanage-iframe-wrapper .pageTitleContainer {
+ margin: 1em 0;
+}
/* GENERAL */
.hidden,
.invisible,
diff --git a/app/webroot/css/co-responsive.css b/app/webroot/css/co-responsive.css
index b957c7f89..14cfa1c5a 100644
--- a/app/webroot/css/co-responsive.css
+++ b/app/webroot/css/co-responsive.css
@@ -52,7 +52,7 @@
}
h2 {
font-size: 2em;
- line-height: 2em;
+ line-height: 1.2em;
}
#logout {
display: block;
@@ -105,7 +105,7 @@
grid-template-columns: 1fr 1fr;
align-items: center;
}
- #person-canvas-roles .field-data-container {
+ #mvea-canvas-roles .field-data-container {
grid-template-columns: 1fr 1fr 2fr auto;
}
/* PAGINATION */
diff --git a/app/webroot/js/comanage/components/mvea/mvea-item.js b/app/webroot/js/comanage/components/mvea/mvea-item.js
index 7a1df06d5..611a5aa04 100644
--- a/app/webroot/js/comanage/components/mvea/mvea-item.js
+++ b/app/webroot/js/comanage/components/mvea/mvea-item.js
@@ -36,7 +36,6 @@ export default {
},
computed: {
mveaLink: function() {
- // For now, link to the underlying PHP form. We will change this behavior as we develop the JS forms.
return this.core.webroot + this.core.mveaController + '/edit/' + this.mvea.id;
}
},
@@ -45,7 +44,11 @@ export default {
return constructLanguageString(lang)
},
followRowLink() {
- location.href = this.mveaLink;
+ //location.href = this.mveaLink;
+ this.$nextTick(() => {
+ var componentReference = 'mvea' + this.core.mveaType;
+ this.$parent.$parent.launchModal(this.core.mveaTitle, this.mveaLink, componentReference);
+ });
}
},
mounted() {
@@ -55,7 +58,7 @@ export default {
-
+
{{ this.txt.unverified }}
@@ -91,7 +94,7 @@ export default {
{{ this.txt.login }}
@@ -101,7 +104,7 @@ export default {
{{ this.mvea.tag }}
@@ -111,7 +114,7 @@ export default {
- {{ this.mvea.room }} {{ this.mvea.street }}
+ {{ this.mvea.room }} {{ this.mvea.street }}
{{ this.mvea.locality }}{{ this.mvea.locality != '' && this.mvea.state != '' ? ', ' : ''}}{{ this.mvea.state }}
@@ -127,7 +130,7 @@ export default {
{{ this.mvea.type.display_name }}
@@ -136,7 +139,7 @@ export default {
@@ -146,7 +149,7 @@ export default {
{{ this.mvea.type.display_name }}
diff --git a/app/webroot/js/comanage/components/mvea/mvea-modal.js b/app/webroot/js/comanage/components/mvea/mvea-modal.js
new file mode 100644
index 000000000..0977d3ae2
--- /dev/null
+++ b/app/webroot/js/comanage/components/mvea/mvea-modal.js
@@ -0,0 +1,49 @@
+/**
+ * COmanage Registry MVEA Modal JavaScript
+ *
+ * Portions licensed to the University Corporation for Advanced Internet
+ * Development, Inc. ("UCAID") under one or more contributor license agreements.
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership.
+ *
+ * UCAID licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @link https://www.internet2.edu/comanage COmanage Project
+ * @package registry
+ * @since COmanage Registry v5.0.0
+ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+ */
+
+export default {
+ props: {
+ modal: Object,
+ core: Object,
+ txt: Object
+ },
+ template: `
+
+
+
+
+
{{ this.modal.title }}
+
+
+
+
+
+
+
+
+ `
+}
\ No newline at end of file
diff --git a/app/webroot/js/comanage/components/mvea/mveas.js b/app/webroot/js/comanage/components/mvea/mveas.js
index 2b98a5292..bd3a7bfa0 100644
--- a/app/webroot/js/comanage/components/mvea/mveas.js
+++ b/app/webroot/js/comanage/components/mvea/mveas.js
@@ -48,6 +48,11 @@ export default {
return this.mveas?.[camelize(this.core.mveaType)]
}
},
+ methods: {
+ refresh() {
+ this.$parent.refreshComponent();
+ }
+ },
template: `