@dvrd/dvr-controls 1.0.14 → 1.0.16

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.
Files changed (180) hide show
  1. package/index.ts +8 -1
  2. package/package.json +29 -23
  3. package/src/js/button/button.tsx +102 -0
  4. package/src/js/button/buttonController.tsx +179 -0
  5. package/src/js/button/closeButton.tsx +29 -0
  6. package/src/js/button/dvrdButton.tsx +128 -0
  7. package/src/js/button/outlinedButton.tsx +105 -0
  8. package/src/js/button/simpleButton.tsx +163 -0
  9. package/src/js/button/style/button.scss +95 -0
  10. package/src/js/button/style/closeButton.scss +15 -0
  11. package/src/js/button/style/dvrdButton.scss +30 -0
  12. package/src/js/button/style/outlinedButton.scss +84 -0
  13. package/src/js/button/style/simpleButton.scss +80 -0
  14. package/src/js/carousel/DVRCarousel.tsx +163 -0
  15. package/src/js/carousel/DVRCarouselController.tsx +95 -0
  16. package/src/js/carousel/style/DVRCarousel.scss +38 -0
  17. package/src/js/checkbox/checkbox.tsx +148 -0
  18. package/src/js/checkbox/checkboxController.tsx +131 -0
  19. package/src/js/checkbox/style/checkbox.scss +109 -0
  20. package/src/js/colorPicker/colorPicker.tsx +118 -0
  21. package/src/js/colorPicker/style/colorPicker.scss +20 -0
  22. package/src/js/date/dvrdDatePicker.tsx +357 -0
  23. package/src/js/date/style/dvrdDatePicker.scss +307 -0
  24. package/src/js/dialog/dialog.tsx +207 -0
  25. package/src/js/dialog/dialogController.tsx +70 -0
  26. package/src/js/dialog/inlineDialog.tsx +127 -0
  27. package/src/js/dialog/style/dialog.scss +61 -0
  28. package/src/js/events/withEvents.tsx +40 -0
  29. package/src/js/head/DVRHead.tsx +49 -0
  30. package/src/js/header/DVRHeader.tsx +417 -0
  31. package/src/js/header/style/header.scss +206 -0
  32. package/src/js/icon/awesomeIcon.tsx +20 -0
  33. package/src/js/image/imageUpload.tsx +69 -0
  34. package/src/js/image/style/imageUpload.scss +11 -0
  35. package/src/js/info/info.tsx +136 -0
  36. package/src/js/info/style/info.scss +39 -0
  37. package/src/js/input/animated/animatedTextField.tsx +159 -0
  38. package/src/js/input/date/dateField.tsx +360 -0
  39. package/src/js/input/date/dateFieldController.tsx +245 -0
  40. package/src/js/input/date/datePicker/datePicker.tsx +186 -0
  41. package/src/js/input/date/datePicker/style/datePicker.scss +102 -0
  42. package/src/js/input/date/input/dateInput.tsx +214 -0
  43. package/src/js/input/date/style/dateField.scss +40 -0
  44. package/src/js/input/date/timePicker/style/timePicker.scss +95 -0
  45. package/src/js/input/date/timePicker/timePicker.tsx +143 -0
  46. package/src/js/input/editor/DVREditor.tsx +21 -0
  47. package/src/js/input/number/numberInput.tsx +157 -0
  48. package/src/js/input/password/passwordInput.tsx +140 -0
  49. package/src/js/input/password/passwordRules.tsx +48 -0
  50. package/src/js/input/password/style/passwordInput.scss +39 -0
  51. package/src/js/input/password/style/passwordRules.scss +41 -0
  52. package/src/js/input/simple/style/simpleInput.scss +98 -0
  53. package/src/js/input/simple/v2/simpleInputV2.tsx +178 -0
  54. package/src/js/input/style/input.scss +138 -0
  55. package/src/js/input/v2/inputController_v2.tsx +250 -0
  56. package/src/js/input/v2/input_v2.tsx +7 -0
  57. package/src/js/label/label.tsx +196 -0
  58. package/src/js/label/style/label.scss +4 -0
  59. package/src/js/link/link.tsx +38 -0
  60. package/src/js/link/style/link.scss +30 -0
  61. package/src/js/loader/loader.tsx +79 -0
  62. package/src/js/loader/loaderController.tsx +61 -0
  63. package/src/js/loader/style/loader.scss +53 -0
  64. package/src/js/media/media.tsx +72 -0
  65. package/src/js/navigator/navigator.tsx +51 -0
  66. package/src/js/optionsList/dvrdOptionsList.tsx +112 -0
  67. package/src/js/optionsList/style/dvrdOptionsList.scss +84 -0
  68. package/src/js/optionsMenu/optionsMenu.tsx +187 -0
  69. package/src/js/optionsMenu/style/optionsMenu.scss +70 -0
  70. package/src/js/pdf/element/pdfElement.tsx +315 -0
  71. package/src/js/pdf/element/style/pdfElement.scss +111 -0
  72. package/src/js/pdf/history/pdfHistory.ts +57 -0
  73. package/src/js/pdf/image/pdfImage.tsx +175 -0
  74. package/src/js/pdf/image/style/pdfImage.scss +34 -0
  75. package/src/js/pdf/invoiceTable/pdfInvoiceTable.tsx +176 -0
  76. package/src/js/pdf/invoiceTable/style/pdfInvoiceTable.scss +32 -0
  77. package/src/js/pdf/pdfTemplateCreator.tsx +279 -0
  78. package/src/js/pdf/settings/buttons/iconButton.tsx +49 -0
  79. package/src/js/pdf/settings/buttons/style/iconButton.scss +50 -0
  80. package/src/js/pdf/settings/image/pdfImageSettings.tsx +82 -0
  81. package/src/js/pdf/settings/image/style/pdfImageSettings.scss +9 -0
  82. package/src/js/pdf/settings/invoiceTable/pdfInvoiceTableSettings.tsx +141 -0
  83. package/src/js/pdf/settings/invoiceTable/style/pdfInvoiceTableSettings.scss +38 -0
  84. package/src/js/pdf/settings/pdfElementSettings.tsx +86 -0
  85. package/src/js/pdf/settings/style/pdfElementSettings.scss +56 -0
  86. package/src/js/pdf/settings/text/pdfTextSettings.tsx +202 -0
  87. package/src/js/pdf/settings/text/style/pdfTextSettings.scss +94 -0
  88. package/src/js/pdf/style/pdfTemplateCreator.scss +118 -0
  89. package/src/js/pdf/text/pdfText.tsx +267 -0
  90. package/src/js/pdf/text/style/pdfText.scss +22 -0
  91. package/src/js/pdf/v2/pdfElement/pdfDraggableElement.tsx +193 -0
  92. package/src/js/pdf/v2/types/pdfTemplateTypes.ts +27 -0
  93. package/src/js/popup/style/withBackground.scss +29 -0
  94. package/src/js/popup/withBackground.tsx +92 -0
  95. package/src/js/select/async/asyncSelect.tsx +46 -0
  96. package/src/js/select/async/style/asyncSelect.scss +23 -0
  97. package/src/js/select/dvrdSelect.tsx +214 -0
  98. package/src/js/select/dvrdSelectController.tsx +81 -0
  99. package/src/js/select/select.tsx +310 -0
  100. package/src/js/select/selectController.tsx +341 -0
  101. package/src/js/select/style/dvrdSelect.scss +140 -0
  102. package/src/js/select/style/select.scss +199 -0
  103. package/src/js/sidebarMenu/sidebarMenu.tsx +167 -0
  104. package/src/js/sidebarMenu/style/sidebarMenu.scss +167 -0
  105. package/src/js/slider/DVRSlider.tsx +107 -0
  106. package/src/js/slider/style/DVRSlider.scss +88 -0
  107. package/src/js/snackbar/snackbar.tsx +72 -0
  108. package/src/js/snackbar/snackbarController.tsx +104 -0
  109. package/src/js/snackbar/style/snackbar.scss +46 -0
  110. package/src/js/switch/dvrdSwitch.tsx +53 -0
  111. package/src/js/switch/style/dvrdSwitch.scss +47 -0
  112. package/src/js/switch/style/switch.scss +84 -0
  113. package/src/js/switch/switch.tsx +115 -0
  114. package/src/js/switch/switchController.tsx +97 -0
  115. package/src/js/textField/dvrdInput.tsx +219 -0
  116. package/src/js/textField/dvrdInputController.tsx +97 -0
  117. package/src/js/textField/dvrdNumberInput.tsx +141 -0
  118. package/src/js/textField/dvrdPasswordInput.tsx +40 -0
  119. package/src/js/textField/style/dvrdInput.scss +114 -0
  120. package/src/js/textField/style/dvrdPassword.scss +15 -0
  121. package/src/js/topButton/style/topButton.scss +54 -0
  122. package/src/js/topButton/topButton.tsx +136 -0
  123. package/src/js/util/analyticsUtil.ts +41 -0
  124. package/src/js/util/colorUtil.ts +230 -0
  125. package/src/js/util/componentUtil.tsx +59 -0
  126. package/src/js/util/constants.ts +12 -0
  127. package/src/js/util/controlContext.tsx +46 -0
  128. package/src/js/util/controlUtil.ts +107 -0
  129. package/src/js/util/cookieUtil.ts +17 -0
  130. package/src/js/util/eventUtil.ts +65 -0
  131. package/src/js/util/googleUtil.ts +88 -0
  132. package/src/js/util/interfaces.ts +180 -0
  133. package/src/js/util/jwtUtil.ts +72 -0
  134. package/src/js/util/miscUtil.ts +170 -0
  135. package/src/js/util/momentUtil.ts +45 -0
  136. package/src/js/util/pdfUtil.ts +124 -0
  137. package/src/js/util/requestUtil.ts +145 -0
  138. package/src/js/util/responsiveUtil.ts +37 -0
  139. package/src/js/util/validationUtil.ts +13 -0
  140. package/src/res/img/lock-handle.png +0 -0
  141. package/src/res/img/lock-handle.webp +0 -0
  142. package/src/res/img/lock.png +0 -0
  143. package/src/res/img/lock.webp +0 -0
  144. package/src/style/common-icons-variables.scss +140 -0
  145. package/src/style/common-icons.scss +714 -0
  146. package/src/style/common-variables.scss +243 -0
  147. package/src/style/display-breakpoints.scss +141 -0
  148. package/src/style/fonts/common-icons.eot +0 -0
  149. package/src/style/fonts/common-icons.svg +150 -0
  150. package/src/style/fonts/common-icons.ttf +0 -0
  151. package/src/style/fonts/common-icons.woff +0 -0
  152. package/src/style/fonts/common-icons.woff2 +0 -0
  153. package/src/style/fonts/fontAwesome/css/all.css +7003 -0
  154. package/src/style/fonts/fontAwesome/css/all.min.css +6 -0
  155. package/src/style/fonts/fontAwesome/css/brands.css +1423 -0
  156. package/src/style/fonts/fontAwesome/css/brands.min.css +6 -0
  157. package/src/style/fonts/fontAwesome/css/fontawesome.css +5519 -0
  158. package/src/style/fonts/fontAwesome/css/fontawesome.min.css +6 -0
  159. package/src/style/fonts/fontAwesome/css/regular.css +19 -0
  160. package/src/style/fonts/fontAwesome/css/regular.min.css +6 -0
  161. package/src/style/fonts/fontAwesome/css/solid.css +19 -0
  162. package/src/style/fonts/fontAwesome/css/solid.min.css +6 -0
  163. package/src/style/fonts/fontAwesome/css/svg-with-js.css +634 -0
  164. package/src/style/fonts/fontAwesome/css/svg-with-js.min.css +6 -0
  165. package/src/style/fonts/fontAwesome/css/v4-font-face.css +26 -0
  166. package/src/style/fonts/fontAwesome/css/v4-font-face.min.css +6 -0
  167. package/src/style/fonts/fontAwesome/css/v4-shims.css +2146 -0
  168. package/src/style/fonts/fontAwesome/css/v4-shims.min.css +6 -0
  169. package/src/style/fonts/fontAwesome/css/v5-font-face.css +22 -0
  170. package/src/style/fonts/fontAwesome/css/v5-font-face.min.css +6 -0
  171. package/src/style/fonts/fontAwesome/webfonts/fa-brands-400.ttf +0 -0
  172. package/src/style/fonts/fontAwesome/webfonts/fa-brands-400.woff2 +0 -0
  173. package/src/style/fonts/fontAwesome/webfonts/fa-regular-400.ttf +0 -0
  174. package/src/style/fonts/fontAwesome/webfonts/fa-regular-400.woff2 +0 -0
  175. package/src/style/fonts/fontAwesome/webfonts/fa-solid-900.ttf +0 -0
  176. package/src/style/fonts/fontAwesome/webfonts/fa-solid-900.woff2 +0 -0
  177. package/src/style/fonts/fontAwesome/webfonts/fa-v4compatibility.ttf +0 -0
  178. package/src/style/fonts/fontAwesome/webfonts/fa-v4compatibility.woff2 +0 -0
  179. package/src/style/variables.scss +11 -0
  180. package/.gitignore +0 -31
