Browse Source

added terms of services

bach 3 years ago
parent
commit
1ac8e08daa
23 changed files with 712 additions and 11 deletions
  1. 2 0
      composer.json
  2. 134 1
      composer.lock
  3. 22 10
      config/sync/commerce_checkout.commerce_checkout_flow.materio_checkout_flow.yml
  4. 17 0
      config/sync/config_pages.type.terms_of_services.yml
  5. 33 0
      config/sync/core.entity_form_display.config_pages.terms_of_services.default.yml
  6. 25 0
      config/sync/core.entity_view_display.config_pages.terms_of_services.default.yml
  7. 33 0
      config/sync/core.entity_view_display.config_pages.terms_of_services.full.yml
  8. 12 0
      config/sync/core.entity_view_mode.config_pages.full.yml
  9. 3 0
      config/sync/core.extension.yml
  10. 26 0
      config/sync/field.field.config_pages.terms_of_services.field_body.yml
  11. 25 0
      config/sync/field.field.config_pages.terms_of_services.field_title.yml
  12. 23 0
      config/sync/field.storage.config_pages.field_body.yml
  13. 25 0
      config/sync/field.storage.config_pages.field_title.yml
  14. 1 0
      config/sync/language/fr/core.entity_view_mode.config_pages.full.yml
  15. 61 0
      config/sync/structure_sync.data.yml
  16. 1 0
      config/sync/user.role.admin.yml
  17. 1 0
      config/sync/user.role.anonymous.yml
  18. 1 0
      config/sync/user.role.authenticated.yml
  19. 9 0
      web/modules/custom/materio_commerce/materio_commerce.info.yml
  20. 1 0
      web/modules/custom/materio_commerce/materio_commerce.module
  21. 7 0
      web/modules/custom/materio_commerce/materio_commerce.routing.yml
  22. 71 0
      web/modules/custom/materio_commerce/src/Controller/MaterioCommerceTermsViewer.php
  23. 179 0
      web/modules/custom/materio_commerce/src/Plugin/Commerce/CheckoutPane/MaterioCommerceAgreeTerms.php

+ 2 - 0
composer.json

@@ -34,6 +34,7 @@
         "drupal/commerce_variation_cart_form": "^1.x-dev",
         "drupal/computed_field": "^2.0@beta",
         "drupal/config_devel": "^1.7",
+        "drupal/config_pages": "^2.9",
         "drupal/config_split": "^1.4",
         "drupal/console": "^1.0.2",
         "drupal/consumer_image_styles": "^3.0",
@@ -81,6 +82,7 @@
         "drupal/social_media_links": "^2.8",
         "drupal/string_translation_ui": "^1.2",
         "drupal/strings_i18n_json_export": "1.x-dev@dev",
+        "drupal/structure_sync": "^2.0",
         "drupal/subrequests": "^2.0",
         "drupal/synonyms": "2.0.0-beta2",
         "drupal/telephone_formatter": "^1.0@beta",

+ 134 - 1
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "8aec23c8aeb752e25608308a47eb8f52",
+    "content-hash": "dc55edf4f15740641dc0903f68085726",
     "packages": [
         {
             "name": "alchemy/zippy",
@@ -4962,6 +4962,67 @@
                 "irc": "irc://irc.freenode.org/drupal-contribute"
             }
         },
