diff --git a/.platform.app.yaml b/.platform.app.yaml deleted file mode 100644 index e7d20177..00000000 --- a/.platform.app.yaml +++ /dev/null @@ -1,219 +0,0 @@ -# This file describes an application. You can have multiple applications -# in the same project. -# -# See https://docs.platform.sh/configuration/app.html - -# The name of this app. Must be unique within a project. -name: 'bixalcom' - -# The runtime the application uses. -type: 'php:8.3' - -dependencies: - php: - composer/composer: '^2' - - nodejs: - # The .nvmrc allows us to install a specific version of nodejs using 'n'. - # https://docs.platform.sh/languages/nodejs/node-version.html - # We needed node 16 and the php 8.1 only came with 12. - n: "*" - # Require gulp to build front end assets. - gulp-cli: "*" - -runtime: - # Enable the redis extension so Drupal can communicate with the Redis cache. - extensions: - - redis - - apcu - - xdebug - -variables: - env: - N_PREFIX: /app/.global - php: - post_max_size: '90M' - upload_max_filesize: '90M' - -# The relationships of the application with services or other applications. -# -# The left-hand side is the name of the relationship as it will be exposed -# to the application in the PLATFORM_RELATIONSHIPS variable. The right-hand -# side is in the form `:`. -relationships: - database: 'database:mysql' - redis: 'cache:redis' - -# The size of the persistent disk of the application (in MB). -disk: 2048 - -# The 'mounts' describe writable, persistent filesystem mounts in the application. -mounts: - # The default Drupal files directory. - '/web/sites/default/files': - source: local - source_path: 'files' - # Needed by upgrade status module by phpstan. - '/web/sites/simpletest': - source: local - source_path: 'simpletest' - # Drupal gets its own dedicated tmp directory. The settings.platformsh.php - # file will automatically configure Drupal to use this directory. - '/tmp': - source: local - source_path: 'tmp' - # Private file uploads are stored outside the web root. The settings.platformsh.php - # file will automatically configure Drupal to use this directory. - '/private': - source: local - source_path: 'private' - # Drush needs a scratch space for its own caches. - '/.drush': - source: local - source_path: 'drush' - # Drush will try to save backups to this directory, so it must be - # writeable even though you will almost never need to use it. - '/drush-backups': - source: local - source_path: 'drush-backups' - # Drupal Console will try to save backups to this directory, so it must be - # writeable even though you will almost never need to use it. - '/.console': - source: local - source_path: 'console' - 'var': - source: local - source_path: var - -# Configuration of the build of this application. -build: - # Don't use composer, instead do it manually in build step. Otherwise, - # when this builds locally for the first time, it will install composer 2 in - # .platform/local/deps/php but for some reason, it does not see it and uses - # the old /usr/local/bin. It's probably because whatever puts composer in $path - # does not fire after composer 2 is installed, but before. - flavor: none - -# The hooks executed at various points in the lifecycle of the application. -hooks: - # The build hook runs after Composer to finish preparing up your code. - # No services are available but the disk is writeable. - build: | - # On Platform.sh, use a single container and install node 16 in it. - # This broke for Mac users with VirtioFS: - # https://github.com/docker/for-mac/issues/6277 - # Install the version specified in the .nvmrc file - n auto - - # Reset the location hash to recognize the newly installed version - hash -r - # Finish setting node version. - - # Rebuild our front end dependencies and build assets. - # Since remotely we are able to set a newer version of node IN the - # PHP service, this command is run in the PHP service. Locally it is - # run in a build step in lando.yml. - $PLATFORM_APP_DIR/orch/build_node.sh - - # Don't install dev dependencies. - export COMPOSER_DEV=0 - - # PHP / Drupal build process. - $PLATFORM_APP_DIR/orch/build.sh - - # The deploy hook runs after your application has been deployed and started. - # Code cannot be modified at this point but the database is available. - # The site is not accepting requests while this script runs so keep it - # fast. - deploy: | - # On production and staging environments, the site is just updated. - if ( [ "${PLATFORM_ENVIRONMENT_TYPE}" = "production" ] || [ "${PLATFORM_ENVIRONMENT_TYPE}" = "staging" ] ); then - export DRUPAL_UPDATE_OR_INSTALL=update - else - export DRUPAL_UPDATE_OR_INSTALL=install - fi - php $PLATFORM_APP_DIR/orch/deploy_generate_drush_yml.php - $PLATFORM_APP_DIR/orch/deploy.sh - - # The post deploy hook runs after the application has been deployed and is - # running. - post_deploy: | - $PLATFORM_APP_DIR/orch/post_deploy.sh - -# The configuration of app when it is exposed to the web. -web: - locations: - # All requests not otherwise specified follow these rules. - '/': - # The folder from which to serve static assets, for this location. - # - # This is a filesystem path, relative to the application root. - root: 'web' - - # How long to allow static assets from this location to be cached. - # - # Can be a time in seconds, or -1 for no caching. Times can be - # suffixed with "s" (seconds), "m" (minutes), "h" (hours), "d" - # (days), "w" (weeks), "M" (months, as 30 days) or "y" (years, as - # 365 days). - expires: 5m - - # Redirect any incoming request to Drupal's front controller. - passthru: '/index.php' - - # Allow 90M files to be uploaded. - request_buffering: - enabled: true - max_request_size: 100m - - # Deny access to all static files, except those specifically allowed below. - allow: false - - # Rules for specific URI patterns. - rules: - # Allow access to common static files. - '\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff|woff2|otf|ttf|webp)$': - allow: true - '^/robots\.txt$': - allow: true - '^/sitemap\.xml$': - allow: true - - # Deny direct access to configuration files. - '^/sites/sites\.php$': - scripts: false - '^/sites/[^/]+/settings.*?\.php$': - scripts: false - - # The files directory has its own special configuration rules. - '/sites/default/files': - # Allow access to all files in the public files directory. - allow: true - expires: 5m - passthru: '/index.php' - root: 'web/sites/default/files' - - # Do not execute PHP scripts from the writeable mount. - scripts: false - - rules: - # Provide a longer TTL (2 weeks) for aggregated CSS and JS files. - '^/sites/default/files/(css|js)': - expires: 2w - -crons: - # Run Drupal's cron tasks every 60 minutes. - drupal: - spec: '0 * * * *' - commands: - start: 'cd web ; drush core-cron' - upload_logs_to_s3: - spec: '0 * * * *' - commands: - start: '[ "$PLATFORM_BRANCH" = main ] && bash cron/upload_logs_to_s3.sh' - -source: - operations: - auto-update: - command: | - curl -fsS https://raw.githubusercontent.com/platformsh/source-operations/main/setup.sh | { bash /dev/fd/3 sop-autoupdate; } 3<&0 diff --git a/.platform/applications.yaml b/.platform/applications.yaml new file mode 100644 index 00000000..1f6c5615 --- /dev/null +++ b/.platform/applications.yaml @@ -0,0 +1,253 @@ +# This file describes an application. You can have multiple applications +# in the same project. +# +# See https://docs.platform.sh/configuration/app.html + +# The name of this app. Must be unique within a project. +bixalcom: + + # The runtime the application uses. + type: 'php:8.3' + + dependencies: + php: + composer/composer: '^2' + + nodejs: + # The .nvmrc allows us to install a specific version of nodejs using 'n'. + # https://docs.platform.sh/languages/nodejs/node-version.html + # We needed node 16 and the php 8.1 only came with 12. + n: "*" + # Require gulp to build front end assets. + gulp-cli: "*" + + runtime: + # Enable the redis extension so Drupal can communicate with the Redis cache. + extensions: + - redis + - apcu + - xdebug + + variables: + env: + N_PREFIX: /app/.global + php: + post_max_size: '300M' + upload_max_filesize: '300M' + + # The relationships of the application with services or other applications. + # + # The left-hand side is the name of the relationship as it will be exposed + # to the application in the PLATFORM_RELATIONSHIPS variable. The right-hand + # side is in the form `:`. + relationships: + database: 'database:mysql' + redis: 'cache:redis' + + # The size of the persistent disk of the application (in MB). + disk: 2048 + + # The 'mounts' describe writable, persistent filesystem mounts in the application. + mounts: + # The default Drupal files directory. + '/web/sites/default/files': + source: local + source_path: 'files' + # Needed by upgrade status module by phpstan. + '/web/sites/simpletest': + source: local + source_path: 'simpletest' + # Drupal gets its own dedicated tmp directory. The settings.platformsh.php + # file will automatically configure Drupal to use this directory. + '/tmp': + source: local + source_path: 'tmp' + # Private file uploads are stored outside the web root. The settings.platformsh.php + # file will automatically configure Drupal to use this directory. + '/private': + source: local + source_path: 'private' + # Drush needs a scratch space for its own caches. + '/.drush': + source: local + source_path: 'drush' + # Drush will try to save backups to this directory, so it must be + # writeable even though you will almost never need to use it. + '/drush-backups': + source: local + source_path: 'drush-backups' + # Drupal Console will try to save backups to this directory, so it must be + # writeable even though you will almost never need to use it. + '/.console': + source: local + source_path: 'console' + 'var': + source: local + source_path: var + + # Configuration of the build of this application. + build: + # Don't use composer, instead do it manually in build step. Otherwise, + # when this builds locally for the first time, it will install composer 2 in + # .platform/local/deps/php but for some reason, it does not see it and uses + # the old /usr/local/bin. It's probably because whatever puts composer in $path + # does not fire after composer 2 is installed, but before. + flavor: none + + # The hooks executed at various points in the lifecycle of the application. + hooks: + # The build hook runs after Composer to finish preparing up your code. + # No services are available but the disk is writeable. + build: | + # On Platform.sh, use a single container and install node 16 in it. + # This broke for Mac users with VirtioFS: + # https://github.com/docker/for-mac/issues/6277 + # Install the version specified in the .nvmrc file + n auto + + # Reset the location hash to recognize the newly installed version + hash -r + # Finish setting node version. + + # Rebuild our front end dependencies and build assets. + # Since remotely we are able to set a newer version of node IN the + # PHP service, this command is run in the PHP service. Locally it is + # run in a build step in lando.yml. + $PLATFORM_APP_DIR/orch/build_node.sh + + # Don't install dev dependencies. + export COMPOSER_DEV=0 + + # PHP / Drupal build process. + $PLATFORM_APP_DIR/orch/build.sh + + # The deploy hook runs after your application has been deployed and started. + # Code cannot be modified at this point but the database is available. + # The site is not accepting requests while this script runs so keep it + # fast. + deploy: | + # On production and staging environments, the site is just updated. + if ( [ "${PLATFORM_ENVIRONMENT_TYPE}" = "production" ] || [ "${PLATFORM_ENVIRONMENT_TYPE}" = "staging" ] ); then + export DRUPAL_UPDATE_OR_INSTALL=update + else + export DRUPAL_UPDATE_OR_INSTALL=install + fi + php $PLATFORM_APP_DIR/orch/deploy_generate_drush_yml.php + $PLATFORM_APP_DIR/orch/deploy.sh + + # The post deploy hook runs after the application has been deployed and is + # running. + post_deploy: | + $PLATFORM_APP_DIR/orch/post_deploy.sh + + # The configuration of app when it is exposed to the web. + web: + locations: + # All requests not otherwise specified follow these rules. + '/': + # The folder from which to serve static assets, for this location. + # + # This is a filesystem path, relative to the application root. + root: 'web' + + # How long to allow static assets from this location to be cached. + # + # Can be a time in seconds, or -1 for no caching. Times can be + # suffixed with "s" (seconds), "m" (minutes), "h" (hours), "d" + # (days), "w" (weeks), "M" (months, as 30 days) or "y" (years, as + # 365 days). + expires: 5m + + # Redirect any incoming request to Drupal's front controller. + passthru: '/index.php' + + # Allow 300M files to be uploaded. + request_buffering: + enabled: true + max_request_size: 320m + + # Deny access to all static files, except those specifically allowed below. + allow: false + + # Rules for specific URI patterns. + rules: + # Allow access to common static files. + '\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff|woff2|otf|ttf|webp)$': + allow: true + '^/robots\.txt$': + allow: true + '^/sitemap\.xml$': + allow: true + + # Deny direct access to configuration files. + '^/sites/sites\.php$': + scripts: false + '^/sites/[^/]+/settings.*?\.php$': + scripts: false + + # The files directory has its own special configuration rules. + '/sites/default/files': + # Allow access to all files in the public files directory. + allow: true + expires: 5m + passthru: '/index.php' + root: 'web/sites/default/files' + + # Do not execute PHP scripts from the writeable mount. + scripts: false + + rules: + # Provide a longer TTL (2 weeks) for aggregated CSS and JS files. + '^/sites/default/files/(css|js)': + expires: 2w + + crons: + # Run Drupal's cron tasks every 60 minutes. + drupal: + spec: '0 * * * *' + commands: + start: 'cd web ; drush core-cron' + upload_logs_to_s3: + spec: '0 * * * *' + commands: + start: '[ "$PLATFORM_BRANCH" = main ] && bash cron/upload_logs_to_s3.sh' + +storybook: + type: nodejs:18 + + web: + locations: + '/': + # The folder from which to serve static assets, for this location. + # + # This is a filesystem path, relative to the application root. + root: 'storybook-static' + + # How long to allow static assets from this location to be cached. + # + # Can be a time in seconds, or -1 for no caching. Times can be + # suffixed with "s" (seconds), "m" (minutes), "h" (hours), "d" + # (days), "w" (weeks), "M" (months, as 30 days) or "y" (years, as + # 365 days). + expires: 5m + + # Allow storybook's landing .html file to be picked up when going to /. + index: + - 'index.html' + + # Disable server side scripts. + scripts: false + + # Allow access to all static files. + allow: true + + commands: + # Run a no-op process that uses no CPU resources since this is a static site + start: sleep infinity + + hooks: + build: | + # Building for a sub-dir caused a 502 on platform that I could not + # figure out. + # BASE_PATH=/sb npm run build-storybook + npm run build-storybook \ No newline at end of file diff --git a/.platform/routes.yaml b/.platform/routes.yaml index b35c5865..257ca871 100644 --- a/.platform/routes.yaml +++ b/.platform/routes.yaml @@ -18,3 +18,16 @@ # Base the cache on the session cookie and custom Drupal cookies. Ignore all other cookies. cookies: ['/^SS?ESS/', '/^Drupal.visitor/'] + +"https://sb.{default}": + type: upstream + upstream: "storybook:http" + tls: + # https://docs.platform.sh/define-routes/https.html#stricttransportsecurity + strict_transport_security: + # This is one year, can't change. + enabled: true + include_subdomains: false + preload: false + cache: + enabled: true diff --git a/.storybook/main.js b/.storybook/main.js index b2f26f38..7e00c552 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -17,6 +17,13 @@ const config = { docs: { autodocs: "tag", }, - staticDirs: ['../stories/assets'] + staticDirs: ['../stories/assets'], + async viteFinal(config, { configType }) { + // This allows starting this in a sub dir: + // BASE_PATH=/sb npm run build-storybook + config.base = process.env.BASE_PATH || config.base; + // return the customized config + return config; + }, }; export default config; diff --git a/README.md b/README.md index b9219448..40d6ffe7 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,40 @@ The remote environments are hosted in platform.sh. See the ./.platform directory The local environment is based on [Drupal Env](https://github.com/mattsqd/drupal-env/wiki) and the [Drupal Env Lando](https://github.com/mattsqd/drupal-env-lando/wiki) packages. +## Branching + +Use the following naming for your git branches. + +```sh +feature/BSD-[ISSUE_NO]-[LOWER_CASE_DESCRIPTION] +``` + +**Example** + +```sh +feature/BSD-64-robo-validate +``` + +## Commit style + +```sh +BSD fixes #64: Fixed coding standards issues. +``` + +Also acceptable: + +- close, closes, closed +- fix, fixes, fixed +- resolve, resolves, resolved + +Example: + +``` +BSD closes #64: Fixed coding standards issues. +``` + +More guidance on git branches and commit style in [robo.yml](https://github.com/Bixal/bixal-site-drupal/blob/develop/robo.yml) + ### Starting the Environment First time: @@ -40,7 +74,7 @@ lando build lando si ``` -This will install all the sample content we have created in web/modules/custom/bixal_default_content. In order to export new content here, create it locally and run ```lando export-content```. +This will install all the sample content we have created in `web/modules/custom/bixal_default_content`. In order to export new content here, create it locally and run `lando export-content`. ### Running Drush @@ -70,6 +104,8 @@ It's important that you always use `lando composer` or `./composer.sh` instead o ### Access story book +[Storybook preview is available here →](https://sb.feature-bsd-286-remote-xcrmjai-tsvj5tw7p3f66.us.platformsh.site) + [Storybook](https://storybook.js.org/) for this project can be found by: - Docker version: http://storybook.bixalcom.lndo.site/ @@ -81,6 +117,6 @@ It's important that you always use `lando composer` or `./composer.sh` instead o - Run all the validation commands that the pipelines run without needing to push remotely `vendor/bin/robo validate:all`. -#### Configure Xdebug +#### Configure Xdebug https://github.com/mattsqd/drupal-env-lando/wiki/XDebug-(Personal) diff --git a/config/sync/core.base_field_override.node.case_study.promote.yml b/config/sync/core.base_field_override.node.case_study.promote.yml new file mode 100644 index 00000000..e31f6a98 --- /dev/null +++ b/config/sync/core.base_field_override.node.case_study.promote.yml @@ -0,0 +1,22 @@ +uuid: 6232c5de-1233-45af-a35b-a1e59732ba1f +langcode: en +status: true +dependencies: + config: + - node.type.case_study +id: node.case_study.promote +field_name: promote +entity_type: node +bundle: case_study +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/config/sync/core.entity_form_display.node.case_study.default.yml b/config/sync/core.entity_form_display.node.case_study.default.yml new file mode 100644 index 00000000..85ed1531 --- /dev/null +++ b/config/sync/core.entity_form_display.node.case_study.default.yml @@ -0,0 +1,120 @@ +uuid: 67c89167-f4a0-4091-acc4-c5ff9b011a1f +langcode: en +status: true +dependencies: + config: + - field.field.node.case_study.field_challenge + - field.field.node.case_study.field_client + - field.field.node.case_study.field_conclusion + - field.field.node.case_study.field_impact + - field.field.node.case_study.field_introduction + - field.field.node.case_study.field_solution + - node.type.case_study + module: + - path + - text +id: node.case_study.default +targetEntityType: node +bundle: case_study +mode: default +content: + created: + type: datetime_timestamp + weight: 3 + region: content + settings: { } + third_party_settings: { } + field_challenge: + type: text_textarea + weight: 28 + region: content + settings: + rows: 5 + placeholder: '' + third_party_settings: { } + field_client: + type: string_textfield + weight: 26 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + field_conclusion: + type: text_textarea + weight: 31 + region: content + settings: + rows: 5 + placeholder: '' + third_party_settings: { } + field_impact: + type: text_textarea + weight: 30 + region: content + settings: + rows: 5 + placeholder: '' + third_party_settings: { } + field_introduction: + type: text_textarea + weight: 27 + region: content + settings: + rows: 5 + placeholder: '' + third_party_settings: { } + field_solution: + type: text_textarea + weight: 29 + region: content + settings: + rows: 5 + placeholder: '' + third_party_settings: { } + langcode: + type: language_select + weight: 1 + region: content + settings: + include_locked: true + third_party_settings: { } + path: + type: path + weight: 4 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + weight: 6 + 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: 2 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + url_redirects: + weight: 5 + region: content + settings: { } + third_party_settings: { } +hidden: + promote: true + sticky: true diff --git a/config/sync/core.entity_view_display.node.case_study.default.yml b/config/sync/core.entity_view_display.node.case_study.default.yml new file mode 100644 index 00000000..eed0de35 --- /dev/null +++ b/config/sync/core.entity_view_display.node.case_study.default.yml @@ -0,0 +1,71 @@ +uuid: c5442b3a-95f8-433a-8560-a439796d5afd +langcode: en +status: true +dependencies: + config: + - field.field.node.case_study.field_challenge + - field.field.node.case_study.field_client + - field.field.node.case_study.field_conclusion + - field.field.node.case_study.field_impact + - field.field.node.case_study.field_introduction + - field.field.node.case_study.field_solution + - node.type.case_study + module: + - text + - user +id: node.case_study.default +targetEntityType: node +bundle: case_study +mode: default +content: + field_challenge: + type: text_default + label: above + settings: { } + third_party_settings: { } + weight: 104 + region: content + field_client: + type: string + label: above + settings: + link_to_entity: false + third_party_settings: { } + weight: 102 + region: content + field_conclusion: + type: text_default + label: above + settings: { } + third_party_settings: { } + weight: 107 + region: content + field_impact: + type: text_default + label: above + settings: { } + third_party_settings: { } + weight: 106 + region: content + field_introduction: + type: text_default + label: above + settings: { } + third_party_settings: { } + weight: 103 + region: content + field_solution: + type: text_default + label: above + settings: { } + third_party_settings: { } + weight: 105 + region: content + links: + settings: { } + third_party_settings: { } + weight: 100 + region: content +hidden: + langcode: true + search_api_excerpt: true diff --git a/config/sync/core.entity_view_display.node.case_study.teaser.yml b/config/sync/core.entity_view_display.node.case_study.teaser.yml new file mode 100644 index 00000000..9c39e335 --- /dev/null +++ b/config/sync/core.entity_view_display.node.case_study.teaser.yml @@ -0,0 +1,34 @@ +uuid: d1045a07-d7eb-48e8-b7d7-be82ad677c30 +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.case_study.field_challenge + - field.field.node.case_study.field_client + - field.field.node.case_study.field_conclusion + - field.field.node.case_study.field_impact + - field.field.node.case_study.field_introduction + - field.field.node.case_study.field_solution + - node.type.case_study + module: + - user +id: node.case_study.teaser +targetEntityType: node +bundle: case_study +mode: teaser +content: + links: + settings: { } + third_party_settings: { } + weight: 100 + region: content +hidden: + field_challenge: true + field_client: true + field_conclusion: true + field_impact: true + field_introduction: true + field_solution: true + langcode: true + search_api_excerpt: true diff --git a/config/sync/field.field.media.image.field_media_image.yml b/config/sync/field.field.media.image.field_media_image.yml index a27e2632..90794bb8 100644 --- a/config/sync/field.field.media.image.field_media_image.yml +++ b/config/sync/field.field.media.image.field_media_image.yml @@ -22,7 +22,7 @@ settings: handler_settings: { } file_directory: '[date:custom:Y]-[date:custom:m]' file_extensions: 'png gif jpg jpeg svg webp' - max_filesize: '' + max_filesize: '100 MB' max_resolution: '' min_resolution: '' alt_field: true diff --git a/config/sync/field.field.media.pdf.field_media_file.yml b/config/sync/field.field.media.pdf.field_media_file.yml index 4f9c405c..b18c9547 100644 --- a/config/sync/field.field.media.pdf.field_media_file.yml +++ b/config/sync/field.field.media.pdf.field_media_file.yml @@ -22,6 +22,6 @@ settings: handler_settings: { } file_directory: '[date:custom:Y]-[date:custom:m]' file_extensions: pdf - max_filesize: '' + max_filesize: '100 MB' description_field: true field_type: file diff --git a/config/sync/field.field.media.video.field_media_video_file.yml b/config/sync/field.field.media.video.field_media_video_file.yml index a30a3dbc..9b324e48 100644 --- a/config/sync/field.field.media.video.field_media_video_file.yml +++ b/config/sync/field.field.media.video.field_media_video_file.yml @@ -22,6 +22,6 @@ settings: handler_settings: { } file_directory: '[date:custom:Y]-[date:custom:m]' file_extensions: 'mp4 webm' - max_filesize: '' + max_filesize: '300 MB' description_field: false field_type: file diff --git a/config/sync/field.field.node.case_study.field_challenge.yml b/config/sync/field.field.node.case_study.field_challenge.yml new file mode 100644 index 00000000..8e277c1d --- /dev/null +++ b/config/sync/field.field.node.case_study.field_challenge.yml @@ -0,0 +1,24 @@ +uuid: 2124894d-d2f1-4cad-8667-1d95cafb0b22 +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_challenge + - filter.format.html_text + - node.type.case_study + module: + - text +id: node.case_study.field_challenge +field_name: field_challenge +entity_type: node +bundle: case_study +label: Challenge +description: '' +required: true +translatable: false +default_value: { } +default_value_callback: '' +settings: + allowed_formats: + - html_text +field_type: text_long diff --git a/config/sync/field.field.node.case_study.field_client.yml b/config/sync/field.field.node.case_study.field_client.yml new file mode 100644 index 00000000..437cf433 --- /dev/null +++ b/config/sync/field.field.node.case_study.field_client.yml @@ -0,0 +1,19 @@ +uuid: 85df398a-e793-4f89-ba0c-2514ce73900f +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_client + - node.type.case_study +id: node.case_study.field_client +field_name: field_client +entity_type: node +bundle: case_study +label: Client +description: '' +required: true +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/config/sync/field.field.node.case_study.field_conclusion.yml b/config/sync/field.field.node.case_study.field_conclusion.yml new file mode 100644 index 00000000..4687d09c --- /dev/null +++ b/config/sync/field.field.node.case_study.field_conclusion.yml @@ -0,0 +1,24 @@ +uuid: eb1ca146-9c25-486c-b0ab-ceb661a4e823 +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_conclusion + - filter.format.html_text + - node.type.case_study + module: + - text +id: node.case_study.field_conclusion +field_name: field_conclusion +entity_type: node +bundle: case_study +label: Conclusion +description: '' +required: true +translatable: false +default_value: { } +default_value_callback: '' +settings: + allowed_formats: + - html_text +field_type: text_long diff --git a/config/sync/field.field.node.case_study.field_impact.yml b/config/sync/field.field.node.case_study.field_impact.yml new file mode 100644 index 00000000..677959f2 --- /dev/null +++ b/config/sync/field.field.node.case_study.field_impact.yml @@ -0,0 +1,24 @@ +uuid: a3795b81-8817-472d-947f-1a7f37a57350 +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_impact + - filter.format.html_text + - node.type.case_study + module: + - text +id: node.case_study.field_impact +field_name: field_impact +entity_type: node +bundle: case_study +label: Impact +description: '' +required: true +translatable: false +default_value: { } +default_value_callback: '' +settings: + allowed_formats: + - html_text +field_type: text_long diff --git a/config/sync/field.field.node.case_study.field_introduction.yml b/config/sync/field.field.node.case_study.field_introduction.yml new file mode 100644 index 00000000..962943dd --- /dev/null +++ b/config/sync/field.field.node.case_study.field_introduction.yml @@ -0,0 +1,24 @@ +uuid: db681dec-4a39-4e65-975f-063822601497 +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_introduction + - filter.format.html_text + - node.type.case_study + module: + - text +id: node.case_study.field_introduction +field_name: field_introduction +entity_type: node +bundle: case_study +label: Introduction +description: '' +required: true +translatable: false +default_value: { } +default_value_callback: '' +settings: + allowed_formats: + - html_text +field_type: text_long diff --git a/config/sync/field.field.node.case_study.field_solution.yml b/config/sync/field.field.node.case_study.field_solution.yml new file mode 100644 index 00000000..8ddae96b --- /dev/null +++ b/config/sync/field.field.node.case_study.field_solution.yml @@ -0,0 +1,24 @@ +uuid: e02e8ba3-5abd-47bd-bb30-f279f2cb74f8 +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_solution + - filter.format.html_text + - node.type.case_study + module: + - text +id: node.case_study.field_solution +field_name: field_solution +entity_type: node +bundle: case_study +label: Solution +description: '' +required: true +translatable: false +default_value: { } +default_value_callback: '' +settings: + allowed_formats: + - html_text +field_type: text_long diff --git a/config/sync/field.storage.node.field_challenge.yml b/config/sync/field.storage.node.field_challenge.yml new file mode 100644 index 00000000..a4c6c85b --- /dev/null +++ b/config/sync/field.storage.node.field_challenge.yml @@ -0,0 +1,19 @@ +uuid: 7cb7c061-f6fa-4053-9734-b34461af7944 +langcode: en +status: true +dependencies: + module: + - node + - text +id: node.field_challenge +field_name: field_challenge +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/config/sync/field.storage.node.field_client.yml b/config/sync/field.storage.node.field_client.yml new file mode 100644 index 00000000..d1dc7e1a --- /dev/null +++ b/config/sync/field.storage.node.field_client.yml @@ -0,0 +1,21 @@ +uuid: 8d55f0c1-c79a-40bc-a4ec-075f338b4106 +langcode: en +status: true +dependencies: + module: + - node +id: node.field_client +field_name: field_client +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/config/sync/field.storage.node.field_conclusion.yml b/config/sync/field.storage.node.field_conclusion.yml new file mode 100644 index 00000000..857838bf --- /dev/null +++ b/config/sync/field.storage.node.field_conclusion.yml @@ -0,0 +1,19 @@ +uuid: b27484f4-483a-4a3c-a661-817f4c3617e4 +langcode: en +status: true +dependencies: + module: + - node + - text +id: node.field_conclusion +field_name: field_conclusion +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/config/sync/field.storage.node.field_impact.yml b/config/sync/field.storage.node.field_impact.yml new file mode 100644 index 00000000..a7c4e7e2 --- /dev/null +++ b/config/sync/field.storage.node.field_impact.yml @@ -0,0 +1,19 @@ +uuid: cfa41597-512c-47ee-b179-3857ccbb304b +langcode: en +status: true +dependencies: + module: + - node + - text +id: node.field_impact +field_name: field_impact +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/config/sync/field.storage.node.field_introduction.yml b/config/sync/field.storage.node.field_introduction.yml new file mode 100644 index 00000000..366cea63 --- /dev/null +++ b/config/sync/field.storage.node.field_introduction.yml @@ -0,0 +1,19 @@ +uuid: d611c5b9-c245-4488-b174-c66dbf093221 +langcode: en +status: true +dependencies: + module: + - node + - text +id: node.field_introduction +field_name: field_introduction +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/config/sync/field.storage.node.field_solution.yml b/config/sync/field.storage.node.field_solution.yml new file mode 100644 index 00000000..02378a86 --- /dev/null +++ b/config/sync/field.storage.node.field_solution.yml @@ -0,0 +1,19 @@ +uuid: 34fb5209-e09d-4e15-9cd4-2845b527197b +langcode: en +status: true +dependencies: + module: + - node + - text +id: node.field_solution +field_name: field_solution +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/config/sync/language.content_settings.node.case_study.yml b/config/sync/language.content_settings.node.case_study.yml new file mode 100644 index 00000000..5423b813 --- /dev/null +++ b/config/sync/language.content_settings.node.case_study.yml @@ -0,0 +1,11 @@ +uuid: e99dc71b-01d0-4894-8d31-ba80bda2fd9b +langcode: en +status: true +dependencies: + config: + - node.type.case_study +id: node.case_study +target_entity_type_id: node +target_bundle: case_study +default_langcode: site_default +language_alterable: false diff --git a/config/sync/node.type.case_study.yml b/config/sync/node.type.case_study.yml new file mode 100644 index 00000000..1b9b410c --- /dev/null +++ b/config/sync/node.type.case_study.yml @@ -0,0 +1,17 @@ +uuid: aa13b02d-6785-4930-831d-8b39e2fef70c +langcode: en +status: true +dependencies: + module: + - menu_ui +third_party_settings: + menu_ui: + available_menus: { } + parent: '' +name: 'Case Study' +type: case_study +description: null +help: null +new_revision: true +preview_mode: 1 +display_submitted: false diff --git a/lando-config/php.ini b/lando-config/php.ini index 2cfc1a4b..0ccd0f41 100644 --- a/lando-config/php.ini +++ b/lando-config/php.ini @@ -3,3 +3,5 @@ ; only critical errors and suppresses these connection errors. ; https://xdebug.org/docs/all_settings#XDEBUG_CONFIG ;xdebug.log_level=0 +post_max_size=300M +upload_max_filesize=300M diff --git a/orch/deploy_install.sh b/orch/deploy_install.sh index b9e0fc25..11366530 100755 --- a/orch/deploy_install.sh +++ b/orch/deploy_install.sh @@ -1,7 +1,5 @@ #!/usr/bin/env bash -set -e - ./orch/show_file.sh $0 # Normally, XDEBUG_MODE=debug,develop but develop breaks the Drupal installation. @@ -12,6 +10,8 @@ fi drush cr +set -e + # If using Postgres, enable the pg_trgm extension which is required before # Drupal is installed. if [ -n "$(drush status | grep pgsql 2>/dev/null)" ]; then diff --git a/stories/assets/styles/global/global.scss b/stories/assets/styles/global/global.scss index 8be8bf8c..b97248e1 100644 --- a/stories/assets/styles/global/global.scss +++ b/stories/assets/styles/global/global.scss @@ -59,9 +59,13 @@ h6 { } h1 { - font-size: px-to-rem(64px); + font-size: px-to-rem(32px); margin-bottom: units(2); text-wrap: balance; + + @include at-media("tablet") { + font-size: px-to-rem(64px); + } } h2 { @@ -177,7 +181,6 @@ a { } p { - // Improves readability in word breaks. &[lang="en"] { hyphens: auto; diff --git a/stories/components/section/section.scss b/stories/components/section/section.scss index 99e48615..8f9f51d5 100644 --- a/stories/components/section/section.scss +++ b/stories/components/section/section.scss @@ -10,6 +10,10 @@ padding-bottom: units(10); } + .bix-section__title:not(:first-of-type) { + margin-top: units(8); + } + &__body p { max-width: px-to-rem(725px); widows: 3; diff --git a/stories/components/section/section.stories.js b/stories/components/section/section.stories.js index b93c58a4..a4078177 100644 --- a/stories/components/section/section.stories.js +++ b/stories/components/section/section.stories.js @@ -65,8 +65,7 @@ export const AccentCool = { export const BackgroundImage = { args: { additional_classes: ["bix-section--primary"], - image: - "static/img-whatwedo-e68b3d20abd32c896d56b122063f7664.jpg", + image: "static/img-whatwedo-e68b3d20abd32c896d56b122063f7664.jpg", prefix: "What we do", title: "The work we do helps our clients unite stakeholders, optimize resources, and better serve citizens all over the world.", @@ -85,8 +84,7 @@ export const Tall = { args: { variant: "tall", center_content: true, - image: - "static/img-careers-269d29ea5a43482c6c0b920bdd5e9d87.jpg", + image: "static/img-careers-269d29ea5a43482c6c0b920bdd5e9d87.jpg", prefix: "What we do", title: "The work we do helps our clients unite stakeholders, optimize resources, and better serve citizens all over the world.", diff --git a/stories/pages/case-study/case-study.html.twig b/stories/pages/case-study/case-study.html.twig index be2998cd..2a198b5d 100644 --- a/stories/pages/case-study/case-study.html.twig +++ b/stories/pages/case-study/case-study.html.twig @@ -1,126 +1,8 @@ {% extends "@pages/base/base.html.twig" %} {% block content %} - {% embed "@components/section/section.html.twig" %} - {% set body %} -
-
-
United States Agency for International Development (USAID)
-
Digital APEX Colombia
-
https://www.usaid.gov/colombia
-
- -
-
Services
-
Cybersecurity Training
-
Virtual Instructor-led Training
-
Capacity Building
-
Instructional Design
-
Accessibility/508 Compliance
-
Bilingual English-Spanish Training Delivery
-
Communications
-
Marketing
-
Cybersecurity Risk Assessments
-
Agile Project Management
-
-
- {% endset %} - {% endembed %} - - {% embed "@components/section/section.html.twig" %} - - {% set body %} -

