@knovator/pagecreator-admin 1.7.6 → 1.7.8

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/index.cjs CHANGED
@@ -1775,6 +1775,16 @@ const TRANSLATION_PAIRS_WIDGET = {
1775
1775
  tabNameRequired: 'Tab Name is required',
1776
1776
  subtitle: 'Subtitle',
1777
1777
  subTitlePlaceholder: 'Enter Subtitle',
1778
+ quote: 'Quote',
1779
+ quotePlaceholder: 'Enter quote',
1780
+ personName: 'Person Name',
1781
+ personNamePlaceholder: 'Enter person name',
1782
+ personRole: 'Person Role',
1783
+ personRolePlaceholder: 'Enter person role',
1784
+ personOrganization: 'Organization',
1785
+ personOrganizationPlaceholder: 'Enter organization',
1786
+ rating: 'Rating',
1787
+ ratingPlaceholder: 'Enter rating',
1778
1788
  altText: 'Alt Text',
1779
1789
  altTextPlaceholder: 'Enter alt text',
1780
1790
  link: 'Link',
@@ -2765,6 +2775,12 @@ const apiList = {
2765
2775
  url: `${prefix}/languages`,
2766
2776
  method: 'GET'
2767
2777
  }),
2778
+ BLOG_CATEGORIES: ({
2779
+ prefix
2780
+ }) => ({
2781
+ url: `${prefix}/blog-categories`,
2782
+ method: 'GET'
2783
+ }),
2768
2784
  // Image Upload API
