Creates geocoordinate-item-metadatum block to have client-side script for displaying maps. #692.

This commit is contained in:
mateuswetah 2022-12-14 11:22:50 -03:00
parent bf28bc96a8
commit e463b935b8
13 changed files with 392 additions and 13 deletions

View File

@ -11,6 +11,7 @@
:zoom-animation="true"
@click="onMapClick"
:options="{
name: 'map--' + itemMetadatumIdentifier,
trackResize: false // We handle this manually in the component
}">
<l-tile-layer

View File

@ -63,19 +63,33 @@ class GeoCoordinate extends Metadata_Type {
$item_metadatum_id .= $metadatum->get_parent() ? ( $metadatum->get_parent() . '_parent_meta_id-') : '';
$return = '';
$return .= '<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css"
integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI="
crossorigin=""/>';
$return .= '<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"
integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM="
crossorigin=""></script>';
$return .= '<script type="text/javascript">
function loadMap() {
map = L.map("map--' . $item_metadatum_id . '").setView([51.505, -0.09], 13);
if ( $item_metadata->is_multiple() ) {
$prefix = $item_metadata->get_multivalue_prefix();
$suffix = $item_metadata->get_multivalue_suffix();
$separator = $item_metadata->get_multivalue_separator();
foreach ( $value as $coordinate ) {
$coordinate_as_array = explode(",", $coordinate);
$latitude = isset($coordinate_as_array[0]) ? $coordinate_as_array[0] : '';
$longitude = isset($coordinate_as_array[1]) ? $coordinate_as_array[1] : '';
$single_value = "<span class='tainacan-coordinates' data-latitude='{$latitude}' data-longitude='{$longitude}'><span>{$latitude}</span><span class='coordinates-separator'>,</span><span>{$longitude}</span></span>";
$return .= empty($return)
? $prefix . $single_value . $suffix
: $separator . $prefix . $single_value . $suffix;
}
loadMap();
</script>';
$return .= '<div data-module="tainacan-maps" id="map--' . $item_metadatum_id . '" style="height: 320px; width:100%; border: 1px solid var(--tainacan-input-border-color, #dbdbdb);"></div/>';
return $return;
} else {
$coordinate_as_array = explode(",", $value);
$latitude = isset($coordinate_as_array[0]) ? $coordinate_as_array[0] : '';
$longitude = isset($coordinate_as_array[1]) ? $coordinate_as_array[1] : '';
$return .= "<span class='tainacan-coordinates' data-latitude='{$latitude}' data-longitude='{$longitude}'><span>{$latitude}</span><span class='coordinates-separator'>,</span><span>{$longitude}</span></span>";
}
return '<span id="tainacan-geocoordinatemetadatum--' . $item_metadatum_id . '" data-module="geocoordinate-item-metadatum">
' . $return . '
</span>';
}
}

View File

@ -0,0 +1,55 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"name": "tainacan/geocoorinate-item-metadatum",
"title": "Tainacan Geo Coordinate Item Metadatum",
"apiVersion": 2,
"category": "tainacan-blocks",
"keywords": [ "item", "location", "geographic", "coordinates", "metadatum", "field", "value" ],
"description": "A single item geographic metadatum, containing location information.",
"textdomain": "tainacan",
"parent": [],
"example": {
"attributes": {
"content": "preview"
}
},
"attributes": {
"content": {
"type": "array",
"source": "query",
"selector": "div"
},
"dataSource": {
"type": "string",
"default": "selection"
},
"templateMode": {
"type": "boolean",
"default": false
},
"collectionId": {
"type": "integer"
},
"itemId": {
"type": "integer"
},
"metadatumId": {
"type": "integer"
},
"isModalOpen": {
"type": "boolean",
"default": false
}
},
"usesContext": [
"tainacan/itemId"
],
"supports": {
"align": ["full", "wide"],
"multiple": true,
"html": true,
"anchor": true
},
"editorScript": "geocoordinate-item-metadatum",
"editorStyle": "geocoordinate-item-metadatum"
}

View File

@ -0,0 +1 @@
export default [];

View File