Challenge

-

- The increased use of technology, mobile phones and digital systems means USAID/Colombia’s IPs face a wide range of vulnerabilities, such as phishing attacks, account impersonation attempts and cyber-based corrupt financial transactions. The scarcity of cybersecurity education for vulnerable IPs translates to a higher risk of attacks and security breaches, which forces organizations to remedy system failures and change user behaviors to mitigate future attacks. Attacks can erode the public’s and stakeholders’ trust in how organizations handle personal and sensitive information, ultimately undermining IPs’ integrity and confidence in the programs they deploy. -

- -

Solution

-

- Working with the USAID/Colombia Mission, Bixal developed and implemented a cybersecurity training program that used an interactive online training format, assessed existing hardware and software assets, and developed action plans aligned to best practices outlined in the Center for Internet Security (CIS) Controls to improve cybersecurity vulnerabilities. -

- -

Results

-

- Through a combined approach of asynchronous training and virtual learning, 298 individuals representing 44 organizations in Colombia increased their knowledge of cybersecurity and improved their digital health practices. Bixal conducted cyber risk assessments with the most vulnerable partner organizations to develop roadmaps with action items designed to increase digital protection and reduce the risk of cyberattacks. -

- -

Design & Approach

-

- Under Digital APEX — implemented by prime contractor Project Management Consulting Group (PMCG) — Bixal collaborated with the USAID/Colombia Mission to develop and implement the Cybersecurity Integration of Partners and Hacking Emergency Response (CIPHER), a cybersecurity training program that uses an easily replicable three-phased approach. -

