diff --git a/.gitignore b/.gitignore index 20ab4f93a8de..231ab1469771 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ !/ext/civi_pledge !/ext/civi_report !/ext/scheduled_communications +!/ext/user_dashboard backdrop/ bower_components CRM/Case/xml/configuration diff --git a/distmaker/core-ext.txt b/distmaker/core-ext.txt index 9e2a64087f9e..1021333ca7c7 100644 --- a/distmaker/core-ext.txt +++ b/distmaker/core-ext.txt @@ -35,3 +35,4 @@ civi_member civi_pledge civi_report scheduled_communications +user_dashboard diff --git a/ext/user_dashboard/ang/afsearchUserDashboard.aff.php b/ext/user_dashboard/ang/afsearchUserDashboard.aff.php new file mode 100644 index 000000000000..acb8944bc934 --- /dev/null +++ b/ext/user_dashboard/ang/afsearchUserDashboard.aff.php @@ -0,0 +1,32 @@ + 'search', + 'title' => E::ts('User Dashboard'), + 'server_route' => 'civicrm/user', + 'permission' => ['access Contact Dashboard'], + 'layout' => '', + // temporary, remove after merging https://github.com/civicrm/civicrm-core/pull/27783 + 'requires' => ['af', 'afCore', 'crmSearchDisplayTable'], +]; + +// Add displays for every SavedSearch tagged "UserDashboard" +$searchDisplays = civicrm_api4('SearchDisplay', 'get', [ + 'checkPermissions' => FALSE, + 'select' => ['name', 'label', 'type:name', 'saved_search_id.name'], + 'where' => [ + ['saved_search_id.is_current', '=', TRUE], + ['saved_search_id.tags:name', 'IN', ['UserDashboard']], + ], + 'orderBy' => ['name' => 'ASC'], +]); +foreach ($searchDisplays as $display) { + $afform['layout'] .= << + <{$display['type:name']} search-name="{$display['saved_search_id.name']}" display-name="$display[name]"> + + HTML; +} + +return $afform; diff --git a/ext/user_dashboard/info.xml b/ext/user_dashboard/info.xml new file mode 100644 index 000000000000..4e87e481b109 --- /dev/null +++ b/ext/user_dashboard/info.xml @@ -0,0 +1,36 @@ + + + user_dashboard + User Dashboard + Adds a page for users to see their contributions, memberships, etc. + AGPL-3.0 + + CiviCRM + info@civicrm.org + + + http://FIXME + http://FIXME + http://FIXME + http://www.gnu.org/licenses/agpl-3.0.html + + 2023-10-07 + 1.0 + alpha + + 5.68.alpha1 + + This extension is still experimental + + + + + + CRM/UserDashboard + 23.02.1 + crmUserDashboard + + + mgd-php@1.0.0 + + diff --git a/ext/user_dashboard/managed/0Tag_UserDashboard.mgd.php b/ext/user_dashboard/managed/0Tag_UserDashboard.mgd.php new file mode 100644 index 000000000000..14d533cafccb --- /dev/null +++ b/ext/user_dashboard/managed/0Tag_UserDashboard.mgd.php @@ -0,0 +1,27 @@ + 'Tag_UserDashboard', + 'entity' => 'Tag', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'label' => E::ts('User Dashboard'), + 'name' => 'UserDashboard', + 'description' => E::ts('Search will appear on the User Dashboard page'), + 'is_reserved' => TRUE, + 'used_for' => [ + 'civicrm_saved_search', + ], + 'color' => '#5d677b', + ], + 'match' => [ + 'name', + ], + ], + ], +]; diff --git a/ext/user_dashboard/managed/SavedSearch_UserDashboard_Groups.mgd.php b/ext/user_dashboard/managed/SavedSearch_UserDashboard_Groups.mgd.php new file mode 100644 index 000000000000..fb100db9d8e4 --- /dev/null +++ b/ext/user_dashboard/managed/SavedSearch_UserDashboard_Groups.mgd.php @@ -0,0 +1,157 @@ + 'SavedSearch_UserDashboard_Groups', + 'entity' => 'SavedSearch', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_Groups', + 'label' => E::ts('User Dashboard - Groups'), + 'api_entity' => 'Group', + 'api_params' => [ + 'version' => 4, + 'select' => [ + 'frontend_title', + 'Group_GroupContact_Contact_01.status:label', + 'MAX(Group_SubscriptionHistory_group_id_01.date) AS MAX_Group_SubscriptionHistory_group_id_01_date', + ], + 'orderBy' => [], + 'where' => [ + [ + 'Group_GroupContact_Contact_01.id', + '=', + 'user_contact_id', + ], + [ + 'visibility:name', + '=', + 'Public Pages', + ], + [ + 'is_active', + '=', + TRUE, + ], + ], + 'groupBy' => [ + 'id', + 'Group_GroupContact_Contact_01.id', + ], + 'join' => [ + [ + 'Contact AS Group_GroupContact_Contact_01', + 'LEFT', + 'GroupContact', + [ + 'id', + '=', + 'Group_GroupContact_Contact_01.group_id', + ], + ], + [ + 'SubscriptionHistory AS Group_SubscriptionHistory_group_id_01', + 'LEFT', + [ + 'id', + '=', + 'Group_SubscriptionHistory_group_id_01.group_id', + ], + [ + 'Group_SubscriptionHistory_group_id_01.contact_id', + '=', + '"user_contact_id"', + ], + ], + ], + 'having' => [], + ], + ], + 'match' => [ + 'name', + ], + 'chain' => [ + 'tag' => [ + 'EntityTag', 'save', [ + 'records' => [['entity_table' => 'civicrm_saved_search', 'entity_id' => '$id', 'tag_id:name' => 'UserDashboard']], + 'match' => ['entity_id', 'tag_id'], + ], + ], + ], + ], + ], + [ + 'name' => 'SavedSearch_UserDashboard_Groups_SearchDisplay_UserDashboard_Groups', + 'entity' => 'SearchDisplay', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_Groups', + 'label' => E::ts('Your Group(s)'), + 'saved_search_id.name' => 'UserDashboard_Groups', + 'type' => 'table', + 'settings' => [ + 'description' => NULL, + 'sort' => [ + [ + 'Group_GroupContact_Contact_01.status', + 'ASC', + ], + ], + 'limit' => 50, + 'pager' => [ + 'expose_limit' => TRUE, + 'hide_single' => TRUE, + ], + 'placeholder' => 1, + 'columns' => [ + [ + 'type' => 'field', + 'key' => 'frontend_title', + 'dataType' => 'String', + 'label' => E::ts('Group'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'Group_GroupContact_Contact_01.status:label', + 'dataType' => 'String', + 'label' => E::ts('Status'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'MAX_Group_SubscriptionHistory_group_id_01_date', + 'dataType' => 'Timestamp', + 'label' => E::ts('Since'), + 'sortable' => TRUE, + ], + ], + 'actions' => FALSE, + 'classes' => [ + 'table', + 'table-striped', + ], + 'cssRules' => [ + [ + 'disabled', + 'Group_GroupContact_Contact_01.status', + '=', + 'Removed', + ], + ], + ], + ], + 'match' => [ + 'name', + 'saved_search_id', + ], + ], + ], +]; diff --git a/ext/user_dashboard/managed/SavedSearch_UserDashboard_Pledges.mgd.php b/ext/user_dashboard/managed/SavedSearch_UserDashboard_Pledges.mgd.php new file mode 100644 index 000000000000..94dfe2e79b75 --- /dev/null +++ b/ext/user_dashboard/managed/SavedSearch_UserDashboard_Pledges.mgd.php @@ -0,0 +1,154 @@ + 'SavedSearch_UserDashboard_Pledges', + 'entity' => 'SavedSearch', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_Pledges', + 'label' => E::ts('User Dashboard - Pledges'), + 'api_entity' => 'Pledge', + 'api_params' => [ + 'version' => 4, + 'select' => [ + 'amount', + 'SUM(Pledge_PledgePayment_pledge_id_01.actual_amount) AS SUM_Pledge_PledgePayment_pledge_id_01_actual_amount', + 'financial_type_id:label', + 'create_date', + 'MIN(Pledge_PledgePayment_pledge_id_02.scheduled_date) AS MIN_Pledge_PledgePayment_pledge_id_02_scheduled_date', + 'MAX(Pledge_PledgePayment_pledge_id_02.scheduled_amount) AS MAX_Pledge_PledgePayment_pledge_id_02_scheduled_amount', + 'status_id:label', + ], + 'orderBy' => [], + 'where' => [ + ['contact_id', '=', 'user_contact_id'], + ], + 'groupBy' => [ + 'id', + ], + 'join' => [ + [ + 'PledgePayment AS Pledge_PledgePayment_pledge_id_01', + 'LEFT', + ['id', '=', 'Pledge_PledgePayment_pledge_id_01.pledge_id'], + ['Pledge_PledgePayment_pledge_id_01.status_id:name', '=', '"Completed"'], + ], + [ + 'PledgePayment AS Pledge_PledgePayment_pledge_id_02', + 'LEFT', + ['id', '=', 'Pledge_PledgePayment_pledge_id_02.pledge_id'], + ['Pledge_PledgePayment_pledge_id_02.status_id:name', '!=', '"Completed"'], + ], + ], + 'having' => [], + ], + ], + 'match' => [ + 'name', + ], + 'chain' => [ + 'tag' => [ + 'EntityTag', 'save', [ + 'records' => [['entity_table' => 'civicrm_saved_search', 'entity_id' => '$id', 'tag_id:name' => 'UserDashboard']], + 'match' => ['entity_id', 'tag_id'], + ], + ], + ], + ], + ], + [ + 'name' => 'SavedSearch_UserDashboard_Pledges_SearchDisplay_UserDashboard_Pledges', + 'entity' => 'SearchDisplay', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_Pledges', + 'label' => E::ts('Your Pledges'), + 'saved_search_id.name' => 'UserDashboard_Pledges', + 'type' => 'table', + 'settings' => [ + 'description' => NULL, + 'sort' => [], + 'limit' => 50, + 'pager' => [ + 'hide_single' => TRUE, + 'expose_limit' => TRUE, + ], + 'placeholder' => 1, + 'columns' => [ + [ + 'type' => 'field', + 'key' => 'amount', + 'dataType' => 'Money', + 'label' => E::ts('Pledged'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'SUM_Pledge_PledgePayment_pledge_id_01_actual_amount', + 'dataType' => 'Money', + 'label' => E::ts('Total Paid'), + 'sortable' => TRUE, + 'empty_value' => '0', + ], + [ + 'type' => 'field', + 'key' => 'financial_type_id:label', + 'dataType' => 'Integer', + 'label' => E::ts('Pledged For'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'create_date', + 'dataType' => 'Timestamp', + 'label' => E::ts('Pledge Made'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'MIN_Pledge_PledgePayment_pledge_id_02_scheduled_date', + 'dataType' => 'Timestamp', + 'label' => E::ts('Next Pay Date'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'MAX_Pledge_PledgePayment_pledge_id_02_scheduled_amount', + 'dataType' => 'Money', + 'label' => E::ts('Next Amount'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'status_id:label', + 'dataType' => 'Integer', + 'label' => E::ts('Status'), + 'sortable' => TRUE, + ], + ], + 'actions' => FALSE, + 'classes' => [ + 'table', + 'table-striped', + ], + ], + ], + 'match' => [ + 'name', + 'saved_search_id', + ], + ], + ], +]; diff --git a/ext/user_dashboard/managed/UserDashboard_Contributions.mgd.php b/ext/user_dashboard/managed/UserDashboard_Contributions.mgd.php new file mode 100644 index 000000000000..d71cbcf064d9 --- /dev/null +++ b/ext/user_dashboard/managed/UserDashboard_Contributions.mgd.php @@ -0,0 +1,122 @@ + 'SavedSearch_UserDashboard_Contributions', + 'entity' => 'SavedSearch', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_Contributions', + 'label' => E::ts('User Dashboard - Contributions'), + 'api_entity' => 'Contribution', + 'api_params' => [ + 'version' => 4, + 'select' => [ + 'total_amount', + 'financial_type_id:label', + 'contribution_status_id:label', + 'receive_date', + 'receipt_date', + ], + 'orderBy' => [], + 'where' => [ + ['contact_id', '=', 'user_contact_id'], + ], + 'groupBy' => [], + 'join' => [], + 'having' => [], + ], + ], + 'match' => [ + 'name', + ], + 'chain' => [ + 'tag' => [ + 'EntityTag', 'save', [ + 'records' => [['entity_table' => 'civicrm_saved_search', 'entity_id' => '$id', 'tag_id:name' => 'UserDashboard']], + 'match' => ['entity_id', 'tag_id'], + ], + ], + ], + ], + ], + [ + 'name' => 'SavedSearch_UserDashboard_Contributions_SearchDisplay_UserDashboard_Contributions', + 'entity' => 'SearchDisplay', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_Contributions', + 'label' => E::ts('Your Contribution(s)'), + 'saved_search_id.name' => 'UserDashboard_Contributions', + 'type' => 'table', + 'settings' => [ + 'description' => NULL, + 'sort' => [], + 'limit' => 50, + 'pager' => [ + 'hide_single' => TRUE, + 'expose_limit' => TRUE, + ], + 'placeholder' => 1, + 'columns' => [ + [ + 'type' => 'field', + 'key' => 'total_amount', + 'dataType' => 'String', + 'label' => E::ts('Total Amount'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'financial_type_id:label', + 'dataType' => 'String', + 'label' => E::ts('Type'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'receive_date', + 'dataType' => 'Date', + 'label' => E::ts('Date'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'receipt_date', + 'dataType' => 'Date', + 'label' => E::ts('Receipt Sent'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'contribution_status_id:label', + 'dataType' => 'String', + 'label' => E::ts('Status'), + 'sortable' => TRUE, + ], + ], + 'actions' => FALSE, + 'classes' => [ + 'table', + 'table-striped', + ], + ], + ], + 'match' => [ + 'name', + 'saved_search_id', + ], + ], + ], +]; diff --git a/ext/user_dashboard/managed/UserDashboard_Events.mgd.php b/ext/user_dashboard/managed/UserDashboard_Events.mgd.php new file mode 100644 index 000000000000..730889c76130 --- /dev/null +++ b/ext/user_dashboard/managed/UserDashboard_Events.mgd.php @@ -0,0 +1,114 @@ + 'SavedSearch_UserDashboard_Events', + 'entity' => 'SavedSearch', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_Events', + 'label' => E::ts('User Dashboard - Events'), + 'api_entity' => 'Participant', + 'api_params' => [ + 'version' => 4, + 'select' => [ + 'event_id.title', + 'role_id:label', + 'status_id:label', + 'event_id.start_date', + ], + 'orderBy' => [], + 'where' => [ + ['contact_id', '=', 'user_contact_id'], + ], + 'groupBy' => [], + 'join' => [], + 'having' => [], + ], + ], + 'match' => [ + 'name', + ], + 'chain' => [ + 'tag' => [ + 'EntityTag', 'save', [ + 'records' => [['entity_table' => 'civicrm_saved_search', 'entity_id' => '$id', 'tag_id:name' => 'UserDashboard']], + 'match' => ['entity_id', 'tag_id'], + ], + ], + ], + ], + ], + [ + 'name' => 'SavedSearch_UserDashboard_Events_SearchDisplay_UserDashboard_Events', + 'entity' => 'SearchDisplay', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_Events', + 'label' => E::ts('Your Event(s)'), + 'saved_search_id.name' => 'UserDashboard_Events', + 'type' => 'table', + 'settings' => [ + 'description' => NULL, + 'sort' => [], + 'limit' => 50, + 'pager' => [ + 'hide_single' => TRUE, + 'expose_limit' => TRUE, + ], + 'placeholder' => 1, + 'columns' => [ + [ + 'type' => 'field', + 'key' => 'event_id.title', + 'dataType' => 'String', + 'label' => E::ts('Event'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'event_id.start_date', + 'dataType' => 'Date', + 'label' => E::ts('Event Date'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'role_id:label', + 'dataType' => 'String', + 'label' => E::ts('Role'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'status_id:label', + 'dataType' => 'String', + 'label' => E::ts('Status'), + 'sortable' => TRUE, + ], + ], + 'actions' => FALSE, + 'classes' => [ + 'table', + 'table-striped', + ], + ], + ], + 'match' => [ + 'name', + 'saved_search_id', + ], + ], + ], +]; diff --git a/ext/user_dashboard/managed/UserDashboard_Memberships.mgd.php b/ext/user_dashboard/managed/UserDashboard_Memberships.mgd.php new file mode 100644 index 000000000000..a3b544457a09 --- /dev/null +++ b/ext/user_dashboard/managed/UserDashboard_Memberships.mgd.php @@ -0,0 +1,122 @@ + 'SavedSearch_UserDashboard_Memberships', + 'entity' => 'SavedSearch', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_Memberships', + 'label' => E::ts('User Dashboard - Memberships'), + 'api_entity' => 'Membership', + 'api_params' => [ + 'version' => 4, + 'select' => [ + 'membership_type_id:label', + 'status_id:label', + 'start_date', + 'end_date', + 'join_date', + ], + 'orderBy' => [], + 'where' => [ + ['contact_id', '=', 'user_contact_id'], + ], + 'groupBy' => [], + 'join' => [], + 'having' => [], + ], + ], + 'match' => [ + 'name', + ], + 'chain' => [ + 'tag' => [ + 'EntityTag', 'save', [ + 'records' => [['entity_table' => 'civicrm_saved_search', 'entity_id' => '$id', 'tag_id:name' => 'UserDashboard']], + 'match' => ['entity_id', 'tag_id'], + ], + ], + ], + ], + ], + [ + 'name' => 'SavedSearch_UserDashboard_Memberships_SearchDisplay_UserDashboard_Memberships', + 'entity' => 'SearchDisplay', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_Memberships', + 'label' => E::ts('Your Membership(s)'), + 'saved_search_id.name' => 'UserDashboard_Memberships', + 'type' => 'table', + 'settings' => [ + 'description' => NULL, + 'sort' => [], + 'limit' => 50, + 'pager' => [ + 'hide_single' => TRUE, + 'expose_limit' => TRUE, + ], + 'placeholder' => 1, + 'columns' => [ + [ + 'type' => 'field', + 'key' => 'membership_type_id:label', + 'dataType' => 'String', + 'label' => E::ts('Type'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'join_date', + 'dataType' => 'Date', + 'label' => E::ts('Member Since'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'start_date', + 'dataType' => 'Date', + 'label' => E::ts('Start Date'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'end_date', + 'dataType' => 'Date', + 'label' => E::ts('End Date'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'status_id:label', + 'dataType' => 'String', + 'label' => E::ts('Status'), + 'sortable' => TRUE, + ], + ], + 'actions' => FALSE, + 'classes' => [ + 'table', + 'table-striped', + ], + ], + ], + 'match' => [ + 'name', + 'saved_search_id', + ], + ], + ], +]; diff --git a/ext/user_dashboard/managed/UserDashboard_PCPs.mgd.php b/ext/user_dashboard/managed/UserDashboard_PCPs.mgd.php new file mode 100644 index 000000000000..f36a56b26b83 --- /dev/null +++ b/ext/user_dashboard/managed/UserDashboard_PCPs.mgd.php @@ -0,0 +1,106 @@ + 'SavedSearch_UserDashboard_PCPs', + 'entity' => 'SavedSearch', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_PCPs', + 'label' => E::ts('User Dashboard - PCPs'), + 'api_entity' => 'PCP', + 'api_params' => [ + 'version' => 4, + 'select' => [ + 'title', + 'status_id:label', + 'page_id.frontend_title', + ], + 'orderBy' => [], + 'where' => [ + ['contact_id', '=', 'user_contact_id'], + ], + 'groupBy' => [], + 'join' => [], + 'having' => [], + ], + ], + 'match' => [ + 'name', + ], + 'chain' => [ + 'tag' => [ + 'EntityTag', 'save', [ + 'records' => [['entity_table' => 'civicrm_saved_search', 'entity_id' => '$id', 'tag_id:name' => 'UserDashboard']], + 'match' => ['entity_id', 'tag_id'], + ], + ], + ], + ], + ], + [ + 'name' => 'SavedSearch_UserDashboard_PCPs_SearchDisplay_UserDashboard_PCPs', + 'entity' => 'SearchDisplay', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_PCPs', + 'label' => E::ts('Personal Campaign Pages'), + 'saved_search_id.name' => 'UserDashboard_PCPs', + 'type' => 'table', + 'settings' => [ + 'description' => NULL, + 'sort' => [], + 'limit' => 50, + 'pager' => [ + 'hide_single' => TRUE, + 'expose_limit' => TRUE, + ], + 'placeholder' => 1, + 'columns' => [ + [ + 'type' => 'field', + 'key' => 'title', + 'dataType' => 'String', + 'label' => E::ts('Title'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'status_id:label', + 'dataType' => 'String', + 'label' => E::ts('Type'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'page_id.frontend_title', + 'dataType' => 'String', + 'label' => E::ts('Campaign'), + 'sortable' => TRUE, + ], + ], + 'actions' => FALSE, + 'classes' => [ + 'table', + 'table-striped', + ], + ], + ], + 'match' => [ + 'name', + 'saved_search_id', + ], + ], + ], +]; diff --git a/ext/user_dashboard/managed/UserDashboard_Relationships.mgd.php b/ext/user_dashboard/managed/UserDashboard_Relationships.mgd.php new file mode 100644 index 000000000000..987c1dfca8ad --- /dev/null +++ b/ext/user_dashboard/managed/UserDashboard_Relationships.mgd.php @@ -0,0 +1,151 @@ + 'SavedSearch_UserDashboard_Relationships', + 'entity' => 'SavedSearch', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_Relationships', + 'label' => E::ts('User Dashboard - Relationships'), + 'api_entity' => 'RelationshipCache', + 'api_params' => [ + 'version' => 4, + 'select' => [ + 'near_relation:label', + 'RelationshipCache_Contact_far_contact_id_01.display_name', + 'start_date', + 'RelationshipCache_Contact_far_contact_id_01.address_primary.city', + 'RelationshipCache_Contact_far_contact_id_01.address_primary.state_province_id:label', + 'RelationshipCache_Contact_far_contact_id_01.email_primary.email', + 'RelationshipCache_Contact_far_contact_id_01.phone_primary.phone', + ], + 'orderBy' => [], + 'where' => [ + ['near_contact_id', '=', 'user_contact_id'], + ['is_current', '=', TRUE], + ], + 'groupBy' => [], + 'join' => [ + [ + 'Contact AS RelationshipCache_Contact_far_contact_id_01', + 'LEFT', + ['far_contact_id', '=', 'RelationshipCache_Contact_far_contact_id_01.id'], + ], + ], + 'having' => [], + ], + ], + 'match' => [ + 'name', + ], + 'chain' => [ + 'tag' => [ + 'EntityTag', 'save', [ + 'records' => [['entity_table' => 'civicrm_saved_search', 'entity_id' => '$id', 'tag_id:name' => 'UserDashboard']], + 'match' => ['entity_id', 'tag_id'], + ], + ], + ], + ], + ], + [ + 'name' => 'SavedSearch_UserDashboard_Relationships_SearchDisplay_UserDashboard_Relationships', + 'entity' => 'SearchDisplay', + 'cleanup' => 'unused', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'UserDashboard_Relationships', + 'label' => E::ts('Your Contacts / Organizations'), + 'saved_search_id.name' => 'UserDashboard_Relationships', + 'type' => 'table', + 'settings' => [ + 'description' => NULL, + 'sort' => [], + 'limit' => 50, + 'pager' => [ + 'hide_single' => TRUE, + 'expose_limit' => TRUE, + ], + 'placeholder' => 1, + 'columns' => [ + [ + 'type' => 'field', + 'key' => 'near_relation:label', + 'dataType' => 'String', + 'label' => E::ts('Relationship'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'RelationshipCache_Contact_far_contact_id_01.display_name', + 'dataType' => 'String', + 'label' => E::ts('With'), + 'sortable' => TRUE, + 'icons' => [ + [ + 'field' => 'RelationshipCache_Contact_far_contact_id_01.contact_sub_type:icon', + 'side' => 'left', + ], + [ + 'field' => 'RelationshipCache_Contact_far_contact_id_01.contact_type:icon', + 'side' => 'left', + ], + ], + ], + [ + 'type' => 'field', + 'key' => 'start_date', + 'dataType' => 'Date', + 'label' => E::ts('Since'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'RelationshipCache_Contact_far_contact_id_01.address_primary.city', + 'dataType' => 'String', + 'label' => E::ts('City'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'RelationshipCache_Contact_far_contact_id_01.address_primary.state_province_id:label', + 'dataType' => 'Integer', + 'label' => E::ts('State/Prov'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'RelationshipCache_Contact_far_contact_id_01.email_primary.email', + 'dataType' => 'String', + 'label' => E::ts('Email'), + 'sortable' => TRUE, + ], + [ + 'type' => 'field', + 'key' => 'RelationshipCache_Contact_far_contact_id_01.phone_primary.phone', + 'dataType' => 'String', + 'label' => E::ts('Phone'), + 'sortable' => TRUE, + ], + ], + 'actions' => FALSE, + 'classes' => [ + 'table', + 'table-striped', + ], + ], + ], + 'match' => [ + 'name', + 'saved_search_id', + ], + ], + ], +]; diff --git a/ext/user_dashboard/user_dashboard.civix.php b/ext/user_dashboard/user_dashboard.civix.php new file mode 100644 index 000000000000..3f00bdefdefe --- /dev/null +++ b/ext/user_dashboard/user_dashboard.civix.php @@ -0,0 +1,200 @@ +getUrl(self::LONG_NAME), '/'); + } + return CRM_Core_Resources::singleton()->getUrl(self::LONG_NAME, $file); + } + + /** + * Get the path of a resource file (in this extension). + * + * @param string|NULL $file + * Ex: NULL. + * Ex: 'css/foo.css'. + * @return string + * Ex: '/var/www/example.org/sites/default/ext/org.example.foo'. + * Ex: '/var/www/example.org/sites/default/ext/org.example.foo/css/foo.css'. + */ + public static function path($file = NULL) { + // return CRM_Core_Resources::singleton()->getPath(self::LONG_NAME, $file); + return __DIR__ . ($file === NULL ? '' : (DIRECTORY_SEPARATOR . $file)); + } + + /** + * Get the name of a class within this extension. + * + * @param string $suffix + * Ex: 'Page_HelloWorld' or 'Page\\HelloWorld'. + * @return string + * Ex: 'CRM_Foo_Page_HelloWorld'. + */ + public static function findClass($suffix) { + return self::CLASS_PREFIX . '_' . str_replace('\\', '_', $suffix); + } + +} + +use CRM_UserDashboard_ExtensionUtil as E; + +/** + * (Delegated) Implements hook_civicrm_config(). + * + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_config + */ +function _user_dashboard_civix_civicrm_config($config = NULL) { + static $configured = FALSE; + if ($configured) { + return; + } + $configured = TRUE; + + $extRoot = __DIR__ . DIRECTORY_SEPARATOR; + $include_path = $extRoot . PATH_SEPARATOR . get_include_path(); + set_include_path($include_path); + // Based on , this does not currently require mixin/polyfill.php. +} + +/** + * Implements hook_civicrm_install(). + * + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_install + */ +function _user_dashboard_civix_civicrm_install() { + _user_dashboard_civix_civicrm_config(); + // Based on , this does not currently require mixin/polyfill.php. +} + +/** + * (Delegated) Implements hook_civicrm_enable(). + * + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_enable + */ +function _user_dashboard_civix_civicrm_enable(): void { + _user_dashboard_civix_civicrm_config(); + // Based on , this does not currently require mixin/polyfill.php. +} + +/** + * Inserts a navigation menu item at a given place in the hierarchy. + * + * @param array $menu - menu hierarchy + * @param string $path - path to parent of this item, e.g. 'my_extension/submenu' + * 'Mailing', or 'Administer/System Settings' + * @param array $item - the item to insert (parent/child attributes will be + * filled for you) + * + * @return bool + */ +function _user_dashboard_civix_insert_navigation_menu(&$menu, $path, $item) { + // If we are done going down the path, insert menu + if (empty($path)) { + $menu[] = [ + 'attributes' => array_merge([ + 'label' => $item['name'] ?? NULL, + 'active' => 1, + ], $item), + ]; + return TRUE; + } + else { + // Find an recurse into the next level down + $found = FALSE; + $path = explode('/', $path); + $first = array_shift($path); + foreach ($menu as $key => &$entry) { + if ($entry['attributes']['name'] == $first) { + if (!isset($entry['child'])) { + $entry['child'] = []; + } + $found = _user_dashboard_civix_insert_navigation_menu($entry['child'], implode('/', $path), $item); + } + } + return $found; + } +} + +/** + * (Delegated) Implements hook_civicrm_navigationMenu(). + */ +function _user_dashboard_civix_navigationMenu(&$nodes) { + if (!is_callable(['CRM_Core_BAO_Navigation', 'fixNavigationMenu'])) { + _user_dashboard_civix_fixNavigationMenu($nodes); + } +} + +/** + * Given a navigation menu, generate navIDs for any items which are + * missing them. + */ +function _user_dashboard_civix_fixNavigationMenu(&$nodes) { + $maxNavID = 1; + array_walk_recursive($nodes, function($item, $key) use (&$maxNavID) { + if ($key === 'navID') { + $maxNavID = max($maxNavID, $item); + } + }); + _user_dashboard_civix_fixNavigationMenuItems($nodes, $maxNavID, NULL); +} + +function _user_dashboard_civix_fixNavigationMenuItems(&$nodes, &$maxNavID, $parentID) { + $origKeys = array_keys($nodes); + foreach ($origKeys as $origKey) { + if (!isset($nodes[$origKey]['attributes']['parentID']) && $parentID !== NULL) { + $nodes[$origKey]['attributes']['parentID'] = $parentID; + } + // If no navID, then assign navID and fix key. + if (!isset($nodes[$origKey]['attributes']['navID'])) { + $newKey = ++$maxNavID; + $nodes[$origKey]['attributes']['navID'] = $newKey; + $nodes[$newKey] = $nodes[$origKey]; + unset($nodes[$origKey]); + $origKey = $newKey; + } + if (isset($nodes[$origKey]['child']) && is_array($nodes[$origKey]['child'])) { + _user_dashboard_civix_fixNavigationMenuItems($nodes[$origKey]['child'], $maxNavID, $nodes[$origKey]['attributes']['navID']); + } + } +} diff --git a/ext/user_dashboard/user_dashboard.php b/ext/user_dashboard/user_dashboard.php new file mode 100644 index 000000000000..7fe4ad88ade7 --- /dev/null +++ b/ext/user_dashboard/user_dashboard.php @@ -0,0 +1,33 @@ +