diff --git a/config/install/user.role.az_content_admin.yml b/config/install/user.role.az_content_admin.yml index a0c0d26f32..8c5ff1a8d9 100644 --- a/config/install/user.role.az_content_admin.yml +++ b/config/install/user.role.az_content_admin.yml @@ -35,6 +35,7 @@ permissions: - 'batch update workbench access' - 'bypass node access' - 'bypass workbench access' + - 'create az_opportunity content' - 'create content translations' - 'create new books' - 'create terms in az_academic_programs' @@ -56,6 +57,7 @@ permissions: - 'delete any az_flexible_page content' - 'delete any az_image media' - 'delete any az_news content' + - 'delete any az_opportunity content' - 'delete any az_person content' - 'delete any az_publication content' - 'delete any az_remote_video media' diff --git a/config/install/user.role.az_content_editor.yml b/config/install/user.role.az_content_editor.yml index 1273afece8..e6228a7531 100644 --- a/config/install/user.role.az_content_editor.yml +++ b/config/install/user.role.az_content_editor.yml @@ -49,6 +49,7 @@ permissions: - 'create az_flexible_page content' - 'create az_image media' - 'create az_news content' + - 'create az_opportunity content' - 'create az_person content' - 'create az_publication content' - 'create az_quick_links block content' @@ -70,6 +71,7 @@ permissions: - 'delete own az_flexible_page content' - 'delete own az_image media' - 'delete own az_news content' + - 'delete own az_opportunity content' - 'delete own az_person content' - 'delete own az_publication content' - 'delete own az_remote_video media' @@ -86,6 +88,7 @@ permissions: - 'edit any az_flexible_page content' - 'edit any az_image media' - 'edit any az_news content' + - 'edit any az_opportunity content' - 'edit any az_person content' - 'edit any az_publication content' - 'edit any az_quick_links block content' @@ -102,6 +105,7 @@ permissions: - 'edit own az_flexible_page content' - 'edit own az_image media' - 'edit own az_news content' + - 'edit own az_opportunity content' - 'edit own az_person content' - 'edit own az_publication content' - 'edit own az_remote_video media' @@ -128,6 +132,7 @@ permissions: - 'revert az_event revisions' - 'revert az_flexible_page revisions' - 'revert az_news revisions' + - 'revert az_opportunity revisions' - 'revert az_person revisions' - 'revert az_publication revisions' - 'revert book revisions' @@ -158,6 +163,7 @@ permissions: - 'view az_event revisions' - 'view az_flexible_page revisions' - 'view az_news revisions' + - 'view az_opportunity revisions' - 'view az_person revisions' - 'view az_publication revisions' - 'view book revisions' diff --git a/modules/custom/az_core/config/install/smart_title.settings.yml b/modules/custom/az_core/config/install/smart_title.settings.yml index d28299b790..4c6b7a82b6 100644 --- a/modules/custom/az_core/config/install/smart_title.settings.yml +++ b/modules/custom/az_core/config/install/smart_title.settings.yml @@ -4,6 +4,7 @@ smart_title: - 'node:az_event' - 'node:az_news' - 'node:az_flexible_page' + - 'node:az_opportunity' - 'node:az_person' - 'node:az_publication' - 'taxonomy_term:az_event_categories' diff --git a/modules/custom/az_opportunity/az_opportunity.info.yml b/modules/custom/az_opportunity/az_opportunity.info.yml new file mode 100644 index 0000000000..b7f81a7a94 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity.info.yml @@ -0,0 +1,32 @@ +name: Quickstart Opportunity +description: 'Provides an Opportunity content type and related configuration. Use this content type to add non-academic opportunities such as Scholarships, Internships or Job Opportunities to your site.' +core_version_requirement: ^10 || ^11 || ^12 +type: module +package: The University of Arizona - Experimental +lifecycle: experimental +lifecycle_link: 'https://github.com/az-digital/az_quickstart/blob/main/RELEASES.md#experimental-features' + +dependencies: + - az_core:az_core + - calendar_link:calendar_link + - date_ap_style:date_ap_style + - field_group:field_group + - jquery_ui_datepicker:jquery_ui_datepicker + - drupal:datetime_range + - drupal:field + - drupal:file + - drupal:link + - drupal:link_class + - drupal:media + - drupal:media_library + - drupal:menu_ui + - drupal:node + - drupal:path + - drupal:taxonomy + - drupal:text + - drupal:user + - pathauto:pathauto + - smart_date:smart_date + - smart_date:smart_date_recur + - smart_title:smart_title + - views_bootstrap:views_bootstrap diff --git a/modules/custom/az_opportunity/az_opportunity.libraries.yml b/modules/custom/az_opportunity/az_opportunity.libraries.yml new file mode 100644 index 0000000000..580f650c10 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity.libraries.yml @@ -0,0 +1,6 @@ +az_opportunity: + css: + theme: + css/az_opportunity.css: {} + dependencies: + - az_barrio/arizona-bootstrap-css diff --git a/modules/custom/az_opportunity/az_opportunity.module b/modules/custom/az_opportunity/az_opportunity.module new file mode 100644 index 0000000000..e4e8247bb4 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity.module @@ -0,0 +1,15 @@ +getType() === 'az_opportunity') { + $variables['#attached']['library'][] = 'az_opportunity/az_opportunity'; + } +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.info.yml b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.info.yml new file mode 100644 index 0000000000..68857f3e5e --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.info.yml @@ -0,0 +1,22 @@ +name: Quickstart Opportunity - Trellis Opportunity Importer +type: module +description: 'Import opportunities from Trellis Programs, the official University of Arizona program management tool.' +core_version_requirement: ^11.3 || ^12 +package: 'The University of Arizona - Experimental' +lifecycle: experimental +lifecycle_link: 'https://github.com/az-digital/az_quickstart/blob/main/RELEASES.md#experimental-features' +php: 8.0 + +dependencies: + - az_core:az_core + - az_enterprise_attributes_import:az_enterprise_attributes_import + - az_opportunity:az_opportunity + - az_migration:az_migration_remote + - drupal:views + - drupal:migrate + - migrate_plus:migrate_plus + - migrate_tools:migrate_tools + - migrate_queue_importer:migrate_queue_importer + - views_remote_data:views_remote_data + +configure: az_opportunity_trellis.settings diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.install b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.install new file mode 100644 index 0000000000..4906f07e42 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.install @@ -0,0 +1,35 @@ +install(['views_remote_data']); +} + +/** + * Ensure az_opp_recurring_import_rule entity type is installed. + */ +function az_opportunity_trellis_update_1021001() { + $changes = \Drupal::entityDefinitionUpdateManager()->getChangeList(); + $status = $changes['az_opp_recurring_import_rule']['entity_type'] ?? ''; + // Determine if recurring import rule entity needs to be created. + if ($status === EntityDefinitionUpdateManagerInterface::DEFINITION_CREATED) { + $entity_type_definition = \Drupal::service('entity_type.manager')->getDefinition('az_opp_recurring_import_rule'); + \Drupal::entityDefinitionUpdateManager()->installEntityType($entity_type_definition); + } +} + +/** + * Ensure az_migration_remote is installed. + */ +function az_opportunity_trellis_update_1021301() { + \Drupal::service('module_installer')->install(['az_migration_remote']); +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.links.action.yml b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.links.action.yml new file mode 100644 index 0000000000..a5e45f3e3a --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.links.action.yml @@ -0,0 +1,5 @@ +entity.az_opp_recurring_import_rule.add_form: + route_name: 'entity.az_opp_recurring_import_rule.add_form' + title: 'Add Recurring Import Rule' + appears_on: + - entity.az_opp_recurring_import_rule.collection diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.links.task.yml b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.links.task.yml new file mode 100644 index 0000000000..bb1e30e836 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.links.task.yml @@ -0,0 +1,18 @@ +az_opportunity_trellis.az_opportunity_trellis_settings_task: + route_name: az_opportunity_trellis.settings + title: 'AZ Trellis Opportunity Importer' + base_route: az_core.az_settings + weight: 0 + +az_opportunity.import_form_task: + title: 'Trellis opportunity importer' + route_name: view.az_opportunity_trellis_import.page_1 + parent_id: system.admin_content + description: 'Import opportunities from the Trellis Opportunity API.' + weight: 101 + +az_opportunity_trellis.az_opp_recurring_import_rules_tab: + route_name: entity.az_opp_recurring_import_rule.collection + title: 'Recurring Opportunity Imports' + base_route: az_core.az_settings + weight: 5 diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.module b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.module new file mode 100644 index 0000000000..13eb9fb082 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.module @@ -0,0 +1,206 @@ + [ + 'base hook' => 'views_view', + ], + ]; +} + +/** + * Implements hook_views_pre_render(). + * + * Suppresses the empty state message on the import view when no search + * has been performed yet (initial page load or blank form submit). + */ +function az_opportunity_trellis_views_pre_render(ViewExecutable $view) { + if ($view->id() !== 'az_opportunity_trellis_import' || $view->current_display !== 'page_1') { + return; + } + $input = $view->getExposedInput(); + // Strip the form submit key and blank values to detect a real search. + unset($input['op']); + $meaningful = array_filter($input, fn($v) => $v !== '' && $v !== [] && $v !== NULL); + if (empty($meaningful)) { + $view->empty = []; + } +} + +/** + * Implements hook_form_FORM_ID_alter() for node_az_opportunity_edit_form. + * + * Adds warning message and disables opportunity detail + * form elements on opportunities + * imported from Trellis Opportunities. + */ +function az_opportunity_trellis_form_node_az_opportunity_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) { + + $form_object = $form_state->getFormObject(); + if ($form_object instanceof EntityFormInterface) { + /** @var \Drupal\node\NodeInterface $node */ + $node = $form_object->getEntity(); + $trellis_id = $node->get('field_az_trellis_id')->getString(); + if (!empty($trellis_id)) { + $trellis_link_url = TrellisHelper::$opportunityViewBasePath . $trellis_id . '/view'; + $trellis_warning = t('This opportunity has been imported from Trellis Opportunities. Opportunity details can only be edited by a Trellis user in Trellis Opportunities.', [ + '@trellis-url' => $trellis_link_url, + ]); + \Drupal::messenger()->addWarning($trellis_warning); + + $disabled_fields = [ + 'title', + 'field_az_application_date', + 'field_az_application_link', + 'field_az_audiences', + 'field_az_opportunity_credit', + 'field_az_eligibility', + 'field_az_enterprise_attributes', + 'field_az_incentives', + 'field_az_opportunity_location', + 'field_az_modality', + 'field_az_offered', + 'field_az_ongoing', + 'field_az_opportunity_type', + 'field_az_body', + 'field_az_parent_account', + 'field_az_program_date', + 'field_az_program_length', + 'field_az_program_website', + 'field_az_topic', + 'field_az_trellis_imported_date', + 'field_az_trellis_id', + ]; + foreach ($disabled_fields as $field) { + $form[$field]['#disabled'] = TRUE; + } + + $no_access_fields = [ + 'field_az_body', + 'field_az_eligibility', + ]; + foreach ($no_access_fields as $field) { + $form[$field]['#access'] = FALSE; + } + } + } +} + +/** + * Gather exposed API parameters from view. + * + * @param mixed $form + * An associative array containing the structure of the form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + * + * @return array + * The remote API search values. + */ +function az_opportunity_trellis_gather_filter_options(&$form, FormStateInterface $form_state) { + $search = []; + /** @var \Drupal\views\ViewExecutable $view */ + $view = $form_state->get('view'); + // Consult the filter handlers of the view. + if (!empty($view->filter)) { + /** @var \Drupal\views\Plugin\views\ViewsHandlerInterface[] $handlers */ + $handlers = $view->filter; + // Get exposed search information. + $input = $view->getExposedInput(); + if (empty($input)) { + return []; + } + // Loops through handlers to find inputs we want. + /** @var \Drupal\views\Plugin\views\filter\FilterPluginBase $handler */ + foreach ($handlers as $handler) { + if ($handler->isExposed()) { + $info = $handler->exposedInfo(); + $identifier = $info['value'] ?? ''; + // Make sure our input for this exposed filter isn't NULL. + // This won't normally happen in an actual GET form. + if (!isset($input[$identifier])) { + $input[$identifier] = ''; + } + // Check if the handler validates versus the input. + if ($handler->acceptExposedInput($input)) { + // If the handler accepts the input, bundle it up. + $value = $input[$identifier] ?? ''; + if (!empty($identifier) && !empty($value)) { + if ($handler instanceof AZOpportunityTrellisViewsAttributeFilter) { + // Attributes handled separately since they are from a remote API. + $search['attributes'][$identifier] = $value; + } + else { + // Map exposed filter identifiers to entity property names. + $identifier_to_property = [ + 'property' => 'opportunity_name', + 'property_2' => 'account_id', + 'parent_account' => 'parent_account_name', + ]; + $property = $identifier_to_property[$identifier] ?? $identifier; + $search[$property] = $value; + } + } + } + } + } + } + // Don't return id or date fields, unnecessary for recurring imports. + unset($search['id']); + unset($search['start']); + unset($search['modified']); + return $search; +} + +/** + * Implements hook_form_FORM_ID_alter(). + * + * Add clickable link that opens import configuration modal. + */ +function az_opportunity_trellis_form_views_exposed_form_alter(&$form, FormStateInterface $form_state, $form_id) { + + $view = $form_state->get('view'); + if (($view->id() === 'az_opportunity_trellis_import') && ($view->current_display === 'page_1')) { + + // Don't create configuration link if user does not have permission. + if (!\Drupal::currentUser()->hasPermission('administer quickstart configuration')) { + return; + } + $search = az_opportunity_trellis_gather_filter_options($form, $form_state); + if (!empty($search)) { + // We cannot use an ajax response here to open a dialog. + // Exposed forms do not support ajax callbacks. Cache search parameters. + // Compute cache key of parameters. + $key = 'az_opp_recurring_import_modal:' . Crypt::hashBase64(serialize($search)); + $expire = time() + 1200; + // Cache the search. + \Drupal::service('cache.default')->set($key, $search, $expire); + $form['#attached']['library'][] = 'core/drupal.dialog.ajax'; + // Add a link to open the modal. + $form['actions']['recurring'] = [ + '#type' => 'link', + '#title' => t('Create Recurring Import'), + '#url' => Url::fromRoute('entity.az_opp_recurring_import_rule.modal'), + // Pass the search parameters cache key as an argument. + '#options' => ['query' => ['search' => $key]], + '#attributes' => ['class' => ['use-ajax', 'button']], + ]; + } + } +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.routing.yml b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.routing.yml new file mode 100644 index 0000000000..26155ef254 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.routing.yml @@ -0,0 +1,47 @@ +az_opportunity_trellis.settings: + path: '/admin/config/az-quickstart/settings/az-opportunity-trellis' + defaults: + _form: '\Drupal\az_opportunity_trellis\Form\TrellisOpportunitySettingsForm' + _title: 'Trellis Opportunity Importer Settings' + requirements: + _permission: 'administer quickstart configuration' + +entity.az_opp_recurring_import_rule.collection: + path: '/admin/config/az-quickstart/settings/az-opportunity-recurring-import-rule' + defaults: + _entity_list: 'az_opp_recurring_import_rule' + _title: 'Recurring Import Rule configuration' + requirements: + _permission: 'administer quickstart configuration' + +entity.az_opp_recurring_import_rule.add_form: + path: '/admin/config/az-quickstart/settings/az-opportunity-recurring-import-rule/add' + defaults: + _entity_form: 'az_opp_recurring_import_rule.add' + _title: 'Add a recurring import rule' + requirements: + _permission: 'administer quickstart configuration' + +entity.az_opp_recurring_import_rule.edit_form: + path: '/admin/config/az-quickstart/settings/az-opportunity-recurring-import-rule/{az_opp_recurring_import_rule}' + defaults: + _entity_form: 'az_opp_recurring_import_rule.edit' + _title: 'Edit a recurring import rule' + requirements: + _permission: 'administer quickstart configuration' + +entity.az_opp_recurring_import_rule.delete_form: + path: '/admin/config/az-quickstart/settings/az-opportunity-recurring-import-rule/{az_opp_recurring_import_rule}/delete' + defaults: + _entity_form: 'az_opp_recurring_import_rule.delete' + _title: 'Delete a recurring import rule' + requirements: + _permission: 'administer quickstart configuration' + +entity.az_opp_recurring_import_rule.modal: + path: '/admin/az-opportunity-trellis-modal' + defaults: + _title: 'Entity Az Recurring Import Rule Modal' + _controller: '\Drupal\az_opportunity_trellis\Controller\AZRecurringImportModalController' + requirements: + _permission: 'administer quickstart configuration' diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.services.yml b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.services.yml new file mode 100644 index 0000000000..cab26fdcf7 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.services.yml @@ -0,0 +1,17 @@ +services: + _defaults: + autoconfigure: true + az_opportunity_trellis.trellis_helper: + class: Drupal\az_opportunity_trellis\TrellisHelper + arguments: + - '@config.factory' + - '@http_client' + - '@cache.default' + - '@entity_type.manager' + az_opportunity_trellis.trellis_opportunity_data: + class: Drupal\az_opportunity_trellis\EventSubscriber\AZOpportunityTrellisDataSubscriber + arguments: + - '@az_opportunity_trellis.trellis_helper' + - '@messenger' + - '@entity_type.manager' + - '@current_user' diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.views.inc b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.views.inc new file mode 100644 index 0000000000..f9b70955c3 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/az_opportunity_trellis.views.inc @@ -0,0 +1,146 @@ + t('Trellis Opportunities'), + 'query_id' => 'views_remote_data_query', + ]; + $data['az_opportunity_trellis_data']['Id'] = [ + 'title' => t('Trellis Opportunity ID'), + 'help' => t('Unique key of Trellis opportunity.'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Length_Of_Program__c'] = [ + 'title' => t('Trellis Opportunity Length of Program'), + 'help' => t('How long does this program typically last'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Incentives__c'] = [ + 'title' => t('Trellis Opportunity Incentives'), + 'help' => t('Does this program have incentives?'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Credit_Type__c'] = [ + 'title' => t('Trellis Opportunity Credits'), + 'help' => t('What credits does this opportunity offer'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Location__c'] = [ + 'title' => t('Trellis Opportunity Location'), + 'help' => t('Where this opportunity takes place'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Program_Website__c'] = [ + 'title' => t('Trellis Opportunity Program Website'), + 'help' => t('Link to Program website'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Program_Description__c'] = [ + 'title' => t('Trellis Opportunity Description'), + 'help' => t('Description'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Eligibility__c'] = [ + 'title' => t('Trellis Opportunity Eligibility'), + 'help' => t('Eligibility'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Application_Open__c'] = [ + 'title' => t('Trellis Opportunity Application Open Date'), + 'help' => t('When the applications are open'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Application_Closed__c'] = [ + 'title' => t('Trellis Opportunity Application Closed Date'), + 'help' => t('When the applications are closed'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Start_Date__c'] = [ + 'title' => t('Trellis Opportunity Program Start Date'), + 'help' => t('When the Program starts'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['End_Date__c'] = [ + 'title' => t('Trellis Opportunity Program End Date'), + 'help' => t('When the Program ends'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Ongoing__c'] = [ + 'title' => t('Trellis Opportunity Ongoing'), + 'help' => t('Does this opportunity repeat'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Last_Modified_Date'] = [ + 'title' => t('Trellis Opportunity Last Modified Date'), + 'help' => t('When the opportunity was last edited'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Parent_Account_Name'] = [ + 'title' => t('Trellis Opportunity Parent Account Name'), + 'help' => t('Parent Opportunity Name'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Parent_Id'] = [ + 'title' => t('Trellis Opportunity Parent Id'), + 'help' => t('Parent Opportunity ID'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Owner_NetID'] = [ + 'title' => t('Trellis Opportunity Owner NetID'), + 'help' => t('Opportunity Owner Netid'), + 'field' => [ + 'id' => 'az_opportunity_trellis_views_field', + ], + ]; + $data['az_opportunity_trellis_data']['Attributes'] = [ + 'title' => t('Enterprise Attribute'), + 'help' => t('Trellis opportunity search API enterprise attributes'), + 'filter' => [ + 'id' => 'az_opportunity_trellis_views_attribute_filter', + ], + ]; + return $data; +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/config/install/az_opportunity_trellis.settings.yml b/modules/custom/az_opportunity/az_opportunity_trellis/config/install/az_opportunity_trellis.settings.yml new file mode 100644 index 0000000000..1797962824 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/config/install/az_opportunity_trellis.settings.yml @@ -0,0 +1 @@ +api_hostname: 'api.eips.arizona.edu' diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/config/install/migrate_plus.migration.az_trellis_opportunities.yml b/modules/custom/az_opportunity/az_opportunity_trellis/config/install/migrate_plus.migration.az_trellis_opportunities.yml new file mode 100644 index 0000000000..4ad9da7987 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/config/install/migrate_plus.migration.az_trellis_opportunities.yml @@ -0,0 +1,293 @@ +langcode: en +status: true +dependencies: { } +id: az_trellis_opportunities +class: null +idMap: { } +field_plugin_method: null +cck_plugin_method: null +migration_tags: + - Opportunities +migration_group: az_trellis_opportunities +label: 'Trellis Opportunities' +source: + plugin: az_trellis_opportunities_api + trellis_ids: { } + track_changes: true + fields: + - + name: id + label: ID + selector: Id + - + name: name + label: Name + selector: Name + - + name: start_options + label: 'Start Options' + selector: Start_Options__c + - + name: program_format + label: 'Program Format' + selector: Program_Format__c + - + name: program_length + label: 'Program Length' + selector: Length_Of_Program__c + - + name: incentives + label: Incentives + selector: Incentives__c + - + name: credit_type + label: 'Credit Type' + selector: Credit_Type__c + - + name: location + label: Location + selector: Location__c + - + name: program_website + label: 'Program Website' + selector: Program_Website__c + - + name: description + label: 'Program Description' + selector: Program_Description__c + - + name: eligibility + label: Eligibility + selector: Eligibility__c + - + name: topic + label: Topic + selector: Topic__c + - + name: application_form_url + label: 'Application Form URL' + selector: Application_Form_URL__c + - + name: audiences + label: Audiences + selector: Audiences__c + - + name: application_open + label: 'Application Open Date' + selector: Application_Open__c + - + name: application_closed + label: 'Application Closed Date' + selector: Application_Closed__c + - + name: start_date + label: 'Program Start Date' + selector: Start_Date__c + - + name: end_date + label: 'Program End Date' + selector: End_Date__c + - + name: ongoing + label: Ongoing + selector: Ongoing__c + - + name: imported_date + label: 'Last Modified Date' + selector: Last_Modified_Date + - + name: parent_account + label: 'Parent Account Name' + selector: Parent_Account_Name + - + name: program_type + label: 'Program Type' + selector: Program_Type__c + - + name: audiences + label: Audiences + selector: Audiences__c + - + name: topic + label: Topic + selector: Topic__c + - + name: program_type + label: 'Program Type' + selector: Program_Type__c + - + name: publish + label: Publish + selector: Publish_Formula + - + name: owner_netid + label: 'Owner NetID' + selector: Owner_NetID + ids: + id: + type: string +process: + field_az_enterprise_attributes: + - plugin: callback + callable: array_filter + source: + - audiences + - topic + - program_type + - program_format + - + plugin: multiple_values + - + plugin: callback + callable: trim + - + plugin: single_value + - + plugin: entity_lookup + entity_type: taxonomy_term + bundle_key: vid + bundle: az_enterprise_attributes + value_key: name + ignore_case: true + title: name + field_az_trellis_id: id + field_az_offered: + - + plugin: skip_on_empty + method: process + source: start_options + - + plugin: entity_generate + entity_type: taxonomy_term + bundle_key: vid + bundle: az_opportunity_semester + source: start_options + value_key: name + ignore_case: true + field_az_opportunity_format: + - + plugin: skip_on_empty + method: process + - + plugin: explode + source: program_format + delimiter: ', ' + - + plugin: multiple_values + - + plugin: static_map + map: + 'Hybrid': hybrid + 'In-Person': in_person + 'Virtual': virtual + field_az_program_length: program_length + field_az_incentives: + - + plugin: skip_on_empty + method: process + source: incentives + - + plugin: static_map + source: incentives + map: + 'Yes': yes + 'No': no + 'Inquire Within': inquire_within + field_az_opportunity_credit: + - + plugin: skip_on_empty + method: process + source: credit_type + - + plugin: explode + delimiter: ';' + - + plugin: callback + callable: trim + - + plugin: multiple_values + - + plugin: static_map + map: + 'Non-Credit': non_credit + 'UA Credit': ua_credit + 'Transfer Credit': transfer_credit + field_az_opportunity_location: location + field_az_program_website/uri: program_website + field_az_program_website/title: + - + plugin: default_value + default_value: 'Program Website' + field_az_eligibility/value: eligibility + field_az_eligibility/format: + plugin: default_value + default_value: az_standard + field_az_body/value: description + field_az_body/format: + plugin: default_value + default_value: az_standard + field_az_application_link/uri: + - + plugin: az_extract_url + source: application_form_url + field_az_application_link/title: + - + plugin: default_value + default_value: 'Apply now' + field_az_application_date/value: + - + plugin: format_date + source: application_open + from_format: Y-m-d + to_format: 'Y-m-d\TH:i:s' + field_az_application_date/end_value: + - + plugin: format_date + source: application_closed + from_format: Y-m-d + to_format: 'Y-m-d\TH:i:s' + field_az_program_date/value: + - + plugin: format_date + source: start_date + from_format: Y-m-d + to_format: 'Y-m-d\TH:i:s' + field_az_program_date/end_value: + - + plugin: format_date + source: end_date + from_format: Y-m-d + to_format: 'Y-m-d\TH:i:s' + field_az_ongoing: + - + plugin: skip_on_empty + method: process + source: ongoing + - + plugin: static_map + source: ongoing + map: + 'false': 0 + 'true': 1 + field_az_trellis_imported_date: + - + plugin: format_date + source: imported_date + from_format: 'Y-m-d\TH:i:s.vp' + to_format: 'Y-m-d\TH:i:s' + field_az_parent_account: parent_account + status: + - + plugin: get + source: publish + - + plugin: default_value + strict: true + default_value: 0 +destination: + plugin: 'entity:node' + default_bundle: az_opportunity + validate: false +migration_dependencies: + null +include: null diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/config/install/migrate_plus.migration_group.az_trellis_opportunities.yml b/modules/custom/az_opportunity/az_opportunity_trellis/config/install/migrate_plus.migration_group.az_trellis_opportunities.yml new file mode 100644 index 0000000000..a6694b66d8 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/config/install/migrate_plus.migration_group.az_trellis_opportunities.yml @@ -0,0 +1,11 @@ +langcode: en +status: true +dependencies: + module: + - az_opportunity_trellis +id: az_trellis_opportunities +label: 'AZ Trellis Opportunities' +description: 'Import AZ Opportunities from Trellis Programs.' +source_type: 'Trellis Opportunity' +module: az_opportunity_trellis +shared_configuration: null diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/config/install/migrate_queue_importer.cron_migration.az_opportunity_trellis.yml b/modules/custom/az_opportunity/az_opportunity_trellis/config/install/migrate_queue_importer.cron_migration.az_opportunity_trellis.yml new file mode 100644 index 0000000000..476bdf3617 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/config/install/migrate_queue_importer.cron_migration.az_opportunity_trellis.yml @@ -0,0 +1,13 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - az_opportunity_trellis +id: az_opportunity_trellis +label: 'Quickstart Trellis Opportunites' +migration: az_trellis_opportunities +time: 43200 +update: true +sync: false +ignore_dependencies: 0 diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/config/install/views.view.az_opportunity_trellis_import.yml b/modules/custom/az_opportunity/az_opportunity_trellis/config/install/views.view.az_opportunity_trellis_import.yml new file mode 100644 index 0000000000..4bea6af00b --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/config/install/views.view.az_opportunity_trellis_import.yml @@ -0,0 +1,847 @@ +langcode: en +status: true +dependencies: + module: + - az_opportunity_trellis + - user + - views_remote_data +id: az_opportunity_trellis_import +label: 'Trellis Opportunity Importer' +module: views +description: '' +tag: '' +base_table: az_opportunity_trellis_data +base_field: '' +display: + default: + id: default + display_title: Default + display_plugin: default + position: 0 + display_options: + title: 'Trellis Opportunity Importer' + fields: + Id: + id: Id + table: az_opportunity_trellis_data + field: Id + relationship: none + group_type: group + admin_label: '' + entity_type: null + entity_field: null + plugin_id: az_opportunity_trellis_views_field + label: 'Trellis Opportunity ID' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + action_title: Action + include_exclude: exclude + selected_actions: { } + property: + id: property + table: az_opportunity_trellis_data + field: property + relationship: none + group_type: group + admin_label: '' + plugin_id: views_remote_data_property + label: Name + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + property_path: Name + property_2: + id: property_2 + table: az_opportunity_trellis_data + field: property + relationship: none + group_type: group + admin_label: '' + plugin_id: views_remote_data_property + label: 'Start Date' + exclude: false + alter: + alter_text: true + text: "{{ property_2 | date('Y-m-d') }}" + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + property_path: Start_Date__c + property_3: + id: property_3 + table: az_opportunity_trellis_data + field: property + relationship: none + group_type: group + admin_label: '' + plugin_id: views_remote_data_property + label: 'Owner NetID' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + property_path: Owner_NetID + property_5: + id: property_5 + table: az_opportunity_trellis_data + field: property + relationship: none + group_type: group + admin_label: '' + plugin_id: views_remote_data_property + label: Audience + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + property_path: Audiences__c + property_7: + id: property_7 + table: az_opportunity_trellis_data + field: property + relationship: none + group_type: group + admin_label: '' + plugin_id: views_remote_data_property + label: Topic + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + property_path: Topic__c + property_8: + id: property_8 + table: az_opportunity_trellis_data + field: property + relationship: none + group_type: group + admin_label: '' + plugin_id: views_remote_data_property + label: 'Program Type' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + property_path: Program_Type__c + property_6: + id: property_6 + table: az_opportunity_trellis_data + field: property + relationship: none + group_type: group + admin_label: '' + plugin_id: views_remote_data_property + label: 'Parent Account Name' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + property_path: Parent_Account_Name + pager: + type: full + options: + offset: 0 + pagination_heading_level: h4 + items_per_page: 10 + total_pages: null + id: 0 + tags: + first: '« First' + previous: '‹ Previous' + next: 'Next ›' + last: 'Last »' + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + quantity: 9 + exposed_form: + type: basic + options: + submit_button: Search + reset_button: true + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: false + sort_asc_label: Asc + sort_desc_label: Desc + access: + type: perm + options: + perm: 'create az_opportunity content' + cache: + type: none + options: { } + empty: + area_text_custom: + id: area_text_custom + table: views + field: area_text_custom + relationship: none + group_type: group + admin_label: '' + plugin_id: text_custom + empty: true + content: 'No results found. Try adjusting search filters above.' + sorts: { } + arguments: { } + filters: + property: + id: property + table: az_opportunity_trellis_data + field: property + relationship: none + group_type: group + admin_label: '' + plugin_id: views_remote_data_property + operator: '=' + value: '' + group: 1 + exposed: true + expose: + operator_id: property_op + label: Name + description: '' + use_operator: false + operator: property_op + operator_limit_selection: false + operator_list: { } + identifier: property + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + property_path: name + property_1: + id: property_1 + table: az_opportunity_trellis_data + field: property + relationship: none + group_type: group + admin_label: '' + plugin_id: views_remote_data_property + operator: '=' + value: '' + group: 1 + exposed: true + expose: + operator_id: property_1_op + label: 'Owner NetID' + description: '' + use_operator: false + operator: property_1_op + operator_limit_selection: false + operator_list: { } + identifier: owner + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + property_path: owner + property_2: + id: property_2 + table: az_opportunity_trellis_data + field: property + relationship: none + group_type: group + admin_label: '' + plugin_id: views_remote_data_property + operator: '=' + value: '' + group: 1 + exposed: true + expose: + operator_id: property_2_op + label: 'Opportunity ID' + description: 'The ID of the Program''s Account' + use_operator: false + operator: property_2_op + operator_limit_selection: false + operator_list: { } + identifier: property_2 + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + property_path: account_id + property_4: + id: property_4 + table: az_opportunity_trellis_data + field: property + relationship: none + group_type: group + admin_label: '' + plugin_id: views_remote_data_property + operator: '=' + value: '' + group: 1 + exposed: true + expose: + operator_id: property_4_op + label: 'Parent Account Name' + description: '' + use_operator: false + operator: property_4_op + operator_limit_selection: false + operator_list: { } + identifier: parent_account + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + property_path: parent_account + property_5: + id: property_5 + table: az_opportunity_trellis_data + field: property + relationship: none + group_type: group + admin_label: '' + plugin_id: views_remote_data_property + operator: '=' + value: '' + group: 1 + exposed: true + expose: + operator_id: property_5_op + label: Keyword + description: '' + use_operator: false + operator: property_5_op + operator_limit_selection: false + operator_list: { } + identifier: keyword + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + property_path: keyword + Attributes_1: + id: Attributes_1 + table: az_opportunity_trellis_data + field: Attributes + relationship: none + group_type: group + admin_label: '' + plugin_id: az_opportunity_trellis_views_attribute_filter + operator: '=' + value: '' + group: 1 + exposed: true + expose: + operator_id: Attributes_1_op + label: Topic + description: '' + use_operator: false + operator: Attributes_1_op + operator_limit_selection: false + operator_list: { } + identifier: topic + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + property_path: topic + az_attribute_key: Topic__c + Attributes_2: + id: Attributes_2 + table: az_opportunity_trellis_data + field: Attributes + relationship: none + group_type: group + admin_label: '' + plugin_id: az_opportunity_trellis_views_attribute_filter + operator: '=' + value: '' + group: 1 + exposed: true + expose: + operator_id: Attributes_2_op + label: Program Type + description: '' + use_operator: false + operator: Attributes_2_op + operator_limit_selection: false + operator_list: { } + identifier: program_type + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + property_path: program_type + az_attribute_key: Program_Type__c + Attributes_3: + id: Attributes_3 + table: az_opportunity_trellis_data + field: Attributes + relationship: none + group_type: group + admin_label: '' + plugin_id: az_opportunity_trellis_views_attribute_filter + operator: '=' + value: '' + group: 1 + exposed: true + expose: + operator_id: Attributes_3_op + label: Format + description: '' + use_operator: false + operator: Attributes_3_op + operator_limit_selection: false + operator_list: { } + identifier: program_format + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + property_path: program_format + az_attribute_key: Program_Format__c + filter_groups: + operator: AND + groups: + 1: AND + style: + type: table + row: + type: fields + query: + type: views_query + options: { } + relationships: { } + use_ajax: true + header: + result: + id: result + table: views + field: result + relationship: none + group_type: group + admin_label: '' + plugin_id: result + empty: false + content: 'Displaying @start–@end of @total results' + footer: { } + display_extenders: { } + cache_metadata: + max-age: 0 + contexts: + - 'languages:language_interface' + - url + - url.query_args + - user.permissions + tags: + - views_remote_data + page_1: + id: page_1 + display_title: Page + display_plugin: page + position: 1 + display_options: + display_extenders: { } + path: admin/trellis-opportunity-importer + cache_metadata: + max-age: 0 + contexts: + - 'languages:language_interface' + - url + - url.query_args + - user.permissions + tags: + - views_remote_data diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/config/schema/az_opportunity_trellis.schema.yml b/modules/custom/az_opportunity/az_opportunity_trellis/config/schema/az_opportunity_trellis.schema.yml new file mode 100644 index 0000000000..684f009b4e --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/config/schema/az_opportunity_trellis.schema.yml @@ -0,0 +1,32 @@ +az_opportunity_trellis.az_opp_recurring_import_rule.*: + type: config_entity + label: Trellis Opportunity Import + mapping: + id: + type: machine_name + label: ID + label: + type: label + label: Label + uuid: + type: uuid + host: + type: string + opportunity_name: + type: string + owner: + type: string + account_id: + type: string + keyword: + type: string + parent_account_name: + type: string + attributes: + type: sequence + label: ‘Enterprise Attributes’ + sequence: + type: string + label: ‘Attribute’ + approval: + type: string diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/src/AZRecurringImportRuleInterface.php b/modules/custom/az_opportunity/az_opportunity_trellis/src/AZRecurringImportRuleInterface.php new file mode 100644 index 0000000000..335b540156 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/src/AZRecurringImportRuleInterface.php @@ -0,0 +1,30 @@ +t('Label'); + $header['id'] = $this->t('Machine name'); + $header['results'] = $this->t('Results'); + $header['status'] = $this->t('Status'); + return $header + parent::buildHeader(); + } + + /** + * {@inheritdoc} + */ + public function buildRow(EntityInterface $entity): array { + /** @var \Drupal\az_opportunity_trellis\AZRecurringImportRuleInterface $entity */ + $row['label'] = $entity->label(); + $row['id'] = $entity->id(); + + // Get entity's query parameters. + $params = $entity->getQueryParameters(); + unset($params['publish']); + + // Map API param names to views exposed filter identifiers. + $api_to_view_identifier = [ + 'name' => 'property', + 'account_id' => 'property_2', + ]; + foreach ($api_to_view_identifier as $api_key => $view_key) { + if (array_key_exists($api_key, $params)) { + $params[$view_key] = $params[$api_key]; + unset($params[$api_key]); + } + } + + if (!empty($params)) { + // Generate link to results page. + $row['result']['data'] = [ + '#type' => 'link', + '#title' => $this->t('View Results'), + '#url' => Url::fromRoute('view.az_opportunity_trellis_import.page_1'), + '#options' => ['query' => $params], + '#attributes' => ['class' => 'button'], + ]; + } + else { + $row['result'] = ''; + } + $row['status'] = $entity->status() ? $this->t('Enabled') : $this->t('Disabled'); + return $row + parent::buildRow($entity); + } + +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/src/Controller/AZRecurringImportModalController.php b/modules/custom/az_opportunity/az_opportunity_trellis/src/Controller/AZRecurringImportModalController.php new file mode 100644 index 0000000000..146eb21d30 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/src/Controller/AZRecurringImportModalController.php @@ -0,0 +1,101 @@ +entityTypeManager = $entityTypeManager; + $this->entityFormBuilder = $entityFormBuilder; + $this->cache = $cache; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container): self { + return new self( + $container->get('entity_type.manager'), + $container->get('entity.form_builder'), + $container->get('cache.default'), + ); + } + + /** + * Open az_opp_recurring_import_rule configuration form as a modal. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The current request. + * + * @return \Drupal\Core\Ajax\AjaxResponse + * AjaxResponse containing command to open a modal. + */ + public function __invoke(Request $request): AjaxResponse { + $search = []; + $key = $request->query->get('search'); + // Attempt to get cached search if we have a valid cache key. + if (!empty($key) && str_starts_with($key, 'az_opp_recurring_import_modal:')) { + // Get a cached search if there is one for our key. + $search = $this->cache->get($key)->data ?? []; + } + + // Create an AjaxResponse that opens a modal copy of the config form. + $response = new AjaxResponse(); + // Entity forms require an entity. + $config = $this->entityTypeManager->getStorage('az_opp_recurring_import_rule')->create($search); + // Generate a copy of the configuration entity form using the stub as basis. + $config_form = $this->entityFormBuilder->getForm($config, 'add'); + // Forms generated during ajax calls do not have the right action path. + $config_form['#action'] = Url::fromRoute('entity.az_opp_recurring_import_rule.add_form')->toString(); + // Add an ajax command to open the modal. + $response->addCommand(new OpenModalDialogCommand($this->t('Create Recurring Import'), $config_form, ['width' => '1000'])); + return $response; + } + +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/src/Entity/AZRecurringImportRule.php b/modules/custom/az_opportunity/az_opportunity_trellis/src/Entity/AZRecurringImportRule.php new file mode 100644 index 0000000000..61b39d9f6d --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/src/Entity/AZRecurringImportRule.php @@ -0,0 +1,136 @@ + AZRecurringImportRuleListBuilder::class, + 'form' => [ + 'add' => AZRecurringImportRuleForm::class, + 'edit' => AZRecurringImportRuleForm::class, + 'delete' => EntityDeleteForm::class, + ], + ], + config_prefix: 'az_opp_recurring_import_rule', + admin_permission: 'administer quickstart configuration', + label_count: [ + 'singular' => '@count recurring import rule', + 'plural' => '@count recurring import rules', + ], + links: [ + 'collection' => '/admin/config/az-quickstart/settings/az-opportunity-recurring-import-rule', + 'add-form' => '/admin/config/az-quickstart/settings/az-opportunity-recurring-import-rule/add', + 'edit-form' => '/admin/config/az-quickstart/settings/az-opportunity-recurring-import-rule/{az_opp_recurring_import_rule}', + 'delete-form' => '/admin/config/az-quickstart/settings/az-opportunity-recurring-import-rule/{az_opp_recurring_import_rule}/delete', + ], + entity_keys: [ + 'id' => 'id', + 'label' => 'label', + 'uuid' => 'uuid', + ], + config_export: [ + 'id', + 'label', + 'opportunity_name', + 'owner', + 'account_id', + 'keyword', + 'attributes', + 'parent_account_name', + ], +)] +final class AZRecurringImportRule extends ConfigEntityBase implements AZRecurringImportRuleInterface { + + /** + * The az_opp_recurring_import_rule ID. + */ + protected string $id; + + /** + * The az_opp_recurring_import_rule label. + */ + protected string $label; + + /** + * The az_opp_recurring_import_rule opportunity name. + */ + protected string $opportunity_name; + + /** + * The az_opp_recurring_import_rule keyword. + */ + protected string $keyword; + + /** + * The az_opp_recurring_import_rule owner. + */ + protected string $owner; + + /** + * The az_opp_recurring_import_rule account ID. + */ + protected string $account_id; + + /** + * The az_opp_recurring_import_rule enterprise attributes. + */ + protected ?array $attributes; + + /** + * The az_opp_recurring_import_rule approval status. + */ + protected string $approval; + + /** + * The az_opp_recurring_import_rule parent account name. + */ + protected string $parent_account_name; + + /** + * {@inheritdoc} + */ + public function getQueryParameters() { + // Build a list of query parameters. + $params = [ + 'publish' => 'true', + ]; + $attributes = array_filter($this->attributes ?? []); + $params += $attributes; + $params['name'] = $this->get('opportunity_name') ?? ''; + $params['owner'] = $this->get('owner') ?? ''; + $params['account_id'] = $this->get('account_id') ?? ''; + $params['keyword'] = $this->get('keyword') ?? ''; + $params['parent_account'] = $this->get('parent_account_name') ?? ''; + $params = array_filter($params); + return $params; + } + + /** + * {@inheritdoc} + */ + public function getOpportunityIds() { + // Build a list of query parameters. + $params = $this->getQueryParameters(); + + return \Drupal::service('az_opportunity_trellis.trellis_helper')->searchOpportunities($params); + } + +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/src/EventSubscriber/AZOpportunityTrellisDataSubscriber.php b/modules/custom/az_opportunity/az_opportunity_trellis/src/EventSubscriber/AZOpportunityTrellisDataSubscriber.php new file mode 100644 index 0000000000..8d0e6567e2 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/src/EventSubscriber/AZOpportunityTrellisDataSubscriber.php @@ -0,0 +1,165 @@ + 'onQuery', + MigrateEvents::POST_ROW_SAVE => 'onPostRowSave', + ]; + } + + /** + * Constructs an AZOpportunitiesTrellisDataSubscriber. + * + * @param \Drupal\az_opportunity_trellis\TrellisHelper $trellisHelper + * The Trellis helper server. + * @param \Drupal\Core\Messenger\Messenger $messenger + * Database connection object. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager + * The entity type manager service. + * @param \Drupal\Core\Session\AccountProxy $currentUser + * The currently logged in user. + */ + public function __construct(TrellisHelper $trellisHelper, Messenger $messenger, EntityTypeManagerInterface $entityTypeManager, AccountProxy $currentUser) { + $this->trellisHelper = $trellisHelper; + $this->messenger = $messenger; + $this->entityTypeManager = $entityTypeManager; + $this->nodeStorage = $this->entityTypeManager->getStorage('node'); + $this->currentUser = $currentUser; + } + + /** + * Respond to events on migration import for relevant migrations. + * + * @param \Drupal\migrate\Event\MigratePostRowSaveEvent $event + * The post save event object. + */ + public function onPostRowSave(MigratePostRowSaveEvent $event) { + $migration = $event->getMigration()->getBaseId(); + $ids = $event->getDestinationIdValues(); + $id = reset($ids); + if ($migration === 'az_trellis_opportunities') { + $opportunity = $this->nodeStorage->load($id); + if (!empty($opportunity)) { + $url = $opportunity->toUrl()->toString(); + // Only show message if current user has permission. + if ($this->currentUser->hasPermission('create az_opportunity content')) { + // Show status message that opportunity was imported. + $this->messenger->addMessage($this->t('Imported @opportunitytitle.', [ + '@opportunitylink' => $url, + '@opportunitytitle' => $opportunity->getTitle(), + ])); + } + } + } + } + + /** + * Subscribes to populate Trellis view results. + * + * @param \Drupal\views_remote_data\Events\RemoteDataQueryEvent $event + * The event. + */ + public function onQuery(RemoteDataQueryEvent $event): void { + $supported_bases = ['az_opportunity_trellis_data']; + $base_tables = array_keys($event->getView()->getBaseTables()); + if (count(array_intersect($supported_bases, $base_tables)) > 0) { + $parameters = []; + $condition_groups = $event->getConditions(); + // Check for conditional parameters. + foreach ($condition_groups as $condition_group) { + if (!empty($condition_group['conditions'])) { + foreach ($condition_group['conditions'] as $condition) { + if (!empty($condition['field'][0]) && !empty($condition['value'])) { + $parameters[$condition['field'][0]] = $condition['value']; + } + } + } + } + // Don't perform search if empty or publish is the only field. + if (empty($parameters)) { + // If (empty($parameters) || (count($parameters) <= 1)) {. + return; + } + $ids = $this->trellisHelper->searchOpportunities($parameters); + if (!empty($ids)) { + $total = count($ids); + $offset = $event->getOffset(); + $limit = $event->getLimit(); + if (!empty($limit)) { + $ids = array_slice($ids, $offset, $limit); + } + // Run data fetch request. + $results = $this->trellisHelper->getOpportunities($ids); + + if (empty($results)) { + return; + } + // Set a results count to pager, only when the data fetch worked. + $event->getView()->pager->total_items = $total; + $datefields = [ + 'Last_Modified_Date', + 'Start_Date__c', + 'End_Date__c', + ]; + foreach ($results as $result) { + // Change date format fields to what views expects to see. + foreach ($datefields as $datefield) { + if (!empty($result[$datefield])) { + $result[$datefield] = strtotime($result[$datefield]); + } + } + $event->addResult(new ResultRow($result)); + } + } + } + } + +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/src/Form/AZRecurringImportRuleForm.php b/modules/custom/az_opportunity/az_opportunity_trellis/src/Form/AZRecurringImportRuleForm.php new file mode 100644 index 0000000000..d13a9ff106 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/src/Form/AZRecurringImportRuleForm.php @@ -0,0 +1,196 @@ +entityRepository = $container->get('entity.repository'); + $instance->trellisHelper = $container->get('az_opportunity_trellis.trellis_helper'); + return $instance; + } + + /** + * {@inheritdoc} + */ + public function form(array $form, FormStateInterface $form_state): array { + + $form = parent::form($form, $form_state); + /** @var \Drupal\az_opportunity_trellis\Entity\AZRecurringImportRule $entity */ + $entity = $this->entity; + // Fetch the list of attributes mapped by the API. + $mappings = $this->trellisHelper->getAttributeMappings(); + + $form['label'] = [ + '#type' => 'textfield', + '#title' => $this->t('Import Rule Name'), + '#maxlength' => 255, + '#default_value' => $entity->label(), + '#description' => $this->t('Describe this rule, e.g., Graduate Lecture Series'), + '#required' => TRUE, + ]; + + $form['id'] = [ + '#type' => 'machine_name', + '#default_value' => $this->entity->id(), + '#machine_name' => [ + 'exists' => [AZRecurringImportRule::class, 'load'], + ], + '#disabled' => !$entity->isNew(), + ]; + + $form['status'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Enabled'), + '#default_value' => $entity->status(), + '#description' => $this->t('Enabled import rules will regularly import matching content into the site automatically.'), + ]; + + $form['query_parameters'] = [ + '#type' => 'details', + '#title' => $this->t('Recurring Search Parameters'), + '#description' => $this->t('When this import rule runs, the following search terms will be used.'), + '#open' => TRUE, + ]; + + $form['query_parameters']['opportunity_name'] = [ + '#type' => 'textfield', + '#title' => $this->t('Name'), + '#maxlength' => 255, + '#default_value' => $entity->get('opportunity_name'), + ]; + + $form['query_parameters']['owner'] = [ + '#type' => 'textfield', + '#title' => $this->t('Owner NetID'), + '#maxlength' => 255, + '#default_value' => $entity->get('owner'), + ]; + + $form['query_parameters']['account_id'] = [ + '#type' => 'textfield', + '#title' => $this->t('Opportunity ID'), + '#maxlength' => 255, + '#description' => $this->t("The ID of the Program's Account"), + '#default_value' => $entity->get('account_id'), + ]; + + $form['query_parameters']['parent_account_name'] = [ + '#type' => 'textfield', + '#title' => $this->t('Parent Account Name'), + '#maxlength' => 255, + '#default_value' => $entity->get('parent_account_name'), + ]; + + // Cut from line 146. + $form['query_parameters']['keyword'] = [ + '#type' => 'textfield', + '#title' => $this->t('Keyword'), + '#maxlength' => 255, + '#default_value' => $entity->get('keyword'), + ]; + + $form['query_parameters']['attributes']['#tree'] = TRUE; + + if (!empty($mappings)) { + // Get the different attributes available. + $term_storage = $this->entityTypeManager->getStorage('taxonomy_term'); + $query = $term_storage->getQuery() + ->accessCheck(TRUE) + ->addTag('taxonomy_term_access') + ->condition('vid', 'az_enterprise_attributes') + ->condition('parent', 0) + ->sort('name') + // Only fetch attributes that have an API mapping. + ->condition('field_az_attribute_key', array_keys($mappings), 'IN'); + $attributes = $query->execute(); + $attributes = $term_storage->loadMultiple($attributes); + + // Build attribute select lists. + foreach ($attributes as $attribute) { + $options = []; + $key = $mappings[$attribute->field_az_attribute_key->value]; + $id = $attribute->id(); + + // Find the options the attribute has, in order. + $query = $term_storage->getQuery() + ->accessCheck(TRUE) + ->addTag('taxonomy_term_access') + ->condition('vid', 'az_enterprise_attributes') + ->condition('parent', $id) + ->sort('name') + ->condition('field_az_attribute_key', '', '<>'); + $terms = $query->execute(); + $terms = $term_storage->loadMultiple($terms); + foreach ($terms as $term) { + $label = $this->entityRepository->getTranslationFromContext($term)->label(); + $options[$label] = $label; + } + + // Build the select element for the attribute. + $form['query_parameters']['attributes'][$key] = [ + '#type' => 'select', + '#options' => $options, + '#empty_option' => $this->t('- Any -'), + '#empty_value' => '', + '#title' => $this->entityRepository->getTranslationFromContext($attribute)->label(), + '#required' => FALSE, + '#default_value' => $entity->get('attributes')[$key] ?? NULL, + ]; + } + } + else { + $form['query_parameters']['attributes']['empty'] = [ + '#type' => 'item', + '#markup' => $this->t('No mapped enterprise attributes found, so the attribute controls are unavailable.'), + ]; + } + return $form; + } + + /** + * {@inheritdoc} + */ + public function save(array $form, FormStateInterface $form_state): int { + $result = parent::save($form, $form_state); + $message_args = ['%label' => $this->entity->label()]; + $this->messenger()->addStatus( + match($result) { + \SAVED_NEW => $this->t('Created new recurring import rule %label.', $message_args), + \SAVED_UPDATED => $this->t('Updated recurring import rule %label.', $message_args), + } + ); + + $form_state->setRedirectUrl($this->entity->toUrl('collection')); + return $result; + } + +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/src/Form/TrellisOpportunitySettingsForm.php b/modules/custom/az_opportunity/az_opportunity_trellis/src/Form/TrellisOpportunitySettingsForm.php new file mode 100644 index 0000000000..47814d18ed --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/src/Form/TrellisOpportunitySettingsForm.php @@ -0,0 +1,53 @@ +config('az_opportunity_trellis.settings'); + + $form['api_hostname'] = [ + '#title' => $this->t("API Hostname"), + '#type' => 'textfield', + '#default_value' => $az_opportunity_trellis_config->get('api_hostname'), + ]; + + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $this->config('az_opportunity_trellis.settings') + ->set('api_hostname', $form_state->getValue('api_hostname')) + ->save(); + + parent::submitForm($form, $form_state); + } + +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/migrate/process/AZExtractUrl.php b/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/migrate/process/AZExtractUrl.php new file mode 100644 index 0000000000..7ebe570fc5 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/migrate/process/AZExtractUrl.php @@ -0,0 +1,52 @@ + + * element instead of a bare URL, this plugin extracts the href attribute value. + * + * @code + * process: + * field_az_application_link/uri: + * plugin: az_extract_url + * source: application_form_url + * @endcode + */ +#[MigrateProcess('az_extract_url')] +class AZExtractUrl extends ProcessPluginBase { + + /** + * {@inheritdoc} + */ + public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { + if (empty($value) || !is_string($value)) { + return $value; + } + + // If the value contains an HTML anchor tag, extract the href. + if (str_contains($value, 'evaluate('string(//a/@href)'); + if (!empty($href)) { + return Html::decodeEntities($href); + } + // Anchor found but no usable href, return empty. + return ''; + } + + return $value; + } + +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/migrate/source/AZTrellisOpportunitySource.php b/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/migrate/source/AZTrellisOpportunitySource.php new file mode 100644 index 0000000000..039799f3b9 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/migrate/source/AZTrellisOpportunitySource.php @@ -0,0 +1,146 @@ +fields = $configuration['fields']; + $this->ids = $configuration['ids']; + // @todo use injection for this. + $this->trellisHelper = \Drupal::service('az_opportunity_trellis.trellis_helper'); + $this->trellisIds = $configuration['trellis_ids'] ?? []; + // If no arguments are supplied, fetch the list currently on the site. + if (empty($this->trellisIds)) { + $ids = array_merge( + $this->trellisHelper->getImportedOpportunityIds(), + $this->trellisHelper->getRecurringOpportunityIds(), + ); + $this->trellisIds = array_unique($ids); + } + } + + /** + * Initializes the iterator with the source data. + * + * @return \Iterator + * Returns an iterable object of data for this source. + */ + protected function initializeIterator() { + // Fetch the opportunities via trellis API. + $items = $this->trellisHelper->getOpportunities($this->trellisIds); + $results = []; + $fields = []; + // Find field selectors. + foreach ($this->fields as $field) { + $fields[$field['name']] = $field['selector'] ?? $field['name']; + } + foreach ($items as $item) { + $result = []; + // Transform selectors into defined fields. + foreach ($fields as $field => $selector) { + if (isset($item[$selector])) { + $result[$field] = $item[$selector]; + } + } + $results[] = $result; + } + // Return an iterable. + $obj = new \ArrayObject($results); + return $obj->getIterator(); + } + + /** + * {@inheritdoc} + */ + public function prepareRow(Row $row) { + // Trellis IDs from source configuration can affect the hash of the row. + $row->setSourceProperty('trellis_ids', []); + // Perform normal source plugin hashing. + return parent::prepareRow($row); + } + + /** + * Return a string representing the source ids. + * + * @return string + * Comma-separated list of ids being imported. + */ + public function __toString(): string { + $ids = implode(', ', $this->trellisIds); + return $ids; + } + + /** + * {@inheritdoc} + */ + public function fields(): array { + $fields = []; + foreach ($this->fields as $field_info) { + $fields[$field_info['name']] = $field_info['label'] ?? $field_info['name']; + } + return $fields; + } + + /** + * {@inheritdoc} + */ + public function getIds(): array { + return $this->ids; + } + +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/views/field/AZOpportunityTrellisViewsField.php b/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/views/field/AZOpportunityTrellisViewsField.php new file mode 100644 index 0000000000..dbe8dae3d2 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/views/field/AZOpportunityTrellisViewsField.php @@ -0,0 +1,140 @@ +migrationRemoteTools = $container->get('az_migration_remote.tools'); + $instance->trellisHelper = $container->get('az_opportunity_trellis.trellis_helper'); + return $instance; + } + + /** + * {@inheritdoc} + */ + public function init(ViewExecutable $view, DisplayPluginBase $display, ?array &$options = NULL) { + FieldPluginBase::init($view, $display, $options); + $this->actions = []; + } + + /** + * {@inheritdoc} + */ + public function viewsForm(&$form, FormStateInterface $form_state) { + $form['#cache']['max-age'] = 0; + + $form[$this->options['id']] = [ + '#tree' => TRUE, + ]; + + foreach ($this->view->result as $row_index => $row) { + $form[$this->options['id']][$row_index] = [ + '#type' => 'checkbox', + // We are not able to determine a main "title" for each row, so we can + // only output a generic label. + '#title' => $this->t('Update this item'), + '#title_display' => 'invisible', + '#return_value' => $row->Id ?? '', + '#default_value' => !empty($form_state->getValue($this->options['id'])[$row_index]) ? 1 : NULL, + ]; + } + + // Change default BulkForm label. + if (!empty($form['actions']['submit'])) { + $form['actions']['submit']['#value'] = $this->t('Import'); + } + } + + /** + * {@inheritdoc} + */ + public function viewsFormValidate(&$form, FormStateInterface $form_state) { + $ids = $form_state->getValue($this->options['id']); + if (empty($ids) || empty(array_filter($ids))) { + $form_state->setErrorByName('', $this->emptySelectedMessage()); + } + // Unlike parent class, do not throw form error when action is empty. + } + + /** + * Submit handler for the Trellis import form. + * + * @param mixed $form + * An associative array containing the structure of the form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + * + * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + * Thrown when the user tried to access an action without access to it. + */ + public function viewsFormSubmit(&$form, FormStateInterface $form_state) { + $values = $form_state->getValues(); + if (!empty($values[$this->options['id']])) { + $ids = $values[$this->options['id']]; + $ids = array_filter($ids); + foreach ($ids as $value) { + if (!empty($value)) { + \Drupal::service('messenger')->addMessage($this->t('Importing Trellis Opportunity @id.', [ + '@id' => $value, + ])); + } + } + + $migrations = [ + 'az_trellis_opportunities' => [ + 'limit' => 0, + 'update' => 1, + 'force' => 0, + 'configuration' => [ + 'source' => [ + 'trellis_ids' => $ids, + ], + ], + ], + ]; + + $this->migrationRemoteTools->batch($migrations); + } + + } + + /** + * {@inheritdoc} + */ + public function isWorkspaceSafeForm(array $form, FormStateInterface $form_state): bool { + // This field is not backed by an entity like BulkForm expects. + return FALSE; + } + +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/views/filter/AZOpportunityTrellisViewsApprovalFilter.php b/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/views/filter/AZOpportunityTrellisViewsApprovalFilter.php new file mode 100644 index 0000000000..555df5c6f4 --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/views/filter/AZOpportunityTrellisViewsApprovalFilter.php @@ -0,0 +1,96 @@ + 'select', + '#title' => $this->t('Value'), + '#options' => [ + 'approved' => $this->t('Approved'), + 'denied' => $this->t('Denied'), + ], + '#required' => FALSE, + '#default_value' => $this->value, + ]; + } + + /** + * {@inheritdoc} + */ + public function operatorOptions(): array { + return [ + '=' => $this->t('Is equal to'), + '!=' => $this->t('Is not equal to'), + ]; + } + + /** + * {@inheritdoc} + */ + protected function defineOptions(): array { + $options = parent::defineOptions(); + $this->definePropertyPathOption($options); + return $options; + } + + /** + * {@inheritdoc} + */ + public function buildOptionsForm(&$form, FormStateInterface $form_state): void { + $this->propertyPathElement($form, $this->options); + parent::buildOptionsForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function adminSummary() { + $prop = $this->options['property_path'] ?? ''; + return '(API value ' . $prop . ') ' . $this->operator . ' ' . $this->value; + } + + /** + * {@inheritdoc} + */ + public function query($group_by = FALSE): void { + if (!($this->query instanceof RemoteDataQuery)) { + return; + } + $this->query->addWhere( + $this->options['group'], + $this->options['property_path'], + $this->value, + $this->operator + ); + } + +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/views/filter/AZOpportunityTrellisViewsAttributeFilter.php b/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/views/filter/AZOpportunityTrellisViewsAttributeFilter.php new file mode 100644 index 0000000000..6c00a86ffc --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/src/Plugin/views/filter/AZOpportunityTrellisViewsAttributeFilter.php @@ -0,0 +1,171 @@ +entityRepository = $container->get('entity.repository'); + $instance->termStorage = $container->get('entity_type.manager')->getStorage('taxonomy_term'); + return $instance; + } + + /** + * {@inheritdoc} + */ + protected function valueForm(&$form, FormStateInterface $form_state): void { + $options = []; + $key = $this->options['az_attribute_key'] ?? ''; + + // Get the applicable attribute terms. + $query = $this->termStorage->getQuery() + ->accessCheck(TRUE) + ->addTag('taxonomy_term_access') + ->condition('vid', 'az_enterprise_attributes') + ->condition('field_az_attribute_key', $key); + $parents = $query->execute(); + $children = []; + if (!empty($parents)) { + $query = $this->termStorage->getQuery() + ->accessCheck(TRUE) + ->sort('name') + ->addTag('taxonomy_term_access') + ->condition('parent', $parents, 'IN'); + $children = $query->execute(); + } + $terms = Term::loadMultiple($children); + // Build option list. + foreach ($terms as $term) { + if ($term->hasField('field_az_attribute_key') && !empty($term->field_az_attribute_key->value)) { + $label = $this->entityRepository->getTranslationFromContext($term)->label(); + $options[$label] = $label; + } + } + $form['value'] = [ + '#type' => 'select', + '#title' => $this->t('Value'), + '#options' => $options, + '#required' => FALSE, + '#access' => !empty($options), + '#default_value' => $this->value, + ]; + } + + /** + * {@inheritdoc} + */ + public function operatorOptions(): array { + return [ + '=' => $this->t('Is equal to'), + '!=' => $this->t('Is not equal to'), + ]; + } + + /** + * {@inheritdoc} + */ + protected function defineOptions(): array { + $options = parent::defineOptions(); + $this->definePropertyPathOption($options); + $options['az_attribute_key'] = ['default' => '']; + return $options; + } + + /** + * {@inheritdoc} + */ + public function buildOptionsForm(&$form, FormStateInterface $form_state): void { + $this->propertyPathElement($form, $this->options); + parent::buildOptionsForm($form, $form_state); + $form['az_attribute_key'] = [ + '#title' => $this->t('Unique key of enterprise attribute'), + '#type' => 'textfield', + '#default_value' => $this->options['az_attribute_key'] ?? '', + '#required' => TRUE, + ]; + } + + /** + * Return the attribute id and api parameter name. + * + * @return array + * An array with the key as the attribute id and the value as the api path. + */ + public function getApiMapping(): array { + $key = $this->options['az_attribute_key'] ?? ''; + $path = $this->options['property_path'] ?? ''; + return [$key => $path]; + } + + /** + * {@inheritdoc} + */ + public function adminSummary() { + $prop = $this->options['property_path'] ?? ''; + $key = $this->options['az_attribute_key'] ?? ''; + return $key . ' (API value ' . $prop . ') ' . $this->operator . ' ' . $this->value; + } + + /** + * {@inheritdoc} + */ + public function query($group_by = FALSE): void { + if (!($this->query instanceof RemoteDataQuery)) { + return; + } + $this->query->addWhere( + $this->options['group'], + $this->options['property_path'], + $this->value, + $this->operator + ); + } + +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/src/TrellisHelper.php b/modules/custom/az_opportunity/az_opportunity_trellis/src/TrellisHelper.php new file mode 100644 index 0000000000..92b74749ad --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/src/TrellisHelper.php @@ -0,0 +1,333 @@ +configFactory = $config_factory; + $this->httpClient = $http_client; + $this->cache = $cache; + $this->entityTypeManager = $entity_type_manager; + } + + /** + * Search based on parameters for opportunities. + * + * @param array $query + * Query parameters to use in search. + * + * @return array + * Array of trellis opportunity ids. + */ + public function searchOpportunities(array $query) { + $ids = []; + // Compute cache key of query. + $key = 'az_trellis_opportunities.search:' . Crypt::hashBase64(serialize($query)); + $cached = $this->cache->get($key); + // If we have this search cached, return it. + if ($cached !== FALSE) { + return $cached->data; + } + + $url = $this->getOpportunitySearchEndpoint(); + try { + // Run search request. + $response = $this->httpClient->request('GET', $url, ['query' => $query]); + if ($response->getStatusCode() === 200) { + $json = (string) $response->getBody(); + $json = json_decode($json, TRUE); + if ($json !== NULL) { + $ids = $json['data']['Program_Cycle_IDs'] ?? []; + // Ensure opportunities are in Id order. + sort($ids); + // @todo determine cache expiration. + $expire = time() + 1800; + // Cache search result. + $this->cache->set($key, $ids, $expire); + } + } + } + catch (GuzzleException $e) { + } + return $ids; + } + + /** + * Returns opportunity data for an array of ids. + * + * @param array $trellis_ids + * Trellis Opportunity IDs in an array. + * + * @return array + * Opportunity data. + */ + public function getOpportunities(array $trellis_ids) { + $opportunities = []; + $fetch = []; + $url = $this->getOpportunityEndpoint(); + // Remove any duplicate ids to mimic remote API. + $trellis_ids = array_unique($trellis_ids); + // Grab opportunities that are in cache. + foreach ($trellis_ids as $trellis_id) { + $cached = $this->getTrellisCache($trellis_id); + if ($cached === FALSE) { + $fetch[] = $trellis_id; + } + else { + $opportunities[] = $cached; + } + } + // Fetch opportunities we did not have cached. + if (!empty($fetch)) { + try { + $data = ['ids' => implode(',', $fetch)]; + $response = $this->httpClient->request('POST', $url, ['json' => $data]); + if ($response->getStatusCode() === 200) { + $json = (string) $response->getBody(); + $json = json_decode($json, TRUE); + if ($json !== NULL) { + $results = $json['data'] ?? []; + foreach ($results as $result) { + // Cache the opportunity and add it to the list. + $opportunities[] = $this->setTrellisCache($result); + } + } + } + } + catch (GuzzleException $e) { + } + } + // Make sure opportunities are in Id order regardless of cached/fetched. + usort($opportunities, function ($a, $b) { + return strcmp($a['Id'], $b['Id']); + }); + return $opportunities; + } + + /** + * Fetch the list of trellis opportunity ids currently imported. + * + * @return array + * Returns an array of opportunity ids. + */ + public function getImportedOpportunityIds() { + $nodeStorage = $this->entityTypeManager->getStorage('node'); + // Check for opportunities that have trellis ids. + $query = $nodeStorage->getQuery() + ->accessCheck(FALSE) + ->condition('type', 'az_opportunity') + ->exists('field_az_trellis_id'); + $nids = $query->execute(); + $nodes = $nodeStorage->loadMultiple($nids); + + $opportunity_api_ids = []; + foreach ($nodes as $n) { + $opportunity_api_ids[] = $n->get('field_az_trellis_id')->getString(); + } + return $opportunity_api_ids; + } + + /** + * Fetch the recurring search list of ids to import. + * + * @return array + * Returns an array of opportunity ids. + */ + public function getRecurringOpportunityIds() { + // Find enabled import configurations. + $imports = $this->entityTypeManager->getStorage('az_opp_recurring_import_rule')->loadByProperties([ + 'status' => [1, TRUE], + ]); + + $opportunity_api_ids = []; + foreach ($imports as $import) { + /** @var \Drupal\az_opportunity_trellis\Entity\AZRecurringImportRule $import */ + $opportunity_api_ids = array_merge($opportunity_api_ids, $import->getOpportunityIds()); + } + // Remove duplicates in case searches overlapped. + $opportunity_api_ids = array_unique($opportunity_api_ids); + return $opportunity_api_ids; + } + + /** + * Return mapped array of api names of attributes. + * + * @return array + * The array of attribute ids mapped to API names. + */ + public function getAttributeMappings() { + $mappings = []; + + $view = Views::getView('az_opportunity_trellis_import'); + if (!$view) { + return $mappings; + } + + // Ensure we are on a display that has filter handlers. + if (!$view->getDisplay()) { + $display_id = $view->current_display ?? 'default'; + if (!$display_id) { + $display_id = 'default'; + } + $view->setDisplay($display_id); + } + + $display = $view->getDisplay(); + if (!$display) { + return $mappings; + } + + $filters = $display->getHandlers('filter'); + foreach ($filters as $filter) { + if ($filter instanceof AZOpportunityTrellisViewsAttributeFilter) { + $mappings += $filter->getApiMapping(); + } + } + + return $mappings; + } + + /** + * Returns the cache for an opportunity if possible. + * + * @param string $trellis_id + * The trellis id of the opportunity. + * + * @return mixed + * The cached data for the opportunity, or FALSE. + */ + protected function getTrellisCache(string $trellis_id) { + $key = 'az_trellis_opportunities:' . $trellis_id; + return $this->cache->get($key)->data ?? FALSE; + } + + /** + * Sets the cache for an opportunity if possible. + * + * @param array $opportunity + * The opportunity data result. + * + * @return array + * The data for the opportunity. + */ + protected function setTrellisCache(array $opportunity) { + if (!empty($opportunity['Id'])) { + $key = 'az_trellis_opportunities:' . $opportunity['Id']; + // @todo determine cache expiration. + $expire = time() + 1800; + $this->cache->set($key, $opportunity, $expire); + } + return $opportunity; + } + + /** + * Returns API URL for given Trellis Opportunity ID. + * + * @param string $trellis_id + * Trellis Opportunity ID. + * + * @return string + * Opportunity API URL. + */ + public function getOpportunityUrl($trellis_id) { + $hostname = $this->configFactory->get('az_opportunity_trellis.settings')->get('api_hostname'); + return 'https://' . $hostname . self::$apiBasePath . $trellis_id; + } + + /** + * Returns API URL. + * + * @return string + * Opportunity API URL. + */ + public function getOpportunityEndpoint() { + $hostname = $this->configFactory->get('az_opportunity_trellis.settings')->get('api_hostname'); + return 'https://' . $hostname . self::$apiBasePath; + } + + /** + * Returns API search URL. + * + * @return string + * Opportunity API search URL. + */ + public function getOpportunitySearchEndpoint() { + $hostname = $this->configFactory->get('az_opportunity_trellis.settings')->get('api_hostname'); + return 'https://' . $hostname . self::$apiSearchPath; + } + +} diff --git a/modules/custom/az_opportunity/az_opportunity_trellis/templates/views-view--az-opportunity-trellis-import.html.twig b/modules/custom/az_opportunity/az_opportunity_trellis/templates/views-view--az-opportunity-trellis-import.html.twig new file mode 100644 index 0000000000..59da5cd1ce --- /dev/null +++ b/modules/custom/az_opportunity/az_opportunity_trellis/templates/views-view--az-opportunity-trellis-import.html.twig @@ -0,0 +1,45 @@ +{# +/** + * @file + * Template for the Trellis Opportunity Importer view. + * + * Overrides views-view.html.twig to place the result summary (header) + * between the exposed filters and the results table. + */ +#} +{% + set classes = [ + dom_id ? 'js-view-dom-id-' ~ dom_id, + ] +%} + + {{ title_prefix }} + {{ title }} + {{ title_suffix }} + + {{ exposed }} + +
+ {% if header %}{{ header }}{% endif %} +
+ + {{ attachment_before }} + + {% if rows -%} + {{ rows }} + {% elseif empty -%} +
{{ empty }}
+ {% endif %} + + {{ pager }} + {{ attachment_after }} + {{ more }} + + {% if footer %} + + {% endif %} + + {{ feed_icons }} + diff --git a/modules/custom/az_opportunity/config/install/core.base_field_override.node.az_opportunity.promote.yml b/modules/custom/az_opportunity/config/install/core.base_field_override.node.az_opportunity.promote.yml new file mode 100644 index 0000000000..238214da05 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/core.base_field_override.node.az_opportunity.promote.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + config: + - node.type.az_opportunity +id: node.az_opportunity.promote +field_name: promote +entity_type: node +bundle: az_opportunity +label: 'Promoted to front page' +description: '' +required: false +translatable: true +default_value: + - + value: 0 +default_value_callback: '' +settings: + on_label: 'On' + off_label: 'Off' +field_type: boolean diff --git a/modules/custom/az_opportunity/config/install/core.entity_form_display.node.az_opportunity.default.yml b/modules/custom/az_opportunity/config/install/core.entity_form_display.node.az_opportunity.default.yml new file mode 100644 index 0000000000..bd1d0c674b --- /dev/null +++ b/modules/custom/az_opportunity/config/install/core.entity_form_display.node.az_opportunity.default.yml @@ -0,0 +1,239 @@ +langcode: en +status: true +dependencies: + config: + - field.field.node.az_opportunity.field_az_application_date + - field.field.node.az_opportunity.field_az_application_link + - field.field.node.az_opportunity.field_az_body + - field.field.node.az_opportunity.field_az_eligibility + - field.field.node.az_opportunity.field_az_enterprise_attributes + - field.field.node.az_opportunity.field_az_incentives + - field.field.node.az_opportunity.field_az_offered + - field.field.node.az_opportunity.field_az_ongoing + - field.field.node.az_opportunity.field_az_opportunity_category + - field.field.node.az_opportunity.field_az_opportunity_credit + - field.field.node.az_opportunity.field_az_opportunity_location + - field.field.node.az_opportunity.field_az_parent_account + - field.field.node.az_opportunity.field_az_program_date + - field.field.node.az_opportunity.field_az_program_length + - field.field.node.az_opportunity.field_az_program_website + - field.field.node.az_opportunity.field_az_trellis_id + - field.field.node.az_opportunity.field_az_trellis_imported_date + - node.type.az_opportunity + module: + - az_core + - link + - link_class + - path + - smart_date + - text +id: node.az_opportunity.default +targetEntityType: node +bundle: az_opportunity +mode: default +content: + created: + type: datetime_timestamp + weight: 17 + region: content + settings: { } + third_party_settings: { } + field_az_application_date: + type: smartdate_only + weight: 5 + region: content + settings: + separator: to + modal: false + default_duration: 60 + default_duration_increments: |- + 30 + 60|1 hour + 90 + 120|2 hours + custom + show_extra: false + hide_date: true + allday: true + remove_seconds: false + duration_overlay: true + third_party_settings: { } + field_az_application_link: + type: link_class_field_widget + weight: 9 + region: content + settings: + placeholder_url: '' + placeholder_title: '' + link_class_mode: force_class + link_class_force: 'btn btn-red' + link_class_select: '' + third_party_settings: { } + field_az_body: + type: text_textarea + weight: 13 + region: content + settings: + rows: 9 + placeholder: '' + third_party_settings: { } + field_az_eligibility: + type: text_textarea + weight: 14 + region: content + settings: + rows: 5 + placeholder: '' + third_party_settings: { } + field_az_enterprise_attributes: + type: attributes_select + weight: 2 + region: content + settings: + allowed_attributes: + Audiences__c: Audiences__c + Event_Format__c: Event_Format__c + Program_Type__c: Program_Type__c + Topic__c: Topic__c + Arizona_County__c: 0 + Category1__c: 0 + Tribal_Nation__c: 0 + Display_Name_Formula__c: 0 + third_party_settings: { } + field_az_incentives: + type: options_select + weight: 11 + region: content + settings: { } + third_party_settings: { } + field_az_offered: + type: entity_reference_autocomplete + weight: 7 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + field_az_ongoing: + type: boolean_checkbox + weight: 4 + region: content + settings: + display_label: true + third_party_settings: { } + field_az_opportunity_category: + type: entity_reference_autocomplete + weight: 1 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + field_az_opportunity_credit: + type: options_select + weight: 12 + region: content + settings: { } + third_party_settings: { } + field_az_opportunity_location: + type: string_textfield + weight: 10 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + field_az_program_date: + type: smartdate_only + weight: 6 + region: content + settings: + separator: to + modal: false + default_duration: 60 + default_duration_increments: |- + 30 + 60|1 hour + 90 + 120|2 hours + custom + show_extra: false + hide_date: true + allday: true + remove_seconds: false + duration_overlay: true + third_party_settings: { } + field_az_program_length: + type: string_textfield + weight: 3 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + field_az_program_website: + type: link_default + weight: 8 + region: content + settings: + placeholder_url: '' + placeholder_title: '' + third_party_settings: { } + path: + type: path + weight: 20 + region: content + settings: { } + third_party_settings: { } + promote: + type: boolean_checkbox + weight: 18 + region: content + settings: + display_label: true + third_party_settings: { } + status: + type: boolean_checkbox + weight: 15 + region: content + settings: + display_label: true + third_party_settings: { } + sticky: + type: boolean_checkbox + weight: 19 + region: content + settings: + display_label: true + third_party_settings: { } + title: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 16 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + url_redirects: + weight: 21 + region: content + settings: { } + third_party_settings: { } +hidden: + field_az_parent_account: true + field_az_trellis_id: true + field_az_trellis_imported_date: true diff --git a/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.az_card.yml b/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.az_card.yml new file mode 100644 index 0000000000..93914a05b2 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.az_card.yml @@ -0,0 +1,194 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.az_card + - field.field.node.az_opportunity.field_az_application_date + - field.field.node.az_opportunity.field_az_application_link + - field.field.node.az_opportunity.field_az_body + - field.field.node.az_opportunity.field_az_eligibility + - field.field.node.az_opportunity.field_az_enterprise_attributes + - field.field.node.az_opportunity.field_az_incentives + - field.field.node.az_opportunity.field_az_offered + - field.field.node.az_opportunity.field_az_ongoing + - field.field.node.az_opportunity.field_az_opportunity_category + - field.field.node.az_opportunity.field_az_opportunity_credit + - field.field.node.az_opportunity.field_az_opportunity_location + - field.field.node.az_opportunity.field_az_parent_account + - field.field.node.az_opportunity.field_az_program_date + - field.field.node.az_opportunity.field_az_program_length + - field.field.node.az_opportunity.field_az_program_website + - field.field.node.az_opportunity.field_az_trellis_id + - field.field.node.az_opportunity.field_az_trellis_imported_date + - node.type.az_opportunity + module: + - date_ap_style + - field_group + - smart_title + - user +third_party_settings: + field_group: + group_card_clickable: + children: + - group_heading + - group_text_body_secondary + - group_link + label: 'Card Clickable' + parent_name: '' + region: content + weight: 0 + format_type: html_element + format_settings: + classes: 'card card-body mb-3 hover shadow h-100' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_link: + children: + - links + label: Link + parent_name: group_card_clickable + region: content + weight: 3 + format_type: link + format_settings: + classes: stretched-link + show_empty_fields: false + id: '' + label_as_html: false + target: custom_uri + custom_uri: '[node:az-canonical-url]' + target_attribute: default + group_heading: + children: + - smart_title + label: Heading + parent_name: group_card_clickable + region: content + weight: 1 + format_type: html_element + format_settings: + classes: 'card-title text-midnight h5 mb-2 hover-text-underline' + show_empty_fields: false + id: '' + label_as_html: false + element: h3 + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_text_body_secondary: + children: + - field_az_program_date + - field_az_application_date + - field_az_opportunity_location + label: 'Text Body Secondary' + parent_name: group_card_clickable + region: content + weight: 2 + format_type: html_element + format_settings: + classes: 'small card-text' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + smart_title: + enabled: true + settings: + smart_title__link: false + smart_title__tag: '' + smart_title__classes: { } +id: node.az_opportunity.az_card +targetEntityType: node +bundle: az_opportunity +mode: az_card +content: + field_az_application_date: + type: daterange_ap_style + label: inline + settings: + always_display_year: false + use_today: false + cap_today: false + display_day: false + display_time: false + hide_date: false + time_before_date: false + display_noon_and_midnight: false + capitalize_noon_and_midnight: false + use_all_day: false + separator: endash + timezone: '' + month_only: false + third_party_settings: { } + weight: 9 + region: content + field_az_opportunity_location: + type: string + label: inline + settings: + link_to_entity: false + third_party_settings: { } + weight: 10 + region: content + field_az_program_date: + type: daterange_ap_style + label: inline + settings: + always_display_year: false + use_today: false + cap_today: false + display_day: false + display_time: false + hide_date: false + time_before_date: false + display_noon_and_midnight: false + capitalize_noon_and_midnight: false + use_all_day: false + separator: endash + timezone: '' + month_only: false + third_party_settings: { } + weight: 8 + region: content + links: + settings: { } + third_party_settings: { } + weight: 0 + region: content + smart_title: + settings: { } + third_party_settings: { } + weight: 1 + region: content +hidden: + field_az_application_link: true + field_az_body: true + field_az_eligibility: true + field_az_enterprise_attributes: true + field_az_incentives: true + field_az_offered: true + field_az_ongoing: true + field_az_opportunity_category: true + field_az_opportunity_credit: true + field_az_parent_account: true + field_az_program_length: true + field_az_program_website: true + field_az_trellis_id: true + field_az_trellis_imported_date: true diff --git a/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.az_row.yml b/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.az_row.yml new file mode 100644 index 0000000000..70e9052b63 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.az_row.yml @@ -0,0 +1,258 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.az_row + - field.field.node.az_opportunity.field_az_application_date + - field.field.node.az_opportunity.field_az_application_link + - field.field.node.az_opportunity.field_az_body + - field.field.node.az_opportunity.field_az_eligibility + - field.field.node.az_opportunity.field_az_enterprise_attributes + - field.field.node.az_opportunity.field_az_incentives + - field.field.node.az_opportunity.field_az_offered + - field.field.node.az_opportunity.field_az_ongoing + - field.field.node.az_opportunity.field_az_opportunity_category + - field.field.node.az_opportunity.field_az_opportunity_credit + - field.field.node.az_opportunity.field_az_opportunity_location + - field.field.node.az_opportunity.field_az_parent_account + - field.field.node.az_opportunity.field_az_program_date + - field.field.node.az_opportunity.field_az_program_length + - field.field.node.az_opportunity.field_az_program_website + - field.field.node.az_opportunity.field_az_trellis_id + - field.field.node.az_opportunity.field_az_trellis_imported_date + - node.type.az_opportunity + module: + - date_ap_style + - field_group + - smart_title + - user +third_party_settings: + field_group: + group_row_wrap: + children: + - group_opportunity_link + - group_row + label: 'row wrap' + parent_name: '' + region: content + weight: 1 + format_type: html_element + format_settings: + classes: 'position-relative d-block list-group-item-action hover container' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_opportunity_link: + children: + - links + label: 'opportunity link' + parent_name: group_row_wrap + region: content + weight: 0 + format_type: link + format_settings: + classes: 'text-decoration-none stretched-link' + show_empty_fields: false + id: '' + label_as_html: false + target: custom_uri + custom_uri: '[node:az-canonical-url]' + target_attribute: default + group_row: + children: + - group_col_1 + - group_col_4 + - group_col_2 + - group_col_3 + label: row + parent_name: group_row_wrap + region: content + weight: 2 + format_type: html_element + format_settings: + classes: 'row shadow-sm p-2 p-md-1 border rounded' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_col_1: + children: + - smart_title + label: 'col 1' + parent_name: group_row + region: content + weight: 2 + format_type: html_element + format_settings: + classes: 'col-12 col-md-4 align-content-center' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_col_2: + children: + - field_az_application_date + label: 'Application date' + parent_name: group_row + region: content + weight: 4 + format_type: html_element + format_settings: + classes: 'col-12 col-md-3' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: true + label_element: h4 + label_element_classes: 'fs-6 fw-bold mb-0 mt-2 mt-md-1' + attributes: '' + effect: none + speed: fast + group_col_3: + children: + - field_az_opportunity_location + label: Location + parent_name: group_row + region: content + weight: 5 + format_type: html_element + format_settings: + classes: 'col-12 col-md-2' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: true + label_element: h4 + label_element_classes: 'fs-6 fw-bold mb-0 mt-2 mt-md-1' + attributes: '' + effect: none + speed: fast + group_col_4: + children: + - field_az_program_date + label: 'Program Date' + parent_name: group_row + region: content + weight: 3 + format_type: html_element + format_settings: + classes: 'col-12 col-md-3' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: true + label_element: h4 + label_element_classes: 'fs-6 fw-bold mb-0 mt-2 mt-md-1' + attributes: '' + effect: none + speed: fast + smart_title: + enabled: true + settings: + smart_title__link: false + smart_title__tag: h3 + smart_title__classes: + - h5 + - my-2 + - my-md-0 + - hover-text-underline +id: node.az_opportunity.az_row +targetEntityType: node +bundle: az_opportunity +mode: az_row +content: + field_az_application_date: + type: daterange_ap_style + label: hidden + settings: + always_display_year: false + use_today: false + cap_today: false + display_day: false + display_time: false + hide_date: false + time_before_date: false + display_noon_and_midnight: false + capitalize_noon_and_midnight: false + use_all_day: false + separator: endash + timezone: '' + month_only: false + third_party_settings: { } + weight: 13 + region: content + field_az_opportunity_location: + type: string + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + weight: 9 + region: content + field_az_program_date: + type: daterange_ap_style + label: hidden + settings: + always_display_year: false + use_today: false + cap_today: false + display_day: false + display_time: false + hide_date: false + time_before_date: false + display_noon_and_midnight: false + capitalize_noon_and_midnight: false + use_all_day: false + separator: endash + timezone: '' + month_only: false + third_party_settings: { } + weight: 1 + region: content + links: + settings: { } + third_party_settings: { } + weight: 7 + region: content + smart_title: + settings: { } + third_party_settings: { } + weight: 0 + region: content +hidden: + field_az_application_link: true + field_az_body: true + field_az_eligibility: true + field_az_enterprise_attributes: true + field_az_incentives: true + field_az_offered: true + field_az_ongoing: true + field_az_opportunity_category: true + field_az_opportunity_credit: true + field_az_parent_account: true + field_az_program_length: true + field_az_program_website: true + field_az_trellis_id: true + field_az_trellis_imported_date: true diff --git a/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.az_row_with_background.yml b/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.az_row_with_background.yml new file mode 100644 index 0000000000..ce2f91ba3f --- /dev/null +++ b/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.az_row_with_background.yml @@ -0,0 +1,54 @@ +langcode: en +status: false +dependencies: + config: + - core.entity_view_mode.node.az_row_with_background + - field.field.node.az_opportunity.field_az_application_date + - field.field.node.az_opportunity.field_az_application_link + - field.field.node.az_opportunity.field_az_body + - field.field.node.az_opportunity.field_az_eligibility + - field.field.node.az_opportunity.field_az_enterprise_attributes + - field.field.node.az_opportunity.field_az_incentives + - field.field.node.az_opportunity.field_az_offered + - field.field.node.az_opportunity.field_az_ongoing + - field.field.node.az_opportunity.field_az_opportunity_category + - field.field.node.az_opportunity.field_az_opportunity_credit + - field.field.node.az_opportunity.field_az_opportunity_location + - field.field.node.az_opportunity.field_az_parent_account + - field.field.node.az_opportunity.field_az_program_date + - field.field.node.az_opportunity.field_az_program_length + - field.field.node.az_opportunity.field_az_program_website + - field.field.node.az_opportunity.field_az_trellis_id + - field.field.node.az_opportunity.field_az_trellis_imported_date + - node.type.az_opportunity + module: + - user +id: node.az_opportunity.az_row_with_background +targetEntityType: node +bundle: az_opportunity +mode: az_row_with_background +content: + links: + settings: { } + third_party_settings: { } + weight: 100 + region: content +hidden: + field_az_application_date: true + field_az_application_link: true + field_az_body: true + field_az_eligibility: true + field_az_enterprise_attributes: true + field_az_incentives: true + field_az_offered: true + field_az_ongoing: true + field_az_opportunity_category: true + field_az_opportunity_credit: true + field_az_opportunity_location: true + field_az_parent_account: true + field_az_program_date: true + field_az_program_length: true + field_az_program_website: true + field_az_trellis_id: true + field_az_trellis_imported_date: true + smart_title: true diff --git a/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.az_small_row.yml b/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.az_small_row.yml new file mode 100644 index 0000000000..327a06352a --- /dev/null +++ b/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.az_small_row.yml @@ -0,0 +1,168 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.az_small_row + - field.field.node.az_opportunity.field_az_application_date + - field.field.node.az_opportunity.field_az_application_link + - field.field.node.az_opportunity.field_az_body + - field.field.node.az_opportunity.field_az_eligibility + - field.field.node.az_opportunity.field_az_enterprise_attributes + - field.field.node.az_opportunity.field_az_incentives + - field.field.node.az_opportunity.field_az_offered + - field.field.node.az_opportunity.field_az_ongoing + - field.field.node.az_opportunity.field_az_opportunity_category + - field.field.node.az_opportunity.field_az_opportunity_credit + - field.field.node.az_opportunity.field_az_opportunity_location + - field.field.node.az_opportunity.field_az_parent_account + - field.field.node.az_opportunity.field_az_program_date + - field.field.node.az_opportunity.field_az_program_length + - field.field.node.az_opportunity.field_az_program_website + - field.field.node.az_opportunity.field_az_trellis_id + - field.field.node.az_opportunity.field_az_trellis_imported_date + - node.type.az_opportunity + module: + - date_ap_style + - field_group + - smart_title + - user +third_party_settings: + field_group: + group_col1: + children: + - smart_title + label: col1 + parent_name: group_header_row + region: content + weight: 21 + format_type: html_element + format_settings: + classes: 'col-12 col-md-6' + show_empty_fields: false + id: '' + label_as_html: true + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_col2: + children: + - field_az_application_date + label: col2 + parent_name: group_header_row + region: content + weight: 22 + format_type: html_element + format_settings: + classes: 'col-12 col-md-6' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_header_row: + children: + - group_col1 + - group_col2 + label: 'header row' + parent_name: group_container + region: content + weight: 1 + format_type: html_element + format_settings: + classes: 'row border-bottom pb-2 mb-2' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_container: + children: + - group_header_row + label: Container + parent_name: '' + region: content + weight: 0 + format_type: html_element + format_settings: + classes: container + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + smart_title: + enabled: true + settings: + smart_title__link: true + smart_title__tag: h3 + smart_title__classes: + - fs-5 + - fw-bold + - m-0 +id: node.az_opportunity.az_small_row +targetEntityType: node +bundle: az_opportunity +mode: az_small_row +content: + field_az_application_date: + type: daterange_ap_style + label: inline + settings: + always_display_year: false + use_today: false + cap_today: false + display_day: false + display_time: false + hide_date: false + time_before_date: false + display_noon_and_midnight: false + capitalize_noon_and_midnight: false + use_all_day: false + separator: endash + timezone: '' + month_only: false + third_party_settings: { } + weight: 5 + region: content + smart_title: + settings: { } + third_party_settings: { } + weight: 6 + region: content +hidden: + field_az_application_link: true + field_az_body: true + field_az_eligibility: true + field_az_enterprise_attributes: true + field_az_incentives: true + field_az_offered: true + field_az_ongoing: true + field_az_opportunity_category: true + field_az_opportunity_credit: true + field_az_opportunity_location: true + field_az_parent_account: true + field_az_program_date: true + field_az_program_length: true + field_az_program_website: true + field_az_trellis_id: true + field_az_trellis_imported_date: true + links: true diff --git a/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.default.yml b/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.default.yml new file mode 100644 index 0000000000..2d2dc0d792 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/core.entity_view_display.node.az_opportunity.default.yml @@ -0,0 +1,447 @@ +langcode: en +status: true +dependencies: + config: + - field.field.node.az_opportunity.field_az_application_date + - field.field.node.az_opportunity.field_az_application_link + - field.field.node.az_opportunity.field_az_body + - field.field.node.az_opportunity.field_az_eligibility + - field.field.node.az_opportunity.field_az_enterprise_attributes + - field.field.node.az_opportunity.field_az_incentives + - field.field.node.az_opportunity.field_az_offered + - field.field.node.az_opportunity.field_az_ongoing + - field.field.node.az_opportunity.field_az_opportunity_category + - field.field.node.az_opportunity.field_az_opportunity_credit + - field.field.node.az_opportunity.field_az_opportunity_location + - field.field.node.az_opportunity.field_az_parent_account + - field.field.node.az_opportunity.field_az_program_date + - field.field.node.az_opportunity.field_az_program_length + - field.field.node.az_opportunity.field_az_program_website + - field.field.node.az_opportunity.field_az_trellis_id + - field.field.node.az_opportunity.field_az_trellis_imported_date + - node.type.az_opportunity + module: + - date_ap_style + - field_group + - link + - options + - smart_title + - text + - user +third_party_settings: + field_group: + group_col1: + children: + - group_where + label: col1 + parent_name: group_header_row + region: content + weight: 1 + format_type: html_element + format_settings: + classes: 'col-12 col-sm-6 col-lg p-card' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: Where + attributes: '' + effect: none + speed: fast + group_col3: + children: + - group_program_length + label: col2 + parent_name: group_header_row + region: content + weight: 3 + format_type: html_element + format_settings: + classes: 'col-12 col-sm-6 col-lg p-card' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_col5: + children: + - group_incentives + label: col3 + parent_name: group_header_row + region: content + weight: 4 + format_type: html_element + format_settings: + classes: 'col-12 col-sm-6 col-lg p-card' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_col7: + children: + - group_date + label: col4 + parent_name: group_header_row + region: content + weight: 5 + format_type: html_element + format_settings: + classes: 'col-12 col-sm-6 col-lg p-card' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_col8: + children: + - group_topics + label: col5 + parent_name: group_header_row + region: content + weight: 6 + format_type: html_element + format_settings: + classes: 'col-12 col-sm-6 col-lg p-card' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_header_row: + children: + - group_col1 + - group_col3 + - group_col5 + - group_col7 + - group_col8 + label: 'header row' + parent_name: group_container + region: content + weight: 1 + format_type: html_element + format_settings: + classes: 'row rounded border' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_where: + children: + - field_az_opportunity_location + label: Location + parent_name: group_col1 + region: content + weight: 5 + format_type: html_element + format_settings: + classes: '' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: true + label_element: h2 + label_element_classes: 'h5 fw-bolder mt-0' + attributes: '' + effect: none + speed: fast + group_date: + children: + - field_az_program_date + - field_az_program_website + label: 'Program Info' + parent_name: group_col7 + region: content + weight: 5 + format_type: html_element + format_settings: + classes: '' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: true + label_element: h2 + label_element_classes: 'h5 fw-bolder mt-0' + attributes: '' + effect: none + speed: fast + group_incentives: + children: + - field_az_incentives + - field_az_opportunity_credit + label: Incentives + parent_name: group_col5 + region: content + weight: 2 + format_type: html_element + format_settings: + classes: '' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: true + label_element: h2 + label_element_classes: 'h5 fw-bolder mt-0' + attributes: '' + effect: none + speed: fast + group_program_length: + children: + - field_az_offered + - field_az_program_length + label: 'Start Options' + parent_name: group_col3 + region: content + weight: 9 + format_type: html_element + format_settings: + classes: '' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: true + label_element: h2 + label_element_classes: 'h5 fw-bolder mt-0' + attributes: '' + effect: none + speed: fast + group_topics: + children: + - field_az_application_date + - field_az_application_link + label: 'Application Info' + parent_name: group_col8 + region: content + weight: 6 + format_type: html_element + format_settings: + classes: '' + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: true + label_element: h2 + label_element_classes: 'h5 fw-bolder mt-0' + attributes: '' + effect: none + speed: fast + group_container: + children: + - group_header_row + label: container + parent_name: '' + region: content + weight: 0 + format_type: html_element + format_settings: + classes: container + show_empty_fields: false + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + group_content_row: + children: + - field_az_body + - field_az_eligibility + - links + - field_az_opportunity_category + label: 'Content row' + parent_name: '' + region: content + weight: 5 + format_type: html_element + format_settings: + classes: 'row mb-5' + show_empty_fields: true + id: '' + label_as_html: false + element: div + show_label: false + label_element: h3 + label_element_classes: '' + attributes: '' + effect: none + speed: fast + smart_title: + enabled: false +id: node.az_opportunity.default +targetEntityType: node +bundle: az_opportunity +mode: default +content: + field_az_application_date: + type: daterange_ap_style + label: hidden + settings: + always_display_year: false + use_today: false + cap_today: false + display_day: false + display_time: false + hide_date: false + time_before_date: false + display_noon_and_midnight: false + capitalize_noon_and_midnight: false + use_all_day: false + separator: endash + timezone: '' + month_only: false + third_party_settings: { } + weight: 7 + region: content + field_az_application_link: + type: link + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '0' + target: '0' + third_party_settings: { } + weight: 8 + region: content + field_az_body: + type: text_default + label: above + settings: { } + third_party_settings: { } + weight: 2 + region: content + field_az_eligibility: + type: text_default + label: above + settings: { } + third_party_settings: { } + weight: 3 + region: content + field_az_incentives: + type: list_default + label: hidden + settings: { } + third_party_settings: { } + weight: 18 + region: content + field_az_offered: + type: entity_reference_label + label: hidden + settings: + link: true + third_party_settings: { } + weight: 7 + region: content + field_az_opportunity_category: + type: entity_reference_entity_view + label: hidden + settings: + view_mode: az_badge + link: false + third_party_settings: { } + weight: 5 + region: content + field_az_opportunity_credit: + type: list_default + label: hidden + settings: { } + third_party_settings: { } + weight: 19 + region: content + field_az_opportunity_location: + type: string + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + weight: 4 + region: content + field_az_program_date: + type: daterange_ap_style + label: hidden + settings: + always_display_year: false + use_today: false + cap_today: false + display_day: false + display_time: false + hide_date: false + time_before_date: false + display_noon_and_midnight: false + capitalize_noon_and_midnight: false + use_all_day: false + separator: endash + timezone: '' + month_only: false + third_party_settings: { } + weight: 7 + region: content + field_az_program_length: + type: string + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + weight: 8 + region: content + field_az_program_website: + type: link + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } + weight: 8 + region: content + links: + settings: { } + third_party_settings: { } + weight: 4 + region: content +hidden: + field_az_enterprise_attributes: true + field_az_ongoing: true + field_az_parent_account: true + field_az_trellis_id: true + field_az_trellis_imported_date: true + smart_title: true diff --git a/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_categories.az_badge.yml b/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_categories.az_badge.yml new file mode 100644 index 0000000000..e5f8f8982f --- /dev/null +++ b/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_categories.az_badge.yml @@ -0,0 +1,45 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.taxonomy_term.az_badge + - taxonomy.vocabulary.az_opportunity_categories + module: + - field_group + - smart_title +third_party_settings: + field_group: + group_link: + children: + - smart_title + label: Link + parent_name: '' + region: content + weight: 0 + format_type: link + format_settings: + classes: 'badge text-bg-light badge-link' + show_empty_fields: false + id: '' + label_as_html: false + target: entity + custom_uri: '' + target_attribute: default + smart_title: + enabled: true + settings: + smart_title__link: false + smart_title__tag: div + smart_title__classes: { } +id: taxonomy_term.az_opportunity_categories.az_badge +targetEntityType: taxonomy_term +bundle: az_opportunity_categories +mode: az_badge +content: + smart_title: + settings: { } + third_party_settings: { } + weight: 0 + region: content +hidden: + description: true diff --git a/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_categories.default.yml b/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_categories.default.yml new file mode 100644 index 0000000000..dbff65ca0c --- /dev/null +++ b/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_categories.default.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + config: + - taxonomy.vocabulary.az_opportunity_categories + module: + - text +id: taxonomy_term.az_opportunity_categories.default +targetEntityType: taxonomy_term +bundle: az_opportunity_categories +mode: default +content: + description: + type: text_default + label: hidden + settings: { } + third_party_settings: { } + weight: 0 + region: content +hidden: { } diff --git a/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_semester.default.yml b/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_semester.default.yml new file mode 100644 index 0000000000..53fd35f123 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_semester.default.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + config: + - taxonomy.vocabulary.az_opportunity_semester + module: + - text +id: taxonomy_term.az_opportunity_semester.default +targetEntityType: taxonomy_term +bundle: az_opportunity_semester +mode: default +content: + description: + type: text_trimmed + label: hidden + settings: + trim_length: 600 + third_party_settings: { } + weight: 0 + region: content +hidden: { } diff --git a/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_topic.default.yml b/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_topic.default.yml new file mode 100644 index 0000000000..6578fd5a5c --- /dev/null +++ b/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_topic.default.yml @@ -0,0 +1 @@ +{ } diff --git a/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_type.default.yml b/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_type.default.yml new file mode 100644 index 0000000000..6578fd5a5c --- /dev/null +++ b/modules/custom/az_opportunity/config/install/core.entity_view_display.taxonomy_term.az_opportunity_type.default.yml @@ -0,0 +1 @@ +{ } diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_application_date.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_application_date.yml new file mode 100644 index 0000000000..a7e239d149 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_application_date.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_application_date + - node.type.az_opportunity + module: + - datetime_range +id: node.az_opportunity.field_az_application_date +field_name: field_az_application_date +entity_type: node +bundle: az_opportunity +label: 'Application Date' +description: "An Application Date is when this opportunity is active for applications.\r\nLeave this field empty for \"TBD\"" +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: daterange diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_application_link.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_application_link.yml new file mode 100644 index 0000000000..a88251ddf5 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_application_link.yml @@ -0,0 +1,22 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_application_link + - node.type.az_opportunity + module: + - link +id: node.az_opportunity.field_az_application_link +field_name: field_az_application_link +entity_type: node +bundle: az_opportunity +label: 'Application Link' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + title: 1 + link_type: 17 +field_type: link diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_body.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_body.yml new file mode 100644 index 0000000000..9a947eb828 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_body.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_body + - filter.format.az_standard + - node.type.az_opportunity + module: + - text +id: node.az_opportunity.field_az_body +field_name: field_az_body +entity_type: node +bundle: az_opportunity +label: Overview +description: 'White text will be highlighted in gray (only while editing) to keep the text visible.' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + allowed_formats: + - az_standard +field_type: text_long diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_eligibility.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_eligibility.yml new file mode 100644 index 0000000000..12361bc4b5 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_eligibility.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_eligibility + - filter.format.az_standard + - node.type.az_opportunity + module: + - text +id: node.az_opportunity.field_az_eligibility +field_name: field_az_eligibility +entity_type: node +bundle: az_opportunity +label: Eligibility +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + allowed_formats: + - az_standard +field_type: text_long diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_enterprise_attributes.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_enterprise_attributes.yml new file mode 100644 index 0000000000..d055642067 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_enterprise_attributes.yml @@ -0,0 +1,28 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_enterprise_attributes + - node.type.az_opportunity + - taxonomy.vocabulary.az_enterprise_attributes +id: node.az_opportunity.field_az_enterprise_attributes +field_name: field_az_enterprise_attributes +entity_type: node +bundle: az_opportunity +label: 'Enterprise Attributes' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + az_enterprise_attributes: az_enterprise_attributes + sort: + field: name + direction: asc + auto_create: false + auto_create_bundle: '' +field_type: entity_reference diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_incentives.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_incentives.yml new file mode 100644 index 0000000000..abe4e12489 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_incentives.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_incentives + - node.type.az_opportunity + module: + - options +id: node.az_opportunity.field_az_incentives +field_name: field_az_incentives +entity_type: node +bundle: az_opportunity +label: Incentives +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: list_string diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_offered.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_offered.yml new file mode 100644 index 0000000000..2edc818cf8 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_offered.yml @@ -0,0 +1,28 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_offered + - node.type.az_opportunity + - taxonomy.vocabulary.az_opportunity_semester +id: node.az_opportunity.field_az_offered +field_name: field_az_offered +entity_type: node +bundle: az_opportunity +label: Offered +description: 'Which semester or season this opportunity is offered.' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + az_opportunity_semester: az_opportunity_semester + sort: + field: name + direction: asc + auto_create: true + auto_create_bundle: '' +field_type: entity_reference diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_ongoing.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_ongoing.yml new file mode 100644 index 0000000000..ed7facdf04 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_ongoing.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_ongoing + - node.type.az_opportunity +id: node.az_opportunity.field_az_ongoing +field_name: field_az_ongoing +entity_type: node +bundle: az_opportunity +label: Ongoing +description: 'Is this content ongoing even though its Application time has passed?' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + on_label: 'On' + off_label: 'Off' +field_type: boolean diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_opportunity_category.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_opportunity_category.yml new file mode 100644 index 0000000000..579546fa76 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_opportunity_category.yml @@ -0,0 +1,28 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_opportunity_category + - node.type.az_opportunity + - taxonomy.vocabulary.az_opportunity_categories +id: node.az_opportunity.field_az_opportunity_category +field_name: field_az_opportunity_category +entity_type: node +bundle: az_opportunity +label: Category +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + az_opportunity_categories: az_opportunity_categories + sort: + field: name + direction: asc + auto_create: true + auto_create_bundle: '' +field_type: entity_reference diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_opportunity_credit.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_opportunity_credit.yml new file mode 100644 index 0000000000..8a7b22aaa8 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_opportunity_credit.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_opportunity_credit + - node.type.az_opportunity + module: + - options +id: node.az_opportunity.field_az_opportunity_credit +field_name: field_az_opportunity_credit +entity_type: node +bundle: az_opportunity +label: Credit +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: list_string diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_opportunity_location.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_opportunity_location.yml new file mode 100644 index 0000000000..12d07281ec --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_opportunity_location.yml @@ -0,0 +1,18 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_opportunity_location + - node.type.az_opportunity +id: node.az_opportunity.field_az_opportunity_location +field_name: field_az_opportunity_location +entity_type: node +bundle: az_opportunity +label: Location +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_parent_account.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_parent_account.yml new file mode 100644 index 0000000000..fbc693d390 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_parent_account.yml @@ -0,0 +1,18 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_parent_account + - node.type.az_opportunity +id: node.az_opportunity.field_az_parent_account +field_name: field_az_parent_account +entity_type: node +bundle: az_opportunity +label: 'Trellis Parent Account' +description: 'Trellis specific field that checks for Parent Accounts, or the parent program content.' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_program_date.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_program_date.yml new file mode 100644 index 0000000000..83da3dc08a --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_program_date.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_program_date + - node.type.az_opportunity + module: + - datetime_range +id: node.az_opportunity.field_az_program_date +field_name: field_az_program_date +entity_type: node +bundle: az_opportunity +label: 'Program Date' +description: "The Program Date, or the Account Date, that the program is active.\r\nLeave this field empty for \"TBD\"" +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: daterange diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_program_length.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_program_length.yml new file mode 100644 index 0000000000..6b3bbd873c --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_program_length.yml @@ -0,0 +1,18 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_program_length + - node.type.az_opportunity +id: node.az_opportunity.field_az_program_length +field_name: field_az_program_length +entity_type: node +bundle: az_opportunity +label: 'Program Length' +description: 'How long a program is running.' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_program_website.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_program_website.yml new file mode 100644 index 0000000000..fd516e45ec --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_program_website.yml @@ -0,0 +1,22 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_program_website + - node.type.az_opportunity + module: + - link +id: node.az_opportunity.field_az_program_website +field_name: field_az_program_website +entity_type: node +bundle: az_opportunity +label: 'Program Website' +description: 'A link to the Program website.' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + title: 1 + link_type: 17 +field_type: link diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_trellis_id.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_trellis_id.yml new file mode 100644 index 0000000000..47c8f495b1 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_trellis_id.yml @@ -0,0 +1,18 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_trellis_id + - node.type.az_opportunity +id: node.az_opportunity.field_az_trellis_id +field_name: field_az_trellis_id +entity_type: node +bundle: az_opportunity +label: 'Trellis Opportunity ID' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_trellis_imported_date.yml b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_trellis_imported_date.yml new file mode 100644 index 0000000000..d2b743f523 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.field.node.az_opportunity.field_az_trellis_imported_date.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_az_trellis_imported_date + - node.type.az_opportunity + module: + - datetime +id: node.az_opportunity.field_az_trellis_imported_date +field_name: field_az_trellis_imported_date +entity_type: node +bundle: az_opportunity +label: 'Trellis Imported Date' +description: 'An internal field that informs us when this content was last updated.' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: datetime diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_application_date.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_application_date.yml new file mode 100644 index 0000000000..84554f56da --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_application_date.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - datetime_range + - node +id: node.field_az_application_date +field_name: field_az_application_date +entity_type: node +type: daterange +settings: + datetime_type: datetime +module: datetime_range +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_application_link.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_application_link.yml new file mode 100644 index 0000000000..530cdc3e0a --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_application_link.yml @@ -0,0 +1,18 @@ +langcode: en +status: true +dependencies: + module: + - link + - node +id: node.field_az_application_link +field_name: field_az_application_link +entity_type: node +type: link +settings: { } +module: link +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_eligibility.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_eligibility.yml new file mode 100644 index 0000000000..ad58d78c55 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_eligibility.yml @@ -0,0 +1,18 @@ +langcode: en +status: true +dependencies: + module: + - node + - text +id: node.field_az_eligibility +field_name: field_az_eligibility +entity_type: node +type: text_long +settings: { } +module: text +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_incentives.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_incentives.yml new file mode 100644 index 0000000000..ade805f693 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_incentives.yml @@ -0,0 +1,29 @@ +langcode: en +status: true +dependencies: + module: + - node + - options +id: node.field_az_incentives +field_name: field_az_incentives +entity_type: node +type: list_string +settings: + allowed_values: + - + value: 'yes' + label: 'Yes' + - + value: 'no' + label: 'No' + - + value: inquire_within + label: 'Inquire Within' + allowed_values_function: '' +module: options +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_offered.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_offered.yml new file mode 100644 index 0000000000..fb55b0a439 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_offered.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - node + - taxonomy +id: node.field_az_offered +field_name: field_az_offered +entity_type: node +type: entity_reference +settings: + target_type: taxonomy_term +module: core +locked: false +cardinality: -1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_ongoing.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_ongoing.yml new file mode 100644 index 0000000000..2b0ec8f908 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_ongoing.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + module: + - node +id: node.field_az_ongoing +field_name: field_az_ongoing +entity_type: node +type: boolean +settings: { } +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_opportunity_category.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_opportunity_category.yml new file mode 100644 index 0000000000..53976583a0 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_opportunity_category.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - node + - taxonomy +id: node.field_az_opportunity_category +field_name: field_az_opportunity_category +entity_type: node +type: entity_reference +settings: + target_type: taxonomy_term +module: core +locked: false +cardinality: -1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_opportunity_credit.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_opportunity_credit.yml new file mode 100644 index 0000000000..665d4f891f --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_opportunity_credit.yml @@ -0,0 +1,29 @@ +langcode: en +status: true +dependencies: + module: + - node + - options +id: node.field_az_opportunity_credit +field_name: field_az_opportunity_credit +entity_type: node +type: list_string +settings: + allowed_values: + - + value: non_credit + label: Non-Credit + - + value: ua_credit + label: 'UA Credit' + - + value: transfer_credit + label: 'Transfer Credit' + allowed_values_function: '' +module: options +locked: false +cardinality: -1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_opportunity_location.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_opportunity_location.yml new file mode 100644 index 0000000000..846023a19b --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_opportunity_location.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + module: + - node +id: node.field_az_opportunity_location +field_name: field_az_opportunity_location +entity_type: node +type: string +settings: + max_length: 255 + case_sensitive: false + is_ascii: false +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_parent_account.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_parent_account.yml new file mode 100644 index 0000000000..b178540f18 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_parent_account.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + module: + - node +id: node.field_az_parent_account +field_name: field_az_parent_account +entity_type: node +type: string +settings: + max_length: 255 + case_sensitive: false + is_ascii: false +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_program_date.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_program_date.yml new file mode 100644 index 0000000000..e0926ea086 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_program_date.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - datetime_range + - node +id: node.field_az_program_date +field_name: field_az_program_date +entity_type: node +type: daterange +settings: + datetime_type: datetime +module: datetime_range +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_program_length.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_program_length.yml new file mode 100644 index 0000000000..7e2d8371d2 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_program_length.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + module: + - node +id: node.field_az_program_length +field_name: field_az_program_length +entity_type: node +type: string +settings: + max_length: 255 + case_sensitive: false + is_ascii: false +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_program_website.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_program_website.yml new file mode 100644 index 0000000000..9208b2bec4 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_program_website.yml @@ -0,0 +1,18 @@ +langcode: en +status: true +dependencies: + module: + - link + - node +id: node.field_az_program_website +field_name: field_az_program_website +entity_type: node +type: link +settings: { } +module: link +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/field.storage.node.field_az_trellis_imported_date.yml b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_trellis_imported_date.yml new file mode 100644 index 0000000000..8d54b2ca18 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/field.storage.node.field_az_trellis_imported_date.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - datetime + - node +id: node.field_az_trellis_imported_date +field_name: field_az_trellis_imported_date +entity_type: node +type: datetime +settings: + datetime_type: datetime +module: datetime +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/az_opportunity/config/install/node.type.az_opportunity.yml b/modules/custom/az_opportunity/config/install/node.type.az_opportunity.yml new file mode 100644 index 0000000000..5fe143b326 --- /dev/null +++ b/modules/custom/az_opportunity/config/install/node.type.az_opportunity.yml @@ -0,0 +1,16 @@ +langcode: en +status: true +dependencies: + module: + - menu_ui +third_party_settings: + menu_ui: + available_menus: { } + parent: '' +name: Opportunity +type: az_opportunity +description: 'Use this content type to add a new Opportunity to your site.' +help: null +new_revision: true +preview_mode: 1 +display_submitted: false diff --git a/modules/custom/az_opportunity/config/install/taxonomy.vocabulary.az_opportunity_categories.yml b/modules/custom/az_opportunity/config/install/taxonomy.vocabulary.az_opportunity_categories.yml new file mode 100644 index 0000000000..de94915eba --- /dev/null +++ b/modules/custom/az_opportunity/config/install/taxonomy.vocabulary.az_opportunity_categories.yml @@ -0,0 +1,8 @@ +langcode: en +status: true +dependencies: { } +name: 'Opportunity Categories' +vid: az_opportunity_categories +description: 'Taxonomy for categorizing the Opportunity content type' +weight: 0 +new_revision: false diff --git a/modules/custom/az_opportunity/config/install/taxonomy.vocabulary.az_opportunity_semester.yml b/modules/custom/az_opportunity/config/install/taxonomy.vocabulary.az_opportunity_semester.yml new file mode 100644 index 0000000000..1560c66d2e --- /dev/null +++ b/modules/custom/az_opportunity/config/install/taxonomy.vocabulary.az_opportunity_semester.yml @@ -0,0 +1,8 @@ +langcode: en +status: true +dependencies: { } +name: 'Opportunity Semester' +vid: az_opportunity_semester +description: 'Taxonomy for the semester in Opportunity content type' +weight: 0 +new_revision: false diff --git a/modules/custom/az_opportunity/config/install/views.view.az_opportunity.yml b/modules/custom/az_opportunity/config/install/views.view.az_opportunity.yml new file mode 100644 index 0000000000..1ad01e323e --- /dev/null +++ b/modules/custom/az_opportunity/config/install/views.view.az_opportunity.yml @@ -0,0 +1,655 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.az_card + - core.entity_view_mode.node.az_row + - core.entity_view_mode.node.az_small_row + - node.type.az_opportunity + module: + - datetime + - node + - options + - user + - views_bootstrap +id: az_opportunity +label: 'AZ Opportunity' +module: views +description: '' +tag: '' +base_table: node_field_data +base_field: nid +display: + default: + id: default + display_title: Default + display_plugin: default + position: 0 + display_options: + fields: + title: + id: title + table: node_field_data + field: title + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: title + plugin_id: field + label: '' + exclude: false + alter: + alter_text: false + make_link: false + absolute: false + word_boundary: false + ellipsis: false + strip_tags: false + trim: false + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: true + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + pager: + type: mini + options: + offset: 0 + pagination_heading_level: h4 + items_per_page: 10 + total_pages: null + id: 0 + tags: + next: ›› + previous: ‹‹ + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + access: + type: perm + options: + perm: 'access content' + cache: + type: tag + options: { } + empty: { } + sorts: + field_az_application_date_value: + id: field_az_application_date_value + table: node__field_az_application_date + field: field_az_application_date_value + relationship: none + group_type: group + admin_label: '' + plugin_id: datetime + order: ASC + expose: + label: '' + field_identifier: '' + exposed: false + granularity: day + field_az_program_date_value: + id: field_az_program_date_value + table: node__field_az_program_date + field: field_az_program_date_value + relationship: none + group_type: group + admin_label: '' + plugin_id: datetime + order: ASC + expose: + label: '' + field_identifier: '' + exposed: false + granularity: day + arguments: { } + filters: + status: + id: status + table: node_field_data + field: status + entity_type: node + entity_field: status + plugin_id: boolean + value: '1' + group: 1 + expose: + operator: '' + type: + id: type + table: node_field_data + field: type + entity_type: node + entity_field: type + plugin_id: bundle + value: + az_opportunity: az_opportunity + style: + type: default + options: + grouping: { } + row_class: '' + default_row_class: true + uses_fields: false + row: + type: fields + options: + default_field_elements: true + inline: { } + separator: '' + hide_empty: false + query: + type: views_query + options: + query_comment: '' + disable_sql_rewrite: false + distinct: false + replica: false + query_tags: { } + relationships: { } + header: { } + footer: { } + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } + block_1: + id: block_1 + display_title: 'Row View with Filter' + display_plugin: block + position: 1 + display_options: + pager: + type: full + options: + offset: 0 + pagination_heading_level: h4 + items_per_page: 10 + total_pages: null + id: 0 + tags: + next: ›› + previous: ‹‹ + first: '« First' + last: 'Last »' + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + quantity: 9 + filters: + status: + id: status + table: node_field_data + field: status + entity_type: node + entity_field: status + plugin_id: boolean + value: '1' + group: 1 + expose: + operator: '' + type: + id: type + table: node_field_data + field: type + entity_type: node + entity_field: type + plugin_id: bundle + value: + az_opportunity: az_opportunity + group: 1 + title: + id: title + table: node_field_data + field: title + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: title + plugin_id: string + operator: contains + value: '' + group: 1 + exposed: true + expose: + operator_id: title_op + label: Title + description: '' + use_operator: false + operator: title_op + operator_limit_selection: false + operator_list: { } + identifier: title + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + placeholder: '' + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + field_az_opportunity_location_value: + id: field_az_opportunity_location_value + table: node__field_az_opportunity_location + field: field_az_opportunity_location_value + relationship: none + group_type: group + admin_label: '' + plugin_id: string + operator: contains + value: '' + group: 1 + exposed: true + expose: + operator_id: field_az_opportunity_location_value_op + label: Location + description: '' + use_operator: false + operator: field_az_opportunity_location_value_op + operator_limit_selection: false + operator_list: { } + identifier: field_az_opportunity_location_value + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + placeholder: '' + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + field_az_incentives_value: + id: field_az_incentives_value + table: node__field_az_incentives + field: field_az_incentives_value + relationship: none + group_type: group + admin_label: '' + plugin_id: list_field + operator: or + value: { } + group: 1 + exposed: true + expose: + operator_id: field_az_incentives_value_op + label: Incentives + description: '' + use_operator: false + operator: field_az_incentives_value_op + operator_limit_selection: false + operator_list: { } + identifier: field_az_incentives_value + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + reduce: false + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + reduce_duplicates: false + filter_groups: + operator: AND + groups: + 1: AND + style: + type: default + options: + grouping: { } + row_class: '' + default_row_class: true + uses_fields: false + row: + type: 'entity:node' + options: + relationship: none + view_mode: az_row + defaults: + pager: false + pager_options: false + style: false + style_options: false + row: false + filters: false + filter_groups: false + display_description: '' + pager_options: null + style_options: null + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } + block_2: + id: block_2 + display_title: 'Card View' + display_plugin: block + position: 1 + display_options: + style: + type: views_bootstrap_grid + options: + row_class: '' + default_row_class: true + uses_fields: false + grid_class: '' + col_xs: col-12 + col_sm: none + col_md: col-md-6 + col_lg: col-lg-4 + col_xl: none + col_xxl: none + row: + type: 'entity:node' + options: + relationship: none + view_mode: az_card + defaults: + style: false + style_options: false + row: false + display_description: '' + style_options: null + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } + block_3: + id: block_3 + display_title: 'Small Row' + display_plugin: block + position: 1 + display_options: + pager: + type: full + options: + offset: 0 + pagination_heading_level: h4 + items_per_page: 10 + total_pages: null + id: 0 + tags: + next: ›› + previous: ‹‹ + first: '« First' + last: 'Last »' + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + quantity: 9 + filters: + status: + id: status + table: node_field_data + field: status + entity_type: node + entity_field: status + plugin_id: boolean + value: '1' + group: 1 + expose: + operator: '' + type: + id: type + table: node_field_data + field: type + entity_type: node + entity_field: type + plugin_id: bundle + value: + az_opportunity: az_opportunity + group: 1 + title: + id: title + table: node_field_data + field: title + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: title + plugin_id: string + operator: contains + value: '' + group: 1 + exposed: true + expose: + operator_id: title_op + label: Title + description: '' + use_operator: false + operator: title_op + operator_limit_selection: false + operator_list: { } + identifier: title + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + placeholder: '' + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + field_az_opportunity_location_value: + id: field_az_opportunity_location_value + table: node__field_az_opportunity_location + field: field_az_opportunity_location_value + relationship: none + group_type: group + admin_label: '' + plugin_id: string + operator: contains + value: '' + group: 1 + exposed: true + expose: + operator_id: field_az_opportunity_location_value_op + label: Location + description: '' + use_operator: false + operator: field_az_opportunity_location_value_op + operator_limit_selection: false + operator_list: { } + identifier: field_az_opportunity_location_value + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + placeholder: '' + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + field_az_incentives_value: + id: field_az_incentives_value + table: node__field_az_incentives + field: field_az_incentives_value + relationship: none + group_type: group + admin_label: '' + plugin_id: list_field + operator: or + value: { } + group: 1 + exposed: true + expose: + operator_id: field_az_incentives_value_op + label: Incentives + description: '' + use_operator: false + operator: field_az_incentives_value_op + operator_limit_selection: false + operator_list: { } + identifier: field_az_incentives_value + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + reduce: false + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + reduce_duplicates: false + filter_groups: + operator: AND + groups: + 1: AND + style: + type: default + options: + grouping: { } + row_class: '' + default_row_class: true + uses_fields: false + row: + type: 'entity:node' + options: + relationship: none + view_mode: az_small_row + defaults: + pager: false + pager_options: false + style: false + style_options: false + row: false + filters: false + filter_groups: false + display_description: '' + pager_options: null + style_options: null + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } diff --git a/modules/custom/az_opportunity/css/az_opportunity.css b/modules/custom/az_opportunity/css/az_opportunity.css new file mode 100644 index 0000000000..c4c8554008 --- /dev/null +++ b/modules/custom/az_opportunity/css/az_opportunity.css @@ -0,0 +1,11 @@ +/** + * @file + * Styles for the az_opportunity content type. + */ + +.field--name-field-az-opportunity-category.field__items { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + padding-bottom: 1.5rem; +} diff --git a/modules/custom/az_paragraphs/az_paragraphs_view/config/install/field.field.paragraph.az_view_reference.field_az_view_reference.yml b/modules/custom/az_paragraphs/az_paragraphs_view/config/install/field.field.paragraph.az_view_reference.field_az_view_reference.yml index 4b0d1e6655..3da243d0d4 100644 --- a/modules/custom/az_paragraphs/az_paragraphs_view/config/install/field.field.paragraph.az_view_reference.field_az_view_reference.yml +++ b/modules/custom/az_paragraphs/az_paragraphs_view/config/install/field.field.paragraph.az_view_reference.field_az_view_reference.yml @@ -29,6 +29,7 @@ settings: az_courses: az_courses az_events: az_events az_news: az_news + az_opportunity: az_opportunity az_page_by_category: az_page_by_category az_person: az_person az_publications: az_publications