Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FLAG-879] Implement new metadata endpoint #4791

Open
wants to merge 23 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5ac835b
fetch widget metadata from RW API
solomon-negusse Oct 3, 2023
59a34b6
chore(metadata): return logic to set metadata for widgets
willian-viana May 2, 2024
a410ff3
feat(metadata): add new request method to cover metadata for widgets …
willian-viana May 3, 2024
0d2a630
chore(metadata): remove ArcGIS button
willian-viana May 6, 2024
23adfe3
chore(metadata): fix modal component name for the map
willian-viana May 6, 2024
6e58e49
testing new metadata response
willian-viana May 24, 2024
7070b87
feat(metadata): add requests to get the full metadata object
willian-viana Jun 10, 2024
dd78b5b
feat(metadata): improve the parseContent method to convert markdown t…
willian-viana Jun 11, 2024
8bbc258
feat(metadata): avoid merging null properties to metadata object
willian-viana Jun 11, 2024
2984923
feat(metadata): remove hardcoded endpoint
willian-viana Sep 10, 2024
7bf2486
fix(metadata): add string validation to replace markdown
willian-viana Sep 25, 2024
6678fdf
feat(metadata): add safe path validation
willian-viana Sep 25, 2024
e9f2cf5
feat(metadata): add RW API request for external metadatas
willian-viana Sep 25, 2024
5facb77
feat(metadata): improve safePaths and add more metadata to JSON
willian-viana Sep 26, 2024
e51164a
feat(metadata): add markdown lib to replace parse method
willian-viana Oct 3, 2024
47b406d
feat(metadata): add resolution description and validate content_date …
willian-viana Nov 28, 2024
0a5a51e
chore(comment): fix metadata comment
willian-viana Dec 3, 2024
eede9cc
feat(react): Bump react to v18
willian-viana Dec 13, 2024
d696328
feat(markdown): add react-markdown to parse md to html
willian-viana Dec 13, 2024
4a2620a
feat(markdown): improve validation for content date
willian-viana Dec 16, 2024
02382aa
chore(metadata): get back the same metadata order from RW API
willian-viana Dec 17, 2024
1239e3a
chore(metadata): improve validations
willian-viana Dec 17, 2024
71a2c6a
chore(metadata): remove download data
willian-viana Dec 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions components/modals/meta/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,26 @@ export const setModalMetaSettings = createThunkAction('setModalMetaSettings');

