@entryscape/rdforms 10.3.0 → 10.5.0

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.
@@ -1,112 +1,96 @@
1
1
  /* eslint-disable no-unused-vars */
2
2
  import React, { useState, useEffect, useMemo } from 'react';
3
- import Grid from '@material-ui/core/Grid';
4
- import { MuiPickersUtilsProvider, KeyboardDatePicker, KeyboardTimePicker } from '@material-ui/pickers';
5
- import MomentUtils from '@date-io/moment';
6
- import MenuItem from '@material-ui/core/MenuItem';
7
- import FormControl from '@material-ui/core/FormControl';
8
- import Select from '@material-ui/core/Select';
3
+ import { DatePicker, TimePicker, LocalizationProvider } from '@mui/lab';
4
+ import DateAdapter from '@mui/lab/AdapterMoment';
5
+ import MenuItem from '@mui/material/MenuItem';
6
+ import FormControl from '@mui/material/FormControl';
7
+ import { TextField } from '@mui/material';
8
+ import Select from '@mui/material/Select';
9
9
  import moment from 'moment';
10
10
  import renderingContext from '../renderingContext';
11
+ import {
12
+ getDate,
13
+ getDatatype,
14
+ getDatatypeURI,
15
+ getDatatypeFromItem,
16
+ getDateValue,
17
+ getAllowedDateAlternatives,
18
+ getDatePresentation,
19
+ } from '../jquery/util';
11
20
 
12
- const getDatatype = (datatype) => {
13
- switch (datatype) {
14
- case 'http://www.w3.org/2001/XMLSchema#dateTime':
15
- case 'http://purl.org/dc/terms/W3CDTF':
16
- return 'Datetime';
17
- case 'http://www.w3.org/2001/XMLSchema#date':
18
- return 'Date';
19
- case 'http://www.w3.org/2001/XMLSchema#gYear':
20
- return 'Year';
21
- default:
22
- return undefined;
23
- }
24
- };
25
-
26
- const getDatatypeFromItem = (item) => {
27
- const dt = item.getDatatype();
28
- if (Array.isArray(dt)) {
29
- return getDatatype(dt[0]);
30
- }
31
- return getDatatype(dt);
32
- };
33
-
34
- const getAllowedDateAlternatives = (item) => {
35
- const dateAllowedDataAlternatives = {};
36
- const dt = item.getDatatype();
37
- const alts = Array.isArray(dt) ? dt : [dt];
38
- alts.forEach((datatype) => {
39
- const alt = getDatatype(datatype);
40
- if (alt) {
41
- dateAllowedDataAlternatives[alt] = true;
42
- }
43
- });
44
- return dateAllowedDataAlternatives;
45
- };
46
21
 
47
22
  const getDatatypeFromBinding = binding => getDatatype(binding.getDatatype()) || getDatatypeFromItem(binding.getItem());
48
23
 
