Skip to content

Commit 584765b

Browse files
authored
Merge pull request #178 from performant-software/feature/udcsl87_cms_fields
UDCSL #87 - CMS fields
2 parents ebdeb2b + bc6ff9f commit 584765b

File tree

17 files changed

+650
-69
lines changed

17 files changed

+650
-69
lines changed

.flowconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[ignore]
22
<PROJECT_ROOT>/types/.*
3+
./node_modules/
34

45
[include]
56

packages/controlled-vocabulary/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@performant-software/controlled-vocabulary",
3-
"version": "1.0.5",
3+
"version": "1.0.6",
44
"description": "A package of components to allow user to configure dropdown elements. Use with the \"controlled_vocabulary\" gem.",
55
"license": "MIT",
66
"main": "./build/index.js",
@@ -12,8 +12,8 @@
1212
"build": "webpack --mode production && flow-copy-source -v src types"
1313
},
1414
"dependencies": {
15-
"@performant-software/semantic-components": "^1.0.5",
16-
"@performant-software/shared-components": "^1.0.5",
15+
"@performant-software/semantic-components": "^1.0.6",
16+
"@performant-software/shared-components": "^1.0.6",
1717
"i18next": "^21.9.2",
1818
"semantic-ui-react": "^2.1.2",
1919
"underscore": "^1.13.2"

packages/semantic-ui/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@performant-software/semantic-components",
3-
"version": "1.0.5",
3+
"version": "1.0.6",
44
"description": "A package of shared components based on the Semantic UI Framework.",
55
"license": "MIT",
66
"main": "./build/index.js",
@@ -12,7 +12,7 @@
1212
"build": "webpack --mode production && flow-copy-source -v src types"
1313
},
1414
"dependencies": {
15-
"@performant-software/shared-components": "^1.0.5",
15+
"@performant-software/shared-components": "^1.0.6",
1616
"@react-google-maps/api": "^2.8.1",
1717
"axios": "^0.26.1",
1818
"citeproc": "^2.4.62",

packages/semantic-ui/src/components/Draggable.js

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,20 @@ import { useDrag, useDrop } from 'react-dnd';
66

77
type Props = {
88
children: Element<any>,
9+
direction: 'horizontal' | 'vertical',
910
id: any,
1011
index: number,
11-
onDrag: (dragIndex: number, hoverIndex: number) => void
12+
onDrag: (dragIndex: number, hoverIndex: number) => void,
13+
onDragEnd?: () => void,
14+
onDragStart?: () => void
1215
};
1316

17+
const DIRECTION_VERTICAL = 'vertical';
18+
1419
const TYPE_ANY = 'any';
1520

1621
const Draggable = (props: Props) => {
17-
const { index, id } = props;
22+
const { index, id, direction = DIRECTION_VERTICAL } = props;
1823

1924
const ref = useRef(null);
2025
const [, drop] = useDrop({
@@ -35,25 +40,36 @@ const Draggable = (props: Props) => {
3540
// Determine rectangle on screen
3641
const hoverBoundingRect = ref.current.getBoundingClientRect();
3742

38-
// Get vertical middle
39-
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
40-
4143
// Determine mouse position
4244
const clientOffset = monitor.getClientOffset();
4345

44-
// Get pixels to the top
45-
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
46+
let hoverMiddle;
47+
let hoverClient;
48+
49+
// Get middle
50+
if (direction === DIRECTION_VERTICAL) {
51+
hoverMiddle = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
52+
} else {
53+
hoverMiddle = (hoverBoundingRect.right - hoverBoundingRect.left) / 2;
54+
}
55+
56+
// Get pixels to the top/left
57+
if (direction === DIRECTION_VERTICAL) {
58+
hoverClient = clientOffset.y - hoverBoundingRect.top;
59+
} else {
60+
hoverClient = clientOffset.x - hoverBoundingRect.left;
61+
}
4662

4763
// Only perform the move when the mouse has crossed half of the items height
4864
// When dragging downwards, only move when the cursor is below 50%
4965
// When dragging upwards, only move when the cursor is above 50%
5066
// Dragging downwards
51-
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
67+
if (dragIndex < hoverIndex && hoverClient < hoverMiddle) {
5268
return;
5369
}
5470

5571
// Dragging upwards
56-
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
72+
if (dragIndex > hoverIndex && hoverClient > hoverMiddle) {
5773
return;
5874
}
5975

@@ -71,6 +87,8 @@ const Draggable = (props: Props) => {
7187

7288
const [{ isDragging }, drag] = useDrag({
7389
item: { type: TYPE_ANY, id, index },
90+
begin: () => props.onDragStart && props.onDragStart(),
91+
end: () => props.onDragEnd && props.onDragEnd(),
7492
collect: (monitor) => ({
7593
isDragging: monitor.isDragging(),
7694
}),

packages/semantic-ui/src/components/HorizontalCards.js

Lines changed: 90 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@ import {
1515
Image,
1616
Ref
1717
} from 'semantic-ui-react';
18+
import Draggable from './Draggable';
1819
import './HorizontalCards.css';
1920

2021
type Props = {
22+
cardClassName?: string,
23+
cardsClassName?: string,
24+
className?: string,
2125
inlineImage?: boolean,
2226
items: Array<any>,
2327
onClick?: (item: any, index: number) => void,
28+
onDrag?: (dragIndex: number, hoverIndex: number) => void,
2429
perPage: number,
2530
renderDescription?: (item: any) => Element<any> | string,
2631
renderExtra?: (item: any) => Element<any> | string,
@@ -46,6 +51,25 @@ const HorizontalCards = (props: Props) => {
4651
flex: `0 0 ${(pageWidth / props.perPage) - marginWidth}px`
4752
}), [pageWidth, marginWidth, props.perPage]);
4853

54+
/**
55+
* Helper function to concatenate class names.
56+
*
57+
* @type {function(*, *=): string}
58+
*/
59+
const getClassName = useCallback((className, defaultClassName = null) => {
60+
const classNames = [];
61+
62+
if (defaultClassName) {
63+
classNames.push(defaultClassName);
64+
}
65+
66+
if (className) {
67+
classNames.push(className);
68+
}
69+
70+
return classNames.join(' ');
71+
}, []);
72+
4973
/**
5074
* Initializes the page width and scroll pages on the sate.
5175
*
@@ -137,45 +161,69 @@ const HorizontalCards = (props: Props) => {
137161
*
138162
* @returns {JSX.Element}
139163
*/
140-
const renderCard = (item, index) => (
141-
<Card
142-
link
143-
onClick={props.onClick && props.onClick.bind(this, item, index)}
144-
style={cardStyle}
145-
>
146-
{ !props.inlineImage && renderImage(item) }
147-
{ (props.renderHeader || props.renderMeta || props.renderDescription) && (
148-
<Card.Content>
149-
{ props.inlineImage && renderImage(item) }
150-
{ props.renderHeader && (
151-
<Card.Header
152-
as={Header}
153-
size='small'
154-
>
155-
{ props.renderHeader(item) }
156-
</Card.Header>
157-
)}
158-
{ props.renderMeta && (
159-
<Card.Meta>
160-
{ props.renderMeta(item) }
161-
</Card.Meta>
162-
)}
163-
{ props.renderDescription && (
164-
<Card.Description>
165-
{ props.renderDescription(item) }
166-
</Card.Description>
167-
)}
168-
</Card.Content>
169-
)}
170-
{ props.renderExtra && (
171-
<Card.Content
172-
extra
164+
const renderCard = (item, index) => {
165+
let card = (
166+
<Card
167+
className={getClassName(props.cardClassName)}
168+
link
169+
onClick={props.onClick && props.onClick.bind(this, item, index)}
170+
style={cardStyle}
171+
>
172+
{ !props.inlineImage && renderImage(item) }
173+
{ (props.renderHeader || props.renderMeta || props.renderDescription) && (
174+
<Card.Content>
175+
{ props.inlineImage && renderImage(item) }
176+
{ props.renderHeader && (
177+
<Card.Header
178+
as={Header}
179+
size='small'
180+
>
181+
{ props.renderHeader(item) }
182+
</Card.Header>
183+
)}
184+
{ props.renderMeta && (
185+
<Card.Meta>
186+
{ props.renderMeta(item) }
187+
</Card.Meta>
188+
)}
189+
{ props.renderDescription && (
190+
<Card.Description>
191+
{ props.renderDescription(item) }
192+
</Card.Description>
193+
)}
194+
</Card.Content>
195+
)}
196+
{ props.renderExtra && (
197+
<Card.Content
198+
extra
199+
>
200+
{ props.renderExtra(item) }
201+
</Card.Content>
202+
)}
203+
</Card>
204+
);
205+
206+
if (props.onDrag) {
207+
// Since the item may not be saved yet, we'll look for the ID or UID columns as the key. This is necessary to
208+
// maintain the correct element when dragging.
209+
const key = item.id || item.uid;
210+
211+
card = (
212+
<Draggable
213+
direction='horizontal'
214+
id={key}
215+
index={index}
216+
item={item}
217+
key={key}
218+
onDrag={props.onDrag}
173219
>
174-
{ props.renderExtra(item) }
175-
</Card.Content>
176-
)}
177-
</Card>
178-
);
220+
{ card }
221+
</Draggable>
222+
);
223+
}
224+
225+
return card;
226+
};
179227

180228
/**
181229
* Renders the image based on the return type of the renderImage prop. String values returned will be assumed to be
@@ -204,12 +252,14 @@ const HorizontalCards = (props: Props) => {
204252

205253
return (
206254
<div
207-
className='horizontal-cards'
255+
className={getClassName(props.className, 'horizontal-cards')}
208256
>
209257
<Ref
210258
innerRef={ref}
211259
>
212-
<Card.Group>
260+
<Card.Group
261+
className={getClassName(props.cardsClassName)}
262+
>
213263
{ _.map(props.items, renderCard.bind(this)) }
214264
</Card.Group>
215265
</Ref>

0 commit comments

Comments
 (0)