export const getModalMetaData = createThunkAction(
'getModalMetaData',
(metaKey) => (dispatch, getState) => {
const { modalMeta } = getState();
if (modalMeta && !modalMeta.loading) {
dispatch(setModalMetaLoading({ loading: true, error: false }));
getMetadata(metaKey)
.then((response) => {
dispatch(setModalMetaData(response.data));
})
.catch(() => {
dispatch(setModalMetaLoading({ loading: false, error: true }));
});
({ metakey, metaType }) =>
(dispatch, getState) => {
const { modalMeta } = getState();

if (modalMeta && !modalMeta.loading) {
dispatch(setModalMetaLoading({ loading: true, error: false }));

getMetadata(metakey, metaType)
.then((response) => {
if (metaType === 'widget') {
dispatch(setModalMetaData(response.data));
} else {
dispatch(setModalMetaData(response.data.metadata));
}
})
.catch(() => {
dispatch(setModalMetaLoading({ loading: false, error: true }));
});
}
}
}
);

export const setModalMetaClosed = createThunkAction(
Expand Down
125 changes: 64 additions & 61 deletions components/modals/meta/component.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { PureComponent } from 'react';
import ReactMarkdown from 'react-markdown';
import rehypeRaw from 'rehype-raw';

import PropTypes from 'prop-types';
import isEmpty from 'lodash/isEmpty';
import lowerCase from 'lodash/lowerCase';
import moment from 'moment';
import ReactHtmlParser from 'react-html-parser';
import { trackEvent } from 'utils/analytics';

import { Button, NoContent } from '@worldresources/gfw-components';
Expand All @@ -15,6 +17,7 @@ class ModalMeta extends PureComponent {
setModalMetaClosed: PropTypes.func,
metaData: PropTypes.object,
getModalMetaData: PropTypes.func,
metaType: PropTypes.string,
metakey: PropTypes.string,
tableData: PropTypes.object,
loading: PropTypes.bool,
Expand All @@ -23,16 +26,16 @@ class ModalMeta extends PureComponent {
};

componentDidMount() {
const { getModalMetaData, metakey } = this.props;
const { getModalMetaData, metakey, metaType } = this.props;
if (metakey) {
getModalMetaData(metakey);
getModalMetaData({ metakey, metaType });
}
}

componentDidUpdate(prevProps) {
const { getModalMetaData, metakey, metaData } = this.props;
const { getModalMetaData, metakey, metaData, metaType } = this.props;
if (metakey && metakey !== prevProps.metakey) {
getModalMetaData(metakey);
getModalMetaData({ metakey, metaType });
}

if (
Expand All @@ -48,24 +51,54 @@ class ModalMeta extends PureComponent {
}
}

/**
* We have 3 different properties to display the content date:
* content_date_description, content_date_range and content_date, in this order of priority
* @returns An object cointaing metadata rows with the correct content_date
*/
setContentDate() {
const {
tableData: {
resolution_description,
content_date_range = {},
content_date_description,
content_date,
...rest
},
} = this.props;

const entries = Object.entries(rest);
const { start_date = null, end_date = null } = content_date_range;

let contentDate = content_date;

if (start_date && end_date) {
contentDate = `${start_date.slice(0, 4)}-${end_date.slice(0, 4)}`;
}

if (content_date_description) {
contentDate = content_date_description;
}

entries.splice(1, 0, ['resolution', resolution_description]);
entries.splice(-2, 0, ['content_date', contentDate]);

return Object.fromEntries(entries);
}

getContent() {
const { metaData, tableData, loading, error, locationName } = this.props;
const {
subtitle,
overview,
citation,
map_service,
learn_more,
download_data,
amazon_link,
} = metaData || {};
const { subtitle, overview, citation, learn_more, download_data } =
metaData || {};

const parsedCitation =
citation &&
citation
.replaceAll('[selected area name]', locationName)
.replaceAll('[date]', moment().format('DD/MM/YYYY'));

const tableDataWithContentDate = this.setContentDate(tableData);

return (
<div className="modal-meta-content">
{error && !loading && (
Expand All @@ -81,16 +114,18 @@ class ModalMeta extends PureComponent {
dangerouslySetInnerHTML={{ __html: subtitle }} // eslint-disable-line
/>
<div className="meta-table element-fullwidth">
{tableData &&
Object.keys(tableData).map((key) =>
tableData[key] ? (
{tableDataWithContentDate &&
Object.keys(tableDataWithContentDate).map((key) =>
tableDataWithContentDate[key] ? (
<div key={key} className="table-row">
<div
className="title-column"
dangerouslySetInnerHTML={{ __html: lowerCase(key) }} // eslint-disable-line
/>
<div className="description-column">
{this.parseContent(tableData[key])}
<ReactMarkdown rehypePlugins={[rehypeRaw]}>
{tableDataWithContentDate[key]}
</ReactMarkdown>
</div>
</div>
) : null
Expand All @@ -99,16 +134,24 @@ class ModalMeta extends PureComponent {
{overview && (
<div className="overview">
<h4>Overview</h4>
<div className="body">{this.parseContent(overview)}</div>
<div className="body">
<ReactMarkdown rehypePlugins={[rehypeRaw]}>
{overview}
</ReactMarkdown>
</div>
</div>
)}
{parsedCitation && (
<div className="citation">
<h5>Citation</h5>
<div className="body">{this.parseContent(parsedCitation)}</div>
<div className="body">
<ReactMarkdown rehypePlugins={[rehypeRaw]}>
{parsedCitation}
</ReactMarkdown>
</div>
</div>
)}
{(learn_more || download_data || map_service || amazon_link) && (
{(learn_more || download_data) && (
<div className="ext-actions">
{learn_more && (
<a
Expand All @@ -119,24 +162,6 @@ class ModalMeta extends PureComponent {
<Button size="medium">LEARN MORE</Button>
</a>
)}
{download_data && (
<a
href={download_data}
target="_blank"
rel="noopener noreferrer"
>
<Button size="medium">DOWNLOAD DATA</Button>
</a>
)}
{(map_service || amazon_link) && (
<a
href={map_service || amazon_link}
target="_blank"
rel="noopener noreferrer"
>
<Button size="medium">OPEN IN ARCGIS</Button>
</a>
)}
</div>
)}
</div>
Expand All @@ -145,28 +170,6 @@ class ModalMeta extends PureComponent {
);
}

parseContent = (html) => {
return (
<div>
{ReactHtmlParser(html, {
transform: (node) =>
node.name === 'a' ? (
<a
key={node.attribs.href}
href={node.attribs.href}
target="_blank"
rel="noopener noreferrer"
>
{node.children[0].data}
</a>
) : (
''
),
})}
</div>
);
};

render() {
const { metakey, setModalMetaClosed, metaData, loading } = this.props;
const { title } = metaData || {};
Expand Down
10 changes: 5 additions & 5 deletions components/modals/meta/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ const META_FIELDS = [
'overview',
'learn_more',
'download_data',
'map_service',
'amazon_link',
];
const TABLE_FIELDS = [
'function',
'resolution',
'resolution_description',
'geographic_coverage',
'source',
'frequency_of_updates',
'date_of_content',
'content_date',
'content_date_description',
'content_date_range',
'update_frequency',
'cautions',
'license',
];
Expand Down
6 changes: 6 additions & 0 deletions data/metadata-exception.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
"places_to_watch",
"nasa_fire_weather",
"waqi_air_quality",
"global_population_jrc"
]
61 changes: 61 additions & 0 deletions data/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
[
"umd_landsat_alerts",
"gfw_integrated_alerts",
"umd_glad_sentinel2_alerts",
"wur_radd_alerts",
"nasa_viirs_fire_alerts",
"umd_tree_cover_loss_from_fires",
"umd_tree_cover_gain_from_height",
"umd_tree_cover_loss",
"gfw_emerging_hot_spots",
"tsc_tree_cover_loss_drivers",
"umd_adm0_net_tree_cover_change_from_height",
"umd_tree_cover_density_2000",
"umd_tree_cover_density_2000",
"wri_tropical_tree_cover",
"wri_tropical_tree_cover",
"umd_regional_primary_forest_2001",
"umd_tree_cover_height_2020",
"wcs_forest_landscape_integrity_index",
"ifl_intact_forest_landscapes",
"esa_land_cover_2015",
"umd_soy_planted_area",
"gfw_planted_forests",
"gfw_peatlands",
"gmw_global_mangrove_extent",
"mapbiomas_bra_land_cover",
"ibge_bra_biomes",
"idn_land_cover_2017",
"gfw_managed_forests",
"gfw_mining_concessions",
"gfw_oil_palm",
"gfw_west_africa_cocoa_plot_density",
"gfw_universal_mill_list",
"rspo_oil_palm",
"gfw_oil_gas",
"gfw_wood_fiber",
"wdpa_protected_areas",
"intl_rivers_dam_hotspots",
"landmark_indigenous_and_community_lands",
"landmark_natural_resource_rights",
"licadho_khm_economic_land_concessions",
"khm_protected_areas",
"haka_idn_leuser",
"idn_forest_area",
"idn_forest_moratorium",
"osinfor_per_forest_concessions",
"osinfor_per_forest_concessions",
"osinfor_peru_permanent_production_forests",
"gfw_forest_carbon_gross_emissions",
"gfw_forest_carbon_net_flux",
"gfw_forest_carbon_gross_removals",
"whrc_aboveground_biomass_stock_2000",
"birdlife_biodiversity_intactness",
"birdlife_biodiversity_significance",
"birdlife_alliance_for_zero_extinction_sites",
"birdlife_key_biodiversity_areas",
"ci_biodiversity_hotspots",
"birdlife_endemic_bird_areas",
"osm_logging_roads",
"per_protected_areas"
]
2 changes: 1 addition & 1 deletion layouts/dashboards/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ class DashboardsPage extends PureComponent {
<MapControls className="map-controls" />
</Desktop>
<Share />
<ModalMeta />
<ModalMeta metaType="widget" />
{widgetAnchor && (
<ScrollTo target={widgetAnchor} afterScroll={clearScrollTo} />
)}
Expand Down
2 changes: 1 addition & 1 deletion layouts/embed/widget/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const WidgetEmbedPage = ({ widget, trase }) => (
<div className={cx('l-embed-widget-page', { '-trase': trase })}>
<Widgets className="embed-widget" embed widget={widget} />
<Share />
<ModalMeta />
<ModalMeta metaType="widget" />
<CountryDataProvider />
<WhitelistsProvider />
<GeodescriberProvider embed />
Expand Down
4 changes: 2 additions & 2 deletions layouts/map/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import MyGFWProvider from 'providers/mygfw-provider';
import MetaProvider from 'providers/meta-provider';

import ModalWelcome from 'components/modals/welcome';
import MetaModal from 'components/modals/meta';
import ModalMeta from 'components/modals/meta';
import ShareModal from 'components/modals/share';
import AreaOfInterestModal from 'components/modals/area-of-interest';
import ClimateModal from 'components/modals/climate';
Expand Down Expand Up @@ -96,7 +96,7 @@ class MainMapComponent extends PureComponent {
)}
<RecentImagery active={recentActive} />
<ShareModal />
<MetaModal />
<ModalMeta metaType="layer" />
<AreaOfInterestModal viewAfterSave clearAfterDelete canDelete />
<ClimateModal />
<FiresModal />
Expand Down
Loading
Loading