+        {
+            "name": "drupal/config_pages",
+            "version": "2.9.0",
+            "source": {
+                "type": "git",
+                "url": "https://git.drupalcode.org/project/config_pages.git",
+                "reference": "8.x-2.9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://ftp.drupal.org/files/projects/config_pages-8.x-2.9.zip",
+                "reference": "8.x-2.9",
+                "shasum": "6b12bbac4b57c9068b472570738d286efe9767a9"
+            },
+            "require": {
+                "drupal/core": "^8.5 | ^9"
+            },
+            "type": "drupal-module",
+            "extra": {
+                "drupal": {
+                    "version": "8.x-2.9",
+                    "datestamp": "1610434193",
+                    "security-coverage": {
+                        "status": "covered",
+                        "message": "Covered by Drupal's security advisory policy"
+                    }
+                },
+                "drush": {
+                    "services": {
+                        "drush.services.yml": "^9"
+                    }
+                }
+            },
+            "notification-url": "https://packages.drupal.org/8/downloads",
+            "license": [
+                "GPL-2.0-or-later"
+            ],
+            "authors": [
+                {
+                    "name": "Qwaygon",
+                    "homepage": "https://www.drupal.org/user/636624"
+                },
+                {
+                    "name": "claymor",
+                    "homepage": "https://www.drupal.org/user/3193903"
+                },
+                {
+                    "name": "shumer",
+                    "homepage": "https://www.drupal.org/user/2297432"
+                }
+            ],
+            "description": "ConfigPages module",
+            "homepage": "http://drupal.org/project/config_pages",
+            "keywords": [
+                "Drupal"
+            ],
+            "support": {
+                "source": "http://cgit.drupalcode.org/config_pages",
+                "issues": "http://drupal.org/project/issues/config_pages"
+            }
+        },
         {
             "name": "drupal/config_split",
             "version": "1.7.0",
@@ -11685,6 +11746,78 @@
             },
             "time": "2020-01-29T18:50:40+00:00"
         },