- -

Phase 1: Generating Cybersecurity Awareness

-

- Bixal introduced cybersecurity concepts to the participating organizations using KnowBe4, a platform that offers asynchronous training available in Spanish, which enabled the organizations’ leadership, program and IT staff to take self-paced courses and learn more about basic cybersecurity concepts. -

- -

Phase 2: Assisting Usaid Ips

-

- To deliver additional training and assistance, Bixal identified the 10 most vulnerable IPs based on data from initial training quizzes. We drafted rules of engagement that detailed system restrictions and boundaries to ensure confidentiality throughout the assessment process. Bixal then conducted the cybersecurity risk assessments, testing external and internal accessible systems, hosts and applications for IT, communications and network systems. After completing the assessments, Bixal scheduled individual sessions with each of the 10 IPs, designing virtual instructor-led training (ILT). The in-depth training enabled IT professionals to further diffuse cybersecurity best practices across the organization and ensure all users are aware of their behaviors and responsibility to mitigate cybersecurity attacks and threats. -

- -

Phase 3: Developing And Disseminating Action Plans

-

- Bixal analyzed data collected through the in-depth training and risk assessments to draft individual action plans for each of the 10 IPs. Action plans communicated assessment results, documented cybersecurity vulnerabilities and provided recommendations for remediation. Bixal and Digital APEX met with IT and management staff of IPs to review action plans and outline steps for IPs to ensure future cybersecurity. -

