Skip to content

Commit

Permalink
Fix geosolutions-it#10785 Review of footer plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
allyoucanmap committed Feb 19, 2025
1 parent c6957a2 commit f3f9e73
Show file tree
Hide file tree
Showing 32 changed files with 639 additions and 481 deletions.
32 changes: 32 additions & 0 deletions docs/developer-guide/mapstore-migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,38 @@ This is a list of things to check if you want to update from a previous version

## Migration from 2024.02.00 to 2025.01.00

### Footer plugin configuration changes

The Footer plugin has been refactored and some properties have been removed:

- `cfg.logo` is not available anymore in favor of translation html snippet
- translation message identifier `home.footerDescription` is not used anymore in the footer by default

It is possible to replicate the old footer structure for existing project that want to keep the homepage footer information as before with the following configurations:

1. configure the new Footer plugin in localConfig.json as follow:

```js
{
"name": "Footer",
"cfg": {
"hideMenuItems": true,
"customFooter": true,
"customFooterMessageId": "home.footerDescription" // by default is using home.footerCustomHTML
}
}
```

2. update the `home.footerDescription` translation by adding the desired html structure, eg:

```js
{
"home": {
"footerDescription": "<footer class=\"ms-flex-box _flex _flex-center-h _padding-md\"><div> ...my previous message </div></footer>"
}
}
```

### Add TagsManager and Favorite plugins to localConfig.json

The new TagsManager and Favorite plugin should be added inside the plugins `maps` section of the `localConfig.json` to visualize a new menu item in the admin menu and to to visualize the button on the resource cards
Expand Down
32 changes: 10 additions & 22 deletions web/client/configs/localConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,8 @@
"FeedbackMask",
"StyleEditor",
"SidebarMenu",
{ "name": "MapViews" }
{ "name": "MapViews" },
{ "name": "Footer", "cfg": { "containerPosition": "footer" } }
],
"embedded": ["Details", {
"name": "Map",
Expand Down Expand Up @@ -708,24 +709,7 @@
"FeedbackMask"
],
"common": [{
"name": "BrandNavbar",
"cfg": {
"rightMenuItems": [{
"type": "link",
"href": "https://docs.mapstore.geosolutionsgroup.com/",
"target": "blank",
"glyph": "book",
"labelId": "Documentation",
"variant": "default"
}, {
"type": "link",
"href": "https://github.com/geosolutions-it/MapStore2",
"target": "blank",
"label": "GitHub",
"glyph": "github",
"variant": "default"
}]
}
"name": "BrandNavbar"
},
{ "name": "ManagerMenu" },
"Login","Language", "ScrollTop", "Notifications"],
Expand Down Expand Up @@ -845,6 +829,7 @@
}
},
{ "name": "Footer"},
{ "name": "About" },
{
"name": "Cookie",
"cfg": {
Expand Down Expand Up @@ -980,7 +965,8 @@
"cfg": {
"containerPosition": "header"
}
}
},
{ "name": "Footer", "cfg": { "containerPosition": "footer" } }
],
"geostory-embedded": [
"GeoStory",
Expand Down Expand Up @@ -1080,7 +1066,8 @@
}
}
},
"Permalink"
"Permalink",
{ "name": "Footer", "cfg": { "containerPosition": "footer" } }
],
"context-creator": [
{
Expand Down Expand Up @@ -1109,7 +1096,8 @@
"cfg": {
"containerPosition": "header"
}
}
},
{ "name": "Footer", "cfg": { "containerPosition": "footer" } }
],
"manager": ["Header", "Redirect", "Manager", "Home", "UserManager", "GroupManager", "Footer"],
"context-manager": ["Header", "Redirect", "Home", "ContextManager", "Footer"]
Expand Down
202 changes: 192 additions & 10 deletions web/client/plugins/ResourcesCatalog/Footer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,207 @@
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import { createPlugin } from "../../utils/PluginsUtils";
import Menu from './components/Menu';
import Button from './components/Button';
import Spinner from './components/Spinner';
import Icon from './components/Icon';
import HTML from '../../components/I18N/HTML';
import Text from './components/Text';
import Message from '../../components/I18N/Message';
import FlexBox from './components/FlexBox';
import usePluginItems from '../../hooks/usePluginItems';
import { withResizeDetector } from 'react-resize-detector';
function FooterMenuItem({
className,
loading,
glyph,
iconType,
labelId,
onClick,
label
}) {
return (
<li>
<Button
onClick={onClick}
className={className}
>
{loading ? <Spinner /> : <Icon glyph={glyph} type={iconType} />}
{' '}
{labelId ? <Message msgId={labelId} /> : label}
</Button>
</li>
);
}