49
- const getDatatypeURI = (datatype) => {
50
- switch (datatype) {
51
- case 'Datetime':
52
- return 'http://www.w3.org/2001/XMLSchema#dateTime';
53
- case 'Date':
54
- return 'http://www.w3.org/2001/XMLSchema#date';
55
- case 'Year':
56
- return 'http://www.w3.org/2001/XMLSchema#gYear';
57
- default:
58
- return '';
59
- }
60
- };
61
-
62
- const getDateValue = (value, datatype) => {
63
- if (value) {
64
- switch (datatype) {
65
- case 'Datetime':
66
- return value.toISOString();
67
- case 'Date':
68
- return value.toISOString().substr(0, 10);
69
- case 'Year':
70
- return value.toISOString().substr(0, 4);
71
- default:
72
- return '';
73
- }
74
- }
75
- return '';
76
- };
77
-
78
-
79
24
  const datePresenter = (fieldDiv, binding, context) => {
80
- const data = binding.getValue();
81
- if (data != null && data !== '') {
82
- try {
83
- let str;
84
- if (data.indexOf('T') > 0) {
85
- str = moment(data).format('lll');
86
- } else if (data.length > 4) {
87
- str = moment(data).format('LL');
88
- } else {
89
- str = moment(data).format('YYYY');
90
- }
91
- fieldDiv.appendChild(<div key={binding.getHash()} >{str}</div>);
92
- } catch (e) {
93
- console.warn(`Could not present date, expected ISO8601 format in the form 2001-01-01 (potentially with time given after a 'T' character as well) but found '${data}' instead.`);
94
- }
25
+ try {
26
+ const pres = getDatePresentation(binding);
27
+ fieldDiv.appendChild(<div key={binding.getHash()} >{pres}</div>);
28
+ } catch (e) {
29
+ console.warn(`Could not present date, expected ISO8601 format in the form 2001-01-01
30
+ (potentially with time given after a 'T' character as well) but found '${binding.getValue()}' instead.`);
95
31
  }
96
32
  };
97
33
 
98
34
  const presenters = renderingContext.presenterRegistry;
35
+ presenters.itemtype('text').datatype('xsd:dateTime').register(datePresenter);
99
36
  presenters.itemtype('text').datatype('xsd:date').register(datePresenter);
37
+ presenters.itemtype('text').datatype('xsd:time').register(datePresenter);
38
+ presenters.itemtype('text').datatype('xsd:gYear').register(datePresenter);
39
+ presenters.itemtype('text').datatype('xsd:gYearMonth').register(datePresenter);
40
+ presenters.itemtype('text').datatype('xsd:gMonthDay').register(datePresenter);
100
41
  presenters.itemtype('text').datatype('dcterms:W3CDTF').register(datePresenter);
101
42
 
43
+ const datePickerConfig = {
44
+ format: {
45
+ Year: 'YYYY',
46
+ DateTime: 'YYYY-MM-DD',
47
+ Date: 'YYYY-MM-DD',
48
+ YearMonth: 'YYYY-MM',
49
+ MonthDay: 'MM-DD',
50
+ Time: 'YYYY-MM-DD', // Since datepicker is sometimes visible but disabled
51
+ },
52
+ mask: {
53
+ Year: '____',
54
+ DateTime: '____-__-__',
55
+ Date: '____-__-__',
56
+ YearMonth: '____-__',
57
+ MonthDay: '__-__',
58
+ Time: '____-__-__', // Since datepicker is sometimes visible but disabled
59
+ },
60
+ views: {
61
+ Year: ['year'],
62
+ DateTime: ['day'],
63
+ Date: ['day'],
64
+ YearMonth: ['year', 'month'],
65
+ MonthDay: ['month', 'day'],
66
+ Time: ['day'], // Since datepicker is sometimes visible but disabled
67
+ },
68
+ labelKey: {
69
+ Year: 'date_year',
70
+ DateTime: 'date_date',
71
+ Date: 'date_date',
72
+ YearMonth: 'date_year_and_month', // TODO
73
+ MonthDay: 'date_month_and_day', // TODO
74
+ Time: 'date_date', // Since datepicker is sometimes visible but disabled
75
+ },
76
+ ariaLabelKey: {
77
+ Year: 'date_openYearPicker',
78
+ DateTime: 'date_openDatePicker',
79
+ Date: 'date_openDatePicker',
80
+ YearMonth: 'date_openDatePicker', // TODO
81
+ MonthDay: 'date_openDatePicker', // TODO
82
+ Time: 'date_openDatePicker', // Since datepicker is sometimes visible but disabled
83
+ },
84
+ };
85
+
102
86
 
103
87
  const dateEditor = (fieldDiv, binding, context) => {
104
88
  const bundle = context.view.messages;
105
89
  const DateComp = () => {
106
90
  const value = binding.getGist();
107
- const alternatives = useMemo(() => getAllowedDateAlternatives(binding.getItem()));
91
+ const alternatives = useMemo(() => getAllowedDateAlternatives(binding.getItem()), []);
108
92
  const onlyOneAlternative = Object.keys(alternatives).length === 1;
109
- const [selectedDate, setSelectedDate] = useState(value === '' ? null : new Date(value));
93
+ const [selectedDate, setSelectedDate] = useState(value === '' ? null : getDate(value));
110
94
  const [selectedDatatype, setDatatype] = useState(getDatatypeFromBinding(binding));
111
95
  useEffect(() => {
112
96
  context.clear = () => {
@@ -130,41 +114,96 @@ const dateEditor = (fieldDiv, binding, context) => {
130
114
  binding.setValue(getDateValue(selectedDate, event.target.value));
131
115
  setDatatype(event.target.value);
132
116
  };
133
- const inputProps = { 'aria-labelledby': context.view.getLabelIndex(binding) };
134
- const dateFormat = selectedDatatype === 'Year' ? 'YYYY' : 'YYYY-MM-DD';
117
+ const inputProps = {
118
+ 'aria-labelledby': context.view.getLabelIndex(binding),
119
+ variant: renderingContext.materialVariant,
120
+ };
121
+ const visibleDatePicker = alternatives.Date || alternatives.DateTime || alternatives.Year
122
+ || alternatives.YearMonth || alternatives.MonthDay;
123
+ const enabledDatePicker = selectedDatatype === 'DateTime' || selectedDatatype === 'Date'
124
+ || selectedDatatype === 'Year' || selectedDatatype === 'YearMonth' || selectedDatatype === 'MonthDay';
135
125
  return (
136
- <MuiPickersUtilsProvider utils={MomentUtils}>
126
+ <LocalizationProvider dateAdapter={DateAdapter}>
137
127
  <span className="rdformsDatePicker">
138
- <KeyboardDatePicker
139
- leftArrowButtonProps={{ 'aria-label': bundle.date_previousMonth }}
140
- rightArrowButtonProps={{ 'aria-label': bundle.date_nextMonth }}
141
- KeyboardButtonProps={{ 'aria-label': selectedDatatype === 'Year' ?
142
- bundle.date_openYearPicker : bundle.date_openDatePicker }}
143
- label={selectedDatatype === 'Year' ? bundle.date_year : bundle.date_date}
144
- value={selectedDate} minDate={new Date('0000-01-01')} format={dateFormat}
145
- views={selectedDatatype === 'Year' ? ['year'] : ['date']}
146
- inputProps={inputProps}
147
- onChange={onDateChange} autoOk={true} inputVariant={renderingContext.materialVariant}/>
148
- {alternatives.Datetime && (<KeyboardTimePicker
149
- label={bundle.date_time}
150
- { ...(selectedDatatype === 'Datetime' ? {} : { disabled: true })}
151
- KeyboardButtonProps={{ 'aria-label': bundle.date_openTimePicker }}
152
- value={selectedDatatype === 'Datetime' ? selectedDate : null}
153
- onChange={onDateChange} ampm={false} autoOk={true}
154
- inputProps={inputProps}
155
- inputVariant={renderingContext.materialVariant}/>)}
156
- {!onlyOneAlternative && (<FormControl variant={renderingContext.materialVariant}>
157
- <Select
158
- value={selectedDatatype}
159
- inputProps={inputProps}
160
- onChange={onDatatypeChange}>
161
- {alternatives.Year && (<MenuItem value="Year">{bundle.date_year}</MenuItem>)}
162
- {alternatives.Date && (<MenuItem value="Date">{bundle.date_date}</MenuItem>)}
163
- {alternatives.Datetime && (<MenuItem value="Datetime">{bundle.date_date_and_time}</MenuItem>)}
164
- </Select>
165
- </FormControl>)}
128
+ {visibleDatePicker && (
129
+ <DatePicker
130
+ renderInput={props => <TextField {...props} {...inputProps} />}
131
+ leftArrowButtonProps={{ 'aria-label': bundle.date_previousMonth }}
132
+ rightArrowButtonProps={{ 'aria-label': bundle.date_nextMonth }}
133
+ KeyboardButtonProps={{ 'aria-label': bundle[datePickerConfig.ariaLabelKey[selectedDatatype]] }}
134
+ label={bundle[datePickerConfig.labelKey[selectedDatatype]]}
135
+ {...(enabledDatePicker ? {} : { disabled: true })}
136
+ value={enabledDatePicker ? selectedDate : null}
137
+ minDate={moment(new Date('0000-01-01'))}
138
+ inputFormat={datePickerConfig.format[selectedDatatype]}
139
+ views={datePickerConfig.views[selectedDatatype]}
140
+ onChange={onDateChange}
141
+ autoOk={true}
142
+ mask={datePickerConfig.mask[selectedDatatype]}
143
+ PopperProps={{
144
+ modifiers: [
145
+ {
146
+ name: 'flip',
147
+ enabled: false,
148
+ },
149
+ ],
150
+ }}
151
+ />
152
+ )}
153
+ {(alternatives.DateTime || alternatives.Time) && (
154
+ <TimePicker
155
+ renderInput={props => <TextField {...props} {...inputProps} />}
156
+ label={bundle.date_time}
157
+ {...(selectedDatatype === 'DateTime' || selectedDatatype === 'Time' ? {} : { disabled: true })}
158
+ KeyboardButtonProps={{
159
+ 'aria-label': bundle.date_openTimePicker,
160
+ }}
161
+ value={selectedDatatype === 'DateTime' || selectedDatatype === 'Time' ? selectedDate : null}
162
+ onChange={onDateChange}
163
+ ampm={false}
164
+ autoOk={true}
165
+ PopperProps={{
166
+ modifiers: [
167
+ {
168
+ name: 'flip',
169
+ enabled: false,
170
+ },
171
+ ],
172
+ }}
173
+ />
174
+ )}
175
+ {!onlyOneAlternative && (
176
+ <FormControl variant={renderingContext.materialVariant}>
177
+ <Select
178
+ value={selectedDatatype}
179
+ inputProps={inputProps}
180
+ onChange={onDatatypeChange}
181
+ >
182
+ {alternatives.Year && (
183
+ <MenuItem value="Year">{bundle.date_year}</MenuItem>
184
+ )}
185
+ {alternatives.Date && (
186
+ <MenuItem value="Date">{bundle.date_date}</MenuItem>
187
+ )}
188
+ {alternatives.DateTime && (
189
+ <MenuItem value="DateTime">
190
+ {bundle.date_date_and_time}
191
+ </MenuItem>
192
+ )}
193
+ {alternatives.YearMonth && (
194
+ <MenuItem value="YearMonth">{bundle.date_year_and_month}</MenuItem>
195
+ )}
196
+ {alternatives.MonthDay && (
197
+ <MenuItem value="MonthDay">{bundle.date_month_and_day}</MenuItem>
198
+ )}
199
+ {alternatives.Time && (
200
+ <MenuItem value="Time">{bundle.date_time}</MenuItem>
201
+ )}
202
+ </Select>
203
+ </FormControl>
204
+ )}
166
205
  </span>
167
- </MuiPickersUtilsProvider>
206
+ </LocalizationProvider>
168
207
  );
169
208
  };
170
209
  fieldDiv.appendChild(<DateComp key={binding.getHash()}></DateComp>);
@@ -174,4 +213,7 @@ const editors = renderingContext.editorRegistry;
174
213
  editors.itemtype('text').datatype('http://www.w3.org/2001/XMLSchema#date').register(dateEditor);
175
214
  editors.itemtype('text').datatype('http://www.w3.org/2001/XMLSchema#dateTime').register(dateEditor);
176
215
  editors.itemtype('text').datatype('http://www.w3.org/2001/XMLSchema#gYear').register(dateEditor);
216
+ editors.itemtype('text').datatype('http://www.w3.org/2001/XMLSchema#gMonthDay').register(dateEditor);
217
+ editors.itemtype('text').datatype('http://www.w3.org/2001/XMLSchema#gYearMonth').register(dateEditor);
218
+ editors.itemtype('text').datatype('http://www.w3.org/2001/XMLSchema#time').register(dateEditor);
177
219
  editors.itemtype('text').datatype('http://purl.org/dc/terms/W3CDTF').register(dateEditor);
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable no-unused-vars */
2
2
  import React, { useState, useEffect, useMemo } from 'react';
3
- import TextField from '@material-ui/core/TextField';
3
+ import TextField from '@mui/material/TextField';
4
4
  import renderingContext from '../renderingContext';
5
5
  import { toDuration, fromDuration } from './util';
6
6
 
@@ -1,25 +1,28 @@
1
1
  /* eslint-disable no-unused-vars */
2
- import React, { useState, useEffect } from 'react';
3
- import Tooltip from '@material-ui/core/Tooltip';
4
- import { withStyles } from '@material-ui/core/styles';
5
- import ClickAwayListener from '@material-ui/core/ClickAwayListener';
2
+ import React, { useState, useEffect, forwardRef } from 'react';
3
+ import Tooltip, { tooltipClasses } from '@mui/material/Tooltip';
4
+ import { styled } from '@mui/material/styles';
5
+ import ClickAwayListener from '@mui/material/ClickAwayListener';
6
6
  import renderingContext from '../renderingContext';
7
7
  import { CODES } from '../../model/engine';
8
8
 
9
- const StyledTooltip = withStyles(theme => ({
10
- tooltip: {
9
+ const StyledTooltip = styled(
10
+ forwardRef(({ className, ...props }, ref) => (
11
+ <Tooltip {...props} classes={{ popper: className }} />
12
+ ))
13
+ )(({ theme }) => ({
14
+ [`& .${tooltipClasses.tooltip}`]: {
11
15
  backgroundColor: theme.palette.background.default,
12
16
  fontSize: 12,
13
17
  color: 'black',
14
18
  boxShadow: theme.shadows[10],
19
+ pointerEvents: 'auto',
15
20
  },
16
- tooltipPlacementBottom: {
21
+ [`& .${tooltipClasses.tooltipPlacementBottom}`]: {
17
22
  margin: '2px 0 24px 0',
23
+ marginTop: '0px !important',
18
24
  },
19
- popper: {
20
- pointerEvents: 'auto',
21
- },
22
- }))(Tooltip);
25
+ }));
23
26
 
24
27
  const ItemTooltip = (props) => {
25
28
  const [open, setOpen] = useState(false);
@@ -36,14 +39,28 @@ const ItemTooltip = (props) => {
36
39
  }
37
40
  const description = props.item.getDescription() || (property ? '' : props.context.view.messages.info_missing || '');
38
41
 
39
- return <ClickAwayListener onClickAway={handleTooltipClose}>
40
- <StyledTooltip title={(<><p className="rdformsLinebreaks rdformsDescription">{description}</p>{propinfo}</>)}
41
- placement="bottom-start" disableHoverListener disableTouchListener
42
- onClose={handleTooltipClose}
43
- onOpen={handleTooltipOpen}
44
- open={open}
45
- ><span onClick={handleTooltipOpen}>{
46
- props.children}</span></StyledTooltip></ClickAwayListener>;
42
+ return (
43
+ <ClickAwayListener onClickAway={handleTooltipClose}>
44
+ <StyledTooltip
45
+ title={
46
+ <>
47
+ <p className="rdformsLinebreaks rdformsDescription">
48
+ {description}
49
+ </p>
50
+ {propinfo}
51
+ </>
52
+ }
53
+ placement="bottom-start"
54
+ disableHoverListener
55
+ disableTouchListener
56
+ onClose={handleTooltipClose}
57
+ onOpen={handleTooltipOpen}
58
+ open={open}
59
+ >
60
+ <span onClick={handleTooltipOpen}>{props.children}</span>
61
+ </StyledTooltip>
62
+ </ClickAwayListener>
63
+ );
47
64
  };
48
65
 
49
66
  renderingContext.renderPresenterLabel = (rowNode, binding, item, context) => {
@@ -133,16 +150,18 @@ const ERR = (props) => {
133
150
 
134
151
  renderingContext.renderEditorLabelScopeEnd = (rowNode, binding, item, context) => {
135
152
  if (!item.hasStyle('nonEditable') && !item.hasStyle('heading')) {
136
- let Button;
137
- const card = item.getCardinality();
138
- if (binding == null) {
139
- Button = renderingContext.addExpandButton(rowNode, null, item, context);
140
- } else if (binding.getPredicate() && !context.view.showAsTable(item) && card.max !== 1 &&
141
- (card.max == null || card.max !== card.min)) {
142
- Button = renderingContext.addCreateChildButton(rowNode, null, binding, context);
143
- }
144
- if (Button) {
145
- rowNode.appendChild(<Button key={`${binding.getHash()}_labelEnd`}></Button>);
153
+ if (!context.view.isMultiValued(item)) {
154
+ let Button;
155
+ const card = item.getCardinality();
156
+ if (binding == null) {
157
+ Button = renderingContext.addExpandButton(rowNode, null, item, context);
158
+ } else if (binding.getPredicate() && !context.view.showAsTable(item) && card.max !== 1 &&
159
+ (card.max == null || card.max !== card.min)) {
160
+ Button = renderingContext.addCreateChildButton(rowNode, null, binding, context);
161
+ }
162
+ if (Button) {
163
+ rowNode.appendChild(<Button key={`${binding.getHash()}_labelEnd`}></Button>);
164
+ }
146
165
  }
147
166
  // If the item is deprecated and there are at least one matching value (binding),
148
167
  // provide a message and make sure the entire row (including the label) is deleted when
@@ -1,12 +1,12 @@
1
1
  /* eslint-disable no-unused-vars */
2
2
  // eslint-disable-next-line no-unused-vars
3
3
  import React, { useState, useEffect, useMemo } from 'react';
4
- import TextField from '@material-ui/core/TextField';
5
- import OpenInNewIcon from '@material-ui/icons/OpenInNew';
6
- import IconButton from '@material-ui/core/IconButton';
7
- import MenuItem from '@material-ui/core/MenuItem';
8
- import FormControl from '@material-ui/core/FormControl';
9
- import Select from '@material-ui/core/Select';
4
+ import TextField from '@mui/material/TextField';
5
+ import OpenInNewIcon from '@mui/icons-material/OpenInNew';
6
+ import IconButton from '@mui/material/IconButton';
7
+ import MenuItem from '@mui/material/MenuItem';
8
+ import FormControl from '@mui/material/FormControl';
9
+ import Select from '@mui/material/Select';
10
10
  import moment from 'moment';
11
11
  import renderingContext from '../renderingContext';
12
12
  import utils from '../../utils';
@@ -41,12 +41,11 @@ const LanguageControl = (props) => {
41
41
  return <FormControl className="rdformsLangControl" variant={renderingContext.materialVariant}>
42
42
  <Select
43
43
  inputProps={{ 'aria-labelledby': props.labelledby }}
44
-
45
44
  value={lang}
46
45
  onChange={onLangChange}>
47
46
  {langs.map(langOption => (langOption === null ?
48
47
  (<MenuItem key="_none" value="_none" disabled>─────</MenuItem>) :
49
- (<MenuItem key={langOption.value} value={langOption.value}>{langOption.label}</MenuItem>)
48
+ (<MenuItem key={langOption.value} value={langOption.value}>{langOption.label || '\u00A0'}</MenuItem>)
50
49
  ))}
51
50
  </Select>
52
51
  </FormControl>;
@@ -31,6 +31,8 @@
31
31
  "date_time": "Time",
32
32
  "date_year": "Year",
33
33
  "date_date_and_time": "Date and time",
34
+ "date_year_and_month": "Year and month",
35
+ "date_month_and_day": "Month and day",
34
36
  "date_openDatePicker": "Open date picker dialog",
35
37
  "date_openTimePicker": "Open time picker dialog",
36
38
  "date_openYearPicker": "Open year picker dialog",