@ -0,0 +1,165 @@
const { __ } = wp.i18n;
const { Button, Placeholder, ToolbarDropdownMenu, SVG, Path } = wp.components;
const ServerSideRender = wp.serverSideRender;
const { useBlockProps, BlockControls, AlignmentControl } = (tainacan_blocks.wp_version < '5.2' ? wp.editor : wp.blockEditor );
import SingleItemMetadatumModal from '../../js/selection/single-item-metadatum-modal.js';
import TainacanBlocksCompatToolbar from '../../js/compatibility/tainacan-blocks-compat-toolbar.js';
import getCollectionIdFromPossibleTemplateEdition from '../../js/template/tainacan-blocks-single-item-template-mode.js';
export default function ({ attributes, setAttributes, className, isSelected }) {
let {
content,
collectionId,
itemId,
metadatumId,
metadatumType,
isModalOpen,
dataSource,
templateMode,
} = attributes;
// Gets blocks props from hook
const blockProps = tainacan_blocks.wp_version < '5.6' ? { className: className } : useBlockProps( {
className: {
[ `has-text-align-${ textAlign }` ]: textAlign,
}
} );
const currentWPVersion = (typeof tainacan_blocks != 'undefined') ? tainacan_blocks.wp_version : tainacan_plugin.wp_version;
// Checks if we are in template mode, if so, gets the collection Id from URL.
if ( !templateMode ) {
const possibleCollectionId = getCollectionIdFromPossibleTemplateEdition();
if (possibleCollectionId) {
collectionId = possibleCollectionId;
templateMode = true
setAttributes({
collectionId: collectionId,
templateMode: templateMode
});
}
}
return content == 'preview' ?
<div className={className}>
<img
width="100%"
src={ `${tainacan_blocks.base_url}/assets/images/related-carousel-items.png` } />
</div>
: (
<div { ...blockProps }>
{ dataSource == 'selection' ? (
<BlockControls group="other">
{
TainacanBlocksCompatToolbar({
label: templateMode ? __('Select metadatum', 'tainacan') : __('Select item metadatum', 'tainacan'),
icon: <svg
xmlns="http://www.w3.org/2000/svg"
viewBox="-2 -2 24 24"
height="24px"
width="24px">
<path d="m 6,3.9960001 h 5.016 c 0.544,0 1.008,0.192 1.392,0.576 L 19.416,11.58 c 0.384,0.384 0.576,0.856 0.576,1.416 0,0.56 -0.192,1.032 -0.576,1.416 l -4.992,4.992 c -0.176,0.176 -0.392,0.32 -0.648,0.432 -0.24,0.112 -0.496,0.168 -0.768,0.168 -0.272,0 -0.536,-0.056 -0.792,-0.168 -0.24,-0.112 -0.448,-0.256 -0.624,-0.432 L 4.608,12.42 c -0.4,-0.4 -0.6,-0.872 -0.6,-1.416 V 5.988 C 4.008,5.428 4.2,4.956 4.584,4.572 4.968,4.188 5.44,3.996 6,3.9960001 Z m 1.512,4.992 c 0.416,0 0.768,-0.144 1.056,-0.432 C 8.856,8.2680001 9,7.916 9,7.5 9,7.084 8.856,6.732 8.568,6.444 8.28,6.14 7.928,5.988 7.512,5.988 7.096,5.988 6.736,6.14 6.432,6.444 6.144,6.732 6,7.084 6,7.5 c 0,0.416 0.144,0.7680001 0.432,1.0560001 0.304,0.288 0.664,0.432 1.08,0.432 z"/>
</svg>,
onClick: () => {
isModalOpen = true;
setAttributes( {
isModalOpen: isModalOpen
});
}
})
}
</BlockControls>
): null
}
{ isSelected ?
(
<div>
{ isModalOpen ?
<SingleItemMetadatumModal
modalTitle={ templateMode ? __('Select one metadatum', 'tainacan') : __('Select one item to render its metadata', 'tainacan') }
existingCollectionId={ collectionId }
existingItemId={ itemId }
existingMetadatumId={ metadatumId }
isTemplateMode={ templateMode }
onSelectCollection={ (selectedCollectionId) => {
collectionId = selectedCollectionId;
setAttributes({
collectionId: collectionId
});
}}
onSelectItem={ (selectedItemId) => {
itemId = selectedItemId;
setAttributes({
itemId: itemId
});
}}
onApplySelectedMetadatum={ (selectedMetadatum) => {
metadatumId = selectedMetadatum.metadatumId;
metadatumType = selectedMetadatum.metadatumType;
setAttributes({
metadatumId: metadatumId,
metadatumType: metadatumType,
isModalOpen: false
});
}}
onCancelSelection={ () => setAttributes({ isModalOpen: false }) }/>
: null
}
</div>
) : null
}
{ dataSource == 'selection' && !(collectionId && (templateMode || itemId) && metadatumId) ? (
<Placeholder
className="tainacan-block-placeholder"
icon={(
<img
width={148}
src={ `${tainacan_blocks.base_url}/assets/images/tainacan_logo_header.svg` }
alt="Tainacan Logo"/>
)}>
<p>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="-2 -2 24 24"
height="24px"
width="24px">
<path d="m 6,3.9960001 h 5.016 c 0.544,0 1.008,0.192 1.392,0.576 L 19.416,11.58 c 0.384,0.384 0.576,0.856 0.576,1.416 0,0.56 -0.192,1.032 -0.576,1.416 l -4.992,4.992 c -0.176,0.176 -0.392,0.32 -0.648,0.432 -0.24,0.112 -0.496,0.168 -0.768,0.168 -0.272,0 -0.536,-0.056 -0.792,-0.168 -0.24,-0.112 -0.448,-0.256 -0.624,-0.432 L 4.608,12.42 c -0.4,-0.4 -0.6,-0.872 -0.6,-1.416 V 5.988 C 4.008,5.428 4.2,4.956 4.584,4.572 4.968,4.188 5.44,3.996 6,3.9960001 Z m 1.512,4.992 c 0.416,0 0.768,-0.144 1.056,-0.432 C 8.856,8.2680001 9,7.916 9,7.5 9,7.084 8.856,6.732 8.568,6.444 8.28,6.14 7.928,5.988 7.512,5.988 7.096,5.988 6.736,6.14 6.432,6.444 6.144,6.732 6,7.084 6,7.5 c 0,0.416 0.144,0.7680001 0.432,1.0560001 0.304,0.288 0.664,0.432 1.08,0.432 z"/>
</svg>
{__('Select an item metadata to display its label and value.', 'tainacan')}
</p>
<Button
isPrimary
type="button"
onClick={ () => {
isModalOpen = true;
setAttributes( {
isModalOpen: isModalOpen
});
}
}>
{__('Select Item Metadatum', 'tainacan')}
</Button>
</Placeholder>
) : null
}
{ (collectionId && (itemId || templateMode) && metadatumId) ? (
<div className={ 'item-metadatum-edit-container' }>
<ServerSideRender
block="tainacan/item-metadatum"
attributes={ attributes }
httpMethod={ currentWPVersion >= '5.5' ? 'POST' : 'GET' }
/>
</div>
) : null
}
</div>
);
};