@@ -0,0 +1,12 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ /*
6
+ ================================================
7
+ KEY CODES
8
+ ================================================
9
+ */
10
+ export const ESCAPE_CODE = 'Escape', ESCAPE_IE_CODE = 'Esc', ENTER_CODE = 'Enter', BACKSPACE_CODE = 'Backspace';
11
+
12
+
@@ -0,0 +1,46 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ import React, {Context, PropsWithChildren, useEffect} from 'react';
6
+ import {ControlVariant} from "./interfaces";
7
+ import {defer} from 'lodash';
8
+
9
+ // noinspection JSUnusedGlobalSymbols
10
+ export interface ThemeContextShape {
11
+ baseColor: string,
12
+ contrastColor: string,
13
+ onChange: Function,
14
+ }
15
+
16
+ export interface ProviderProps {
17
+ theme: ThemeShape;
18
+ }
19
+
20
+ export interface ThemeShape {
21
+ baseColor: string,
22
+ contrastColor: string,
23
+ controlVariant?: ControlVariant;
24
+ borderColor?: string;
25
+ onChange?: (theme?: ThemeShape) => void;
26
+ }
27
+
28
+ export const ControlContext: Context<ThemeShape> = React.createContext<ThemeShape>(
29
+ {baseColor: 'black', contrastColor: 'white', controlVariant: ControlVariant.STANDARD});
30
+
31
+ export default function ThemeContextProvider(props: PropsWithChildren<ProviderProps>) {
32
+ const {theme, children} = props;
33
+ useEffect(() => {
34
+ defer(() => {
35
+ const root = document.documentElement;
36
+ root.style.setProperty('--base-color', theme.baseColor);
37
+ root.style.setProperty('--contrast-color', theme.contrastColor);
38
+ });
39
+ }, [theme]);
40
+
41
+ return (
42
+ <ControlContext.Provider value={theme}>
43
+ {children}
44
+ </ControlContext.Provider>
45
+ )
46
+ }
@@ -0,0 +1,107 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ import React from 'react';
6
+ import {v4} from 'uuid';
7
+ import {ENTER_CODE, ESCAPE_CODE, ESCAPE_IE_CODE} from "./constants";
8
+ import {Breakpoint} from "./interfaces";
9
+
10
+ export const generateUUID = (): string => {
11
+ // Crypto is not supported by some browsers, so we use another method if crypto is not supported.
12
+ if (window.crypto)
13
+ // @ts-ignore
14
+ return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c: any) =>
15
+ (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
16
+ );
17
+ return v4();
18
+ };
19
+
20
+ export const isNotNull = (obj: any): boolean => {
21
+ if (obj === undefined || obj === null)
22
+ return false;
23
+ return !(obj.hasOwnProperty('length') && obj.length === 0);
24
+ };
25
+
26
+ export const isNull = (obj: any): boolean => !isNotNull(obj);
27
+
28
+ export const hasHover = (element: HTMLElement | null): boolean => {
29
+ if(!element) return false;
30
+ if (isNotNull(element) && element.parentElement !== null) {
31
+ return element.parentElement.querySelector(':hover') === element;
32
+ }
33
+ return false;
34
+ };
35
+
36
+ export const pxToRem = (pxValue: number) => {
37
+ let fontSize: number = getFontSize();
38
+ return pxValue / fontSize;
39
+ };
40
+
41
+ export const remToPx = (remValue: number) => {
42
+ let htmlElement = document.getElementsByTagName('html')[0];
43
+ let fontSize: number | string = window.getComputedStyle(htmlElement, null).getPropertyValue('font-size');
44
+ fontSize = parseInt(fontSize.slice(0, fontSize.length - 2), 10);
45
+ return remValue * fontSize;
46
+ };
47
+
48
+ const getFontSize = (): number => {
49
+ let fontSize: number | string = getComputedProperty('font-size');
50
+ fontSize = parseInt(fontSize.slice(0, fontSize.length - 2), 10);
51
+ return fontSize;
52
+ };
53
+
54
+ export const getComputedProperty = (propertyName: string, element?: Element): string => {
55
+ const htmlElement = element || document.getElementsByTagName('html')[0];
56
+ return window.getComputedStyle(htmlElement, null).getPropertyValue(propertyName);
57
+ };
58
+
59
+ export const stringStartsWith = (string: string, value: string): boolean => {
60
+ value = value.trim().toLowerCase();
61
+ const valueLength = value.length;
62
+ return string.toLowerCase().slice(0, valueLength) === value;
63
+ };
64
+
65
+ export const stringContains = (string: string, value: string): boolean =>
66
+ string.toLowerCase().includes(value.toLowerCase());
67
+
68
+ export const voidFunction = () => null;
69
+
70
+ export const escapePressed = (evt: React.KeyboardEvent | KeyboardEvent) => {
71
+ return ((evt.key && (evt.key === ESCAPE_IE_CODE || evt.key === ESCAPE_CODE))) || evt.keyCode === 27 || evt.which ===
72
+ 27;
73
+ };
74
+
75
+ export const enterPressed = (evt: React.KeyboardEvent | KeyboardEvent) => {
76
+ return ((evt.key && evt.key === ENTER_CODE) || evt.keyCode === 13 || evt.which === 13);
77
+ };
78
+
79
+ let canvas: HTMLCanvasElement | null = null;
80
+ export const calculateTextWidth = (text: string, fontSize?: number, fontFamily?: string): number => {
81
+ canvas = canvas || document.createElement('canvas');
82
+ const context = canvas.getContext('2d');
83
+ if (fontSize === undefined) fontSize = getFontSize();
84
+ if (fontFamily === undefined || !fontFamily.length) fontFamily = getComputedProperty('font-family');
85
+
86
+ let width = 0;
87
+ if (context) {
88
+ context.font = `${fontSize}px ${fontFamily}`;
89
+ width = context.measureText(text).width;
90
+ }
91
+ return Math.ceil(width);
92
+ };
93
+
94
+ export const pad = (num: string | number): string => ('0' + num).slice(-2);
95
+
96
+ export const stopPropagation = (evt: Event | React.SyntheticEvent) => {
97
+ evt.stopPropagation();
98
+ };
99
+
100
+ export const assert = (condition: boolean, errMsg?: string | null) => {
101
+ const message = errMsg || 'Undocumented assertion error';
102
+ if (!condition) {
103
+ if (typeof Error !== 'undefined')
104
+ throw new Error(message);
105
+ else throw message;
106
+ }
107
+ };
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ import Cookies, {CookieAttributes} from "js-cookie";
6
+
7
+ export const setCookie = (key: string, value: string, args?: CookieAttributes) => {
8
+ Cookies.set(key, value, {...args})
9
+ }
10
+
11
+ export const removeCookie = (key: string, args?: CookieAttributes) => {
12
+ Cookies.remove(key, args);
13
+ };
14
+
15
+ export const getCookie = (key: string): string | undefined => {
16
+ return Cookies.get(key);
17
+ }
@@ -0,0 +1,65 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ import React from 'react';
6
+ import {DialogActions} from "../dialog/dialogController";
7
+ import {DialogConfig, Snack} from "./interfaces";
8
+
9
+ interface ListenerShape {
10
+ component: string,
11
+ eventName: string,
12
+ eventHandler: Function,
13
+ }
14
+
15
+ const listeners: ListenerShape[] = [];
16
+
17
+ export const addCustomEventListener = (componentName: string, eventName: string, eventHandler: Function): boolean => {
18
+ if (listenerExists(componentName, eventName)) return false;
19
+ listeners.push({component: componentName, eventName, eventHandler});
20
+ return true;
21
+ };
22
+
23
+ export const removeCustomEventListener = (componentName: string, eventName: string): boolean => {
24
+ let foundListeners = false;
25
+ for (let i = listeners.length - 1; i >= 0; i--) {
26
+ const listener = listeners[i];
27
+ if (listener.component === componentName && listener.eventName === eventName) {
28
+ listeners.splice(i, 1);
29
+ foundListeners = true;
30
+ }
31
+ }
32
+ return foundListeners;
33
+ };
34
+
35
+ export const dispatchCustomEvent = (eventName: string, data?: any | null) => {
36
+ let listenerFound = false;
37
+ for (const listener of listeners) {
38
+ if (listener.eventName === eventName) {
39
+ listenerFound = true;
40
+ listener.eventHandler(data);
41
+ }
42
+ }
43
+ };
44
+
45
+ const listenerExists = (componentName: string, eventName: string) => {
46
+ for (let i = 0; i < listeners.length; i++) {
47
+ const listener = listeners[i];
48
+ if (listener.component === componentName && listener.eventName === eventName) return true;
49
+ }
50
+ return false;
51
+ };
52
+
53
+ //==========================
54
+ // Events
55
+ //==========================
56
+
57
+ export const showDialog = (message: string | React.ReactElement, title: string = 'Bericht van het systeem',
58
+ actions?: DialogActions | null,
59
+ persistent?: boolean, transparent?: boolean) => {
60
+ dispatchCustomEvent('onOpenDialog', {message, title, actions, transparent, persistent});
61
+ };
62
+
63
+ export const showSnackbar = (text: string | React.ReactElement, config?: DialogConfig) => {
64
+ dispatchCustomEvent('onShowSnackbar', {text, config});
65
+ };
@@ -0,0 +1,88 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ /**
6
+ * Loads Google SDK.
7
+ * @see https://developers.google.com/api-client-library/javascript/reference/referencedocs#gapiclientloadname--------version--------callback
8
+ * @see https://developers.google.com/api-client-library/javascript/reference/referencedocs#gapiauth2initparams
9
+ * @see https://developers.google.com/api-client-library/javascript/reference/referencedocs#gapiauth2getauthinstance
10
+ */
11
+ export const loadSocial = (appId: string): Promise<void> => new Promise((resolve, reject) => {
12
+ const firstJS = document.getElementsByTagName('script')[0];
13
+ const js = document.createElement('script');
14
+
15
+ js.src = '//apis.google.com/js/platform.js';
16
+ js.id = 'gapi-client';
17
+ js.onload = () => {
18
+ window.gapi.load('auth2', () => {
19
+ if (!window.gapi.auth2.getAuthInstance()) {
20
+ window.gapi.auth2.init({
21
+ client_id: appId,
22
+ fetchBasicProfile: true,
23
+ scope: null
24
+ }).then(() => resolve(), (err: any) => reject({
25
+ provider: 'google',
26
+ type: 'load',
27
+ description: 'Failed to load SDK',
28
+ error: err
29
+ }));
30
+ } else resolve();
31
+ });
32
+ };
33
+
34
+ if (!firstJS?.parentNode) document.appendChild(js);
35
+ else firstJS.parentNode.appendChild(js);
36
+ });
37
+
38
+ /**
39
+ * Checks if user is logged in to app through Google.
40
+ * Requires SDK to be loaded first.
41
+ * @see https://developers.google.com/api-client-library/javascript/reference/referencedocs#gapiauth2getauthinstance
42
+ * @see https://developers.google.com/api-client-library/javascript/reference/referencedocs#googleauthissignedinget
43
+ * @see https://developers.google.com/api-client-library/javascript/reference/referencedocs#googleauthcurrentuserget
44
+ */
45
+ export const checkLogin = () => new Promise((resolve, reject) => {
46
+ const GoogleAuth = window.gapi.auth2.getAuthInstance();
47
+
48
+ if (!GoogleAuth.isSignedIn.get()) {
49
+ return reject({
50
+ provider: 'google',
51
+ type: 'check_login',
52
+ description: 'Not authenticated',
53
+ error: null
54
+ });
55
+ }
56
+
57
+ return resolve(GoogleAuth.currentUser.get());
58
+ });
59
+
60
+ /**
61
+ * Trigger Google login process.
62
+ * Requires SDK to be loaded first.
63
+ * @see https://developers.google.com/api-client-library/javascript/reference/referencedocs#gapiauth2getauthinstance
64
+ * @see https://developers.google.com/api-client-library/javascript/reference/referencedocs#googleauthsignin
65
+ */
66
+ export const login = () => new Promise((resolve, reject) => {
67
+ const GoogleAuth = window.gapi.auth2.getAuthInstance();
68
+
69
+ GoogleAuth.signIn().then(
70
+ () => checkLogin().then(resolve, reject),
71
+ (err: any) => reject({
72
+ provider: 'google',
73
+ type: 'auth',
74
+ description: 'Authentication failed',
75
+ error: err
76
+ })
77
+ );
78
+ });
79
+
80
+ /**
81
+ * Trigger Google logout.
82
+ * Requires SDK to be loaded first.
83
+ * @see https://developers.google.com/api-client-library/javascript/reference/referencedocs#googleauthsignout
84
+ */
85
+ export const googleLogout = () => new Promise((resolve, reject) => {
86
+ const GoogleAuth = window.gapi.auth2.getAuthInstance();
87
+ GoogleAuth.signOut().then(resolve, reject);
88
+ })
@@ -0,0 +1,180 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ import React, {CSSProperties, ReactElement} from 'react';
6
+
7
+ // =========== INTERFACES
8
+
9
+ export interface MenuItem {
10
+ label?: string;
11
+ component?: React.ReactNode;
12
+ subItems?: MenuItem[];
13
+ onClick?: Function;
14
+ normalCase?: boolean;
15
+ id?: string;
16
+ allowPropagation?: boolean;
17
+ }
18
+
19
+ export interface PasswordRule {
20
+ label: string;
21
+ validator: (password: string) => boolean;
22
+ }
23
+
24
+ export interface IndexedObject<T> {
25
+ [key: string]: T;
26
+ }
27
+
28
+ export interface ColorSet {
29
+ base: string;
30
+ contrast: string;
31
+ }
32
+
33
+ export interface OrnamentShape {
34
+ placement?: ElementPosition;
35
+ element: React.ReactElement | string;
36
+ allowPropagation?: boolean;
37
+ }
38
+
39
+ export interface ResponseData extends IndexedObject<any> {
40
+ status: string;
41
+ message?: string;
42
+ success?: boolean;
43
+ }
44
+
45
+ export interface SelectItemShape {
46
+ value: string | number,
47
+ label: string | number | ReactElement,
48
+ inputLabel?: string,
49
+ selectable?: boolean,
50
+ labelClass?: string;
51
+ labelStyle?: CSSProperties;
52
+ valueLabel?: string;
53
+
54
+ [key: string]: any,
55
+ }
56
+
57
+ export interface DialogConfig {
58
+ backgroundColor?: string;
59
+ textColor?: string;
60
+ }
61
+
62
+ // =========== ENUMS
63
+
64
+ export enum ModeEnum {DETAIL = 'detail', EDIT = 'edit', NEW = 'new'}
65
+
66
+ export enum Breakpoint {XS = 0, SM = 600, MD = 960, LG = 1280, XL = 1920}
67
+
68
+ export enum MenuPlacement {TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT}
69
+
70
+ export enum ColorPickerType {
71
+ SKETCH, PHOTOSHOP, CHROME, CIRCLE, TWITTER, BLOCK, COMPACT
72
+ }
73
+
74
+ export enum ColorPickerResultType {HEX, RGB, HSL}
75
+
76
+ export enum ControlVariant {OUTLINED = 'outlined', STANDARD = 'standard', SIMPLE = 'simple'}
77
+
78
+ export enum ControlPadding {SMALL = 'sp', NORMAL = 'np', LARGE = 'lp'}
79
+
80
+ export enum ElementPosition {LEFT = 'left', RIGHT = 'right', TOP = 'top', BOTTOM = 'bottom', CENTER = 'center'}
81
+
82
+ export enum EventType {CREATE, UPDATE, DELETE}
83
+
84
+ export enum FetchMethod {GET = 'GET', POST = 'POST', PUT = 'PUT', DELETE = 'DELETE', PATCH = 'PATCH'}
85
+
86
+ export enum PDFSettingType {TEXT, IMAGE}
87
+
88
+ export enum PDFElementType {TEXT = 'text', IMAGE = 'image', INVOICE_TABLE = 'invoice_table'}
89
+
90
+ export enum PDFElementSubType {INVOICE_TITLE = 'invoice_title'}
91
+
92
+ export enum PDFElementPersist {CONFIRM = 'confirm', PERSISTENT = 'persistent', NOT_PERSISTENT = 'not-persistent'}
93
+
94
+ export enum PdfFont {
95
+ LATO = 'lato',
96
+ MERRIWEATHER = 'merriweather',
97
+ NOTO_SANS = 'noto-sans',
98
+ NOTO_SERIF = 'noto-serif',
99
+ OPEN_SANS = 'open-sans',
100
+ PLAYFAIR = 'playfair',
101
+ PT_SERIF = 'pt-serif',
102
+ ROBOTO = 'roboto',
103
+ ROBOTO_MONO = 'roboto-mono',
104
+ HELVETICA = 'helvetica',
105
+ SOURCE_SANS_PRO = 'source-sans-pro'
106
+ }
107
+
108
+ export enum MediaType {VIDEO, IMAGE}
109
+
110
+ export enum SideMenuMode {COMPACT, FULL}
111
+
112
+ export enum PDFDisplay {FIRST_PAGE = 'first_page', LAST_PAGE = 'last_page', ALL_PAGES = 'all_pages'}
113
+
114
+ // =========== TYPES
115
+ export type OptionsMenuItem = {
116
+ label: string;
117
+ icon?: React.ReactNode;
118
+ iconPlacement?: ElementPosition;
119
+ onClick?: Function;
120
+ disabled?: boolean;
121
+ };
122
+
123
+ export type ErrorType = string | null;
124
+
125
+ export type CustomAppEvent = {
126
+ eventName: string,
127
+ handler: Function,
128
+ }
129
+
130
+ export type ChangeFunction<T = any> = (value: T, evt?: React.ChangeEvent) => void;
131
+ export type ChangeKeyFunction<K = string, V = any> = (key: K) => ChangeFunction<V>;
132
+ export type ModelResponse<T> = (obj: T, success: boolean | undefined, data: ResponseData) => void;
133
+ export type StrengthGauche = { validator: (password: string) => boolean };
134
+ export type PDFSetting = { key: string; label: string; type: PDFSettingType; value: any };
135
+
136
+ export type PDFElementParams<T extends PDFElementType, O extends IndexedObject<any>> = {
137
+ key: string;
138
+ type: T;
139
+ sub_type?: PDFElementSubType | null;
140
+ dimensions: { left: number; top: number; width: number; height: number };
141
+ options: O;
142
+ persistent?: PDFElementPersist;
143
+ linkedID?: string;
144
+ }
145
+ export type DefaultPDFElementParams<T extends PDFElementType, O extends IndexedObject<any>> = Partial<{
146
+ type: T;
147
+ dimensions: Partial<{ left: number; top: number; width: number; height: number }>;
148
+ options: O;
149
+ persistent?: PDFElementPersist;
150
+ key: string;
151
+ linkedID?: string;
152
+ }>
153
+ export type PDFImageParams = { img: File | string | null, persistent: PDFElementPersist; alignment?: ElementPosition; display?: PDFDisplay };
154
+ export type PDFTextParams = { bold: boolean; underline: boolean; italic: boolean; fontSize: number; text: string; alignment?: ElementPosition; disabled?: boolean, font: PdfFont, color: string; persistent: PDFElementPersist; display?: PDFDisplay };
155
+ export type PDFInvoiceTableParams = { fontSize: number; widths: number[], font: PdfFont, color: string, alignment?: ElementPosition; persistent: PDFElementPersist };
156
+ export type PDFInvoiceWidths = { name: number; price: number; quantity: number; subtotal: number }
157
+ export type PDFTextVariables = { company: IndexedObject<string>; client: IndexedObject<string>; invoice: IndexedObject<string>; }
158
+ export type PDFSubmitHandler = (items: PDFElementParams<any, any>[], callback?: VoidFunction) => void;
159
+ export type PDFElementDimensions = { left: number; top: number; width: number; height: number };
160
+
161
+ export type SidebarItem = {
162
+ label: string; icon?: string | React.ReactNode;
163
+ className?: string;
164
+ id: string;
165
+ onBottom?: boolean;
166
+ route?: string | string[];
167
+ exactRoute?: boolean;
168
+ children?: SidebarItem[];
169
+ }
170
+ export type ResponseCallback = (data: ResponseData) => void;
171
+ export type RNDDimensions = { x: number, y: number, height: number, width: number };
172
+ export type HTMLVideoEvent = (evt: React.SyntheticEvent<HTMLVideoElement, Event>) => void;
173
+ export type RenderFile = {
174
+ filename: string;
175
+ src: string;
176
+ }
177
+ export type Snack = {
178
+ text: string | React.ReactElement;
179
+ config?: DialogConfig;
180
+ }
@@ -0,0 +1,72 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ import Cookies, {CookieAttributes} from "js-cookie";
6
+ import {debug, getSetting} from "./miscUtil";
7
+
8
+ let jwtToken: string | null = null;
9
+
10
+ export const getJwt = (): string | null => {
11
+ if (jwtToken && jwtToken.length) return jwtToken;
12
+
13
+ const jwt = getJwtFromStorage();
14
+ if (jwt && jwt.length) return jwt;
15
+
16
+ const cookieJwt = Cookies.get('JWT');
17
+ if (cookieJwt && cookieJwt.length)
18
+ return cookieJwt;
19
+ return null;
20
+ };
21
+
22
+ export const setJwt = (token: string | null, preserveOnNull: boolean = false, includeStorage: boolean = true) => {
23
+ jwtToken = token;
24
+ if (window.allowCookies || !token) {
25
+ if (token) {
26
+ let options: CookieAttributes = {expires: 1, sameSite: 'strict'};
27
+ if (getSetting('mode') !== 'dev') {
28
+ options.secure = true;
29
+ options.sameSite = 'strict';
30
+ }
31
+ Cookies.set('JWT', token, options);
32
+ } else if (!preserveOnNull) removeJwtCookie();
33
+ if (includeStorage)
34
+ setJwtToStorage(token, preserveOnNull);
35
+ }
36
+ };
37
+
38
+ const setJwtToStorage = (token: string | null, preserveOnNull: boolean = false) => {
39
+ if ((token === null || token === undefined) && !preserveOnNull) removeJwtFromStorage();
40
+ else if (token !== null && token !== undefined) {
41
+ try {
42
+ if (window.localStorage)
43
+ window.localStorage.setItem('JWT', JSON.stringify(token));
44
+ } catch {
45
+ // Localstorage not supported
46
+ }
47
+ }
48
+ };
49
+
50
+ const removeJwtFromStorage = () => {
51
+ try {
52
+ if (window.localStorage)
53
+ window.localStorage.removeItem('JWT');
54
+ } catch {
55
+ // Localstorage not supported
56
+ }
57
+ };
58
+
59
+ const removeJwtCookie = () => {
60
+ Cookies.remove('JWT');
61
+ };
62
+
63
+ const getJwtFromStorage = (): string | null => {
64
+ try {
65
+ if (window.localStorage) {
66
+ const item: string | null = window.localStorage.getItem('JWT');
67
+ if (item === null) return null;
68
+ return JSON.parse(item);
69
+ }
70
+ } catch {}
71
+ return null;
72
+ };