- -

Delivering the Solution

-

- Bixal uses proven methods for delivering the right solution to the right client. -

- -

Collaboration, Learning And Adapting (Cla) Approach

-

- Strong CLA practices enabled Bixal to learn from client feedback and incorporate process improvements to generate better outcomes. The Bixal team met with the client weekly to plan activities, make decisions on preferred approaches for activity implementation, discuss impediments, and identify solutions. This level of client collaboration allowed us to continuously adapt to changing circumstances and stakeholder needs. -

- -

Local Cybersecurity Expertise

-

- We leveraged a new partnership with Functional Cybersecurity International LLC (FC International), engaging local SMEs with extensive knowledge of cybersecurity threats in Colombia. -

- -

Data-Centered Methodology

-

- We used data from the cybersecurity training and testing to identify the most vulnerable organizations participating in the program, to inform cybersecurity solutions and topics covered in webinars tailored to selected partners, and to assess the effectiveness of training provided. -

- -

Unexpected Challenge

-

- As the COVID-19 pandemic worsened and international travel was restricted, Bixal converted our training plan from instructor led to virtual delivery. In-house instructional designers worked with cybersecurity experts to design a highly interactive virtual course that used adult-learning techniques, collaborative whiteboards, short quizzes and pop-up polls to keep participants engaged. As a result of virtual training, 146 participants from 10 IPs experienced a substantial improvement in their cybersecurity knowledge. -

