Skip to content

Commit bd349bb

Browse files
authored
Merge pull request #149 from gravity-ui/lakate/map-block
feat: add Map-block
2 parents 6fc5543 + 13874f7 commit bd349bb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1270
-90
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ node_modules
1616

1717
*.tgz
1818
.env
19+
.env.development

.storybook/maps.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const ymapApiKeyForStorybook = '536c9fe2-9365-40c1-aedc-f6f21817f82e';
2+
3+
export const scriptsSrc = {
4+
yandex: 'https://api-maps.yandex.ru/2.1',
5+
google: 'https://www.google.com/maps/embed/v1/place',
6+
};

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ interface PageConstructorProviderProps {
4646
metrika?: Metrika; //Functions for sending analytics
4747
ssrConfig?: SSR; //A flag indicating that the code is run on the server size.
4848
theme?: 'light' | 'dark'; //Theme to render the page with.
49+
mapsContext?: MapsContextType; //Params for map: apikey, type, scriptSrc, nonce
4950
}
5051

5152
export interface PageContent extends Animatable {
@@ -211,6 +212,13 @@ import {configure, Lang} from '@gravity-ui/page-constructor';
211212
configure({lang: Lang.En});
212213
```
213214

215+
### Maps
216+
217+
To use maps, put the map type, scriptSrc and apiKey in field `mapContext` in `PageConstructorProvider`.
218+
219+
You can define environment variables for dev-mode in .env.development file within project root.
220+
`STORYBOOK_GMAP_API_KEY` - apiKey for google maps
221+
214222
## Development
215223

216224
```bash

src/blocks/Map/Map.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React from 'react';
2+
3+
import {MapBlockProps} from '../../models';
4+
import Map from '../../components/Map/Map';
5+
import MediaBase from '../../components/MediaBase/MediaBase';
6+
7+
export const MapBlock = ({map, ...props}: MapBlockProps) => (
8+
<MediaBase {...props}>
9+
<MediaBase.Card>
10+
<Map {...map} />
11+
</MediaBase.Card>
12+
</MediaBase>
13+
);
14+
15+
export default MapBlock;

src/blocks/Map/README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Map block
2+
3+
`type: map-block`
4+
5+
`title: string` — Title.
6+
7+
`description: string` — Description.
8+
9+
[`button: Button` — Button](?path=/story/information--common-types&viewMode=docs#button---button)
10+
11+
[`map: Map` — Map description](?path=/story/components-map--y-map&viewMode=docs)
12+
13+
`direction: 'media-content' | 'content-media'` — Relative position of map and content.
14+
15+
`mobileDirection: 'media-content' | 'content-media'` - Relative position of map and content for touch
16+
17+
`largeMedia?: boolean` — An image/video takes 8 columns.
18+
19+
`disableShadow?: boolean` — Disable shadow for the block.
20+
21+
`additionalInfo?: string` — Gray text (with YFM support)
22+
23+
[`links?: Link[]` — An array with link objects](?path=/story/information--common-types&viewMode=docs#link---link)
24+
25+
[`buttons?: Button[]` — An array with button objects](?path=/story/information--common-types&viewMode=docs#button---button)
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
import React from 'react';
2+
import {Meta, Story} from '@storybook/react/types-6-0';
3+
import {yfmTransform} from '../../../../.storybook/utils';
4+
import {ButtonProps, LinkProps, MapBlockModel, MapBlockProps} from '../../../models';
5+
import MapBlock from '../Map';
6+
import {PageConstructor} from '../../../containers/PageConstructor';
7+
import {MapProvider, gmapApiKeyIdInLS} from '../../../context/mapsContext/mapsProvider';
8+
import {MapType} from '../../../context/mapsContext/mapsContext';
9+
import {ApiKeyInput} from '../../../components/Map/__stories__/ApiKeyInput';
10+
import {ymapApiKeyForStorybook, scriptsSrc} from '../../../../.storybook/maps';
11+
12+
import data from './data.json';
13+
14+
export default {
15+
title: 'Blocks/Map',
16+
component: MapBlock,
17+
args: {
18+
largeMedia: false,
19+
mediaOnly: false,
20+
size: 'l',
21+
},
22+
} as Meta;
23+
24+
const DefaultTemplate: Story<MapBlockModel> = (args) => (
25+
<MapProvider
26+
scriptSrc={scriptsSrc[MapType.Yandex]}
27+
apiKey={ymapApiKeyForStorybook}
28+
type={MapType.Yandex}
29+
>
30+
<PageConstructor
31+
content={{
32+
blocks: [
33+
{
34+
...args,
35+
additionalInfo: yfmTransform(data.common.additionalInfo),
36+
map: data.ymap,
37+
},
38+
{
39+
...args,
40+
links: data.common.links as LinkProps[],
41+
map: {
42+
...data.ymap,
43+
id: 'common-places-2',
44+
},
45+
},
46+
{
47+
...args,
48+
buttons: data.common.buttons as ButtonProps[],
49+
map: {
50+
...data.ymap,
51+
id: 'common-places-3',
52+
},
53+
},
54+
],
55+
}}
56+
/>
57+
</MapProvider>
58+
);
59+
60+
const SizeTemplate: Story<MapBlockModel> = (args) => (
61+
<MapProvider
62+
scriptSrc={scriptsSrc[MapType.Yandex]}
63+
apiKey={ymapApiKeyForStorybook}
64+
type={MapType.Yandex}
65+
>
66+
<PageConstructor
67+
content={{
68+
blocks: [
69+
{
70+
...args,
71+
title: data.size.defaultMediaTitle,
72+
map: data.ymap,
73+
},
74+
{
75+
...args,
76+
largeMedia: true,
77+
title: data.size.largeMediaTitle,
78+
map: {
79+
...data.ymap,
80+
id: 'common-places-2',
81+
},
82+
},
83+
{
84+
...args,
85+
mediaOnly: true,
86+
description: undefined,
87+
title: data.size.mediaOnlyTitle,
88+
map: {
89+
...data.ymap,
90+
id: 'common-places-3',
91+
},
92+
},
93+
],
94+
}}
95+
/>
96+
</MapProvider>
97+
);
98+
99+
const DirectionTemplate: Story<MapBlockModel> = (args) => (
100+
<MapProvider
101+
scriptSrc={scriptsSrc[MapType.Yandex]}
102+
apiKey={ymapApiKeyForStorybook}
103+
type={MapType.Yandex}
104+
>
105+
<PageConstructor
106+
content={{
107+
blocks: [
108+
{
109+
...args,
110+
title: data.direction.defaultDirectionTitle,
111+
map: data.ymap,
112+
},
113+
{
114+
...args,
115+
title: data.direction.ReverseDirectionTitle,
116+
direction: 'media-content',
117+
map: {
118+
...data.ymap,
119+
id: 'common-places-2',
120+
},
121+
},
122+
{
123+
...args,
124+
title: data.direction.ReverseDirectionTitle,
125+
mobileDirection: 'media-content',
126+
map: {
127+
...data.ymap,
128+
id: 'common-places-3',
129+
},
130+
},
131+
],
132+
}}
133+
/>
134+
</MapProvider>
135+
);
136+
137+
const GMAP_API_KEY = process.env.STORYBOOK_GMAP_API_KEY;
138+
139+
const MapsTypesTemplate: Story<MapBlockModel> = (args) => (
140+
<>
141+
<MapProvider
142+
scriptSrc={scriptsSrc[MapType.Yandex]}
143+
apiKey={ymapApiKeyForStorybook}
144+
type={MapType.Yandex}
145+
>
146+
<PageConstructor
147+
content={{
148+
blocks: [
149+
{
150+
...args,
151+
title: data.direction.defaultDirectionTitle,
152+
map: data.ymap,
153+
},
154+
],
155+
}}
156+
/>
157+
</MapProvider>
158+
<MapProvider
159+
scriptSrc={scriptsSrc[MapType.Google]}
160+
type={MapType.Google}
161+
apiKey={GMAP_API_KEY}
162+
>
163+
{!GMAP_API_KEY && (
164+
<div style={{maxWidth: '500px', marginLeft: '40px'}}>
165+
<ApiKeyInput id={gmapApiKeyIdInLS} />
166+
</div>
167+
)}
168+
<PageConstructor
169+
content={{
170+
blocks: [
171+
{
172+
...args,
173+
title: data.direction.ReverseDirectionTitle,
174+
direction: 'media-content',
175+
map: data.gmap,
176+
},
177+
],
178+
}}
179+
/>
180+
</MapProvider>
181+
</>
182+
);
183+
184+
export const Default = DefaultTemplate.bind({});
185+
export const Size = SizeTemplate.bind({});
186+
export const Direction = DirectionTemplate.bind({});
187+
export const MapsTypes = MapsTypesTemplate.bind({});
188+
189+
const DefaultArgs = {
190+
...data.default.content,
191+
title: data.common.title,
192+
description: yfmTransform(data.common.description),
193+
map: data.ymap,
194+
};
195+
196+
Default.args = DefaultArgs as MapBlockProps;
197+
198+
Size.args = DefaultArgs as MapBlockProps;
199+
Direction.args = DefaultArgs as MapBlockProps;
200+
201+
MapsTypes.args = DefaultArgs as MapBlockProps;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"common": {
3+
"title": "Lorem ipsum dolor sit",
4+
"description": "**Ut enim ad minim veniam** [quis nostrud](https://example.com) exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
5+
"additionalInfo": "Duis aute irure dolor in [reprehenderit](https://example.com) n voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
6+
"links": [
7+
{
8+
"url": "#",
9+
"text": "Learn more",
10+
"theme": "normal",
11+
"arrow": true
12+
}
13+
],
14+
"buttons": [
15+
{
16+
"text": "Button",
17+
"theme": "action",
18+
"url": "https://example.com"
19+
},
20+
{
21+
"text": "Button",
22+
"theme": "outlined",
23+
"url": "#"
24+
}
25+
]
26+
},
27+
"default": {
28+
"content": {
29+
"type": "map-block"
30+
}
31+
},
32+
"ymap": {
33+
"zoom": 9,
34+
"id": "common-places",
35+
"center": [55.753994, 37.622093],
36+
"markers": [
37+
{
38+
"address": "Moscow Arbat",
39+
"label": {
40+
"preset": "islands#circleIcon"
41+
}
42+
},
43+
{
44+
"coordinate": [55.733974, 37.587093],
45+
"label": {
46+
"iconCaption": "Yandex",
47+
"iconColor": "#3caa3c"
48+
}
49+
}
50+
]
51+
},
52+
"gmap": {
53+
"zoom": 9,
54+
"address": "Anthony Fokkerweg 1, 1059 CM Amsterdam"
55+
},
56+
"size": {
57+
"defaultMediaTitle": "Default map",
58+
"largeMediaTitle": "Large map",
59+
"mediaOnlyTitle": "map Only"
60+
},
61+
"direction": {
62+
"defaultDirectionTitle": "Default Direction",
63+
"ReverseDirectionTitle": "Reverse Direction"
64+
}
65+
}

src/blocks/Map/schema.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {MapProps} from '../../schema/validators/common';
2+
import {MediaBlockBaseProps} from '../Media/schema';
3+
4+
export const Map = {
5+
type: 'object',
6+
additionalProperties: false,
7+
required: [],
8+
properties: MapProps,
9+
};
10+
11+
export const MapBlock = {
12+
'map-block': {
13+
additionalProperties: false,
14+
required: ['title', 'map'],
15+
properties: {
16+
...MediaBlockBaseProps,
17+
map: Map,
18+
},
19+
},
20+
};

0 commit comments

Comments
 (0)