@openlettermarketing/olc-react-sdk 0.0.16 → 0.0.18

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.
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import type { StoreType } from 'polotno/model/store';
3
3
  interface Props {
4
4
  store: StoreType;
5
+ currentTemplateType: string;
5
6
  }
6
7
  declare const SidePanel: React.FC<Props>;
7
8
  export default SidePanel;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@openlettermarketing/olc-react-sdk",
3
3
  "private": false,
4
- "version": "0.0.16",
4
+ "version": "0.0.18",
5
5
  "type": "module",
6
6
  "description": "Simplify template builder integration for any product.",
7
7
  "main": "build/index.js",
package/src/App.tsx CHANGED
@@ -5,7 +5,6 @@ import {Routes, Route} from 'react-router-dom';
5
5
  import {createStore, StoreType} from 'polotno/model/store';
6
6
 
7
7
  // components
8
- // import GenericSnackbar from './components/GenericUIBlocks/GenericSnackbar';
9
8
  import CreateTemplate from './components/CreateTemplate';
10
9
  import TemplateBuilder from './components/TemplateBuilder';
11
10
  import {createGlobalStyle} from 'styled-components';
@@ -66,9 +65,6 @@ const App: React.FC<AppProps> = ({secretKey, returnRoute, styles}) => {
66
65
  element={<TemplateBuilder store={store} returnRoute={returnRoute} />}
67
66
  />
68
67
  </Routes>
69
-
70
- {/* SNACKBAR FOR NOTIFICATIONS */}
71
- {/* <GenericSnackbar /> */}
72
68
  </>
73
69
  );
74
70
  };
@@ -11,5 +11,5 @@
11
11
  display: flex;
12
12
  justify-content: center;
13
13
  align-items: center;
14
- font-weight: 500;
14
+ font-weight: 600;
15
15
  }
