@eeacms/volto-clms-theme 1.0.206 → 1.0.208
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -2
- package/package.json +1 -1
- package/src/components/Blocks/CclFAQBlock/CclFAQBlockView.jsx +83 -156
- package/src/components/CclTab/CclTabs.jsx +10 -0
- package/src/components/Widgets/DownloadableFilesTableWidget.jsx +53 -33
- package/src/components/Widgets/SchemaCreatorWidget.jsx +7 -4
- package/theme/clms/css/volto-block-style-override.css +4 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,11 +4,19 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
-
### [1.0.
|
|
7
|
+
### [1.0.208](https://github.com/eea/volto-clms-theme/compare/1.0.207...1.0.208) - 19 May 2023
|
|
8
|
+
|
|
9
|
+
#### :hammer_and_wrench: Others
|
|
10
|
+
|
|
11
|
+
- feat CLMS-2185 block chooser padding fix [Unai - [`2809c9f`](https://github.com/eea/volto-clms-theme/commit/2809c9ff01e6f9acd35f03c3f5aa903d689b4ed0)]
|
|
12
|
+
### [1.0.207](https://github.com/eea/volto-clms-theme/compare/1.0.206...1.0.207) - 19 May 2023
|
|
8
13
|
|
|
9
14
|
#### :hammer_and_wrench: Others
|
|
10
15
|
|
|
11
|
-
-
|
|
16
|
+
- refactor FAQ block view. Small modification done for CclTabs to set active the second tab if the first is a parent tab [ionlizarazu - [`e79f44f`](https://github.com/eea/volto-clms-theme/commit/e79f44f93444fe38ce5209c94cfbc00775e5c124)]
|
|
17
|
+
- CLMS-2024 empty columns and export order for Downloadable File [ionlizarazu - [`4f289f8`](https://github.com/eea/volto-clms-theme/commit/4f289f87d1dd0b91102579ef1b4fcf7796aba801)]
|
|
18
|
+
### [1.0.206](https://github.com/eea/volto-clms-theme/compare/1.0.205...1.0.206) - 18 May 2023
|
|
19
|
+
|
|
12
20
|
### [1.0.205](https://github.com/eea/volto-clms-theme/compare/1.0.204...1.0.205) - 17 May 2023
|
|
13
21
|
|
|
14
22
|
### [1.0.204](https://github.com/eea/volto-clms-theme/compare/1.0.203...1.0.204) - 17 May 2023
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import AnimateHeight from 'react-animate-height';
|
|
3
3
|
import { useDispatch, useSelector } from 'react-redux';
|
|
4
4
|
import { Accordion, Segment } from 'semantic-ui-react';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { getContextNavigation } from '@plone/volto/actions';
|
|
7
7
|
import { Icon, UniversalLink } from '@plone/volto/components';
|
|
8
8
|
import RenderBlocks from '@plone/volto/components/theme/View/RenderBlocks';
|
|
9
9
|
import { hasBlocksData } from '@plone/volto/helpers';
|
|
@@ -16,8 +16,8 @@ const CclFAQBlockView = (props) => {
|
|
|
16
16
|
const { isEditMode } = props;
|
|
17
17
|
const dispatch = useDispatch();
|
|
18
18
|
const path = useSelector((state) => state.router.location.pathname);
|
|
19
|
-
const
|
|
20
|
-
const
|
|
19
|
+
const contextNavigation = useSelector((state) => state.contextNavigation);
|
|
20
|
+
const cn_key = `${path.replace('/edit', '')}/@contextnavigation`;
|
|
21
21
|
const handleClick = ({ index }) => {
|
|
22
22
|
const newIndex =
|
|
23
23
|
activeIndex.indexOf(index) === -1
|
|
@@ -26,181 +26,108 @@ const CclFAQBlockView = (props) => {
|
|
|
26
26
|
|
|
27
27
|
setActiveIndex(newIndex);
|
|
28
28
|
};
|
|
29
|
+
|
|
30
|
+
const flattenCN = (cn_items) => {
|
|
31
|
+
return cn_items.reduce((prev, curr) => {
|
|
32
|
+
prev.push(curr);
|
|
33
|
+
if (curr.items.filter((i) => i.type === 'document').length > 0) {
|
|
34
|
+
curr.items
|
|
35
|
+
.filter((i) => i.type === 'document')
|
|
36
|
+
.forEach((i_i) => prev.push({ ...i_i, isSubtab: true }));
|
|
37
|
+
}
|
|
38
|
+
return prev;
|
|
39
|
+
}, []);
|
|
40
|
+
};
|
|
41
|
+
const flatCN = flattenCN(
|
|
42
|
+
contextNavigation?.[cn_key]?.data?.items
|
|
43
|
+
? contextNavigation?.[cn_key]?.data?.items.filter(
|
|
44
|
+
(i) => i.type === 'document',
|
|
45
|
+
)
|
|
46
|
+
: [],
|
|
47
|
+
);
|
|
48
|
+
const [activeIndex, setActiveIndex] = useState([0]);
|
|
29
49
|
React.useEffect(() => {
|
|
30
|
-
dispatch(
|
|
31
|
-
searchContent(
|
|
32
|
-
path.replace('/edit', ''),
|
|
33
|
-
{
|
|
34
|
-
fullobjects: 1,
|
|
35
|
-
portal_type: 'FAQ',
|
|
36
|
-
b_size: 999,
|
|
37
|
-
sort_on: 'getObjPositionInParent',
|
|
38
|
-
},
|
|
39
|
-
search_key,
|
|
40
|
-
),
|
|
41
|
-
);
|
|
50
|
+
dispatch(getContextNavigation(path.replace('/edit', '')));
|
|
42
51
|
}, [path, dispatch]);
|
|
43
|
-
|
|
44
|
-
if (search?.subrequests?.[search_key]?.loaded) {
|
|
45
|
-
const firstOfCategories = categories.map((cat, key, self) => {
|
|
46
|
-
const cat_indexes = search?.subrequests?.[search_key]?.items.reduce(
|
|
47
|
-
(filtered, item, index) => {
|
|
48
|
-
if (filtered.UID) {
|
|
49
|
-
filtered = [];
|
|
50
|
-
}
|
|
51
|
-
if (
|
|
52
|
-
item.taxonomy_faqcategories.filter(
|
|
53
|
-
(item_cat) =>
|
|
54
|
-
item_cat.title && item_cat.title.includes(cat.title),
|
|
55
|
-
).length > 0
|
|
56
|
-
) {
|
|
57
|
-
if (index === 1) {
|
|
58
|
-
filtered.push(0);
|
|
59
|
-
} else {
|
|
60
|
-
filtered.push(index);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return filtered;
|
|
64
|
-
},
|
|
65
|
-
);
|
|
66
|
-
return cat_indexes.length > 0 ? cat_indexes[0] : 0;
|
|
67
|
-
});
|
|
68
|
-
setActiveIndex(firstOfCategories);
|
|
69
|
-
}
|
|
70
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
71
|
-
}, [search?.subrequests]);
|
|
72
|
-
let categories =
|
|
73
|
-
search?.subrequests &&
|
|
74
|
-
search?.subrequests?.[search_key] &&
|
|
75
|
-
search?.subrequests?.[search_key]?.loaded &&
|
|
76
|
-
search?.subrequests?.[search_key]?.items.length > 0
|
|
77
|
-
? [
|
|
78
|
-
...new Set(
|
|
79
|
-
search?.subrequests?.[search_key]?.items
|
|
80
|
-
.map((item) => item.taxonomy_faqcategories)
|
|
81
|
-
.flat(),
|
|
82
|
-
),
|
|
83
|
-
]
|
|
84
|
-
.map((cat) => {
|
|
85
|
-
if (cat.title) {
|
|
86
|
-
const cat_family = cat.title?.split(' » ');
|
|
87
|
-
if (cat_family && cat_family.length > 1) {
|
|
88
|
-
cat['subTab'] = true;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return cat;
|
|
92
|
-
})
|
|
93
|
-
.filter(
|
|
94
|
-
(thing, index, self) =>
|
|
95
|
-
index === self.findIndex((t) => t.token === thing.token),
|
|
96
|
-
)
|
|
97
|
-
.sort((a, b) => {
|
|
98
|
-
if (a.title < b.title) {
|
|
99
|
-
return -1;
|
|
100
|
-
} else if (a.title > b.title) {
|
|
101
|
-
return 1;
|
|
102
|
-
}
|
|
103
|
-
return 0;
|
|
104
|
-
})
|
|
105
|
-
: [];
|
|
106
|
-
categories.forEach((cat, index) => {
|
|
107
|
-
if (cat.subTab && !categories[index - 1].subTab) {
|
|
108
|
-
categories[index - 1]['parent'] = true;
|
|
109
|
-
}
|
|
110
|
-
});
|
|
52
|
+
|
|
111
53
|
const titleIcons = config.blocks?.blocksConfig?.accordion?.titleIcons;
|
|
112
54
|
|
|
113
|
-
const [activeIndex, setActiveIndex] = React.useState([0]);
|
|
114
55
|
return (
|
|
115
56
|
<div id="faq-listing" className="ccl-container tab-container">
|
|
116
|
-
{
|
|
117
|
-
|
|
118
|
-
categories.length > 0 && (
|
|
57
|
+
{contextNavigation?.[cn_key]?.loaded ? (
|
|
58
|
+
contextNavigation?.[cn_key]?.data?.items?.length > 0 && (
|
|
119
59
|
<CclTabs routing={true}>
|
|
120
|
-
{
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (cat.title) {
|
|
124
|
-
cat_family = cat.title.split(' » ');
|
|
125
|
-
cat_title =
|
|
126
|
-
cat_family.length > 1
|
|
127
|
-
? cat_family[1].split('#')[1]
|
|
128
|
-
: cat_family[0].split('#')[1];
|
|
129
|
-
}
|
|
130
|
-
return (
|
|
60
|
+
{flatCN
|
|
61
|
+
.filter((cn) => cn.type === 'document')
|
|
62
|
+
.map((cn, key) => (
|
|
131
63
|
<div
|
|
132
64
|
key={key}
|
|
133
|
-
tabTitle={
|
|
134
|
-
className={
|
|
135
|
-
|
|
65
|
+
tabTitle={cn.title}
|
|
66
|
+
className={
|
|
67
|
+
cn.isSubtab
|
|
68
|
+
? 'subcard'
|
|
69
|
+
: cn.items.filter((i) => i.type === 'document').length > 0
|
|
70
|
+
}
|
|
71
|
+
parent={
|
|
72
|
+
cn.items.filter((i) => i.type === 'document').length > 0
|
|
73
|
+
}
|
|
136
74
|
>
|
|
137
75
|
<div className="accordion-block">
|
|
138
|
-
{
|
|
139
|
-
(item
|
|
76
|
+
{cn.items
|
|
77
|
+
.filter((item) => item.type === 'faq')
|
|
78
|
+
.map((item, item_key) => {
|
|
140
79
|
return (
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
80
|
+
<Accordion fluid styled key={item_key}>
|
|
81
|
+
<Accordion.Title
|
|
82
|
+
as={'h2'}
|
|
83
|
+
onClick={() => handleClick({ index: item_key })}
|
|
84
|
+
className={'accordion-title align-arrow-right'}
|
|
85
|
+
>
|
|
86
|
+
{activeIndex.includes(item_key) ? (
|
|
87
|
+
<Icon name={titleIcons.opened.rightPosition} />
|
|
88
|
+
) : (
|
|
89
|
+
<Icon name={titleIcons.closed.rightPosition} />
|
|
90
|
+
)}
|
|
91
|
+
{isEditMode && (
|
|
92
|
+
<UniversalLink
|
|
93
|
+
openLinkInNewTab={true}
|
|
94
|
+
href={`${item['@id']}/edit`}
|
|
95
|
+
>
|
|
157
96
|
<Icon
|
|
158
|
-
name={
|
|
97
|
+
name={penSVG}
|
|
98
|
+
className="circled"
|
|
99
|
+
title={'Edit'}
|
|
159
100
|
/>
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
</UniversalLink>
|
|
172
|
-
)}
|
|
173
|
-
<span>{item.title}</span>
|
|
174
|
-
</Accordion.Title>
|
|
175
|
-
<Accordion.Content
|
|
176
|
-
active={activeIndex.includes(item_key)}
|
|
101
|
+
</UniversalLink>
|
|
102
|
+
)}
|
|
103
|
+
<span>{item.title}</span>
|
|
104
|
+
</Accordion.Title>
|
|
105
|
+
<Accordion.Content
|
|
106
|
+
active={activeIndex.includes(item_key)}
|
|
107
|
+
>
|
|
108
|
+
<AnimateHeight
|
|
109
|
+
animateOpacity
|
|
110
|
+
duration={500}
|
|
111
|
+
height={'auto'}
|
|
177
112
|
>
|
|
178
|
-
<
|
|
179
|
-
animateOpacity
|
|
180
|
-
duration={500}
|
|
181
|
-
height={'auto'}
|
|
182
|
-
>
|
|
183
|
-
{/* <StringToHTML
|
|
113
|
+
{/* <StringToHTML
|
|
184
114
|
string={item.text ? item.text.data : ''}
|
|
185
115
|
/> */}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
)
|
|
116
|
+
{hasBlocksData(item) && (
|
|
117
|
+
<RenderBlocks content={item} />
|
|
118
|
+
)}
|
|
119
|
+
</AnimateHeight>
|
|
120
|
+
</Accordion.Content>
|
|
121
|
+
</Accordion>
|
|
193
122
|
);
|
|
194
|
-
}
|
|
195
|
-
)}
|
|
123
|
+
})}
|
|
196
124
|
</div>
|
|
197
125
|
</div>
|
|
198
|
-
)
|
|
199
|
-
})}
|
|
126
|
+
))}
|
|
200
127
|
</CclTabs>
|
|
201
128
|
)
|
|
202
129
|
) : (
|
|
203
|
-
<Segment loading={
|
|
130
|
+
<Segment loading={contextNavigation?.[cn_key]?.loading}></Segment>
|
|
204
131
|
)}
|
|
205
132
|
</div>
|
|
206
133
|
);
|
|
@@ -38,6 +38,16 @@ const CclTabs = (props) => {
|
|
|
38
38
|
setActiveTab(slugify(firstTab.props?.tabTitle));
|
|
39
39
|
} else if (hash) {
|
|
40
40
|
setActiveTab(hash);
|
|
41
|
+
} else if (
|
|
42
|
+
children.filter((item) => !!item?.props?.tabTitle).length > 1 &&
|
|
43
|
+
firstTab.props?.parent
|
|
44
|
+
) {
|
|
45
|
+
setActiveTab(
|
|
46
|
+
slugify(
|
|
47
|
+
children.filter((item) => !!item?.props?.tabTitle)[1].props
|
|
48
|
+
?.tabTitle,
|
|
49
|
+
),
|
|
50
|
+
);
|
|
41
51
|
} else {
|
|
42
52
|
setActiveTab(slugify(firstTab.props?.tabTitle));
|
|
43
53
|
}
|
|
@@ -6,6 +6,41 @@ import CclButton from '../CclButton/CclButton';
|
|
|
6
6
|
import { Segment, Loader, Header, Divider } from 'semantic-ui-react';
|
|
7
7
|
import './DownloadableFilesTableWidget.less';
|
|
8
8
|
|
|
9
|
+
const orderKeysBy = (array, data) => {
|
|
10
|
+
if (data) {
|
|
11
|
+
return JSON.stringify(
|
|
12
|
+
array.reduce((obj, key) => {
|
|
13
|
+
obj[key] = data[key] || '';
|
|
14
|
+
return obj;
|
|
15
|
+
}, {}),
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
return {};
|
|
19
|
+
};
|
|
20
|
+
const deleteNotExistingColumnsData = (props, schema, uiSchema) => {
|
|
21
|
+
const { id, value } = props;
|
|
22
|
+
const validFields = ['@id', ...Object.keys(schema?.properties)];
|
|
23
|
+
for (let i in value?.items) {
|
|
24
|
+
Object.keys(value?.items[i]).forEach((k) => {
|
|
25
|
+
if (!validFields.includes(k)) {
|
|
26
|
+
delete value?.items[i][k];
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
props.onChange(id, {
|
|
31
|
+
items: value.items,
|
|
32
|
+
schema,
|
|
33
|
+
uiSchema,
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const fixSchema = (schema) => {
|
|
38
|
+
schema.properties = Object.fromEntries(
|
|
39
|
+
Object.entries(schema.properties).filter(([k, v]) => v != null && k),
|
|
40
|
+
);
|
|
41
|
+
schema.fieldsets[0].fields = schema.fieldsets[0].fields.filter((f) => f);
|
|
42
|
+
};
|
|
43
|
+
|
|
9
44
|
const DownloadableFilesTableWidget = (props) => {
|
|
10
45
|
const { functions, data } = useSchema(
|
|
11
46
|
props?.value?.schema,
|
|
@@ -15,30 +50,6 @@ const DownloadableFilesTableWidget = (props) => {
|
|
|
15
50
|
const { setSchema, setUISchema, setSchemaHandler } = functions;
|
|
16
51
|
const [edited, setEdited] = React.useState(false);
|
|
17
52
|
|
|
18
|
-
const fixSchema = (schema) => {
|
|
19
|
-
schema.properties = Object.fromEntries(
|
|
20
|
-
Object.entries(schema.properties).filter(([k, v]) => v != null && k),
|
|
21
|
-
);
|
|
22
|
-
schema.fieldsets[0].fields = schema.fieldsets[0].fields.filter((f) => f);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const deleteNotExistingColumnsData = (props, schema) => {
|
|
26
|
-
const { id, value } = props;
|
|
27
|
-
const validFields = ['@id', ...Object.keys(schema?.properties)];
|
|
28
|
-
for (let i in value?.items) {
|
|
29
|
-
Object.keys(value?.items[i]).forEach((k) => {
|
|
30
|
-
if (!validFields.includes(k)) {
|
|
31
|
-
delete value?.items[i][k];
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
props.onChange(id, {
|
|
36
|
-
items: value.items,
|
|
37
|
-
...props?.schema,
|
|
38
|
-
...props?.uiSchema,
|
|
39
|
-
});
|
|
40
|
-
};
|
|
41
|
-
|
|
42
53
|
return (
|
|
43
54
|
<>
|
|
44
55
|
<div className="ui container">
|
|
@@ -93,15 +104,11 @@ const DownloadableFilesTableWidget = (props) => {
|
|
|
93
104
|
setSchemaHandler(
|
|
94
105
|
schema,
|
|
95
106
|
uiSchema,
|
|
96
|
-
|
|
97
|
-
props.onChange(id, {
|
|
98
|
-
...props.value,
|
|
99
|
-
schema: schema,
|
|
100
|
-
uiSchema: uiSchema,
|
|
101
|
-
}),
|
|
107
|
+
props.onChange,
|
|
102
108
|
props.id,
|
|
109
|
+
props.value,
|
|
103
110
|
);
|
|
104
|
-
deleteNotExistingColumnsData(props, schema);
|
|
111
|
+
deleteNotExistingColumnsData(props, schema, uiSchema);
|
|
105
112
|
}}
|
|
106
113
|
>
|
|
107
114
|
APPLY MODIFIED SCHEMA
|
|
@@ -121,9 +128,22 @@ const DownloadableFilesTableWidget = (props) => {
|
|
|
121
128
|
schema={schema}
|
|
122
129
|
csvexport={true}
|
|
123
130
|
csvimport={true}
|
|
124
|
-
value={
|
|
131
|
+
value={
|
|
132
|
+
[
|
|
133
|
+
...props.value?.items.map((i) =>
|
|
134
|
+
JSON.parse(orderKeysBy(['@id', ...uiSchema['ui:order']], i)),
|
|
135
|
+
),
|
|
136
|
+
] ||
|
|
137
|
+
props.default?.items ||
|
|
138
|
+
[]
|
|
139
|
+
}
|
|
125
140
|
onChange={(id, value) =>
|
|
126
|
-
props.onChange(id, {
|
|
141
|
+
props.onChange(id, {
|
|
142
|
+
...props.value,
|
|
143
|
+
items: value,
|
|
144
|
+
schema: schema,
|
|
145
|
+
uiSchema: uiSchema,
|
|
146
|
+
})
|
|
127
147
|
}
|
|
128
148
|
/>
|
|
129
149
|
)}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
|
+
|
|
2
3
|
export const useSchema = (baseSchema, baseUISchema) => {
|
|
3
4
|
const [schema, setSchema] = useState(
|
|
4
5
|
baseSchema || {
|
|
@@ -91,9 +92,8 @@ export const useSchema = (baseSchema, baseUISchema) => {
|
|
|
91
92
|
},
|
|
92
93
|
);
|
|
93
94
|
const [ready, setReady] = useState(true);
|
|
94
|
-
const setSchemaHandler = (schema, uiSchema, onChange, id) => {
|
|
95
|
+
const setSchemaHandler = (schema, uiSchema, onChange, id, value) => {
|
|
95
96
|
setReady(false);
|
|
96
|
-
// console.log('schema', schema);
|
|
97
97
|
Object.keys(schema.properties).forEach((pr) => {
|
|
98
98
|
//modify the Dropdown field type to make it compatible with Volto select
|
|
99
99
|
if (schema.properties[pr].enum) {
|
|
@@ -104,8 +104,11 @@ export const useSchema = (baseSchema, baseUISchema) => {
|
|
|
104
104
|
}
|
|
105
105
|
});
|
|
106
106
|
setSchema(schema);
|
|
107
|
-
onChange(id,
|
|
108
|
-
|
|
107
|
+
onChange(id, {
|
|
108
|
+
...value,
|
|
109
|
+
schema: schema,
|
|
110
|
+
uiSchema: uiSchema,
|
|
111
|
+
});
|
|
109
112
|
setTimeout(() => setReady(true), 1500);
|
|
110
113
|
};
|
|
111
114
|
|
|
@@ -390,10 +390,8 @@ body:not(.is-authenticated):not(.document_wide_view).stretch {
|
|
|
390
390
|
}
|
|
391
391
|
}
|
|
392
392
|
|
|
393
|
-
.tabs-block {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
margin-top: 50px;
|
|
398
|
-
}
|
|
393
|
+
.tabs-block .blocks-chooser {
|
|
394
|
+
right: 0;
|
|
395
|
+
left: auto !important;
|
|
396
|
+
margin-top: 50px;
|
|
399
397
|
}
|