+        {
+            "name": "drupal/structure_sync",
+            "version": "2.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://git.drupalcode.org/project/structure_sync.git",
+                "reference": "2.0.2"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://ftp.drupal.org/files/projects/structure_sync-2.0.2.zip",
+                "reference": "2.0.2",
+                "shasum": "7c1cda02629cdd90113b95de2d353e8d5a7aa90e"
+            },
+            "require": {
+                "drupal/core": "^8 || ^9"
+            },
+            "type": "drupal-module",
+            "extra": {
+                "drupal": {
+                    "version": "2.0.2",
+                    "datestamp": "1614096703",
+                    "security-coverage": {
+                        "status": "covered",
+                        "message": "Covered by Drupal's security advisory policy"
+                    }
+                }
+            },
+            "notification-url": "https://packages.drupal.org/8/downloads",
+            "license": [
+                "GPL-2.0-or-later"
+            ],
+            "authors": [
+                {
+                    "name": "colan",
+                    "homepage": "https://www.drupal.org/user/58704"
+                },
+                {
+                    "name": "fidovdbos",
+                    "homepage": "https://www.drupal.org/user/1494332"
+                },
+                {
+                    "name": "joachim",
+                    "homepage": "https://www.drupal.org/user/107701"
+                },
+                {
+                    "name": "legolasbo",
+                    "homepage": "https://www.drupal.org/user/2480548"
+                },
+                {
+                    "name": "mparker17",
+                    "homepage": "https://www.drupal.org/user/536298"
+                },
+                {
+                    "name": "spiderman",
+                    "homepage": "https://www.drupal.org/user/1631"
+                },
+                {
+                    "name": "timKruijsen",
+                    "homepage": "https://www.drupal.org/user/3513437"
+                },
+                {
+                    "name": "vinlaurens",
+                    "homepage": "https://www.drupal.org/user/2945689"
+                }
+            ],
+            "description": "Tool for syncing structural data that is stored as content.",
+            "homepage": "https://www.drupal.org/project/structure_sync",
+            "support": {
+                "source": "https://git.drupalcode.org/project/structure_sync"
+            }
+        },
         {
             "name": "drupal/subrequests",
             "version": "2.3.0",

+ 22 - 10
config/sync/commerce_checkout.commerce_checkout_flow.materio_checkout_flow.yml

@@ -7,6 +7,7 @@ dependencies:
     - commerce_promotion
     - commerce_stripe
     - email_registration
+    - materio_commerce
 id: materio_checkout_flow
 label: 'materio checkout flow'
 plugin: multistep_default
@@ -23,44 +24,55 @@ configuration:
     payment_information:
       step: order_information
       weight: 1
+    materio_commerce_agree_terms:
+      path:
+        route_name: materio_commerce.terms_viewer
+        route_parameters: {  }
+      link_text: 'Terms and Conditions'
+      prefix_text: 'I agree with the %terms'
+      invalid_text: 'You must agree with the %terms before continuing'
+      new_window: '1'
+      step: order_information
+      weight: 2
+      nid: '1'
     review:
       step: review
-      weight: 2
+      weight: 3
     stripe_review:
       button_id: edit-actions-next
       step: review
-      weight: 3
+      weight: 4
     payment_process:
       capture: true
       step: payment
-      weight: 4
+      weight: 5
     completion_message:
       message:
         value: "<p class=\"welcom\">[current-user:customer:address:given_name]&nbsp;[current-user:customer:address:family_name] thank you and welcome&nbsp;to <strong>[site:name]</strong>!</p>\r\n\r\n<p class=\"base\">You now have full access to our <a href=\"/base\">8000+ materials</a></p>\r\n\r\n<p class=\"order\">&nbsp;</p>\r\n"
         format: wysiwyg
       step: complete
-      weight: 5
+      weight: 6
     order_summary:
       view: commerce_checkout_order_summary
       step: _sidebar
-      weight: 6
+      weight: 7
     coupon_redemption:
       allow_multiple: false
       step: _sidebar
-      weight: 7
+      weight: 8
     email_registration_login:
       allow_guest_checkout: true
       allow_registration: false
       step: _disabled
-      weight: 8
+      weight: 10
     email_registration_completion_registration:
       step: _disabled
-      weight: 9
+      weight: 11
     completion_register:
       step: _disabled
-      weight: 10
+      weight: 12
     login:
       allow_guest_checkout: true
       allow_registration: false
       step: _disabled
-      weight: 11
+      weight: 13

+ 17 - 0
config/sync/config_pages.type.terms_of_services.yml

@@ -0,0 +1,17 @@
+uuid: 689d8780-02a4-4787-bf07-ab36c5ff7454
+langcode: en
+status: true
+dependencies: {  }
+id: terms_of_services
+label: 'Terms of services'
+context:
+  show_warning: true
+  group:
+    language: true
+  fallback:
+    language: ''
+menu:
+  path: /admin/content/tos
+  weight: 0
+  description: ''
+token: false

+ 33 - 0
config/sync/core.entity_form_display.config_pages.terms_of_services.default.yml

@@ -0,0 +1,33 @@
+uuid: 37d76e44-2b2f-4519-bf47-408fd73ceb04
+langcode: en
+status: true
+dependencies:
+  config:
+    - config_pages.type.terms_of_services
+    - field.field.config_pages.terms_of_services.field_body
+    - field.field.config_pages.terms_of_services.field_title
+  module:
+    - text
+id: config_pages.terms_of_services.default
+targetEntityType: config_pages
+bundle: terms_of_services
+mode: default
+content:
+  field_body:
+    weight: 1
+    settings:
+      rows: 5
+      placeholder: ''
+    third_party_settings: {  }
+    type: text_textarea
+    region: content
+  field_title:
+    weight: 0
+    settings:
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+    type: string_textfield
+    region: content
+hidden:
+  label: true

+ 25 - 0
config/sync/core.entity_view_display.config_pages.terms_of_services.default.yml

@@ -0,0 +1,25 @@
+uuid: 50e2e477-ed96-4949-8583-cd9abc1aa05a
+langcode: en
+status: true
+dependencies:
+  config:
+    - config_pages.type.terms_of_services
+    - field.field.config_pages.terms_of_services.field_body
+    - field.field.config_pages.terms_of_services.field_title
+  module:
+    - text
+id: config_pages.terms_of_services.default
+targetEntityType: config_pages
+bundle: terms_of_services
+mode: default
+content:
+  field_body:
+    weight: 0
+    label: hidden
+    settings: {  }
+    third_party_settings: {  }
+    type: text_default
+    region: content
+hidden:
+  field_title: true
+  search_api_excerpt: true

+ 33 - 0
config/sync/core.entity_view_display.config_pages.terms_of_services.full.yml

@@ -0,0 +1,33 @@
+uuid: 0ae78753-31b9-41bf-bcaa-e269fd835be1
+langcode: en
+status: false
+dependencies:
+  config:
+    - config_pages.type.terms_of_services
+    - core.entity_view_mode.config_pages.full
+    - field.field.config_pages.terms_of_services.field_body
+    - field.field.config_pages.terms_of_services.field_title
+  module:
+    - text
+id: config_pages.terms_of_services.full
+targetEntityType: config_pages
+bundle: terms_of_services
+mode: full
+content:
+  field_body:
+    weight: 1
+    label: hidden
+    settings: {  }
+    third_party_settings: {  }
+    type: text_default
+    region: content
+  field_title:
+    weight: 0
+    label: hidden
+    settings:
+      link_to_entity: false
+    third_party_settings: {  }
+    type: string
+    region: content
+hidden:
+  search_api_excerpt: true

+ 12 - 0
config/sync/core.entity_view_mode.config_pages.full.yml

@@ -0,0 +1,12 @@
+uuid: ff6b374f-0a7e-4fb5-a40c-8642053df484
+langcode: en
+status: true
+dependencies:
+  module:
+    - config_pages
+_core:
+  default_config_hash: VYERDzPNi1-oUm7KMLjol4oLcjbHr-onKbitt4dZuN0
+id: config_pages.full
+label: Full
+targetEntityType: config_pages
+cache: true

+ 3 - 0
config/sync/core.extension.yml

@@ -43,6 +43,7 @@ module:
   config: 0
   config_filter: 0
   config_ignore: 0
+  config_pages: 0
   config_split: 0
   config_translation: 0
   config_update: 0
@@ -111,6 +112,7 @@ module:
   mailgun: 0
   maillog: 0
   mailsystem: 0
+  materio_commerce: 0
   materio_decoupled: 0
   materio_flag: 0
   materio_graphql: 0
@@ -170,6 +172,7 @@ module:
   state_machine: 0
   string_translation_ui: 0
   strings_i18n_json_export: 0
+  structure_sync: 0
   synonyms: 0
   syslog: 0
   system: 0

+ 26 - 0
config/sync/field.field.config_pages.terms_of_services.field_body.yml

@@ -0,0 +1,26 @@
+uuid: d890c8c1-7fbd-420d-9039-77d8445e024d
+langcode: en
+status: true
+dependencies:
+  config:
+    - config_pages.type.terms_of_services
+    - field.storage.config_pages.field_body
+  module:
+    - text
+    - unique_content_field_validation
+third_party_settings:
+  unique_content_field_validation:
+    unique: false
+    unique_text: ''
+id: config_pages.terms_of_services.field_body
+field_name: field_body
+entity_type: config_pages
+bundle: terms_of_services
+label: Body
+description: ''
+required: false
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings: {  }
+field_type: text_long

+ 25 - 0
config/sync/field.field.config_pages.terms_of_services.field_title.yml

@@ -0,0 +1,25 @@
+uuid: 9d4ede0c-a9e6-47b5-8f54-070eb262d7a0
+langcode: en
+status: true
+dependencies:
+  config:
+    - config_pages.type.terms_of_services
+    - field.storage.config_pages.field_title
+  module:
+    - unique_content_field_validation
+third_party_settings:
+  unique_content_field_validation:
+    unique: false
+    unique_text: ''
+id: config_pages.terms_of_services.field_title
+field_name: field_title
+entity_type: config_pages
+bundle: terms_of_services
+label: Title
+description: ''
+required: true
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings: {  }
+field_type: string

+ 23 - 0
config/sync/field.storage.config_pages.field_body.yml

@@ -0,0 +1,23 @@
+uuid: ab37dccc-ec5e-46b4-b2a7-5eeee0787968
+langcode: en
+status: true
+dependencies:
+  module:
+    - config_pages
+    - field_permissions
+    - text
+third_party_settings:
+  field_permissions:
+    permission_type: public
+id: config_pages.field_body
+field_name: field_body
+entity_type: config_pages
+type: text_long
+settings: {  }
+module: text
+locked: false
+cardinality: 1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false

+ 25 - 0
config/sync/field.storage.config_pages.field_title.yml

@@ -0,0 +1,25 @@
+uuid: 86a82680-7c48-4d42-a9cb-991a7803e6d9
+langcode: en
+status: true
+dependencies:
+  module:
+    - config_pages
+    - field_permissions
+third_party_settings:
+  field_permissions:
+    permission_type: public
+id: config_pages.field_title
+field_name: field_title
+entity_type: config_pages
+type: string
+settings:
+  max_length: 255
+  is_ascii: false
+  case_sensitive: false
+module: core
+locked: false
+cardinality: 1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false

+ 1 - 0
config/sync/language/fr/core.entity_view_mode.config_pages.full.yml

@@ -0,0 +1 @@
+label: Complet

+ 61 - 0
config/sync/structure_sync.data.yml

@@ -0,0 +1,61 @@
+menus:
+  -
+    menu_name: editors
+    title: Thematiques
+    parent: editors_menus.contents
+    uri: 'internal:/admin/content/thematiques'
+    link_title: ''
+    description: null
+    enabled: '1'
+    expanded: '0'
+    weight: '-48'
+    langcode: en
+    uuid: bc70db0f-78a3-4957-8730-5523192830d7
+  -
+    menu_name: editors
+    title: 'Interface Translation'
+    parent: null
+    uri: 'internal:/admin/config/regional/translate'
+    link_title: ''
+    description: null
+    enabled: '1'
+    expanded: '0'
+    weight: '0'
+    langcode: en
+    uuid: 91e07677-0035-4e5a-8bdd-cfb52c1da4f8
+  -
+    menu_name: editors
+    title: 'Home page'
+    parent: editors_menus.contents
+    uri: 'internal:/node/1/edit'
+    link_title: ''
+    description: null
+    enabled: '1'
+    expanded: '0'
+    weight: '-50'
+    langcode: en
+    uuid: af51f6df-dbce-4e35-b4bc-7ef21314110b
+  -
+    menu_name: editors
+    title: Products
+    parent: editors_menus.commerce
+    uri: 'internal:/admin/commerce/products'
+    link_title: ''
+    description: null
+    enabled: '1'
+    expanded: '0'
+    weight: '0'
+    langcode: en
+    uuid: 27e5f4e1-1ea7-425e-aabb-81404d40a864
+  -
+    menu_name: editors
+    title: 'Terms of services'
+    parent: null
+    uri: 'internal:/admin/content/tos'
+    link_title: ''
+    description: null
+    enabled: '1'
+    expanded: '0'
+    weight: '0'
+    langcode: en
+    uuid: b8ad0bb1-69f4-44ff-9ab3-20e9d9ae1ee9

+ 1 - 0
config/sync/user.role.admin.yml

@@ -102,6 +102,7 @@ permissions:
   - 'edit terms in showroom'
   - 'edit terms in tags'
   - 'edit terms in thesaurus'
+  - 'edit terms_of_services config page entity'
   - 'execute entity:save_action menu_link_content'
   - 'execute entity:save_action node'
   - 'execute entity:save_action taxonomy_term'

+ 1 - 0
config/sync/user.role.anonymous.yml

@@ -31,4 +31,5 @@ permissions:
   - 'view commerce_product'
   - 'view published fil entities'
   - 'view search api pages'
+  - 'view terms_of_services config page entity'
   - 'view webprofiler toolbar'

+ 1 - 0
config/sync/user.role.authenticated.yml

@@ -45,4 +45,5 @@ permissions:
   - 'view published composition entities'
   - 'view published fil entities'
   - 'view search api pages'
+  - 'view terms_of_services config page entity'
   - 'view webprofiler toolbar'

+ 9 - 0
web/modules/custom/materio_commerce/materio_commerce.info.yml

@@ -0,0 +1,9 @@
+name: Materio Commerce
+description: Materio commerce custom module
+package: Materio
+
+type: module
+core: 8.x
+
+dependencies:
+  - drupal:commerce

+ 1 - 0
web/modules/custom/materio_commerce/materio_commerce.module

@@ -0,0 +1 @@
+<?php

+ 7 - 0
web/modules/custom/materio_commerce/materio_commerce.routing.yml

@@ -0,0 +1,7 @@
+materio_commerce.terms_viewer:
+  path: 'tos'
+  defaults:
+    _controller: '\Drupal\materio_commerce\Controller\MaterioCommerceTermsViewer::getTos'
+    _title_callback: '\Drupal\materio_commerce\Controller\MaterioCommerceTermsViewer::getTitle'
+  requirements:
+    _permission: 'access content'

+ 71 - 0
web/modules/custom/materio_commerce/src/Controller/MaterioCommerceTermsViewer.php

@@ -0,0 +1,71 @@
+<?php
+
+namespace Drupal\materio_commerce\Controller;
+
+use Drupal\Core\Controller\ControllerBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Core\Language\LanguageManagerInterface;
+use Drupal\Core\Url;
+use Symfony\Component\HttpFoundation\Request;
+// use Symfony\Component\HttpFoundation\JsonResponse;
+use Drupal\config_pages\Entity\ConfigPages;
+use Drupal\config_pages\Entity\ConfigPagesType;
+
+/**
+ * Class AjaxHomeController.
+ */
+class MaterioCommerceTermsViewer extends ControllerBase {
+
+
+  /*
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $languageManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('language_manager')
+    );
+  }
+
+  /**
+   * Constructs a new MaterioDecoupledLanguageLinks object.
+   *
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+   *   The language manager.
+   */
+  public function __construct(LanguageManagerInterface $language_manager) {
+    $this->languageManager = $language_manager;
+  }
+
+  /**
+   * getTerms
+   *
+   * @return string
+   *   Return config_page terms_of_services display.
+   */
+  public function getTos(Request $request) {
+    $config_page = $this->getConfigPage();
+
+    // Correct metatags attachment.
+    if (function_exists('metatag_get_tags_from_route')) {
+      $metatag_attachments = &drupal_static('metatag_attachments');
+      $metatag_attachments = metatag_get_tags_from_route($config_page);
+    }
+
+    return parent::entityTypeManager()->getViewBuilder('config_pages')->view($config_page, 'full');
+
+  }
+
+  public function getTitle(Request $request) {
+    $config_page = $this->getConfigPage();
+    return $config_page->get('field_title')->getString();
+  }
+
+  private function getConfigPage(){
+    return ConfigPages::load("terms_of_services");
+  }
+}

+ 179 - 0
web/modules/custom/materio_commerce/src/Plugin/Commerce/CheckoutPane/MaterioCommerceAgreeTerms.php

@@ -0,0 +1,179 @@
+<?php
+
+namespace Drupal\materio_commerce\Plugin\Commerce\CheckoutPane;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneBase;
+use Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneInterface;
+use Drupal\node\Entity\Node;
+use Drupal\Core\Link;
+
+/**
+ * Provides the completion message pane.
+ *
+ * @CommerceCheckoutPane(
+ *   id = "materio_commerce_agree_terms",
+ *   label = @Translation("Agree to the terms and conditions"),
+ *   default_step = "review",
+ * )
+ */
+class MaterioCommerceAgreeTerms extends CheckoutPaneBase implements CheckoutPaneInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return [
+        'path' => NULL,
+        'link_text' => 'Terms and Conditions',
+        'prefix_text' => 'I agree with the %terms',
+        'invalid_text' => 'You must agree with the %terms before continuing',
+        'new_window' => 1,
+      ] + parent::defaultConfiguration();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationSummary() {
+    $prefix = $this->configuration['prefix_text'];
+    $link_text = $this->configuration['link_text'];
+    $invalid_text = $this->configuration['invalid_text'];
+    $new_window = $this->configuration['new_window'];
+    $path = $this->configuration['path'];
+    $summary = '';
+    if (!empty($prefix)) {
+      $summary = $this->t('Prefix text: @text', ['@text' => $prefix]) . '<br/>';
+    }
+    if (!empty($link_text)) {
+      $summary .= $this->t('Link text: @text', ['@text' => $link_text]) . '<br/>';
+    }
+    if (!empty($invalid_text)) {
+      $summary .= $this->t('Error text: @text', ['@text' => $invalid_text]) . '<br/>';
+    }
+    if (!empty($window_target)) {
+      $window_text = ($new_window === 1) ? $this->t('New window') : $this->t('Same window');
+      $summary .= $this->t('Window opens in: @opens', ['@text' => $window_text]) . '<br/>';
+    }
+    if (!empty($path)) {
+      $summary .= $this->t('Terms page: @path', ['@path' => $path['route_name']]);
+    }
+
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+    $form = parent::buildConfigurationForm($form, $form_state);
+    $form['prefix_text'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Prefix text'),
+      '#default_value' => $this->configuration['prefix_text'],
+    ];
+    $form['link_text'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Link text'),
+      '#default_value' => $this->configuration['link_text'],
+      '#required' => TRUE,
+    ];
+    $form['invalid_text'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Invalid text'),
+      '#default_value' => $this->configuration['invalid_text'],
+    ];
+    $form['new_window'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Open window link in new window'),
+      '#default_value' => $this->configuration['new_window'],
+    ];
+
+    if ($this->configuration['path']) {
+      $path = $this->configuration['path'];
+    }
+    else {
+      $path = NULL;
+    }
+    $form['path'] = [
+      '#type' => 'path',
+      '#default_value' => $path,
+      '#required' => TRUE
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
+    parent::submitConfigurationForm($form, $form_state);
+    // Todo  validate existing path
+    // Get route name and parameters from path.
+    // $url_object = \Drupal::service('path.validator')->getUrlIfValid($path);
+    // $route_name = $url_object->getRouteName();
+    // $route_parameters = $url_object->getrouteParameters();
+    
+    if (!$form_state->getErrors()) {
+      $values = $form_state->getValue($form['#parents']);
+      $this->configuration['prefix_text'] = $values['prefix_text'];
+      $this->configuration['link_text'] = $values['link_text'];
+      $this->configuration['invalid_text'] = $values['invalid_text'];
+      $this->configuration['new_window'] = $values['new_window'];
+      $this->configuration['path'] = $values['path'];
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) {
+    $prefix_text = $this->configuration['prefix_text'];
+    $link_text = $this->configuration['link_text'];
+    $path = $this->configuration['path'];
+    if ($path) {
+      // $node = Node::load($nid);
+      $attributes = [];
+      if ($this->configuration['new_window']) {
+        $attributes = ['attributes' => ['target' => '_blank']];
+      }
+      $link = Link::createFromRoute(
+        $this->t($link_text),
+        $path['route_name'],
+        $path['route_parameters'],
+        $attributes
+      )->toString();
+      if ($prefix_text) {
+        $pane_form['terms_and_conditions'] = [
+          '#type' => 'checkbox',
+          '#default_value' => FALSE,
+          '#title' => $this->t($prefix_text, ['%terms' => $link]),
+          '#required' => TRUE,
+          '#weight' => $this->getWeight(),
+        ];
+      }
+      else {
+        $pane_form['terms_and_conditions'] = [
+          '#type' => 'checkbox',
+          '#default_value' => FALSE,
+          '#title' => $link,
+          '#required' => TRUE,
+          '#weight' => $this->getWeight(),
+        ];
+      }
+    }
+    return $pane_form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validatePaneForm(array &$pane_form, FormStateInterface $form_state, array &$complete_form) {
+    $values = $form_state->getValue($pane_form['#parents']);
+    if (!$values['terms_and_conditions']) {
+      $form_state->setError($pane_form, $this->configuration['invalid_text']);
+    }
+  }
+
+}