@@ -18,7 +18,7 @@
18
18
  .generic-select-container {
19
19
  width: 100%;
20
20
  cursor: pointer;
21
- font-size: 14px;
21
+ font-size: 16px;
22
22
  line-height: 21px;
23
23
  .generic-select__control {
24
24
  height: 100%;
@@ -52,12 +52,23 @@ const customFieldSection: SideSection = {
52
52
  dispatch(fetchCustomFields());
53
53
  }, [dispatch]);
54
54
 
55
- const handleAddElementOnScreen = (event: any, value: any, type: any) => {
56
- event.preventDefault();
57
55
 
58
- if (currentTemplateType === 'Real Penned Letter') {
56
+ const copyCustomFieldText = (value: string) => {
57
+ if (currentTemplateType === "Real Penned Letter") {
58
+ let modifiedString = value.replace(/{{/g, "((").replace(/}}/g, "))");
59
+ copyToClipboard(modifiedString);
60
+ dispatch(success(`${modifiedString} Copied`));
61
+ } else {
59
62
  copyToClipboard(value);
60
63
  dispatch(success(`${value} Copied`));
64
+ }
65
+ };
66
+
67
+ const handleAddElementOnScreen = (event: any, value: any, type: any) => {
68
+ event.preventDefault();
69
+
70
+ if (currentTemplateType === "Real Penned Letter") {
71
+ copyCustomFieldText(value);
61
72
  return;
62
73
  }
63
74
 
@@ -111,7 +122,7 @@ const customFieldSection: SideSection = {
111
122
  </span>
112
123
  <Button
113
124
  style={iconButtonStyles}
114
- onClick={() => copyToClipboard(key)}
125
+ onClick={() => copyCustomFieldText(key)}
115
126
  >
116
127
  <ContentCopyIcon className="copy" />
117
128
  </Button>
@@ -132,7 +143,7 @@ const customFieldSection: SideSection = {
132
143
  </div>
133
144
  <Button onClick={handleShowDialog}></Button>
134
145
  </div>
135
- {customFields.data?.map(
146
+ {customFields?.data?.map(
136
147
  ({key, value}: {key: string; value: string}, i: number) => (
137
148
  <div style={{display: 'flex', alignItems: 'center'}} key={i}>
138
149
  <span
@@ -145,7 +156,7 @@ const customFieldSection: SideSection = {
145
156
  </span>
146
157
  <Button
147
158
  style={iconButtonStyles}
148
- onClick={() => copyToClipboard(key)}
159
+ onClick={() => copyCustomFieldText(key)}
149
160
  >
150
161
  <ContentCopyIcon
151
162
  className="copy"
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  // Polotno Imports
4
4
  import { SidePanelWrap } from 'polotno';
5
5
  import type { StoreType } from 'polotno/model/store';
6
- import {SidePanel as PolotnoSidePanel, DEFAULT_SECTIONS} from 'polotno/side-panel';
6
+ import { SidePanel as PolotnoSidePanel, DEFAULT_SECTIONS } from 'polotno/side-panel';
7
7
 
8
8
  // Custom Sections
9
9
  import customTemplateSection from './templates/customTemplateSection';
@@ -12,16 +12,28 @@ import customFieldSection from './customFields/customFieldSection';
12
12
 
13
13
  interface Props {
14
14
  store: StoreType;
15
+ currentTemplateType: string;
15
16
  }
16
17
 
17
18
  const SidePanel: React.FC<Props> = (props) => {
18
- const sections = DEFAULT_SECTIONS.filter(
19
- (section) => !['photos', 'size', 'templates'].includes(section.name)
20
- );
21
-
19
+ const sections =
20
+ props.currentTemplateType === "Real Penned Letter"
21
+ ? DEFAULT_SECTIONS.filter((section) => section.name === "")
22
+ : DEFAULT_SECTIONS.filter(
23
+ (section) => !["photos", "size", "templates"].includes(section.name)
24
+ );
25
+
22
26
  return (
23
27
  <SidePanelWrap>
24
- <PolotnoSidePanel store={props.store} sections={[customTemplateSection, ...sections, customFieldSection]} defaultSection="text" />
28
+ <PolotnoSidePanel store={props.store}
29
+ sections={[
30
+ ...(props.currentTemplateType !== "Real Penned Letter"
31
+ ? [customTemplateSection]
32
+ : []),
33
+ ...sections,
34
+ customFieldSection,
35
+ ]}
36
+ defaultSection="text" />
25
37
  </SidePanelWrap>
26
38
  );
27
39
  };
@@ -1,39 +1,39 @@
1
- import React, { useEffect , useState} from 'react';
2
- import { observer } from 'mobx-react-lite';
3
- import { SectionTab, } from 'polotno/side-panel';
4
- import { useDispatch, useSelector } from 'react-redux';
5
- import type { StoreType } from 'polotno/model/store';
6
- import type { TemplatesSection } from 'polotno/side-panel';
1
+ import React, {useEffect, useState} from 'react';
2
+ import {observer} from 'mobx-react-lite';
3
+ import {SectionTab} from 'polotno/side-panel';
4
+ import {useDispatch, useSelector} from 'react-redux';
5
+ import type {StoreType} from 'polotno/model/store';
6
+ import type {TemplatesSection} from 'polotno/side-panel';
7
7
  import {
8
8
  clearAllTemplates,
9
9
  getOneTemplate,
10
10
  getAllTemplateCategories,
11
11
  getAllTemplatesByTab,
12
12
  } from '../../../../src/redux/actions/templateActions';
13
- import { AppDispatch, RootState } from '../../../redux/store';
13
+ import {AppDispatch, RootState} from '../../../redux/store';
14
14
  // @ts-ignore
15
- import DesignIcon from '../../../assets/images/templates/template-default-design.tsx'
15
+ import DesignIcon from '../../../assets/images/templates/template-default-design.tsx';
16
16
  // @ts-ignore
17
- import dummyTemplateIcon from "../../../assets/images/templates/dummy-template.svg";
17
+ import dummyTemplateIcon from '../../../assets/images/templates/dummy-template.svg';
18
18
  // @ts-ignore
19
19
  import CustomTemplate from '../../../assets/images/templates/custom-template';
20
20
  import Typography from '../../GenericUIBlocks/Typography';
21
21
  import './styles.scss';
22
22
  import Dialog from '../../GenericUIBlocks/Dialog';
23
- import { multiPageLetters, templateTypes, DPI } from '../../../utils/constants';
24
- import { drawRestrictedAreaOnPage } from "../../../utils/template-builder";
25
- import GeneralSelect from '../../GenericUIBlocks/GeneralSelect'
26
- import Input from '../../GenericUIBlocks/Input'
23
+ import {multiPageLetters, templateTypes, DPI} from '../../../utils/constants';
24
+ import {drawRestrictedAreaOnPage} from '../../../utils/template-builder';
25
+ import GeneralSelect from '../../GenericUIBlocks/GeneralSelect';
26
+ import Input from '../../GenericUIBlocks/Input';
27
27
  import ModalCross from '../../../assets/images/modal-icons/modal-cross';
28
- import { MESSAGES } from '../../../utils/message';
29
- import { TEMPLATE_LOADING } from '../../../redux/actions/action-types'
28
+ import {MESSAGES} from '../../../utils/message';
29
+ import {TEMPLATE_LOADING} from '../../../redux/actions/action-types';
30
30
 
31
31
  type SideSection = typeof TemplatesSection;
32
32
 
33
33
  const designDialogStyles = {
34
- maxWidth: "600px",
35
- minHeight: "270px"
36
- }
34
+ maxWidth: '600px',
35
+ minHeight: '270px',
36
+ };
37
37
 
38
38
  const templateTextStyles: React.CSSProperties = {
39
39
  color: `var(--textColor)`,
@@ -44,7 +44,6 @@ const templateTextStyles: React.CSSProperties = {
44
44
  marginBottom: `16px`,
45
45
  };
46
46
 
47
-
48
47
  export type Payload = {
49
48
  tab: string;
50
49
  page: number;
@@ -133,8 +132,8 @@ const customTemplateSection: SideSection = {
133
132
  currentTemplateType?.id === '1'
134
133
  ? 'my-templates'
135
134
  : currentTemplateType?.id === '2'
136
- ? 'team-templates'
137
- : 'olc-templates',
135
+ ? 'team-templates'
136
+ : 'olc-templates',
138
137
  page: 1,
139
138
  pageSize: 500,
140
139
  productId: product?.id,
@@ -326,7 +325,7 @@ const customTemplateSection: SideSection = {
326
325
  <div className="custom-template-section">
327
326
  {isShowDialog.open && isShowDialog.model === 'design-own' && (
328
327
  <Dialog
329
- icon={<ModalCross fill="var(--primaryColor)"/>}
328
+ icon={<ModalCross fill="var(--primaryColor)" />}
330
329
  title={MESSAGES.TEMPLATE.DESIGN_YOUR_OWN.TITLE}
331
330
  subHeading={MESSAGES.TEMPLATE.DESIGN_YOUR_OWN.HEADING}
332
331
  description={MESSAGES.TEMPLATE.DESIGN_YOUR_OWN.PARAGRAPH}
@@ -413,7 +412,7 @@ const customTemplateSection: SideSection = {
413
412
  className="default-design"
414
413
  onClick={() => handleDialogChange('design-own')}
415
414
  >
416
- <DesignIcon fill="var(--svgColor)" />
415
+ <DesignIcon fill="var(--svgColorSecondary)" />
417
416
  <Typography style={templateTextStyles}>
418
417
  Design Your Own
419
418
  </Typography>
@@ -502,4 +501,3 @@ const customTemplateSection: SideSection = {
502
501
  };
503
502
 
504
503
  export default customTemplateSection;
505
-
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState, useLayoutEffect } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
 
3
3
  // Import Polotno and third-party libraries
4
4
  import { PolotnoContainer, WorkspaceWrap } from 'polotno';
@@ -272,9 +272,7 @@ const TemplateBuilder: React.FC<TemplateBuilderProps> = ({ store, styles, return
272
272
  <PolotnoContainer
273
273
  style={containerStyle}
274
274
  >
275
- {currentTemplateType !== "Real Penned Letter" &&
276
- <SidePanel store={store} />
277
- }
275
+ <SidePanel store={store} currentTemplateType={currentTemplateType} />
278
276
  <WorkspaceWrap>
279
277
  {currentTemplateType !== "Real Penned Letter" && (
280
278
  <Toolbar store={store} downloadButtonEnabled={false} />
@@ -130,7 +130,7 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
130
130
  setItem('formData', JSON.stringify(data));
131
131
  };
132
132
 
133
- const handleBackPress = () => {
133
+ const handleBackPress = () => {
134
134
  if (isStoreUpdated) {
135
135
  setShowNavigateDialog(!showNavigateDialog);
136
136
  } else {
@@ -140,7 +140,7 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
140
140
 
141
141
  const handleNavigation = async (route = '/') => {
142
142
  handleClearFilters();
143
- if (templateType === 'json') {
143
+ if (templateType === 'json' && product?.productType !== 'Real Penned Letter') {
144
144
  await store.history.clear();
145
145
  }
146
146
  navigate(route);
@@ -152,7 +152,13 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
152
152
  try {
153
153
  setDownloaingProof(true);
154
154
  const fields = [...defaultFields, ...Object.values(dynamicFields)];
155
- const json = store.toJSON();
155
+ let json = store.toJSON();
156
+ if (product?.productType === "Real Penned Letter") {
157
+ let clonedJson = JSON.stringify(json)
158
+ .replace(/\(\(/g, "{{")
159
+ .replace(/\)\)/g, "}}");
160
+ json = JSON.parse(clonedJson);
161
+ }
156
162
  let jsonString = JSON.stringify(json);
157
163
  fields.forEach(({ key, defaultValue, value }) => {
158
164
  const regex = new RegExp(key, 'g');
@@ -200,7 +206,14 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
200
206
  let selectedFields: typeof allFields = [];
201
207
  if (templateType === 'json') {
202
208
  const blob = await store.toBlob();
203
- const jsonData = store.toJSON();
209
+ let jsonData = store.toJSON();
210
+
211
+ if (product?.productType === "Real Penned Letter") {
212
+ let clonedJson = JSON.stringify(jsonData)
213
+ .replace(/\(\(/g, "{{")
214
+ .replace(/\)\)/g, "}}");
215
+ jsonData = JSON.parse(clonedJson);
216
+ }
204
217
 
205
218
  // get all fonts family from json
206
219
  const fontFamilies = extractFontFamilies(jsonData?.pages);
@@ -270,7 +283,9 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
270
283
  });
271
284
  if (response.status === 200) {
272
285
  dispatch(success(response.data.message));
273
- handleNavigation();
286
+ setTimeout(() => {
287
+ handleNavigation();
288
+ }, 2000);
274
289
  } else if (response.status == 418) {
275
290
  // nothing to do
276
291
  } else {
@@ -279,7 +294,9 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
279
294
  } catch (error) {
280
295
  handleChangeModel('', 'false');
281
296
  } finally {
282
- setIsShowModel((prev) => ({ ...prev, loading: false }));
297
+ setTimeout(() => {
298
+ setIsShowModel((prev) => ({ ...prev, loading: false }));
299
+ }, 2000);
283
300
  }
284
301
  };
285
302
 
@@ -335,7 +352,7 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
335
352
  handleSave={handleSave}
336
353
  />
337
354
  )}
338
- <GridContainer style={{alignItems: 'center'}}>
355
+ <GridContainer style={{ alignItems: 'center' }}>
339
356
  <GridItem lg={4} md={4} sm={2} xs={12}></GridItem>
340
357
  <GridItem lg={4} md={2} sm={2} xs={12}>
341
358
  <div className="middle">
@@ -348,7 +365,7 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
348
365
  <GridItem lg={4} md={6} sm={8} xs={12}>
349
366
  <div className="actionsBtnWrapper right">
350
367
  <Button
351
- style={{...buttonStyles, maxWidth: 'auto', minWidth: '100px'}}
368
+ style={{ ...buttonStyles, maxWidth: 'auto', minWidth: '100px' }}
352
369
  onClick={handleViewProofWithLamda}
353
370
  >
354
371
  {downloadingProof ? (
package/src/index.scss CHANGED
@@ -5,6 +5,9 @@
5
5
  // primary color
6
6
  --primaryColor: #ed5c2f;
7
7
  --svgColor: #fdb515;
8
+ --svgColorSecondary: #ed5c2f;
9
+ // main background color
10
+ --mainBackgroundColor: #ffffff;
8
11
  // text colors
9
12
  --textColor: #000;
10
13
  // product Card Background color
@@ -31,7 +34,7 @@
31
34
  --selectOptionFocusedTextColor: #000;
32
35
  --selectOptionSelectedColor: #fff8ee;
33
36
  --selectOptionSelectedTextColor: #000;
34
- --selectOptionSelectedBg: #FFF8EE;
37
+ --selectOptionSelectedBg: #fff8ee;
35
38
  // template builder colors
36
39
  --topbarBgColor: #fff;
37
40
  --sidepanelBgColor: #fff;
@@ -39,6 +42,7 @@
39
42
  --sidepanelSVGColor: #303030;
40
43
  --sidepanelSVGColorActive: #ed5c2f;
41
44
  --sidepanelOptionHoverColor: #fff8ee;
45
+ --sidepanelTextColorHover: #ed5c2f;
42
46
  // custom fields colors
43
47
  --customFieldBorderColor: #303030;
44
48
  --customFieldTextColor: #303030;
@@ -91,20 +95,23 @@
91
95
  }
92
96
 
93
97
  .bp5-navbar {
94
- z-index: auto !important;
98
+ z-index: 10;
95
99
  color: var(--textColor);
96
100
  background-color: var(--mainBackgroundColor);
97
101
  .bp5-card {
98
102
  color: var(--cardTextColor);
99
103
  background-color: var(--cardBgColor);
100
104
  }
101
- .bp5-button-text {
105
+ .polotno-close-panel .bp5-button-text {
102
106
  color: var(--textColor);
103
107
  }
104
108
  }
105
109
 
106
110
  .go4160152499,
107
111
  .polotno-workspace-inner,
112
+ .polotno-panel-container,
113
+ .polotno-panel-container > div,
114
+ .polotno-panel-container > div > div,
108
115
  .polotno-panel-container > div > div > div {
109
116
  &::-webkit-scrollbar {
110
117
  width: 10px;
package/src/index.tsx CHANGED
@@ -5,7 +5,6 @@ import { BrowserRouter as Router } from 'react-router-dom';
5
5
  import { Provider } from 'react-redux';
6
6
  import store from './redux/store';
7
7
  import App from './App';
8
-
9
8
  import './index.scss';
10
9
 
11
10
  // fonts
@@ -49,16 +48,17 @@ const TemplateBuilder = ({
49
48
  setMode(mode);
50
49
  const root = ReactDOM.createRoot(container);
51
50
  root.render(
52
- <React.StrictMode>
53
- <Router>
54
- <Provider store={store}>
51
+ <>
52
+ <Provider store={store}>
53
+ <Router>
54
+
55
55
  <App
56
56
  secretKey={secretKey}
57
57
  styles={styles}
58
58
  returnRoute={returnRoute} />
59
- </Provider>
60
- </Router>
61
- </React.StrictMode>
59
+ </Router>
60
+ </Provider>
61
+ </>
62
62
  );
63
63
  };
64
64
 
@@ -84,45 +84,6 @@ export const addElementsforRealPennedLetters = (store: Store): void => {
84
84
  const page = store.pages[0];
85
85
 
86
86
  const elements: Element[] = [
87
- {
88
- id: "blocked",
89
- type: "figure",
90
- name: "",
91
- opacity: 1,
92
- visible: true,
93
- selectable: false,
94
- removable: false,
95
- alwaysOnTop: true,
96
- showInExport: true,
97
- x: -1.850472230905276e-12,
98
- y: -2.9487523534043754e-13,
99
- width: 528,
100
- height: 80.739,
101
- rotation: 0,
102
- animations: [],
103
- blurEnabled: false,
104
- blurRadius: 10,
105
- brightnessEnabled: false,
106
- brightness: 0,
107
- sepiaEnabled: false,
108
- grayscaleEnabled: false,
109
- shadowEnabled: false,
110
- shadowBlur: 5,
111
- shadowOffsetX: 0,
112
- shadowOffsetY: 0,
113
- shadowColor: "black",
114
- shadowOpacity: 1,
115
- draggable: false,
116
- resizable: false,
117
- contentEditable: false,
118
- styleEditable: true,
119
- subType: "rect",
120
- fill: "rgba(208,0,0,1)",
121
- dash: [],
122
- strokeWidth: 0,
123
- stroke: "#0c0c0c",
124
- cornerRadius: 0,
125
- },
126
87
  {
127
88
  id: 'header',
128
89
  type: 'text',
@@ -135,7 +96,7 @@ export const addElementsforRealPennedLetters = (store: Store): void => {
135
96
  showInExport: true,
136
97
  x: 25,
137
98
  y: 130,
138
- width: 300,
99
+ width: 480,
139
100
  height: 40,
140
101
  rotation: 0,
141
102
  animations: [],
@@ -155,7 +116,7 @@ export const addElementsforRealPennedLetters = (store: Store): void => {
155
116
  resizable: false,
156
117
  contentEditable: true,
157
118
  styleEditable: false,
158
- text: "Hi FirstNaame,",
119
+ text: "Hi ((C.FIRST_NAME)),",
159
120
  fontSize: 20,
160
121
  fontFamily: 'lexi Regular',
161
122
  fontStyle: 'normal',
@@ -235,9 +196,9 @@ export const addElementsforRealPennedLetters = (store: Store): void => {
235
196
  removable: false,
236
197
  alwaysOnTop: true,
237
198
  showInExport: true,
238
- x: 322.49999999499846,
199
+ x: 165.49999999499846,
239
200
  y: 651.7346179851188,
240
- width: 180,
201
+ width: 335,
241
202
  height: 75,
242
203
  rotation: 0,
243
204
  animations: [],
@@ -275,7 +236,7 @@ export const addElementsforRealPennedLetters = (store: Store): void => {
275
236
  backgroundOpacity: 1,
276
237
  backgroundCornerRadius: 0.5,
277
238
  backgroundPadding: 0.5,
278
- }
239
+ },
279
240
  ]
280
241
 
281
242
  elements.forEach(element => page.addElement(element));