diff --git a/composer.json b/composer.json index 0b5c4e1..deed314 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ ], "require": { "composer/installers": "^2.0", + "drupal/block_field": "^1.0@RC", "drupal/config_pages": "^2.15", "drupal/core-composer-scaffold": "^10.2", "drupal/core-project-message": "^10.2", diff --git a/composer.lock b/composer.lock index 86a3600..2afe550 100644 --- a/composer.lock +++ b/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": "365559febcbdf4e52ca276eed5a58fe5", + "content-hash": "d9c788ae880184300ad1f5beb62e85a1", "packages": [ { "name": "asm89/stack-cors", @@ -2271,6 +2271,70 @@ "irc": "irc://irc.freenode.org/drupal-contribute" } }, + { + "name": "drupal/block_field", + "version": "1.0.0-rc5", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/block_field.git", + "reference": "8.x-1.0-rc5" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/block_field-8.x-1.0-rc5.zip", + "reference": "8.x-1.0-rc5", + "shasum": "b87e43e9bbaaf6cff6d8946d5e45db492978cbb6" + }, + "require": { + "drupal/core": "^9 || ^10 || ^11" + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "8.x-1.0-rc5", + "datestamp": "1723550576", + "security-coverage": { + "status": "not-covered", + "message": "RC releases are not covered by Drupal security advisories." + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "acbramley", + "homepage": "https://www.drupal.org/user/1036766" + }, + { + "name": "berdir", + "homepage": "https://www.drupal.org/user/214652" + }, + { + "name": "fenstrat", + "homepage": "https://www.drupal.org/user/362649" + }, + { + "name": "jrockowitz", + "homepage": "https://www.drupal.org/user/371407" + }, + { + "name": "michaellander", + "homepage": "https://www.drupal.org/user/636494" + }, + { + "name": "paulocs", + "homepage": "https://www.drupal.org/user/3640109" + } + ], + "description": "Provides a field that allows a content entity to create and configure custom block instances.", + "homepage": "https://www.drupal.org/project/block_field", + "support": { + "source": "https://git.drupalcode.org/project/block_field" + } + }, { "name": "drupal/bulkdelete", "version": "dev-1.x", @@ -12825,6 +12889,7 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { + "drupal/block_field": 5, "drupal/page_manager": 5, "drupal/viewsreference": 10, "drupal/advanced_text_formatter": 5, diff --git a/config/sync/core.entity_form_display.node.static.default.yml b/config/sync/core.entity_form_display.node.static.default.yml index b8aa4b4..2195181 100644 --- a/config/sync/core.entity_form_display.node.static.default.yml +++ b/config/sync/core.entity_form_display.node.static.default.yml @@ -5,16 +5,17 @@ dependencies: config: - field.field.node.static.body - field.field.node.static.field_map + - field.field.node.static.field_map_block - field.field.node.static.field_pieces_jointes - field.field.node.static.field_textes - node.type.static module: + - block_field - field_group - file - paragraphs - path - text - - viewsreference third_party_settings: field_group: group_details: @@ -57,15 +58,14 @@ content: region: content settings: { } third_party_settings: { } - field_map: - type: viewsreference_autocomplete + field_map_block: + type: block_field_default weight: 2 region: content settings: - match_operator: CONTAINS - match_limit: 10 - size: 60 - placeholder: '' + plugin_id: '' + settings: { } + configuration_form: full third_party_settings: { } field_pieces_jointes: type: file_generic @@ -159,4 +159,5 @@ content: size: 60 placeholder: '' third_party_settings: { } -hidden: { } +hidden: + field_map: true diff --git a/config/sync/core.entity_view_display.node.static.default.yml b/config/sync/core.entity_view_display.node.static.default.yml index b5876d1..5c2e7fe 100644 --- a/config/sync/core.entity_view_display.node.static.default.yml +++ b/config/sync/core.entity_view_display.node.static.default.yml @@ -5,14 +5,15 @@ dependencies: config: - field.field.node.static.body - field.field.node.static.field_map + - field.field.node.static.field_map_block - field.field.node.static.field_pieces_jointes - field.field.node.static.field_textes - node.type.static module: + - block_field - entity_reference_revisions - manage_display - text - - viewsreference _core: default_config_hash: 9mgezio6-8HiMYhQHSfouZjKyY4BFKR71Yh4kbSmAYU id: node.static.default @@ -27,12 +28,10 @@ content: third_party_settings: { } weight: 1 region: content - field_map: - type: viewsreference_formatter - label: visually_hidden - settings: - plugin_types: - - block + field_map_block: + type: block_field + label: above + settings: { } third_party_settings: { } weight: 2 region: content @@ -61,6 +60,7 @@ content: region: content hidden: created: true + field_map: true field_pieces_jointes: true langcode: true search_api_excerpt: true diff --git a/config/sync/core.entity_view_display.node.static.full.yml b/config/sync/core.entity_view_display.node.static.full.yml index 000f18f..44fd713 100644 --- a/config/sync/core.entity_view_display.node.static.full.yml +++ b/config/sync/core.entity_view_display.node.static.full.yml @@ -6,14 +6,15 @@ dependencies: - core.entity_view_mode.node.full - field.field.node.static.body - field.field.node.static.field_map + - field.field.node.static.field_map_block - field.field.node.static.field_pieces_jointes - field.field.node.static.field_textes - node.type.static module: + - block_field - entity_reference_revisions - manage_display - text - - viewsreference _core: default_config_hash: 9mgezio6-8HiMYhQHSfouZjKyY4BFKR71Yh4kbSmAYU id: node.static.full @@ -28,15 +29,10 @@ content: third_party_settings: { } weight: 1 region: content - field_map: - type: viewsreference_formatter + field_map_block: + type: block_field label: hidden - settings: - plugin_types: - block: block - default: '0' - page: '0' - feed: '0' + settings: { } third_party_settings: { } weight: 2 region: content @@ -65,6 +61,7 @@ content: region: content hidden: created: true + field_map: true field_pieces_jointes: true langcode: true search_api_excerpt: true diff --git a/config/sync/core.entity_view_display.node.static.teaser.yml b/config/sync/core.entity_view_display.node.static.teaser.yml index 4c5023e..3e2369c 100644 --- a/config/sync/core.entity_view_display.node.static.teaser.yml +++ b/config/sync/core.entity_view_display.node.static.teaser.yml @@ -6,6 +6,7 @@ dependencies: - core.entity_view_mode.node.teaser - field.field.node.static.body - field.field.node.static.field_map + - field.field.node.static.field_map_block - field.field.node.static.field_pieces_jointes - field.field.node.static.field_textes - node.type.static @@ -35,6 +36,7 @@ content: hidden: created: true field_map: true + field_map_block: true field_pieces_jointes: true field_textes: true langcode: true diff --git a/config/sync/core.extension.yml b/config/sync/core.extension.yml index b57c7eb..0e9e8be 100644 --- a/config/sync/core.extension.yml +++ b/config/sync/core.extension.yml @@ -13,6 +13,7 @@ module: block: 0 block_class: 0 block_content: 0 + block_field: 0 breakpoint: 0 bulkdelete: 0 ckeditor5: 0 diff --git a/config/sync/field.field.node.static.field_map_block.yml b/config/sync/field.field.node.static.field_map_block.yml new file mode 100644 index 0000000..5b47170 --- /dev/null +++ b/config/sync/field.field.node.static.field_map_block.yml @@ -0,0 +1,25 @@ +uuid: f1d706d7-b94c-4070-a98d-e00418611b82 +langcode: fr +status: true +dependencies: + config: + - field.storage.node.field_map_block + - node.type.static + module: + - block_field +id: node.static.field_map_block +field_name: field_map_block +entity_type: node +bundle: static +label: 'map block' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + selection: blocks + selection_settings: + plugin_ids: + sitesmap_block: sitesmap_block +field_type: block_field diff --git a/config/sync/field.storage.node.field_map_block.yml b/config/sync/field.storage.node.field_map_block.yml new file mode 100644 index 0000000..d05e641 --- /dev/null +++ b/config/sync/field.storage.node.field_map_block.yml @@ -0,0 +1,19 @@ +uuid: fe870b67-228b-460b-848b-b696a91b740c +langcode: fr +status: true +dependencies: + module: + - block_field + - node +id: node.field_map_block +field_name: field_map_block +entity_type: node +type: block_field +settings: { } +module: block_field +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/config/sync/page_manager.page_variant.node_view-panels_variant-0.yml b/config/sync/page_manager.page_variant.node_view-panels_variant-0.yml index 0a673b0..864f931 100644 --- a/config/sync/page_manager.page_variant.node_view-panels_variant-0.yml +++ b/config/sync/page_manager.page_variant.node_view-panels_variant-0.yml @@ -202,18 +202,15 @@ variant_settings: - '' html_id: '' css_styles: '' - 9c0f77a5-efea-4e81-99c4-2199c1d0d07d: - id: 'views_block:site-block_2' - label: '' + f3919785-5a3a-4926-9de5-e63613bcba52: + id: sitesmap_block + label: 'Sites map Block' label_display: '0' - provider: views + provider: q2d_mod context_mapping: { } - views_label: '' - items_per_page: none - exposed: { } region: first weight: -4 - uuid: 9c0f77a5-efea-4e81-99c4-2199c1d0d07d + uuid: f3919785-5a3a-4926-9de5-e63613bcba52 css_classes: - '' html_id: '' diff --git a/config/sync/views.view.statics_fields.yml b/config/sync/views.view.statics_fields.yml index 36fd839..e94148a 100644 --- a/config/sync/views.view.statics_fields.yml +++ b/config/sync/views.view.statics_fields.yml @@ -39,7 +39,7 @@ display: alter_text: false text: '' make_link: false - path: '' + path: '{{ field_pieces_jointes }}' absolute: false external: false replace_spaces: false @@ -50,7 +50,7 @@ display: link_class: '' prefix: '' suffix: '' - target: '' + target: _blank nl2br: false max_length: 0 word_boundary: true diff --git a/web/modules/custom/q2d_mod/assets/css/carte-interactive-qdd.css b/web/modules/custom/q2d_mod/assets/css/carte-interactive-qdd.css new file mode 100644 index 0000000..f4fb740 --- /dev/null +++ b/web/modules/custom/q2d_mod/assets/css/carte-interactive-qdd.css @@ -0,0 +1,57 @@ +@font-face { + font-family: 'gilroy-semibold'; + src: url('fonts/Gilroy/gilroy-semibold-webfont.woff') format('woff'); +} +#sites-map-container { + background-color: #c3cef2; + text-align: center; +} +/* #sites-map-container .circle { + fill: black; + stroke: white; + stroke-width: 0.7; +} */ + +/* Changer la couleur au survol (hover) */ +#sites-map-container .site-link:hover{ + cursor: pointer; +} + +#sites-map-container .site-link:hover circle.circle { + fill: #f7002b!important; +} + +/* Styles du popup (caché par défaut) */ +#sites-map-container #popup { + font-family: 'gilroy-semibold'; + display: none; + position: fixed; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + z-index: 1000; +} + +#sites-map-container strong{ + color: #f7002b; + font-family: 'gilroy-semibold'; +} +#sites-map-container a{ + display: inline-flex; + align-items: center; + color: white; + background: black; + text-transform: uppercase; + font-size: 0.8rem; + padding-left: 0.5rem; + text-decoration: none; + margin-top: 0.7rem; + height: 1.3rem; +} +#sites-map-container a:after{ + display: inline-flex; + content: url("../img/noun-arrow-to-right.svg"); + padding-right: 0.2rem; + padding-left: 0.2rem; + +} diff --git a/web/modules/custom/q2d_mod/assets/css/fontface.css b/web/modules/custom/q2d_mod/assets/css/fontface.css new file mode 100644 index 0000000..e69de29 diff --git a/web/modules/custom/q2d_mod/assets/css/fonts/Gilroy/gilroy-semibold-webfont.woff b/web/modules/custom/q2d_mod/assets/css/fonts/Gilroy/gilroy-semibold-webfont.woff new file mode 100644 index 0000000..8abd458 Binary files /dev/null and b/web/modules/custom/q2d_mod/assets/css/fonts/Gilroy/gilroy-semibold-webfont.woff differ diff --git a/web/modules/custom/q2d_mod/assets/js/carte-interactive-qdd.js b/web/modules/custom/q2d_mod/assets/js/carte-interactive-qdd.js new file mode 100644 index 0000000..e83bc3c --- /dev/null +++ b/web/modules/custom/q2d_mod/assets/js/carte-interactive-qdd.js @@ -0,0 +1,91 @@ +// Sélection des éléments au préalable pour éviter de les rechercher plusieurs fois +const svgElement = document.querySelector('#sites-map-container svg'); +const popup = document.querySelector('#sites-map-container #popup'); +const popupContent = document.querySelector('#sites-map-container #popup-content'); +const modalBackground = document.querySelector('#sites-map-container #modal-background'); +console.log('svgElement', svgElement); + +// Fonction pour afficher le popup +function showPopup(content, x, y) { + console.log('showPopup', content, x, y); + + popupContent.innerHTML = content; + + // Récupérer la position de l'élément SVG seulement une fois + const rect = svgElement.getBoundingClientRect(); + + // Calculer la position du popup par rapport à l'élément SVG + const popupX = rect.left + x + 120; // Décalage de 120px à droite + const popupY = rect.top + y + 20; // Décalage de 20px en dessous + + // Dimensions de la fenêtre et du popup + const viewportWidth = window.innerWidth; + const viewportHeight = window.innerHeight; + const popupWidth = popup.offsetWidth; + const popupHeight = popup.offsetHeight; + + // Vérification des bordures droite et gauche + if (popupX + popupWidth > viewportWidth) { + popupX = viewportWidth - popupWidth - 10; // Ajuster pour qu'il ne dépasse pas à droite + } + if (popupX < 0) { + popupX = 10; // S'assurer que le popup ne dépasse pas à gauche + } + + // Vérification des bordures inférieure et supérieure + if (popupY + popupHeight > viewportHeight) { + popupY = viewportHeight - popupHeight - 10; // Ajuster pour qu'il ne dépasse pas en bas + } + if (popupY < 0) { + popupY = 10; // S'assurer que le popup ne dépasse pas en haut + } + + popup.style.left = `${popupX}px`; + popup.style.top = `${popupY}px`; + popup.style.display = 'block'; + modalBackground.style.display = 'block'; // Activer le fond modal si nécessaire +} + +// Recalculer la position du popup lors du redimensionnement de la fenêtre +window.addEventListener('resize', function() { + if (popup.style.display === 'block') { + // Recalculer les coordonnées et ajuster la position + const currentPopupRect = popup.getBoundingClientRect(); + showPopup(popupContent.innerHTML, currentPopupRect.left, currentPopupRect.top); + } +}); + +// Fonction pour fermer le popup +function closePopup() { + popup.style.display = 'none'; + modalBackground.style.display = 'none'; // Désactiver le fond modal +} + +// Ajout d'un écouteur d'événement sur l'élément SVG pour tous les cercles +svgElement.addEventListener('click', function(event) { + console.log('svgElement click', event.target); + + if (event.target.classList.contains('site-link')) { + // Récupérer le contenu personnalisé de l'attribut data-content + const content = event.target.getAttribute('data-content'); + + // Récupérer la position du cercle cliqué par rapport à l'élément SVG + const rect = svgElement.getBoundingClientRect(); + const circleX = event.clientX - rect.left; + const circleY = event.clientY - rect.top; + + // Afficher le popup avec le contenu spécifique + showPopup(content, circleX, circleY); + + // Empêcher la propagation de l'événement pour éviter la fermeture immédiate + event.stopPropagation(); + } +}); + +// Ferme le popup quand on clique n'importe où sur la page, sauf sur le popup +document.addEventListener('click', function(event) { + // Vérifier si le clic s'est produit en dehors du popup + if (popup.style.display === 'block' && !popup.contains(event.target)) { + closePopup(); + } +}); diff --git a/web/modules/custom/q2d_mod/q2d_mod.libraries.yml b/web/modules/custom/q2d_mod/q2d_mod.libraries.yml new file mode 100644 index 0000000..674b807 --- /dev/null +++ b/web/modules/custom/q2d_mod/q2d_mod.libraries.yml @@ -0,0 +1,7 @@ +sites_map_block: + css: + theme: + assets/css/fontface.css: {} + assets/css/carte-interactive-qdd.css: {} + js: + assets/js/carte-interactive-qdd.js: {} \ No newline at end of file diff --git a/web/modules/custom/q2d_mod/q2d_mod.module b/web/modules/custom/q2d_mod/q2d_mod.module index 9178a83..b1a6529 100644 --- a/web/modules/custom/q2d_mod/q2d_mod.module +++ b/web/modules/custom/q2d_mod/q2d_mod.module @@ -5,3 +5,13 @@ * Primary module hooks for reha module. */ +/** + * Implements hook_theme(). + */ +function q2d_mod_theme() { + return array( + 'svg_mapsites' => array( + 'variables' => array('vpw' => null, 'vph' => null, 'sites' => []), + ), + ); +} \ No newline at end of file diff --git a/web/modules/custom/q2d_mod/src/Plugin/Block/SitesMap.php b/web/modules/custom/q2d_mod/src/Plugin/Block/SitesMap.php new file mode 100644 index 0000000..88774f5 --- /dev/null +++ b/web/modules/custom/q2d_mod/src/Plugin/Block/SitesMap.php @@ -0,0 +1,113 @@ +getStorage('node') + ->loadByProperties(['type' => 'site', 'status' => 1]); + + $sites_paths = ""; + + $vp_w = 400; + $vp_h = 400; + + // Coordonnées géographiques des coins de la carte (France) + $latTop = 52.0; // Nord-Ouest (coin supérieur gauche) + $lonLeft = -6.0; + $latBottom = 40.0; // Sud-Est (coin inférieur droit) + $lonRight = 11.0; + + + foreach($allSites as $index => $site){ + $title = $site->get('title')->getString(); + $subtitle = $site->get('field_sous_titre')->getString(); + + $link_options = ['absolute' => FALSE, 'attributes' => ['class' => 'site-link']]; + $site_link_object = Link::createFromRoute("voir le site", 'entity.node.canonical', ['node' => $site->id()], $link_options); + $link = $site_link_object->toString()->getGeneratedLink(); + + $datacontent = htmlspecialchars("$title
$subtitle
$link"); + + $geofield = $site->get('field_geofield')->get(0); + $lon = $geofield->lon; + $lat = $geofield->lat; + + $x = round(($lon - $lonLeft) / ($lonRight - $lonLeft) * $vp_w); + $y = round(($latTop - $lat) / ($latTop - $latBottom) * $vp_h); + + $r = 10; + $m = -$r+2; + $l = $r*2-4; + $sites_paths .= << + + + + + + SVGSITEPATH; + } + + + $return = [ + '#cache' => [ + 'max-age' => 0, + ], + 'svg_mapsites' => [ + '#theme' => 'svg_mapsites', + '#sites' => $sites_paths, + '#vpw' => $vp_w, + '#vph' => $vp_h, + '#attached' => [ + 'library' => [ + 'q2d_mod/sites_map_block', + ], + ], + ] + ]; + + return $return; + // return [ + // '#markup' => $this->t('Hello, Sites Map!'), + // ]; + } + public function getCacheMaxAge() { + return 0; + } +} \ No newline at end of file diff --git a/web/modules/custom/q2d_mod/templates/svg-mapsites.html.twig b/web/modules/custom/q2d_mod/templates/svg-mapsites.html.twig new file mode 100644 index 0000000..9985a2c --- /dev/null +++ b/web/modules/custom/q2d_mod/templates/svg-mapsites.html.twig @@ -0,0 +1,50 @@ +
+ {# + + #} + + + + + + + + + + {{ sites|raw }} + + + + + + + + +
\ No newline at end of file