2769
2785
  IMAGE_UPLOAD: ({
2770
2786
  prefix
@@ -3843,6 +3859,7 @@ const SimpleForm = /*#__PURE__*/React.forwardRef(({
3843
3859
  setError,
3844
3860
  languages
3845
3861
  }, ref) => {
3862
+ const isMultilingualWidgetField = accessor => accessor === 'widgetTitles' || accessor === 'widgetSubtitles';
3846
3863
  const inputRenderer = schema => {
3847
3864
  var _a, _b, _c, _d;
3848
3865
  let input;
@@ -3927,7 +3944,7 @@ const SimpleForm = /*#__PURE__*/React.forwardRef(({
3927
3944
  case 'url':
3928
3945
  case 'color':
3929
3946
  default:
3930
- if (Array.isArray(languages) && languages.length > 0 && schema.accessor === 'widgetTitles') {
3947
+ if (Array.isArray(languages) && languages.length > 0 && isMultilingualWidgetField(schema.accessor)) {
3931
3948
  input = languages.map(lang => {
3932
3949
  var _a, _b;
3933
3950
  return /*#__PURE__*/React__default["default"].createElement(Input, {
@@ -3959,7 +3976,7 @@ const SimpleForm = /*#__PURE__*/React.forwardRef(({
3959
3976
  break;
3960
3977
  }
3961
3978
  } else if (schema.Input) {
3962
- if (Array.isArray(languages) && languages.length > 0 && schema.accessor === 'widgetTitles') {
3979
+ if (Array.isArray(languages) && languages.length > 0 && isMultilingualWidgetField(schema.accessor)) {
3963
3980
  input = languages.map(lang => (/*#__PURE__*/React__default["default"].createElement("div", {
3964
3981
  key: lang.code,
3965
3982
  className: classNames__default["default"]('khb_input-wrapper', schema.wrapperClassName)
@@ -6800,6 +6817,7 @@ const ItemsAccordian = ({
6800
6817
  itemType,
6801
6818
  languages,
6802
6819
  clearError,
6820
+ customItemRenderer,
6803
6821
  addText: _addText = 'Add',
6804
6822
  deleteText: _deleteText = 'Delete'
6805
6823
  }) => {
@@ -6840,6 +6858,13 @@ const ItemsAccordian = ({
6840
6858
  // eslint-disable-next-line react-hooks/exhaustive-deps
6841
6859
  }, [errors, name, errors === null || errors === void 0 ? void 0 : errors[name]]);
6842
6860
  const addTab = index => {
6861
+ if (customItemRenderer === null || customItemRenderer === void 0 ? void 0 : customItemRenderer.createItem) {
6862
+ appendItem(customItemRenderer.createItem({
6863
+ index,
6864
+ itemType
6865
+ }));
6866
+ return;
6867
+ }
6843
6868
  appendItem({
6844
6869
  altText: '',
6845
6870
  link: '',
@@ -6883,7 +6908,20 @@ const ItemsAccordian = ({
6883
6908
  }, _deleteText))
6884
6909
  }, /*#__PURE__*/React__default["default"].createElement("div", {
6885
6910
  className: "khb-form-items"
6886
- }, Array.isArray(languages) && languages.length > 0 ? (/*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, languages.map(lang => {
6911
+ }, customItemRenderer ? customItemRenderer.render({
6912
+ name,
6913
+ index,
6914
+ itemType,
6915
+ errors,
6916
+ control,
6917
+ register,
6918
+ setError,
6919
+ clearError,
6920
+ languages,
6921
+ loading,
6922
+ widgetTranslations,
6923
+ commonTranslations
6924
+ }) : (/*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, Array.isArray(languages) && languages.length > 0 ? (/*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, languages.map(lang => {
6887
6925
  var _a, _b, _c, _d, _e, _f, _g, _h;
6888
6926
  return /*#__PURE__*/React__default["default"].createElement(Input, {
6889
6927
  rest: register(`${name}.${index}.titles.${lang.code}`),
@@ -6986,7 +7024,7 @@ const ItemsAccordian = ({
6986
7024
  }, widgetTranslations.dragDrop)), /*#__PURE__*/React__default["default"].createElement("p", {
6987
7025
  className: "khb_img-text-2"
6988
7026
  }, widgetTranslations.allowedFormat))
6989
- }))));
7027
+ }))))));
6990
7028
  })));
6991
7029
  };
6992
7030
 
@@ -7173,6 +7211,7 @@ const constants = {
7173
7211
  textWidgetTypeValue: 'Text',
7174
7212
  htmlWidgetTypeValue: 'HTML',
7175
7213
  linksWidgetTypeValue: 'Links',
7214
+ testimonialWidgetTypeValue: 'Testimonial',
7176
7215
  pagesItemsTypeValue: 'pages',
7177
7216
  tabsAccessor: 'tabs',
7178
7217
  webItems: 'webItems',
@@ -7182,6 +7221,7 @@ const constants = {
7182
7221
  const WidgetForm = ({
7183
7222
  formRef,
7184
7223
  customInputs,
7224
+ customItemRenderers,
7185
7225
  onPrimaryButtonClick
7186
7226
  }) => {
7187
7227
  const {
@@ -7245,6 +7285,8 @@ const WidgetForm = ({
7245
7285
  const [blogCategoriesLoading, setBlogCategoriesLoading] = React.useState(false);
7246
7286
  const pagesLoadedRef = React.useRef(false);
7247
7287
  const blogCategoryInitialized = React.useRef(false);
7288
+ const selectedWidgetTypeValue = (selectedWidgetType === null || selectedWidgetType === void 0 ? void 0 : selectedWidgetType.value) || getValues(constants.widgetTypeAccessor);
7289
+ const selectedCustomItemRenderer = selectedWidgetTypeValue ? customItemRenderers === null || customItemRenderers === void 0 ? void 0 : customItemRenderers[selectedWidgetTypeValue] : undefined;
7248
7290
  React.useEffect(() => {
7249
7291
  if (data && formState === 'UPDATE') {
7250
7292
  const widgetType = widgetTypes.find(type => type.value === (data === null || data === void 0 ? void 0 : data.widgetType));
@@ -7284,13 +7326,8 @@ const WidgetForm = ({
7284
7326
  const response = yield commonApi({
7285
7327
  baseUrl,
7286
7328
  token,
7287
- method: 'POST',
7288
- url: `${widgetRoutesPrefix}/collection-data`,
7289
- data: {
7290
- search: '',
7291
- collectionName: 'blog',
7292
- collectionItems: []
7293
- },
7329
+ method: 'GET',
7330
+ url: `${widgetRoutesPrefix}/blog-categories`,
7294
7331
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7295
7332
  onError: error => console.error('Error fetching blog categories:', error)
7296
7333
  });
@@ -7298,7 +7335,7 @@ const WidgetForm = ({
7298
7335
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7299
7336
  const categories = response.data.docs.map(cat => ({
7300
7337
  value: cat._id || cat.id,
7301
- label: cat.title || cat.name || cat.nm || cat.label,
7338
+ label: cat.name || cat.nm || cat.label,
7302
7339
  slug: cat.slug
7303
7340
  }));
7304
7341
  setBlogCategories(categories);
@@ -7453,6 +7490,15 @@ const WidgetForm = ({
7453
7490
  setValue(constants.collectionNameAccessor, constants.pagesItemsTypeValue);
7454
7491
  const pagesOption = itemsTypes.find(item => item.value === constants.pagesItemsTypeValue);
7455
7492
  if (pagesOption) setSelectedCollectionType(pagesOption);
7493
+ } else if ((widgetType === null || widgetType === void 0 ? void 0 : widgetType.value) === constants.testimonialWidgetTypeValue) {
7494
+ setItemsEnabled(true);
7495
+ setSelectedCollectionType(undefined);
7496
+ setSelectedCollectionItems([]);
7497
+ setValue(constants.itemTypeAccessor, constants.imageItemsTypeValue);
7498
+ setValue(constants.collectionNameAccessor, constants.imageItemsTypeValue);
7499
+ setValue('webPerRow', 4);
7500
+ setValue('tabletPerRow', 2);
7501
+ setValue('mobilePerRow', 1);
7456
7502
  } else {
7457
7503
  setItemsEnabled(true);
7458
7504
  }
@@ -7668,6 +7714,22 @@ const WidgetForm = ({
7668
7714
  },
7669
7715
  info: widgetTranslations.widgetTitleInfo,
7670
7716
  Input: customInputs && customInputs['widgetTitle'] ? customInputs['widgetTitle'] : undefined
7717
+ }, Array.isArray(languages) && languages.length > 0 ? {
7718
+ label: widgetTranslations.subtitle,
7719
+ accessor: 'widgetSubtitles',
7720
+ required: false,
7721
+ type: customInputs && customInputs['widgetSubtitles'] ? undefined : 'text',
7722
+ placeholder: widgetTranslations.subTitlePlaceholder,
7723
+ onInput: handleCapitalize,
7724
+ Input: customInputs && customInputs['widgetSubtitles'] ? customInputs['widgetSubtitles'] : undefined
7725
+ } : {
7726
+ label: widgetTranslations.subtitle,
7727
+ accessor: 'widgetSubtitle',
7728
+ required: false,
7729
+ type: customInputs && customInputs['widgetSubtitle'] ? undefined : 'text',
7730
+ onInput: handleCapitalize,
7731
+ placeholder: widgetTranslations.subTitlePlaceholder,
7732
+ Input: customInputs && customInputs['widgetSubtitle'] ? customInputs['widgetSubtitle'] : undefined
7671
7733
  }, {
7672
7734
  label: widgetTranslations.widgetType,
7673
7735
  required: true,
@@ -7712,7 +7774,7 @@ const WidgetForm = ({
7712
7774
  label: widgetTranslations.itemsType,
7713
7775
  required: true,
7714
7776
  editable: false,
7715
- show: (selectedWidgetType === null || selectedWidgetType === void 0 ? void 0 : selectedWidgetType.value) !== constants.textWidgetTypeValue && (selectedWidgetType === null || selectedWidgetType === void 0 ? void 0 : selectedWidgetType.value) !== constants.htmlWidgetTypeValue,
7777
+ show: selectedWidgetTypeValue !== constants.textWidgetTypeValue && selectedWidgetTypeValue !== constants.htmlWidgetTypeValue && selectedWidgetTypeValue !== constants.testimonialWidgetTypeValue,
7716
7778
  accessor: constants.itemTypeAccessor,
7717
7779
  type: 'select',
7718
7780
  validations: {
@@ -7924,7 +7986,8 @@ const WidgetForm = ({
7924
7986
  register: register,
7925
7987
  loading: loading,
7926
7988
  addText: commonTranslations.add,
7927
- deleteText: commonTranslations.delete
7989
+ deleteText: commonTranslations.delete,
7990
+ customItemRenderer: selectedCustomItemRenderer
7928
7991
  }), /*#__PURE__*/React__default["default"].createElement(ItemsAccordian, {
7929
7992
  languages: languages,
7930
7993
  clearError: clearErrors,
@@ -7941,7 +8004,8 @@ const WidgetForm = ({
7941
8004
  control: control,
7942
8005
  register: register,
7943
8006
  addText: commonTranslations.add,
7944
- deleteText: commonTranslations.delete
8007
+ deleteText: commonTranslations.delete,
8008
+ customItemRenderer: selectedCustomItemRenderer
7945
8009
  }))));
7946
8010
  };
7947
8011
 
@@ -8064,6 +8128,79 @@ const WiddgetFormWrapper = ({
8064
8128
  }) : null;
8065
8129
  };
8066
8130
 
8131
+ const TestimonialItemRenderer = ({
8132
+ name,
8133
+ index,
8134
+ register,
8135
+ errors,
8136
+ widgetTranslations
8137
+ }) => {
8138
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
8139
+ return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(Input, {
8140
+ rest: register(`${name}.${index}.quote`),
8141
+ label: widgetTranslations.quote,
8142
+ error: (_d = (_c = (_b = (_a = errors[name]) === null || _a === void 0 ? void 0 : _a[index]) === null || _b === void 0 ? void 0 : _b['quote']) === null || _c === void 0 ? void 0 : _c.message) === null || _d === void 0 ? void 0 : _d.toString(),
8143
+ type: "textarea",
8144
+ className: "w-full p-2",
8145
+ placeholder: widgetTranslations.quotePlaceholder
8146
+ }), /*#__PURE__*/React__default["default"].createElement(Input, {
8147
+ rest: register(`${name}.${index}.personName`),
8148
+ label: widgetTranslations.personName,
8149
+ error: (_h = (_g = (_f = (_e = errors[name]) === null || _e === void 0 ? void 0 : _e[index]) === null || _f === void 0 ? void 0 : _f['personName']) === null || _g === void 0 ? void 0 : _g.message) === null || _h === void 0 ? void 0 : _h.toString(),
8150
+ type: "text",
8151
+ className: "w-full p-2",
8152
+ placeholder: widgetTranslations.personNamePlaceholder
8153
+ }), /*#__PURE__*/React__default["default"].createElement(Input, {
8154
+ rest: register(`${name}.${index}.personRole`),
8155
+ label: widgetTranslations.personRole,
8156
+ error: (_m = (_l = (_k = (_j = errors[name]) === null || _j === void 0 ? void 0 : _j[index]) === null || _k === void 0 ? void 0 : _k['personRole']) === null || _l === void 0 ? void 0 : _l.message) === null || _m === void 0 ? void 0 : _m.toString(),
8157
+ type: "text",
8158
+ className: "w-full p-2",
8159
+ placeholder: widgetTranslations.personRolePlaceholder
8160
+ }), /*#__PURE__*/React__default["default"].createElement(Input, {
8161
+ rest: register(`${name}.${index}.personOrganization`),
8162
+ label: widgetTranslations.personOrganization,
8163
+ error: (_r = (_q = (_p = (_o = errors[name]) === null || _o === void 0 ? void 0 : _o[index]) === null || _p === void 0 ? void 0 : _p['personOrganization']) === null || _q === void 0 ? void 0 : _q.message) === null || _r === void 0 ? void 0 : _r.toString(),
8164
+ type: "text",
8165
+ className: "w-full p-2",
8166
+ placeholder: widgetTranslations.personOrganizationPlaceholder
8167
+ }), /*#__PURE__*/React__default["default"].createElement(Input, {
8168
+ rest: register(`${name}.${index}.rating`, {
8169
+ min: {
8170
+ value: 0,
8171
+ message: 'Rating should be greater than or equal to 0'
8172
+ },
8173
+ max: {
8174
+ value: 5,
8175
+ message: 'Rating should be less than or equal to 5'
8176
+ }
8177
+ }),
8178
+ label: widgetTranslations.rating,
8179
+ error: (_v = (_u = (_t = (_s = errors[name]) === null || _s === void 0 ? void 0 : _s[index]) === null || _t === void 0 ? void 0 : _t['rating']) === null || _u === void 0 ? void 0 : _u.message) === null || _v === void 0 ? void 0 : _v.toString(),
8180
+ type: "number",
8181
+ className: "w-full p-2",
8182
+ placeholder: widgetTranslations.ratingPlaceholder
8183
+ }));
8184
+ };
8185
+
8186
+ const getDefaultCustomItemRenderers = () => ({
8187
+ Testimonial: {
8188
+ render: TestimonialItemRenderer,
8189
+ createItem: ({
8190
+ index,
8191
+ itemType
8192
+ }) => ({
8193
+ quote: '',
8194
+ personName: '',
8195
+ personRole: '',
8196
+ personOrganization: '',
8197
+ rating: 5,
8198
+ itemType,
8199
+ sequence: index
8200
+ })
8201
+ }
8202
+ });
8203
+
8067
8204
  const Widget = ({
8068
8205
  routes,
8069
8206
  loader,
@@ -8078,7 +8215,8 @@ const Widget = ({
8078
8215
  imageMaxSize,
8079
8216
  translations,
8080
8217
  children,
8081
- onPrimaryButtonClick
8218
+ onPrimaryButtonClick,
8219
+ customItemRenderers
8082
8220
  }) => {
8083
8221
  const {
8084
8222
  commonTranslations
@@ -8086,6 +8224,8 @@ const Widget = ({
8086
8224
  const derivedPermissions = Object.assign(DEFAULT_PERMISSIONS, _permissions);
8087
8225
  const widgetFormRef = React.useRef(null);
8088
8226
  const derivedT = Object.assign(Object.assign({}, TRANSLATION_PAIRS_WIDGET), translations || {});
8227
+ const defaultCustomItemRenderers = getDefaultCustomItemRenderers();
8228
+ const derivedCustomItemRenderers = Object.assign(Object.assign({}, defaultCustomItemRenderers), customItemRenderers || {});
8089
8229
  const {
8090
8230
  list,
8091
8231
  loading,
@@ -8170,7 +8310,8 @@ const Widget = ({
8170
8310
  })
8171
8311
  }, /*#__PURE__*/React__default["default"].createElement(WidgetForm, {
8172
8312
  formRef: widgetFormRef,
8173
- onPrimaryButtonClick: onPrimaryButtonClick
8313
+ onPrimaryButtonClick: onPrimaryButtonClick,
8314
+ customItemRenderers: derivedCustomItemRenderers
8174
8315
  }))), itemData && (/*#__PURE__*/React__default["default"].createElement(DeleteModal, {
8175
8316
  formState: formState,
8176
8317
  itemData: itemData,
package/index.js CHANGED
@@ -1763,6 +1763,16 @@ const TRANSLATION_PAIRS_WIDGET = {
1763
1763
  tabNameRequired: 'Tab Name is required',
1764
1764
  subtitle: 'Subtitle',
1765
1765
  subTitlePlaceholder: 'Enter Subtitle',
1766
+ quote: 'Quote',
1767
+ quotePlaceholder: 'Enter quote',
1768
+ personName: 'Person Name',
1769
+ personNamePlaceholder: 'Enter person name',
1770
+ personRole: 'Person Role',
1771
+ personRolePlaceholder: 'Enter person role',
1772
+ personOrganization: 'Organization',
1773
+ personOrganizationPlaceholder: 'Enter organization',
1774
+ rating: 'Rating',
1775
+ ratingPlaceholder: 'Enter rating',
1766
1776
  altText: 'Alt Text',
1767
1777
  altTextPlaceholder: 'Enter alt text',
1768
1778
  link: 'Link',
@@ -2753,6 +2763,12 @@ const apiList = {
2753
2763
  url: `${prefix}/languages`,
2754
2764
  method: 'GET'
2755
2765
  }),
2766
+ BLOG_CATEGORIES: ({
2767
+ prefix
2768
+ }) => ({
2769
+ url: `${prefix}/blog-categories`,
2770
+ method: 'GET'
2771
+ }),
2756
2772
  // Image Upload API
2757
2773
  IMAGE_UPLOAD: ({
2758
2774
  prefix
@@ -3831,6 +3847,7 @@ const SimpleForm = /*#__PURE__*/forwardRef(({
3831
3847
  setError,
3832
3848
  languages
3833
3849
  }, ref) => {
3850
+ const isMultilingualWidgetField = accessor => accessor === 'widgetTitles' || accessor === 'widgetSubtitles';
3834
3851
  const inputRenderer = schema => {
3835
3852
  var _a, _b, _c, _d;
3836
3853
  let input;
@@ -3915,7 +3932,7 @@ const SimpleForm = /*#__PURE__*/forwardRef(({
3915
3932
  case 'url':
3916
3933
  case 'color':
3917
3934
  default:
3918
- if (Array.isArray(languages) && languages.length > 0 && schema.accessor === 'widgetTitles') {
3935
+ if (Array.isArray(languages) && languages.length > 0 && isMultilingualWidgetField(schema.accessor)) {
3919
3936
  input = languages.map(lang => {
3920
3937
  var _a, _b;
3921
3938
  return /*#__PURE__*/React.createElement(Input, {
@@ -3947,7 +3964,7 @@ const SimpleForm = /*#__PURE__*/forwardRef(({
3947
3964
  break;
3948
3965
  }
3949
3966
  } else if (schema.Input) {
3950
- if (Array.isArray(languages) && languages.length > 0 && schema.accessor === 'widgetTitles') {
3967
+ if (Array.isArray(languages) && languages.length > 0 && isMultilingualWidgetField(schema.accessor)) {
3951
3968
  input = languages.map(lang => (/*#__PURE__*/React.createElement("div", {
3952
3969
  key: lang.code,
3953
3970
  className: classNames('khb_input-wrapper', schema.wrapperClassName)
@@ -6788,6 +6805,7 @@ const ItemsAccordian = ({
6788
6805
  itemType,
6789
6806
  languages,
6790
6807
  clearError,
6808
+ customItemRenderer,
6791
6809
  addText: _addText = 'Add',
6792
6810
  deleteText: _deleteText = 'Delete'
6793
6811
  }) => {
@@ -6828,6 +6846,13 @@ const ItemsAccordian = ({
6828
6846
  // eslint-disable-next-line react-hooks/exhaustive-deps
6829
6847
  }, [errors, name, errors === null || errors === void 0 ? void 0 : errors[name]]);
6830
6848
  const addTab = index => {
6849
+ if (customItemRenderer === null || customItemRenderer === void 0 ? void 0 : customItemRenderer.createItem) {
6850
+ appendItem(customItemRenderer.createItem({
6851
+ index,
6852
+ itemType
6853
+ }));
6854
+ return;
6855
+ }
6831
6856
  appendItem({
6832
6857
  altText: '',
6833
6858
  link: '',
@@ -6871,7 +6896,20 @@ const ItemsAccordian = ({
6871
6896
  }, _deleteText))
6872
6897
  }, /*#__PURE__*/React.createElement("div", {
6873
6898
  className: "khb-form-items"
6874
- }, Array.isArray(languages) && languages.length > 0 ? (/*#__PURE__*/React.createElement(React.Fragment, null, languages.map(lang => {
6899
+ }, customItemRenderer ? customItemRenderer.render({
6900
+ name,
6901
+ index,
6902
+ itemType,
6903
+ errors,
6904
+ control,
6905
+ register,
6906
+ setError,
6907
+ clearError,
6908
+ languages,
6909
+ loading,
6910
+ widgetTranslations,
6911
+ commonTranslations
6912
+ }) : (/*#__PURE__*/React.createElement(React.Fragment, null, Array.isArray(languages) && languages.length > 0 ? (/*#__PURE__*/React.createElement(React.Fragment, null, languages.map(lang => {
6875
6913
  var _a, _b, _c, _d, _e, _f, _g, _h;
6876
6914
  return /*#__PURE__*/React.createElement(Input, {
6877
6915
  rest: register(`${name}.${index}.titles.${lang.code}`),
@@ -6974,7 +7012,7 @@ const ItemsAccordian = ({
6974
7012
  }, widgetTranslations.dragDrop)), /*#__PURE__*/React.createElement("p", {
6975
7013
  className: "khb_img-text-2"
6976
7014
  }, widgetTranslations.allowedFormat))
6977
- }))));
7015
+ }))))));
6978
7016
  })));
6979
7017
  };
6980
7018
 
@@ -7161,6 +7199,7 @@ const constants = {
7161
7199
  textWidgetTypeValue: 'Text',
7162
7200
  htmlWidgetTypeValue: 'HTML',
7163
7201
  linksWidgetTypeValue: 'Links',
7202
+ testimonialWidgetTypeValue: 'Testimonial',
7164
7203
  pagesItemsTypeValue: 'pages',
7165
7204
  tabsAccessor: 'tabs',
7166
7205
  webItems: 'webItems',
@@ -7170,6 +7209,7 @@ const constants = {
7170
7209
  const WidgetForm = ({
7171
7210
  formRef,
7172
7211
  customInputs,
7212
+ customItemRenderers,
7173
7213
  onPrimaryButtonClick
7174
7214
  }) => {
7175
7215
  const {
@@ -7233,6 +7273,8 @@ const WidgetForm = ({
7233
7273
  const [blogCategoriesLoading, setBlogCategoriesLoading] = useState(false);
7234
7274
  const pagesLoadedRef = useRef(false);
7235
7275
  const blogCategoryInitialized = useRef(false);
7276
+ const selectedWidgetTypeValue = (selectedWidgetType === null || selectedWidgetType === void 0 ? void 0 : selectedWidgetType.value) || getValues(constants.widgetTypeAccessor);
7277
+ const selectedCustomItemRenderer = selectedWidgetTypeValue ? customItemRenderers === null || customItemRenderers === void 0 ? void 0 : customItemRenderers[selectedWidgetTypeValue] : undefined;
7236
7278
  useEffect(() => {
7237
7279
  if (data && formState === 'UPDATE') {
7238
7280
  const widgetType = widgetTypes.find(type => type.value === (data === null || data === void 0 ? void 0 : data.widgetType));
@@ -7272,13 +7314,8 @@ const WidgetForm = ({
7272
7314
  const response = yield commonApi({
7273
7315
  baseUrl,
7274
7316
  token,
7275
- method: 'POST',
7276
- url: `${widgetRoutesPrefix}/collection-data`,
7277
- data: {
7278
- search: '',
7279
- collectionName: 'blog',
7280
- collectionItems: []
7281
- },
7317
+ method: 'GET',
7318
+ url: `${widgetRoutesPrefix}/blog-categories`,
7282
7319
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7283
7320
  onError: error => console.error('Error fetching blog categories:', error)
7284
7321
  });
@@ -7286,7 +7323,7 @@ const WidgetForm = ({
7286
7323
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7287
7324
  const categories = response.data.docs.map(cat => ({
7288
7325
  value: cat._id || cat.id,
7289
- label: cat.title || cat.name || cat.nm || cat.label,
7326
+ label: cat.name || cat.nm || cat.label,
7290
7327
  slug: cat.slug
7291
7328
  }));
7292
7329
  setBlogCategories(categories);
@@ -7441,6 +7478,15 @@ const WidgetForm = ({
7441
7478
  setValue(constants.collectionNameAccessor, constants.pagesItemsTypeValue);
7442
7479
  const pagesOption = itemsTypes.find(item => item.value === constants.pagesItemsTypeValue);
7443
7480
  if (pagesOption) setSelectedCollectionType(pagesOption);
7481
+ } else if ((widgetType === null || widgetType === void 0 ? void 0 : widgetType.value) === constants.testimonialWidgetTypeValue) {
7482
+ setItemsEnabled(true);
7483
+ setSelectedCollectionType(undefined);
7484
+ setSelectedCollectionItems([]);
7485
+ setValue(constants.itemTypeAccessor, constants.imageItemsTypeValue);
7486
+ setValue(constants.collectionNameAccessor, constants.imageItemsTypeValue);
7487
+ setValue('webPerRow', 4);
7488
+ setValue('tabletPerRow', 2);
7489
+ setValue('mobilePerRow', 1);
7444
7490
  } else {
7445
7491
  setItemsEnabled(true);
7446
7492
  }
@@ -7656,6 +7702,22 @@ const WidgetForm = ({
7656
7702
  },
7657
7703
  info: widgetTranslations.widgetTitleInfo,
7658
7704
  Input: customInputs && customInputs['widgetTitle'] ? customInputs['widgetTitle'] : undefined
7705
+ }, Array.isArray(languages) && languages.length > 0 ? {
7706
+ label: widgetTranslations.subtitle,
7707
+ accessor: 'widgetSubtitles',
7708
+ required: false,
7709
+ type: customInputs && customInputs['widgetSubtitles'] ? undefined : 'text',
7710
+ placeholder: widgetTranslations.subTitlePlaceholder,
7711
+ onInput: handleCapitalize,
7712
+ Input: customInputs && customInputs['widgetSubtitles'] ? customInputs['widgetSubtitles'] : undefined
7713
+ } : {
7714
+ label: widgetTranslations.subtitle,
7715
+ accessor: 'widgetSubtitle',
7716
+ required: false,
7717
+ type: customInputs && customInputs['widgetSubtitle'] ? undefined : 'text',
7718
+ onInput: handleCapitalize,
7719
+ placeholder: widgetTranslations.subTitlePlaceholder,
7720
+ Input: customInputs && customInputs['widgetSubtitle'] ? customInputs['widgetSubtitle'] : undefined
7659
7721
  }, {
7660
7722
  label: widgetTranslations.widgetType,
7661
7723
  required: true,
@@ -7700,7 +7762,7 @@ const WidgetForm = ({
7700
7762
  label: widgetTranslations.itemsType,
7701
7763
  required: true,
7702
7764
  editable: false,
7703
- show: (selectedWidgetType === null || selectedWidgetType === void 0 ? void 0 : selectedWidgetType.value) !== constants.textWidgetTypeValue && (selectedWidgetType === null || selectedWidgetType === void 0 ? void 0 : selectedWidgetType.value) !== constants.htmlWidgetTypeValue,
7765
+ show: selectedWidgetTypeValue !== constants.textWidgetTypeValue && selectedWidgetTypeValue !== constants.htmlWidgetTypeValue && selectedWidgetTypeValue !== constants.testimonialWidgetTypeValue,
7704
7766
  accessor: constants.itemTypeAccessor,
7705
7767
  type: 'select',
7706
7768
  validations: {
@@ -7912,7 +7974,8 @@ const WidgetForm = ({
7912
7974
  register: register,
7913
7975
  loading: loading,
7914
7976
  addText: commonTranslations.add,
7915
- deleteText: commonTranslations.delete
7977
+ deleteText: commonTranslations.delete,
7978
+ customItemRenderer: selectedCustomItemRenderer
7916
7979
  }), /*#__PURE__*/React.createElement(ItemsAccordian, {
7917
7980
  languages: languages,
7918
7981
  clearError: clearErrors,
@@ -7929,7 +7992,8 @@ const WidgetForm = ({
7929
7992
  control: control,
7930
7993
  register: register,
7931
7994
  addText: commonTranslations.add,
7932
- deleteText: commonTranslations.delete
7995
+ deleteText: commonTranslations.delete,
7996
+ customItemRenderer: selectedCustomItemRenderer
7933
7997
  }))));
7934
7998
  };
7935
7999
 
@@ -8052,6 +8116,79 @@ const WiddgetFormWrapper = ({
8052
8116
  }) : null;
8053
8117
  };
8054
8118
 
8119
+ const TestimonialItemRenderer = ({
8120
+ name,
8121
+ index,
8122
+ register,
8123
+ errors,
8124
+ widgetTranslations
8125
+ }) => {
8126
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
8127
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Input, {
8128
+ rest: register(`${name}.${index}.quote`),
8129
+ label: widgetTranslations.quote,
8130
+ error: (_d = (_c = (_b = (_a = errors[name]) === null || _a === void 0 ? void 0 : _a[index]) === null || _b === void 0 ? void 0 : _b['quote']) === null || _c === void 0 ? void 0 : _c.message) === null || _d === void 0 ? void 0 : _d.toString(),
8131
+ type: "textarea",
8132
+ className: "w-full p-2",
8133
+ placeholder: widgetTranslations.quotePlaceholder
8134
+ }), /*#__PURE__*/React.createElement(Input, {
8135
+ rest: register(`${name}.${index}.personName`),
8136
+ label: widgetTranslations.personName,
8137
+ error: (_h = (_g = (_f = (_e = errors[name]) === null || _e === void 0 ? void 0 : _e[index]) === null || _f === void 0 ? void 0 : _f['personName']) === null || _g === void 0 ? void 0 : _g.message) === null || _h === void 0 ? void 0 : _h.toString(),
8138
+ type: "text",
8139
+ className: "w-full p-2",
8140
+ placeholder: widgetTranslations.personNamePlaceholder
8141
+ }), /*#__PURE__*/React.createElement(Input, {
8142
+ rest: register(`${name}.${index}.personRole`),
8143
+ label: widgetTranslations.personRole,
8144
+ error: (_m = (_l = (_k = (_j = errors[name]) === null || _j === void 0 ? void 0 : _j[index]) === null || _k === void 0 ? void 0 : _k['personRole']) === null || _l === void 0 ? void 0 : _l.message) === null || _m === void 0 ? void 0 : _m.toString(),
8145
+ type: "text",
8146
+ className: "w-full p-2",
8147
+ placeholder: widgetTranslations.personRolePlaceholder
8148
+ }), /*#__PURE__*/React.createElement(Input, {
8149
+ rest: register(`${name}.${index}.personOrganization`),
8150
+ label: widgetTranslations.personOrganization,
8151
+ error: (_r = (_q = (_p = (_o = errors[name]) === null || _o === void 0 ? void 0 : _o[index]) === null || _p === void 0 ? void 0 : _p['personOrganization']) === null || _q === void 0 ? void 0 : _q.message) === null || _r === void 0 ? void 0 : _r.toString(),
8152
+ type: "text",
8153
+ className: "w-full p-2",
8154
+ placeholder: widgetTranslations.personOrganizationPlaceholder
8155
+ }), /*#__PURE__*/React.createElement(Input, {
8156
+ rest: register(`${name}.${index}.rating`, {
8157
+ min: {
8158
+ value: 0,
8159
+ message: 'Rating should be greater than or equal to 0'
8160
+ },
8161
+ max: {
8162
+ value: 5,
8163
+ message: 'Rating should be less than or equal to 5'
8164
+ }
8165
+ }),
8166
+ label: widgetTranslations.rating,
8167
+ error: (_v = (_u = (_t = (_s = errors[name]) === null || _s === void 0 ? void 0 : _s[index]) === null || _t === void 0 ? void 0 : _t['rating']) === null || _u === void 0 ? void 0 : _u.message) === null || _v === void 0 ? void 0 : _v.toString(),
8168
+ type: "number",
8169
+ className: "w-full p-2",
8170
+ placeholder: widgetTranslations.ratingPlaceholder
8171
+ }));
8172
+ };
8173
+
8174
+ const getDefaultCustomItemRenderers = () => ({
8175
+ Testimonial: {
8176
+ render: TestimonialItemRenderer,
8177
+ createItem: ({
8178
+ index,
8179
+ itemType
8180
+ }) => ({
8181
+ quote: '',
8182
+ personName: '',
8183
+ personRole: '',
8184
+ personOrganization: '',
8185
+ rating: 5,
8186
+ itemType,
8187
+ sequence: index
8188
+ })
8189
+ }
8190
+ });
8191
+
8055
8192
  const Widget = ({
8056
8193
  routes,
8057
8194
  loader,
@@ -8066,7 +8203,8 @@ const Widget = ({
8066
8203
  imageMaxSize,
8067
8204
  translations,
8068
8205
  children,
8069
- onPrimaryButtonClick
8206
+ onPrimaryButtonClick,
8207
+ customItemRenderers
8070
8208
  }) => {
8071
8209
  const {
8072
8210
  commonTranslations
@@ -8074,6 +8212,8 @@ const Widget = ({
8074
8212
  const derivedPermissions = Object.assign(DEFAULT_PERMISSIONS, _permissions);
8075
8213
  const widgetFormRef = useRef(null);
8076
8214
  const derivedT = Object.assign(Object.assign({}, TRANSLATION_PAIRS_WIDGET), translations || {});
8215
+ const defaultCustomItemRenderers = getDefaultCustomItemRenderers();
8216
+ const derivedCustomItemRenderers = Object.assign(Object.assign({}, defaultCustomItemRenderers), customItemRenderers || {});
8077
8217
  const {
8078
8218
  list,
8079
8219
  loading,
@@ -8158,7 +8298,8 @@ const Widget = ({
8158
8298
  })
8159
8299
  }, /*#__PURE__*/React.createElement(WidgetForm, {
8160
8300
  formRef: widgetFormRef,
8161
- onPrimaryButtonClick: onPrimaryButtonClick
8301
+ onPrimaryButtonClick: onPrimaryButtonClick,
8302
+ customItemRenderers: derivedCustomItemRenderers
8162
8303
  }))), itemData && (/*#__PURE__*/React.createElement(DeleteModal, {
8163
8304
  formState: formState,
8164
8305
  itemData: itemData,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knovator/pagecreator-admin",
3
- "version": "1.7.6",
3
+ "version": "1.7.8",
4
4
  "dependencies": {
5
5
  "classnames": "^2.3.1",
6
6
  "react-beautiful-dnd": "^13.1.0",
@@ -44,6 +44,10 @@ declare const apiList: {
44
44
  url: string;
45
45
  method: string;
46
46
  };
47
+ BLOG_CATEGORIES: ({ prefix }: API_INPUT_TYPE) => {
48
+ url: string;
49
+ method: string;
50
+ };
47
51
  IMAGE_UPLOAD: ({ prefix }: API_INPUT_TYPE) => {
48
52
  url: string;
49
53
  method: string;
@@ -1,4 +1,4 @@
1
1
  /// <reference types="react" />
2
2
  import { ItemsAccordianProps } from '../../../types';
3
- declare const ItemsAccordian: ({ show, title, id, collapseId, toggleShow, loading, name, errors, control, register, setError, itemType, languages, clearError, addText, deleteText, }: ItemsAccordianProps) => JSX.Element;
3
+ declare const ItemsAccordian: ({ show, title, id, collapseId, toggleShow, loading, name, errors, control, register, setError, itemType, languages, clearError, customItemRenderer, addText, deleteText, }: ItemsAccordianProps) => JSX.Element;
4
4
  export default ItemsAccordian;
@@ -1,4 +1,4 @@
1
1
  /// <reference types="react" />
2
2
  import { FormProps } from '../../../types';
3
- declare const WidgetForm: ({ formRef, customInputs, onPrimaryButtonClick }: FormProps) => JSX.Element | null;
3
+ declare const WidgetForm: ({ formRef, customInputs, customItemRenderers, onPrimaryButtonClick, }: FormProps) => JSX.Element | null;
4
4
  export default WidgetForm;
@@ -0,0 +1,4 @@
1
+ /// <reference types="react" />
2
+ import { ItemRendererProps } from '../../../../types';
3
+ declare const TestimonialItemRenderer: ({ name, index, register, errors, widgetTranslations }: ItemRendererProps) => JSX.Element;
4
+ export default TestimonialItemRenderer;
@@ -0,0 +1,3 @@
1
+ import { CustomItemRendererConfig } from '../../../../types';
2
+ export declare const getDefaultCustomItemRenderers: () => Record<string, CustomItemRendererConfig>;
3
+ export default getDefaultCustomItemRenderers;
@@ -1,9 +1,9 @@
1
1
  /// <reference types="react" />
2
2
  import { WidgetProps } from '../../../types';
3
3
  declare const Widget: {
4
- ({ routes, loader, explicitForm, imageBaseUrl, permissions, preConfirmDelete, formatListItem, formatOptionLabel, imageMaxSize, translations, children, onPrimaryButtonClick, }: WidgetProps): JSX.Element;
4
+ ({ routes, loader, explicitForm, imageBaseUrl, permissions, preConfirmDelete, formatListItem, formatOptionLabel, imageMaxSize, translations, children, onPrimaryButtonClick, customItemRenderers, }: WidgetProps): JSX.Element;
5
5
  Table: ({ extraActions, extraColumns }: import("../../../types").DerivedTableProps) => JSX.Element;
6
- Form: ({ formRef, customInputs, onPrimaryButtonClick }: import("../../../types").FormProps) => JSX.Element | null;
6
+ Form: ({ formRef, customInputs, customItemRenderers, onPrimaryButtonClick, }: import("../../../types").FormProps) => JSX.Element | null;
7
7
  AddButton: () => JSX.Element;
8
8
  Search: () => JSX.Element;
9
9
  Pagination: () => JSX.Element;
@@ -86,6 +86,16 @@ declare const TRANSLATION_PAIRS_WIDGET: {
86
86
  tabNameRequired: string;
87
87
  subtitle: string;
88
88
  subTitlePlaceholder: string;
89
+ quote: string;
90
+ quotePlaceholder: string;
91
+ personName: string;
92
+ personNamePlaceholder: string;
93
+ personRole: string;
94
+ personRolePlaceholder: string;
95
+ personOrganization: string;
96
+ personOrganizationPlaceholder: string;
97
+ rating: string;
98
+ ratingPlaceholder: string;
89
99
  altText: string;
90
100
  altTextPlaceholder: string;
91
101
  link: string;
@@ -2,7 +2,8 @@ import React, { MutableRefObject } from 'react';
2
2
  import { DropResult } from 'react-beautiful-dnd';
3
3
  import { FieldValues, RegisterOptions, UseFormClearErrors, UseFormGetValues, UseFormSetValue, ValidationRule } from 'react-hook-form';
4
4
  import { Routes_Input } from './api';
5
- import { OptionType, FormActionTypes, PermissionsObj, ObjectType, LanguageType } from './common';
5
+ import { OptionType, FormActionTypes, PermissionsObj, ObjectType, CombineObjectType, LanguageType } from './common';
6
+ import type { CommonTranslationPairs } from './context';
6
7
  export interface DNDItemsListProps {
7
8
  onDragEnd: (result: DropResult) => void;
8
9
  items: OptionType[];
@@ -140,6 +141,7 @@ export interface FormProps {
140
141
  filterQuery?: string;
141
142
  formRef: MutableRefObject<HTMLFormElement | null>;
142
143
  customInputs?: Record<string, (props: InputRendererProps) => JSX.Element>;
144
+ customItemRenderers?: Record<string, CustomItemRendererConfig>;
143
145
  onPrimaryButtonClick?: (e?: React.MouseEvent<HTMLButtonElement, MouseEvent>, data?: any) => void;
144
146
  }
145
147
  export interface InputRendererProps {
@@ -148,6 +150,27 @@ export interface InputRendererProps {
148
150
  setError: (msg: string) => void;
149
151
  disabled?: boolean;
150
152
  }
153
+ export interface ItemRendererProps {
154
+ name: string;
155
+ index: number;
156
+ itemType: 'Web' | 'Mobile';
157
+ errors: any;
158
+ control: any;
159
+ register: any;
160
+ setError: any;
161
+ clearError: (key: string) => void;
162
+ languages?: LanguageType[];
163
+ loading?: boolean;
164
+ widgetTranslations: WidgetTranslationPairs;
165
+ commonTranslations: CommonTranslationPairs;
166
+ }
167
+ export interface CustomItemRendererConfig {
168
+ render: (props: ItemRendererProps) => JSX.Element;
169
+ createItem?: (props: {
170
+ index: number;
171
+ itemType: 'Web' | 'Mobile';
172
+ }) => CombineObjectType;
173
+ }
151
174
  export interface WidgetTranslationPairs {
152
175
  htmlContentRequired: string | ValidationRule<boolean> | undefined;
153
176
  htmlContentPlaceholder: string | undefined;
@@ -178,6 +201,16 @@ export interface WidgetTranslationPairs {
178
201
  tabNameRequired: string;
179
202
  subtitle: string;
180
203
  subTitlePlaceholder: string;
204
+ quote: string;
205
+ quotePlaceholder: string;
206
+ personName: string;
207
+ personNamePlaceholder: string;
208
+ personRole: string;
209
+ personRolePlaceholder: string;
210
+ personOrganization: string;
211
+ personOrganizationPlaceholder: string;
212
+ rating: string;
213
+ ratingPlaceholder: string;
181
214
  altText: string;
182
215
  altTextPlaceholder: string;
183
216
  link: string;
@@ -214,6 +247,7 @@ export interface WidgetProps {
214
247
  imageBaseUrl?: string;
215
248
  imageMaxSize?: number;
216
249
  translations?: WidgetTranslationPairs;
250
+ customItemRenderers?: Record<string, CustomItemRendererConfig>;
217
251
  onPrimaryButtonClick?: (e?: React.MouseEvent<HTMLButtonElement, MouseEvent>, data?: any) => void;
218
252
  }
219
253
  export interface DerivedTableProps {
@@ -313,6 +347,7 @@ export interface ItemsAccordianProps {
313
347
  register: any;
314
348
  setError: any;
315
349
  clearError: (key: string) => void;
350
+ customItemRenderer?: CustomItemRendererConfig;
316
351
  }
317
352
  export interface TabItemProps {
318
353
  showDelete?: boolean;