- {% endset %} - {% endembed %} - - {% embed "@components/section/section.html.twig" %} - {% set variant = "primary-alt" %} - - {% set body %} -

Outcomes

-

Bixal applied an Agile learning approach in designing and developing a cybersecurity training program to help USAID IPs and civil society organizations in Colombia improve their digital health, build local capacity and strengthen cybersecurity practices. As part of this program, Bixal provided access to asynchronous training modules and delivered 15 synchronous virtual ILT sessions to over 298 participants from 44 USAID partners. The topics selected contributed to a growing knowledge base on cybersecurity vulnerabilities that impact organizations’ governance structure, technology infrastructure and business operations.

- -

Working with the USAID/Colombia Mission, Bixal assessed existing hardware and software assets for cybersecurity vulnerabilities and delivered training organized into five learning topics that mapped to 20 CIS controls.

- -

In Bixal’s experience, when people understand cybersecurity threats and demonstrate familiarity with best practices to combat cyberattacks, the likelihood of destructive cyberattacks decreases.

- -

Webinar quiz results demonstrated that USAID/Colombia’s IPs had a low baseline knowledge of cybersecurity. Data from the 10 risk assessments conducted in Phase II confirmed the need for cybersecurity action plans. Over 95 percent of participants who identified as “novice” before the training advanced their knowledge to align with higher competency levels as a result of the program. Detailed post-training survey results are captured in the following chart.