View File

@ -0,0 +1,14 @@
const { SVG, Path } = wp.components;
export default (
<SVG
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
height="24px"
width="24px">
<Path
d="m 6,3.9960001 h 5.016 c 0.544,0 1.008,0.192 1.392,0.576 L 19.416,11.58 c 0.384,0.384 0.576,0.856 0.576,1.416 0,0.56 -0.192,1.032 -0.576,1.416 l -4.992,4.992 c -0.176,0.176 -0.392,0.32 -0.648,0.432 -0.24,0.112 -0.496,0.168 -0.768,0.168 -0.272,0 -0.536,-0.056 -0.792,-0.168 -0.24,-0.112 -0.448,-0.256 -0.624,-0.432 L 4.608,12.42 c -0.4,-0.4 -0.6,-0.872 -0.6,-1.416 V 5.988 C 4.008,5.428 4.2,4.956 4.584,4.572 4.968,4.188 5.44,3.996 6,3.9960001 Z m 1.512,4.992 c 0.416,0 0.768,-0.144 1.056,-0.432 C 8.856,8.2680001 9,7.916 9,7.5 9,7.084 8.856,6.732 8.568,6.444 8.28,6.14 7.928,5.988 7.512,5.988 7.096,5.988 6.736,6.14 6.432,6.444 6.144,6.732 6,7.084 6,7.5 c 0,0.416 0.144,0.7680001 0.432,1.0560001 0.304,0.288 0.664,0.432 1.08,0.432 z"
/>
</SVG>
);

View File

@ -0,0 +1,15 @@
import tainacanRegisterBlockType from '../../js/compatibility/tainacan-blocks-compat-register.js';
import metadata from './block.json';
import icon from './icon.js';
import edit from './edit.js';
import save from './save.js';
import deprecated from './deprecated.js';
tainacanRegisterBlockType({
metadata,
icon,
edit,
save,
deprecated
});

View File

@ -0,0 +1,3 @@
export default function() {
return null
};

View File

