ish-ui 1.0.2
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/.eslintrc.json +39 -0
- package/.gitattributes +3 -0
- package/.github/workflows/release-package.yml +33 -0
- package/.prettierrc +5 -0
- package/README.md +80 -0
- package/assets/fonts/inter/Inter-Italic.var.woff2 +0 -0
- package/assets/fonts/inter/Inter-Roman.var.woff2 +0 -0
- package/assets/fonts/inter/LICENSE.txt +92 -0
- package/assets/fonts/inter/index.d.ts +10 -0
- package/assets/fonts/inter/inter.scss +17 -0
- package/package.json +108 -0
- package/src/actions/FieldProcessing.ts +21 -0
- package/src/actions/index.ts +10 -0
- package/src/appBar/AppBarHelpMenu.tsx +139 -0
- package/src/appBar/index.ts +9 -0
- package/src/buttons/AddButton.tsx +30 -0
- package/src/buttons/TimetableButton.tsx +19 -0
- package/src/buttons/index.ts +10 -0
- package/src/colorPicker/ColorPicker.tsx +223 -0
- package/src/colorPicker/index.ts +9 -0
- package/src/dialog/BrowserWarning.tsx +24 -0
- package/src/dialog/confirm/ConfirmBase.tsx +59 -0
- package/src/dialog/index.ts +11 -0
- package/src/dialog/message/Message.tsx +140 -0
- package/src/documents/DocumentIconsChooser.tsx +69 -0
- package/src/documents/index.ts +10 -0
- package/src/documents/utils/index.tsx +71 -0
- package/src/dynamicSizeList/DynamicSizeList.tsx +208 -0
- package/src/dynamicSizeList/index.ts +9 -0
- package/src/fieldMessage/ErrorMessage.tsx +28 -0
- package/src/fieldMessage/WarningMessage.tsx +28 -0
- package/src/fieldMessage/index.ts +11 -0
- package/src/fieldMessage/styles.ts +21 -0
- package/src/fileUploader/FileUploaderDialog.tsx +158 -0
- package/src/fileUploader/index.ts +9 -0
- package/src/formFields/CheckboxField.tsx +90 -0
- package/src/formFields/CodeEditorField.tsx +103 -0
- package/src/formFields/ColoredCheckBox.tsx +74 -0
- package/src/formFields/DateTimeField.tsx +61 -0
- package/src/formFields/EditInPlaceDateTimeField.tsx +285 -0
- package/src/formFields/EditInPlaceDurationField.tsx +79 -0
- package/src/formFields/EditInPlaceField.tsx +131 -0
- package/src/formFields/EditInPlaceFieldBase.tsx +241 -0
- package/src/formFields/EditInPlaceFileField.tsx +67 -0
- package/src/formFields/EditInPlaceMoneyField.tsx +64 -0
- package/src/formFields/EditInPlacePhoneField.tsx +97 -0
- package/src/formFields/EditInPlaceSearchSelect.tsx +562 -0
- package/src/formFields/FieldAdornments.tsx +70 -0
- package/src/formFields/FilePreview.tsx +149 -0
- package/src/formFields/FormRadioButtons.tsx +62 -0
- package/src/formFields/SelectCustomComponents.tsx +228 -0
- package/src/formFields/Switch.tsx +146 -0
- package/src/formFields/TextField.tsx +60 -0
- package/src/formFields/UneditableBase.tsx +101 -0
- package/src/formFields/index.ts +27 -0
- package/src/index.ts +26 -0
- package/src/layout/InfoPill.tsx +36 -0
- package/src/layout/index.ts +10 -0
- package/src/layout/resizable/ResizableWrapper.tsx +87 -0
- package/src/markdownEditor/HtmlEditor.tsx +44 -0
- package/src/markdownEditor/WysiwygEditor.tsx +137 -0
- package/src/markdownEditor/index.ts +12 -0
- package/src/markdownEditor/style.ts +188 -0
- package/src/markdownEditor/utils/index.ts +48 -0
- package/src/model/AppBar.ts +20 -0
- package/src/model/CommomObjects.ts +8 -0
- package/src/model/CommonFunctions.ts +20 -0
- package/src/model/Confirm.ts +27 -0
- package/src/model/Fields.ts +254 -0
- package/src/model/NestedEntity.ts +14 -0
- package/src/model/Theme.ts +42 -0
- package/src/model/index.ts +16 -0
- package/src/styles/GlobalStylesProvider.tsx +520 -0
- package/src/styles/StylesProviderCustom.tsx +8 -0
- package/src/styles/animateStyles.ts +94 -0
- package/src/styles/bootstrap.ts +503 -0
- package/src/styles/hooks.ts +44 -0
- package/src/styles/index.ts +18 -0
- package/src/styles/makeStyles.ts +21 -0
- package/src/styles/mixins/common.ts +40 -0
- package/src/styles/mixins/keyframes.ts +16 -0
- package/src/styles/mixins/prefixer.ts +21 -0
- package/src/tagsInput/AddTagMenu.tsx +74 -0
- package/src/tagsInput/AddTagMenuItem.tsx +50 -0
- package/src/tagsInput/TagInputList.tsx +428 -0
- package/src/tagsInput/index.ts +4 -0
- package/src/themes/appTheme.ts +324 -0
- package/src/themes/index.ts +10 -0
- package/src/themes/ishTheme.ts +401 -0
- package/src/timetable/datePeriodFilter/DayPeriodIcons.tsx +95 -0
- package/src/timetable/datePeriodFilter/index.ts +10 -0
- package/src/timetable/index.ts +11 -0
- package/src/timetable/miniCalendar/CalendarDay.tsx +109 -0
- package/src/timetable/miniCalendar/CalendarHeader.tsx +37 -0
- package/src/timetable/miniCalendar/CalendarWeekPanel.tsx +35 -0
- package/src/timetable/miniCalendar/WeekDay.tsx +49 -0
- package/src/timetable/miniCalendar/index.ts +13 -0
- package/src/utils/DOM/Links.ts +17 -0
- package/src/utils/DOM/getCaretCoordinates.ts +122 -0
- package/src/utils/DOM/getOS.ts +32 -0
- package/src/utils/DOM/index.ts +34 -0
- package/src/utils/dates/datesNormalizing.ts +4 -0
- package/src/utils/dates/format.ts +52 -0
- package/src/utils/dates/formatRelative.ts +22 -0
- package/src/utils/dates/formatString.ts +233 -0
- package/src/utils/dates/formatTimezone.ts +37 -0
- package/src/utils/dates/index.ts +15 -0
- package/src/utils/dates/timetable.ts +46 -0
- package/src/utils/events/index.ts +8 -0
- package/src/utils/fields/index.ts +23 -0
- package/src/utils/formatting/PhoneMasks.ts +320 -0
- package/src/utils/formatting/index.tsx +20 -0
- package/src/utils/hooks/index.ts +19 -0
- package/src/utils/index.ts +15 -0
- package/src/utils/numbers/decimalCalculation.ts +26 -0
- package/src/utils/numbers/index.ts +11 -0
- package/src/utils/numbers/numbersNormalizing.ts +52 -0
- package/src/utils/stubs/index.tsx +12 -0
- package/src/utils/tags/index.ts +53 -0
- package/tools/webpack/webpack.aliases.js +13 -0
- package/tools/webpack/webpack.config.dev.js +29 -0
- package/tools/webpack/webpack.config.prod.js +36 -0
- package/tools/webpack/webpack.helpers.js +26 -0
- package/tools/webpack/webpack.plugins.js +15 -0
- package/tools/webpack/webpack.rules.js +51 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2022.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React, {
|
|
10
|
+
useCallback, useEffect, useMemo, useRef, useState
|
|
11
|
+
} from 'react';
|
|
12
|
+
import ButtonBase from '@mui/material/ButtonBase';
|
|
13
|
+
import Popper from '@mui/material/Popper';
|
|
14
|
+
import { AlphaPicker, HuePicker } from 'react-color';
|
|
15
|
+
import { ClickAwayListener, PopperPlacementType, Theme } from '@mui/material';
|
|
16
|
+
import { createStyles, withStyles } from '@mui/styles';
|
|
17
|
+
import Paper from '@mui/material/Paper';
|
|
18
|
+
import Grow from '@mui/material/Grow';
|
|
19
|
+
import clsx from 'clsx';
|
|
20
|
+
import { FieldInputProps } from '@src/model';
|
|
21
|
+
import { stopEventPropagation } from '@src/utils/events';
|
|
22
|
+
|
|
23
|
+
interface ColorPickerWrapperProps {
|
|
24
|
+
input?: FieldInputProps;
|
|
25
|
+
classes?: any;
|
|
26
|
+
theme?: Theme;
|
|
27
|
+
placement?: PopperPlacementType;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface ColorPickerBaseProps extends ColorPickerWrapperProps {
|
|
31
|
+
color: any;
|
|
32
|
+
TransitionProps: any;
|
|
33
|
+
setAnchorEl: any;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const styles = createStyles(({
|
|
37
|
+
spacing, transitions, palette, zIndex
|
|
38
|
+
}: Theme) => ({
|
|
39
|
+
paper: {
|
|
40
|
+
width: 200,
|
|
41
|
+
padding: spacing(2),
|
|
42
|
+
position: 'relative',
|
|
43
|
+
bottom: '12px',
|
|
44
|
+
background: palette.background.paper,
|
|
45
|
+
'&:after': {
|
|
46
|
+
bottom: '0px',
|
|
47
|
+
left: '50%',
|
|
48
|
+
width: '22px',
|
|
49
|
+
height: '10px',
|
|
50
|
+
position: 'absolute',
|
|
51
|
+
transform: 'translateX(-50%)',
|
|
52
|
+
background: palette.background.paper,
|
|
53
|
+
content: '\'\'',
|
|
54
|
+
zIndex: 1
|
|
55
|
+
},
|
|
56
|
+
'&:before': {
|
|
57
|
+
content: '\'\'',
|
|
58
|
+
bottom: '-6px',
|
|
59
|
+
left: '50%',
|
|
60
|
+
width: '12px',
|
|
61
|
+
height: '12px',
|
|
62
|
+
position: 'absolute',
|
|
63
|
+
transform: 'translateX(-50%) rotate(45deg)',
|
|
64
|
+
background: palette.background.paper,
|
|
65
|
+
boxShadow: '1px 1px 2px 0px rgba(0,0,0,0.2), 2px 1px 2px -1px rgba(0,0,0,0.12), 1px 1px 1px 0px rgba(0,0,0,0.12);'
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
paperPlaceBottom: {
|
|
69
|
+
marginTop: spacing(3),
|
|
70
|
+
'&:after': {
|
|
71
|
+
bottom: 'unset',
|
|
72
|
+
top: '0px'
|
|
73
|
+
},
|
|
74
|
+
'&:before': {
|
|
75
|
+
bottom: 'unset',
|
|
76
|
+
top: '-6px',
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
colorPickerButton: {
|
|
80
|
+
width: '14px',
|
|
81
|
+
height: '14px',
|
|
82
|
+
borderRadius: '100%',
|
|
83
|
+
transition: transitions.create('transform', {
|
|
84
|
+
duration: transitions.duration.shorter,
|
|
85
|
+
easing: transitions.easing.easeInOut
|
|
86
|
+
}),
|
|
87
|
+
'&:hover,&$opened': {
|
|
88
|
+
transform: 'scale(2)'
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
popper: {
|
|
92
|
+
zIndex: zIndex.tooltip
|
|
93
|
+
},
|
|
94
|
+
bottomOffset: {
|
|
95
|
+
marginBottom: spacing(1.25)
|
|
96
|
+
},
|
|
97
|
+
customAlfa: {
|
|
98
|
+
'& > div > div:first-child > div': {
|
|
99
|
+
background: 'none !important'
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
opened: {}
|
|
103
|
+
}));
|
|
104
|
+
|
|
105
|
+
const ColorPickerBase = React.memo<ColorPickerBaseProps>(
|
|
106
|
+
({
|
|
107
|
+
classes, color, input: { value, onChange }, TransitionProps, setAnchorEl, placement
|
|
108
|
+
}) => {
|
|
109
|
+
const [hueColor, setHueColor] = useState(color);
|
|
110
|
+
const [alfaColor, setAlfaColor] = useState(color);
|
|
111
|
+
|
|
112
|
+
const hueRef = useRef<any>();
|
|
113
|
+
|
|
114
|
+
const onHueChange = useCallback(color => {
|
|
115
|
+
setHueColor(color.hsv);
|
|
116
|
+
setAlfaColor(color.hsv);
|
|
117
|
+
}, []);
|
|
118
|
+
|
|
119
|
+
const onAlfaChange = useCallback(
|
|
120
|
+
color => {
|
|
121
|
+
setHueColor({
|
|
122
|
+
h: color.hsv.h, s: color.hsv.a, v: color.hsv.v, a: 1
|
|
123
|
+
});
|
|
124
|
+
setAlfaColor(color.hsv);
|
|
125
|
+
},
|
|
126
|
+
[]
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const handleClickAway = useCallback(() => {
|
|
130
|
+
setAnchorEl(null);
|
|
131
|
+
}, []);
|
|
132
|
+
|
|
133
|
+
useEffect(
|
|
134
|
+
() => {
|
|
135
|
+
if (!hueColor && value) {
|
|
136
|
+
setHueColor('#' + value);
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
[value, hueColor]
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
useEffect(
|
|
143
|
+
() => {
|
|
144
|
+
const hueHsv = hueRef.current.state.hsv;
|
|
145
|
+
setAlfaColor({
|
|
146
|
+
h: hueHsv.h, s: 1, v: hueHsv.v, a: hueHsv.s
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
[hueRef.current]
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
const onChangeComplete = () => {
|
|
153
|
+
onChange(hueRef.current.state.hex.replace('#', ''));
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<ClickAwayListener onClickAway={handleClickAway}>
|
|
158
|
+
<Grow {...TransitionProps} timeout={200}>
|
|
159
|
+
<div>
|
|
160
|
+
<Paper className={clsx(classes.paper, placement === 'bottom' && classes.paperPlaceBottom)}>
|
|
161
|
+
<HuePicker
|
|
162
|
+
ref={hueRef}
|
|
163
|
+
color={hueColor}
|
|
164
|
+
onChange={onHueChange}
|
|
165
|
+
onChangeComplete={onChangeComplete}
|
|
166
|
+
width="168"
|
|
167
|
+
className={classes.bottomOffset}
|
|
168
|
+
/>
|
|
169
|
+
<AlphaPicker
|
|
170
|
+
className={classes.customAlfa}
|
|
171
|
+
color={alfaColor}
|
|
172
|
+
width="168"
|
|
173
|
+
onChange={onAlfaChange}
|
|
174
|
+
onChangeComplete={onChangeComplete}
|
|
175
|
+
/>
|
|
176
|
+
</Paper>
|
|
177
|
+
</div>
|
|
178
|
+
</Grow>
|
|
179
|
+
</ClickAwayListener>
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
const ColorPickerWrapper = React.memo<ColorPickerWrapperProps>(({
|
|
185
|
+
classes, theme, input, placement = 'top'
|
|
186
|
+
}) => {
|
|
187
|
+
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
|
188
|
+
|
|
189
|
+
const handleClick = useCallback(
|
|
190
|
+
(event: React.MouseEvent<HTMLElement>) => {
|
|
191
|
+
setAnchorEl(anchorEl ? null : event.currentTarget);
|
|
192
|
+
},
|
|
193
|
+
[anchorEl]
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
const color = useMemo(() => (input.value ? '#' + input.value : theme.palette.primary.main), [theme, input.value]);
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<div className="d-flex" onClick={stopEventPropagation}>
|
|
200
|
+
<ButtonBase onClick={handleClick} className={clsx(classes.colorPickerButton, anchorEl && classes.opened)} style={{ backgroundColor: color }} />
|
|
201
|
+
<Popper
|
|
202
|
+
open={Boolean(anchorEl)}
|
|
203
|
+
anchorEl={anchorEl}
|
|
204
|
+
placement={placement}
|
|
205
|
+
className={classes.popper}
|
|
206
|
+
transition
|
|
207
|
+
>
|
|
208
|
+
{({ TransitionProps }) => (
|
|
209
|
+
<ColorPickerBase
|
|
210
|
+
classes={classes}
|
|
211
|
+
color={color}
|
|
212
|
+
input={input}
|
|
213
|
+
TransitionProps={TransitionProps}
|
|
214
|
+
setAnchorEl={setAnchorEl}
|
|
215
|
+
placement={placement}
|
|
216
|
+
/>
|
|
217
|
+
)}
|
|
218
|
+
</Popper>
|
|
219
|
+
</div>
|
|
220
|
+
);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
export default withStyles(styles, { withTheme: true })(ColorPickerWrapper);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2023.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './ColorPicker';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Alert } from '@mui/lab';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
const BROWSER_WARNING_TEXT = 'Your current browser is not supported. Please ensure you are using an up to date version of Chrome, Firefox or Edge.';
|
|
5
|
+
|
|
6
|
+
export const isOldIE = () => {
|
|
7
|
+
const ua = window.navigator.userAgent;
|
|
8
|
+
const msie = ua.indexOf('MSIE ');
|
|
9
|
+
return msie !== -1;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const BrowserWarning = () => isOldIE() && (
|
|
13
|
+
<div style={{
|
|
14
|
+
position: 'fixed',
|
|
15
|
+
bottom: '50vh',
|
|
16
|
+
left: '35vw',
|
|
17
|
+
right: '35vw',
|
|
18
|
+
zIndex: 10000
|
|
19
|
+
}}>
|
|
20
|
+
<Alert variant="filled" severity="error">
|
|
21
|
+
{BROWSER_WARNING_TEXT}
|
|
22
|
+
</Alert>
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2023.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Common confirm dialog
|
|
11
|
+
* */
|
|
12
|
+
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import Button from '@mui/material/Button';
|
|
15
|
+
import Dialog from '@mui/material/Dialog';
|
|
16
|
+
import DialogActions from '@mui/material/DialogActions';
|
|
17
|
+
import DialogContent from '@mui/material/DialogContent';
|
|
18
|
+
import DialogContentText from '@mui/material/DialogContentText';
|
|
19
|
+
import DialogTitle from '@mui/material/DialogTitle';
|
|
20
|
+
import { ConfirmState } from '@src/model';
|
|
21
|
+
|
|
22
|
+
const ConfirmBase: React.FunctionComponent<ConfirmState> = props => {
|
|
23
|
+
const {
|
|
24
|
+
open,
|
|
25
|
+
onCancel,
|
|
26
|
+
title,
|
|
27
|
+
confirmMessage,
|
|
28
|
+
onConfirm,
|
|
29
|
+
cancelButtonText,
|
|
30
|
+
confirmButtonText,
|
|
31
|
+
onCancelCustom,
|
|
32
|
+
confirmCustomComponent
|
|
33
|
+
} = props;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Dialog open={open} onClose={onCancel}>
|
|
37
|
+
{title && <DialogTitle id="alert-dialog-title">{title}</DialogTitle>}
|
|
38
|
+
{confirmMessage && (
|
|
39
|
+
<DialogContent>
|
|
40
|
+
<DialogContentText id="alert-dialog-description">{confirmMessage}</DialogContentText>
|
|
41
|
+
</DialogContent>
|
|
42
|
+
)}
|
|
43
|
+
|
|
44
|
+
<DialogActions>
|
|
45
|
+
<Button onClick={onCancelCustom || onCancel} color="primary">
|
|
46
|
+
{cancelButtonText}
|
|
47
|
+
</Button>
|
|
48
|
+
{onConfirm && !confirmCustomComponent && (
|
|
49
|
+
<Button onClick={() => onConfirm()} variant="contained" color="primary">
|
|
50
|
+
{confirmButtonText}
|
|
51
|
+
</Button>
|
|
52
|
+
)}
|
|
53
|
+
{confirmCustomComponent && confirmCustomComponent}
|
|
54
|
+
</DialogActions>
|
|
55
|
+
</Dialog>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export default ConfirmBase;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2023.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './message/Message';
|
|
10
|
+
export * from './confirm/ConfirmBase';
|
|
11
|
+
export * from './BrowserWarning';
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd. All rights reserved. https://www.ish.com.au
|
|
3
|
+
* No copying or use of this code is allowed without permission in writing from ish.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import clsx from 'clsx';
|
|
8
|
+
import { withStyles } from '@mui/styles';
|
|
9
|
+
import Snackbar from '@mui/material/Snackbar';
|
|
10
|
+
import IconButton from '@mui/material/IconButton';
|
|
11
|
+
import Alert from '@mui/material/Alert';
|
|
12
|
+
import CloseIcon from '@mui/icons-material/Close';
|
|
13
|
+
import { AnyArgFunction } from '@src/model';
|
|
14
|
+
|
|
15
|
+
const styles = theme => ({
|
|
16
|
+
close: {
|
|
17
|
+
color: theme.palette.primary.contrastText,
|
|
18
|
+
width: theme.spacing(4),
|
|
19
|
+
height: theme.spacing(4),
|
|
20
|
+
padding: theme.spacing(0.5)
|
|
21
|
+
},
|
|
22
|
+
success: {
|
|
23
|
+
maxWidth: 'unset'
|
|
24
|
+
},
|
|
25
|
+
autoWidth: {
|
|
26
|
+
[theme.breakpoints.down('md')]: {
|
|
27
|
+
flexGrow: 'unset',
|
|
28
|
+
borderRadius: `${theme.shape.borderRadius}px`
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
autoWidthRoot: {
|
|
32
|
+
[theme.breakpoints.down('md')]: {
|
|
33
|
+
left: '24px',
|
|
34
|
+
right: 'auto',
|
|
35
|
+
bottom: '24px'
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
fullScreenMessage: {
|
|
39
|
+
maxHeight: 'calc(100vh - 90px)',
|
|
40
|
+
overflow: 'auto',
|
|
41
|
+
marginRight: theme.spacing(-2),
|
|
42
|
+
paddingRight: theme.spacing(2)
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
interface Props {
|
|
47
|
+
opened: boolean;
|
|
48
|
+
text: string;
|
|
49
|
+
clearMessage: AnyArgFunction;
|
|
50
|
+
isSuccess?: boolean;
|
|
51
|
+
persist?: boolean;
|
|
52
|
+
classes?: any;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
class Message extends React.Component<Props, any> {
|
|
56
|
+
constructor(props) {
|
|
57
|
+
super(props);
|
|
58
|
+
|
|
59
|
+
this.state = {
|
|
60
|
+
success: props.isSuccess,
|
|
61
|
+
text: props.text,
|
|
62
|
+
persist: props.persist
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
componentDidUpdate(prevProps) {
|
|
67
|
+
if (this.props.opened !== prevProps.opened) {
|
|
68
|
+
this.setState({
|
|
69
|
+
success: this.props.opened ? this.props.isSuccess : this.state.success,
|
|
70
|
+
text: this.props.opened ? this.props.text : this.state.text,
|
|
71
|
+
persist: this.props.opened ? this.props.persist : this.state.persist
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
handleClose = () => {
|
|
77
|
+
if (!this.state.persist) {
|
|
78
|
+
this.props.clearMessage();
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
render() {
|
|
83
|
+
const { classes, opened, clearMessage } = this.props;
|
|
84
|
+
|
|
85
|
+
const { success, text, persist } = this.state;
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
|
|
89
|
+
<Snackbar
|
|
90
|
+
open={opened}
|
|
91
|
+
anchorOrigin={{
|
|
92
|
+
vertical: 'bottom',
|
|
93
|
+
horizontal: 'left'
|
|
94
|
+
}}
|
|
95
|
+
classes={{
|
|
96
|
+
root: classes.autoWidthRoot
|
|
97
|
+
}}
|
|
98
|
+
ContentProps={{
|
|
99
|
+
classes: {
|
|
100
|
+
root: clsx(classes.autoWidth, {
|
|
101
|
+
[classes.success]: success
|
|
102
|
+
}),
|
|
103
|
+
message: persist ? classes.fullScreenMessage : undefined
|
|
104
|
+
}
|
|
105
|
+
}}
|
|
106
|
+
ClickAwayListenerProps={{
|
|
107
|
+
onClickAway: this.handleClose
|
|
108
|
+
}}
|
|
109
|
+
autoHideDuration={persist ? null : 6000}
|
|
110
|
+
onClose={this.handleClose}
|
|
111
|
+
disableWindowBlurListener={persist}
|
|
112
|
+
>
|
|
113
|
+
<Alert
|
|
114
|
+
variant="filled"
|
|
115
|
+
severity={success ? 'success' : 'error'}
|
|
116
|
+
classes={{
|
|
117
|
+
message: 'text-pre-wrap',
|
|
118
|
+
standardError: 'errorBackgroundColor',
|
|
119
|
+
standardSuccess: 'successBackgroundColor'
|
|
120
|
+
}}
|
|
121
|
+
action={(
|
|
122
|
+
<IconButton
|
|
123
|
+
key="close"
|
|
124
|
+
aria-label="Close"
|
|
125
|
+
color="inherit"
|
|
126
|
+
className={classes.close}
|
|
127
|
+
onClick={clearMessage}
|
|
128
|
+
>
|
|
129
|
+
<CloseIcon />
|
|
130
|
+
</IconButton>
|
|
131
|
+
)}
|
|
132
|
+
>
|
|
133
|
+
{text}
|
|
134
|
+
</Alert>
|
|
135
|
+
</Snackbar>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export default withStyles(styles as any)(Message);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2023.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as React from 'react';
|
|
10
|
+
import createStyles from '@mui/styles/createStyles';
|
|
11
|
+
import withStyles from '@mui/styles/withStyles';
|
|
12
|
+
import clsx from 'clsx';
|
|
13
|
+
import { FileTypeIcon } from './utils';
|
|
14
|
+
|
|
15
|
+
const styles = theme =>
|
|
16
|
+
createStyles({
|
|
17
|
+
preview: {
|
|
18
|
+
backgroundSize: 'cover',
|
|
19
|
+
width: '36px',
|
|
20
|
+
height: '48px',
|
|
21
|
+
borderRadius: '4px',
|
|
22
|
+
marginRight: '16px',
|
|
23
|
+
color: 'rgba(0,0,0,.2)',
|
|
24
|
+
transition: 'color 200ms ease-in-out',
|
|
25
|
+
backgroundPosition: 'center'
|
|
26
|
+
},
|
|
27
|
+
previewNormal: {
|
|
28
|
+
width: '60px',
|
|
29
|
+
height: 'calc(100% - 16px)'
|
|
30
|
+
},
|
|
31
|
+
previewHoverIcon: {
|
|
32
|
+
'&:hover': {
|
|
33
|
+
color: theme.palette.primary.main
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
previewHoverImage: {
|
|
37
|
+
'&:hover': {
|
|
38
|
+
boxShadow: `0 0 1px 1px ${theme.palette.primary.main}`
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const DocumentIconsChooser = props => {
|
|
44
|
+
const {
|
|
45
|
+
type, thumbnail, classes, hovered = true, isHeader
|
|
46
|
+
} = props;
|
|
47
|
+
|
|
48
|
+
return thumbnail ? (
|
|
49
|
+
<div
|
|
50
|
+
style={{
|
|
51
|
+
backgroundImage: `url(data:image;base64,${thumbnail})`
|
|
52
|
+
}}
|
|
53
|
+
className={clsx(classes.preview, {
|
|
54
|
+
[classes.previewHoverImage]: hovered,
|
|
55
|
+
[classes.previewNormal]: isHeader
|
|
56
|
+
})}
|
|
57
|
+
/>
|
|
58
|
+
) : (
|
|
59
|
+
<div
|
|
60
|
+
className={clsx(classes.preview, {
|
|
61
|
+
[classes.previewHoverIcon]: hovered
|
|
62
|
+
})}
|
|
63
|
+
>
|
|
64
|
+
<FileTypeIcon mimeType={type} />
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export default withStyles(styles)(DocumentIconsChooser);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2023.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './utils';
|
|
10
|
+
export * from './DocumentIconsChooser';
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2022.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React from 'react';
|
|
10
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
11
|
+
|
|
12
|
+
export const formatDocumentSize = (size: number): string => {
|
|
13
|
+
if (size < Math.pow(1024, 2)) {
|
|
14
|
+
return `${Math.round(size / 1024)} kb`;
|
|
15
|
+
}
|
|
16
|
+
if (size < Math.pow(1024, 3)) {
|
|
17
|
+
return `${Math.round(size / 1024 / 1024)} Mb`;
|
|
18
|
+
}
|
|
19
|
+
if (size < Math.pow(1024, 4)) {
|
|
20
|
+
return `${Math.round(size / 1024 / 1024 / 1024)} Gb`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return size.toString();
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const getDocumentContent = (file: File): Promise<string> => {
|
|
27
|
+
const reader = new FileReader();
|
|
28
|
+
|
|
29
|
+
return new Promise(resolve => {
|
|
30
|
+
reader.onload = () => resolve(reader.result);
|
|
31
|
+
reader.readAsDataURL(file);
|
|
32
|
+
}).then((result: any) => result.replace(`data:${file.type};base64,`, ''));
|
|
33
|
+
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const getDocumentThumbnail = (file: File): Promise<string> => {
|
|
37
|
+
if (file.type.match(/image/)) {
|
|
38
|
+
return getDocumentContent(file);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return new Promise(resolve => resolve(''));
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const getIcon = type => {
|
|
45
|
+
switch (type) {
|
|
46
|
+
case 'image/tiff':
|
|
47
|
+
case 'image/bmp':
|
|
48
|
+
case 'image/png':
|
|
49
|
+
case 'image/gif':
|
|
50
|
+
case 'image/jpeg':
|
|
51
|
+
return 'file-image';
|
|
52
|
+
case 'application/pdf':
|
|
53
|
+
return 'file-pdf';
|
|
54
|
+
case 'application/msword':
|
|
55
|
+
return 'file-word';
|
|
56
|
+
case 'application/vnd.ms-excel':
|
|
57
|
+
return 'file-excel';
|
|
58
|
+
case 'application/vnd.ms-powerpoint':
|
|
59
|
+
return 'file-powerpoint';
|
|
60
|
+
case 'application/zip':
|
|
61
|
+
return 'file-archive';
|
|
62
|
+
case 'application/x-gzip':
|
|
63
|
+
return 'file-archive';
|
|
64
|
+
case 'application/txt':
|
|
65
|
+
return 'file-alt';
|
|
66
|
+
default:
|
|
67
|
+
return 'file';
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const FileTypeIcon = ({ mimeType }) => <FontAwesomeIcon icon={getIcon(mimeType)} fixedWidth className="w-100 h-100" />;
|