- -

These results demonstrate that a multi-faceted approach, coupling asynchronous and virtual ILT with risk assessments and roadmaps for improvement, can result in significant improvements in cybersecurity awareness.

- {% endset %} - - - {% endembed %} - - {% embed "@components/section/section.html.twig" %} - {% set body %} - -

Improvements in recipients’ cybersecurity knowledge after in-depth interactive training.

-

These results demonstrate that a multi-faceted approach, coupling asynchronous and virtual ILT with risk assessments and roadmaps for improvement, can result in significant improvements in cybersecurity awareness.

- - {# @TODO: Highlight component #} -

Highlight

-

Overall, Bixal delivered cybersecurity training to 298 individuals, supporting capacity development for 44 organizations to improve their digital health.

- {% endset %} - {% endembed %} + {% for section in sections %} + {% include "@components/section/section.html.twig" with section %} + {% endfor %} {% endblock %} diff --git a/stories/pages/case-study/case-study.stories.js b/stories/pages/case-study/case-study.stories.js index 6235f920..0bc9116a 100644 --- a/stories/pages/case-study/case-study.stories.js +++ b/stories/pages/case-study/case-study.stories.js @@ -2,7 +2,6 @@ import CaseStudy from "./case-study.html.twig"; import * as Header from "../../components/header/header.stories"; import "../../components/hero/hero.stories"; -import * as Blurb from "../../components/blurb/blurb.stories"; import "../../components/contact-us/contact-us.stories"; import "../../components/footer/footer.stories"; import * as FooterContent from "../../components/footer/footer.stories"; @@ -15,11 +14,83 @@ export default { export const Default = { args: { header: Header.default.args, - hero: { - variant: "image-bg", - title: "Building cybersecurity capacity of civil society organizations in Colombia to improve digital health and protect against cyber threats.", - image: "/static/d6b25ad6c22c438dde0709d18958c405/digital-apex-1.png", - }, - footerContent: FooterContent.default.args + sections: [ + { + variant: "primary-alt", + heading_type: "h1", + prefix: "Department of Labor and Education", + title: + "Working for Americans: Bixal helps transform WIOA state plan portal", + }, + { + body: ` +

Introduction

+

+ The Workforce Innovation and Opportunity Act (WIOA) is designed to strengthen the public workforce system by expanding access to education and training, helping employers hire and retain skilled workers, and creating opportunities for Americans — especially those with significant barriers to employment—to thrive in high-quality careers. +

+

Challenge

+

+ WIOA requires all U.S. states, territories, and the District of Columbia to regularly submit State Plans outlining how the workforce development system will be implemented. The WIOA State Plan Portal facilitates this process from draft to publication, connecting state and local partners with several federal agencies, including the Departments of Education (ED), and Labor (DOL). Funding is contingent on states having approved plans. +

+

+ In 2018, ED and DOL awarded Bixal the contract to streamline the submission process with a comprehensive upgrade of the platform. The legacy site lacked crucial functionalities, making WIOA compliance burdensome for stakeholders on all sides. Bixal and our federal partners committed to co-creating a robust, user-friendly platform that would remain nimble for years to come. +

+

Solution

+

+ Bixal began by auditing the user experience (UX) across the State Plan lifecycle, building a solid foundation for holistic UX that adheres to the highest standards of accessibility, in order to translate customer needs into optimized functionality and processes. +

+ Key aspects of our solution included: +
    +
  • Building an application to manage creation, modification, and year-to-year traceability of thousands of requirements.
  • +
  • Developing templates for individual state plans, supported by rigorous, multi-tiered, role-based workflow.
  • +
  • Integrating nearly 60,000 pages of data into a single, easily navigable site.
  • +
  • Pivoting several times to meet new and emerging security and governance requirements, for example: +
      +
    • Pivoted to Acquia cloud-based hosting as a service (PaaS) when the ED platform faced delays.
    • +
    • Integrated login.gov to comply with new OMB directive.
    • +
    +
  • +
+ `, + }, + { + variant: "accent-cool", + title: "Impact", + body: ` + State Plan submission processes optimized: +
    +
  • Thousands of previously separate grant requirements for every state — spread across nine offices within five agencies, a total of 15 programs — streamline into a single grant process.
  • +
  • All plan elements from previous plan years (2016 and 2018) readily available for reference and knowledge management. +
      +
    • Complex workflow management controls who can view, comment, or edit portions of a State Plan based on role and plan status
    • +
    +
  • +
  • + The upgraded State Plan Portal gives federal teams shared visibility into workforce development needs in and across states and regions, allowing for integrated and comprehensive approaches in addressing businesses' and workers' needs. +
  • +
  • + Improved user experience, as reflected in consistently and enthusiastically positive stakeholder feedback. +
  • +
+ Upgraded functionality features of State Plan Portal include: +
    +
  • Multi-factor authentication.
  • +
  • Multi-tier moderation.
  • +
  • Overhauled reporting tools provide a reliable audit trail.
  • +
  • Dashboards meet users' changing needs.
  • +
+ `, + }, + { + variant: "primary-alt", + title: "Conclusion", + body: ` +

+ Bixal's work for ED and DOL made it much easier for state and local partners to adhere to WIOA's provisions, facilitated the created of more and better career paths for all Americans, in particular those facing significant hurdles to employment, and demonstrated how well federal agencies can work for the people they serve when they lead with human-centered design and an ethos of constant improvement. +

+ `, + }, + ], + footerContent: FooterContent.default.args, }, }; diff --git a/stories/pages/contract-vehicle/contract-vehicle.html.twig b/stories/pages/contract-vehicle/contract-vehicle.html.twig index bae6bbd4..2a198b5d 100644 --- a/stories/pages/contract-vehicle/contract-vehicle.html.twig +++ b/stories/pages/contract-vehicle/contract-vehicle.html.twig @@ -1,18 +1,8 @@ {% extends "@pages/base/base.html.twig" %} {% block content %} - {% embed "@components/section/section.html.twig" %} - {% set body %} - {% for section in sections %} - - {% set heading_type = section.heading_type | default("h2") %} - - <{{ heading_type }}> - {{ section.title }} - - {{ section.text | raw }} - {% endfor %} - {% endset %} - {% endembed %} + {% for section in sections %} + {% include "@components/section/section.html.twig" with section %} + {% endfor %} {% endblock %} diff --git a/stories/pages/contract-vehicle/contract-vehicle.stories.js b/stories/pages/contract-vehicle/contract-vehicle.stories.js index 053b74a2..c2e013b4 100644 --- a/stories/pages/contract-vehicle/contract-vehicle.stories.js +++ b/stories/pages/contract-vehicle/contract-vehicle.stories.js @@ -1,4 +1,4 @@ -import ContractVehicle from "./contract-vehicle.html.twig" +import ContractVehicle from "./contract-vehicle.html.twig"; import * as Header from "../../components/header/header.stories"; import "../../components/contact-us/contact-us.stories"; @@ -14,31 +14,70 @@ export default { { heading_type: "h1", title: "General overview", - text: "

Bixal is the sole holder of a blanket purchase agreement (BPA) providing independent monitoring and evaluation (M&E) services in support of the U.S. Department of the Treasury’s Office of Technical Assistance (OTA). With over 90 technical assistance projects in 51 developing and transitional countries around the globe, the OTA works with finance ministries and central banks to safeguard financial sectors and strengthen their ability to manage public finances effectively. M&E services under this BPA include designing and conducting evaluations of OTA initiatives, supporting M&E process improvements and facilitating program learning.

This three-year BPA builds on Bixal’s M&E capabilities, which were significantly augmented in January 2021, when we acquired Clear Outcomes. As Bixal furthers our data science and analytics practice area, we also continue to enhance our M&E services by integrating them with our transformational technology and data-driven capabilities.

" - }, - { - title: "Marketing materials", - text: "" - }, - { - title: "Contractor Capabilities", - text: "

As prime contractor, Bixal offers a global perspective to help federal agencies identify their needs and create systems that support business objectives with the customer in mind.

Bixal leverages agile methodologies that align with our commitment to exceptional service, ensuring the delivery of value, quality, and security. Our core capabilities suited specifically for the USDA IDIQ vehicle include:

  • Enterprise Digital Communications & Technology
  • Content Strategy & Marketing Advanced Brand Recognition
" - }, - { - title: "Key points of Contact", - text: "

To contact us for information on the USDA IDIQ vehicle, please use the following contact information:

Fred Jorgensen, VP of Strategic Growth
fred.jorgensen@bixal.com
703.634.5701
Fred Jorgensen, VP of Strategic Growth
fred.jorgensen@bixal.com
703.634.5701
" - }, - { - title: "Conformed Contract Documents", - text: "" + body: ` +

Introduction

+

Bixal is the sole holder of a blanket purchase agreement (BPA) providing independent monitoring and evaluation (M&E) services in support of the U.S. Department of the Treasury’s Office of Technical Assistance (OTA). With over 90 technical assistance projects in 51 developing and transitional countries around the globe, the OTA works with finance ministries and central banks to safeguard financial sectors and strengthen their ability to manage public finances effectively. M&E services under this BPA include designing and conducting evaluations of OTA initiatives, supporting M&E process improvements and facilitating program learning.

This three-year BPA builds on Bixal’s M&E capabilities, which were significantly augmented in January 2021, when we acquired Clear Outcomes. As Bixal furthers our data science and analytics practice area, we also continue to enhance our M&E services by integrating them with our transformational technology and data-driven capabilities.

+

Marketing materials

+ +

Contractor Capabilities

+

As prime contractor, Bixal offers a global perspective to help federal agencies identify their needs and create systems that support business objectives with the customer in mind.

Bixal leverages agile methodologies that align with our commitment to exceptional service, ensuring the delivery of value, quality, and security. Our core capabilities suited specifically for the USDA IDIQ vehicle include: +

+
    +
  • + Enterprise Digital Communications & Technology +
  • +
  • + Content Strategy & Marketing Advanced Brand Recognition +
  • +
+

Key points of Contact

+

To contact us for information on the USDA IDIQ vehicle, please use the following contact information:

Fred Jorgensen, VP of Strategic Growth
fred.jorgensen@bixal.com
703.634.5701
Fred Jorgensen, VP of Strategic Growth
fred.jorgensen@bixal.com
703.634.5701
+ + +

+ Conformed Contract Documents +

+ +

+ Contract information +

+

OASIS SB

+
    +
  • Contract Number: 47QRAD20D1074
  • +
  • DUNS Number: 100128086
  • +
  • CAGE Code: 4QRJ3
  • +
+

OASIS 8(a)

+
    +
  • Contract Number: 47QRAD20D1074
  • +
  • DUNS Number: 100128086
  • +
  • CAGE Code: 4QRJ3
  • +
+ `, }, - { - title: "Contract information", - text: "

OASIS SB

  • Contract Number: 47QRAD20D1074
  • DUNS Number: 100128086
  • CAGE Code: 4QRJ3

OASIS 8(a)

  • Contract Number: 47QRAD20D1074
  • DUNS Number: 100128086
  • CAGE Code: 4QRJ3
" - } ], - footerContent: FooterContent.default.args - } + footerContent: FooterContent.default.args, + }, }; export const Default = {}; diff --git a/web/modules/custom/case_studies/case_studies.install b/web/modules/custom/case_studies/case_studies.install index ab363bc2..6b5fd6e2 100644 --- a/web/modules/custom/case_studies/case_studies.install +++ b/web/modules/custom/case_studies/case_studies.install @@ -5,6 +5,8 @@ * Install, update and uninstall functions for the Case Studies module. */ +use Drupal\Core\Config\FileStorage; + /** * Implements hook_install(). */ @@ -46,3 +48,19 @@ function _case_studies_add_case_study_xmlsitemap_entries() { ]); } } + +/** + * Implements hook_update_n(). + * + * Add path alias settings for case studies. + */ +function case_studies_update_8002($is_syncing) { + // Get all configs in the config install dir and install them. + $source = new FileStorage(__DIR__ . '/config/install'); + $config_storage = \Drupal::service('config.storage'); + foreach ($source->listAll() as $config_name) { + $config_storage->write($config_name, $source->read($config_name)); + \Drupal::logger('case_studies')->info('Configuration for @config_name was successfully imported as text.', ['@config_name' => $config_name]); + } + +} diff --git a/web/modules/custom/case_studies/config/install/pathauto.pattern.case_studies.yml b/web/modules/custom/case_studies/config/install/pathauto.pattern.case_studies.yml new file mode 100644 index 00000000..e5bc85dc --- /dev/null +++ b/web/modules/custom/case_studies/config/install/pathauto.pattern.case_studies.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + module: + - node +id: case_studies +label: 'Case Studies' +type: 'canonical_entities:node' +pattern: 'our-work/[node:title]' +selection_criteria: + c5da88d6-f0e4-4202-ba8d-c0c5c6ff8a6b: + id: 'entity_bundle:node' + negate: false + uuid: c5da88d6-f0e4-4202-ba8d-c0c5c6ff8a6b + context_mapping: + node: node + bundles: + case_study: case_study +selection_logic: and +weight: -5 +relationships: { } \ No newline at end of file diff --git a/web/sites/default/settings.memcache.php b/web/sites/default/settings.memcache.php index 8796e2c8..ff476ad3 100644 --- a/web/sites/default/settings.memcache.php +++ b/web/sites/default/settings.memcache.php @@ -5,7 +5,8 @@ if (( !InstallerKernel::installationAttempted() && (extension_loaded('memcached') || extension_loaded('memcache')) && - file_exists($app_root . '/modules/contrib/memcache') + file_exists($app_root . '/modules/contrib/memcache') && + !function_exists('_settings_memcache') )) { function _settings_memcache(array &$settings, string $host): void { $settings['memcache']['servers'][$host] = 'default'; diff --git a/web/sites/default/settings.redis.php b/web/sites/default/settings.redis.php index 29ed533d..33ce67e7 100644 --- a/web/sites/default/settings.redis.php +++ b/web/sites/default/settings.redis.php @@ -5,7 +5,8 @@ if (( !InstallerKernel::installationAttempted() && extension_loaded('redis') && - class_exists('Drupal\redis\ClientFactory') + class_exists('Drupal\redis\ClientFactory') && + !function_exists('_settings_redis') )) { function _settings_redis(array &$settings, string $host, string $port): void { $settings['redis.connection']['host'] = $host;