@ -0,0 +1,51 @@
<?php
/**
* Renders the content of the item metadata block
* using Tainacan template functions
*/
function tainacan_blocks_render_geocoordinate_item_metadatum( $block_attributes, $content, $block ) {
// Basic check, otherwise we don't have nothing to render here.
$item_id = !empty($block->context['tainacan/itemId']) ? $block->context['tainacan/itemId'] : (isset($block_attributes['itemId']) ? $block_attributes['itemId'] : false);
$metadatum_id = isset($block_attributes['metadatumId']) ? $block_attributes['metadatumId'] : false;
$collection_id = isset($block_attributes['collectionId']) ? $block_attributes['collectionId'] : false;
$data_source = isset($block_attributes['dataSource']) ? $block_attributes['dataSource'] : 'parent';
$template_mode = isset($block_attributes['templateMode']) ? $block_attributes['templateMode'] : false;
if ( !$metadatum_id )
return '';
// Builds args from backend query
$args = array(
'metadata' => $metadatum_id,
'before_title' => '<h3 class="wp-block-tainacan-item-metadatum__metadatum-label">',
'after_title' => '</h3>',
'before_value' => '<p class="wp-block-tainacan-item-metadatum__metadatum-value">',
'after_value' => '</p>'
);
// Classes from block and Text alignment
$wrapper_attributes = get_block_wrapper_attributes(
array(
'class' => 'metadata-type-$type',
)
);
$args['before'] = '<div ' . $wrapper_attributes . '>';
$args['after'] = '</div>';
if ( $template_mode && $collection_id ) {
// Checks if we are in the edit page or in the published
$current_post = get_post();
$collection_pt_pattern = '/' . \Tainacan\Entities\Collection::$db_identifier_prefix . '\d+' . \Tainacan\Entities\Collection::$db_identifier_sufix . '/';
if ( $current_post === NULL )
return '<div>Map Demo</div>';
else if ( $current_post->post_type !== false && preg_match($collection_pt_pattern, $current_post->post_type) ) {
return tainacan_get_the_metadata( $args, $current_post->ID );
}
} else if ( $item_id ) {
return tainacan_get_the_metadata( $args, $item_id );
}
}

View File

@ -0,0 +1,5 @@
.tainacan-leaflet-map-container {
display: block;
height: 320px;
width:100%;
}

View File

@ -0,0 +1,53 @@
// TAINACAN LEAFLET MAP COMPONENT --------------------------------------------------------
//
// Counts on some HMTL markup to instantiate some leaflet maps
import * as TainacanLeaflet from "leaflet";
import 'leaflet/dist/leaflet.css';
import iconUrl from 'leaflet/dist/images/marker-icon.png';
import iconRetinaUrl from 'leaflet/dist/images/marker-icon-2x.png';
import shadowUrl from 'leaflet/dist/images/marker-shadow.png';
delete TainacanLeaflet.Icon.Default.prototype._getIconUrl;
TainacanLeaflet.Icon.Default.mergeOptions({
iconRetinaUrl: iconRetinaUrl,
iconUrl: iconUrl,
shadowUrl: shadowUrl
});
/* Loads and instantiates map components passed to data-module="geocoordinate-item-metadatum"*/
export default (element) => {
if (element && element.id) {
const children = element.children ? element.children : [];
if ( !children.length )
return;
const coordinates = [];
for (let i = 0; i < children.length; i++) {
if ( children[i].hasAttribute('data-latitude') && children[i].hasAttribute('data-longitude') )
coordinates.push([children[i].getAttribute('data-latitude'), children[i].getAttribute('data-longitude')]);
}
if ( !coordinates.length )
return;
// Sets basic css that should be here only if this javascript is loaded.
element.classList.add('tainacan-leaflet-map-container');
element.style.setProperty('height', '320px');
element.style.setProperty('width', '100%');
element.style.setProperty('display', 'block');
var tainacanMap = TainacanLeaflet.map(element.id).setView([-14.4086569, -51.31668], 5);
TainacanLeaflet.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
})
.addTo(tainacanMap);
coordinates.forEach(coordinate => {
TainacanLeaflet.marker(coordinate).addTo(tainacanMap);
});
tainacanMap.panInsideBounds(coordinates);
}
};

View File

@ -21,6 +21,7 @@ const TAINACAN_BLOCKS = [
'item-metadata-section' => ['render_callback' => 'tainacan_blocks_render_metadata_section'],
'item-metadata' => ['render_callback' => 'tainacan_blocks_render_item_metadata'],
'item-metadatum' => ['render_callback' => 'tainacan_blocks_render_item_metadatum'],
'geocoordinate-item-metadatum' => ['render_callback' => 'tainacan_blocks_render_geocoordinate_item_metadatum'],
'metadata-section-name' => [],
'metadata-section-description' => []
];

View File

@ -27,6 +27,7 @@ module.exports = {
block_item_metadata_section: './src/views/gutenberg-blocks/blocks/item-metadata-section/index.js',
block_item_metadata: './src/views/gutenberg-blocks/blocks/item-metadata/index.js',
block_item_metadatum: './src/views/gutenberg-blocks/blocks/item-metadatum/index.js',
block_geocoordinate_item_metadatum: './src/views/gutenberg-blocks/blocks/geocoordinate-item-metadatum/index.js',
block_metadata_section_name: './src/views/gutenberg-blocks/blocks/metadata-section-name/index.js',
block_metadata_section_description: './src/views/gutenberg-blocks/blocks/metadata-section-description/index.js'
},