function Footer({
FooterMenuItem.propTypes = {
className: PropTypes.string,
loading: PropTypes.bool,
glyph: PropTypes.string,
iconType: PropTypes.string,
labelId: PropTypes.string,
onClick: PropTypes.func
};

}) {
FooterMenuItem.defaultProps = {
iconType: 'glyphicon',
onClick: () => { }
};

/**
* This plugin shows the footer
* @memberof plugins
* @class
* @name Footer
* @prop {boolean} cfg.customFooter params that can be used to render a custom html to be used instead of the default one
* @prop {string} cfg.customFooterMessageId replace custom footer translations message identifier
* @prop {object[]} cfg.menuItems list of menu items objects
* @prop {boolean} cfg.hideMenuItems hide menu items menu
* @prop {object[]} items this property contains the items injected from the other plugins,
* using the `containers` option in the plugin that want to inject new menu items.
* ```javascript
* const MyMenuItemComponent = connect(selector, { onActivateTool })(({
* component, // default component that provides a consistent UI (see BrandNavbarMenuItem in BrandNavbar plugin for props)
* variant, // one of style variant (primary, success, danger or warning)
* size, // button size
* className, // custom class name provided by configuration
* onActivateTool, // example of a custom connected action
* }) => {
* const ItemComponent = component;
* return (
* <ItemComponent
* className="my-class-name"
* loading={false}
* glyph="heart"
* iconType="glyphicon"
* labelId="myMessageId"
* onClick={() => onActivateTool()}
* />
* );
* });
* createPlugin(
* 'MyPlugin',
* {
* containers: {
* Footer: {
* name: "TOOLNAME", // a name for the current tool.
* target: 'menu',
* Component: MyMenuItemComponent
* },
* // ...
* ```
* @example
* {
* "name": "Footer",
* "cfg": {
* "menuItems": [
* {
* "type": "link",
* "href": "/my-link",
* "target": "blank",
* "glyph": "heart",
* "labelId": "myMessageId",
* "variant": "default"
* },
* {
* "type": "logo",
* "href": "/my-link",
* "target": "blank",
* "src": "/my-image.jpg",
* "style": {}
* },
* {
* "type": "button",
* "href": "/my-link",
* "target": "blank",
* "glyph": "heart",
* "iconType": "glyphicon",
* "tooltipId": "myMessageId",
* "variant": "default",
* "square": true
* },
* {
* "type": "divider"
* },
* {
* "type": "message",
* "labelId": "myTranslationMessageId"
* }
* ]
* }
* }
*/
function Footer({
menuItems: menuItemsProp,
hideMenuItems,
items,
customFooter,
customFooterMessageId
}, context) {
const { loadedPlugins } = context;
const ref = useRef();
const configuredItems = usePluginItems({ items, loadedPlugins });
const pluginMenuItems = configuredItems.filter(({ target }) => target === 'menu').map(item => ({ ...item, type: 'plugin' }));
const menuItems = [
...menuItemsProp.map((menuItem, idx) => ({ ...menuItem, position: idx + 1 })),
...pluginMenuItems
].sort((a, b) => a.position - b.position);
return (
<div className="ms-footer _padding-tb-lg _padding-lr-md">
<Text textAlign="center">
<HTML msgId="home.footerDescription"/>
</Text>
</div>
<>
{customFooter ? <HTML msgId={customFooterMessageId} /> : null}
{!hideMenuItems || menuItems.length === 0 ? <>
<div style={{ height: ref?.current?.clientHeight }}></div>
<FlexBox ref={ref} component="footer" id="ms-footer" className="ms-footer _padding-xs" centerChildren>
<Menu
centerChildrenVertically
gap="md"
alignRight
wrap
menuItemComponent={FooterMenuItem}
items={menuItems}
/>
</FlexBox>
</> : false}
</>
);
}

Footer.propTypes = {
menuItems: PropTypes.array,
hideMenuItems: PropTypes.bool,
items: PropTypes.array,
customFooter: PropTypes.bool,
customFooterMessageId: PropTypes.string
};

Footer.contextTypes = {
loadedPlugins: PropTypes.object
};

Footer.defaultProps = {
menuItems: [
{
type: 'link',
href: "https://docs.mapstore.geosolutionsgroup.com/",
target: 'blank',
glyph: 'book',
labelId: 'resourcesCatalog.documentation'
},
{
type: 'link',
href: 'https://github.com/geosolutions-it/MapStore2',
target: 'blank',
label: 'GitHub',
glyph: 'github'
}
],
customFooter: false,
customFooterMessageId: 'home.footerCustomHTML'
};


export default createPlugin('Footer', {
component: Footer
component: withResizeDetector(Footer)
});
2 changes: 1 addition & 1 deletion web/client/plugins/ResourcesCatalog/ResourceDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ function ResourceDetails({
targetSelector,
headerNodeSelector = '#ms-brand-navbar',
navbarNodeSelector = '',
footerNodeSelector = '',
footerNodeSelector = '#ms-footer',
width,
height,
show,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ function ResourcesFiltersForm({
targetSelector,
headerNodeSelector = '#ms-brand-navbar',
navbarNodeSelector = '',
footerNodeSelector = '',
footerNodeSelector = '#ms-footer',
width,
height,
user
Expand Down
Loading

0 comments on commit f3f9e73

Please sign in to comment.