gatsby-core-theme 44.4.18 → 44.4.19

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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [44.4.19](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.4.18...v44.4.19) (2025-07-23)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * added reply + voting ([a2e161b](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/a2e161ba9dea871d666e237e06cfd6aaf5038c8c))
7
+
1
8
  ## [44.4.18](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.4.17...v44.4.18) (2025-07-23)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gatsby-core-theme",
3
- "version": "44.4.18",
3
+ "version": "44.4.19",
4
4
  "description": "Gatsby Theme NPM Package",
5
5
  "author": "",
6
6
  "license": "ISC",
@@ -114,4 +114,8 @@
114
114
  text-transform: capitalize;
115
115
  margin-left: .8rem;
116
116
  padding: 0 1.6rem;
117
+ }
118
+
119
+ .replySection{
120
+ display: grid;
117
121
  }
@@ -1,45 +1,54 @@
1
+ /* eslint-disable react-hooks/rules-of-hooks */
1
2
  /* eslint-disable no-console */
2
3
  /* eslint-disable react-hooks/exhaustive-deps */
3
4
  /* eslint-disable jsx-a11y/click-events-have-key-events */
4
5
  /* eslint-disable import/no-extraneous-dependencies */
5
- import React from 'react';
6
+ import React, { useState } from 'react';
6
7
  import axios from 'axios';
7
8
  import PropTypes from 'prop-types';
8
9
  import LazyImage from '~hooks/lazy-image';
9
-
10
+ import LeaveCommentForm from '../leave-comment-form';
10
11
  import useTranslate from '~hooks/useTranslate/useTranslate';
11
12
  import styles from './comment.module.scss';
12
13
 
13
- const Comment = ({ comment, authors, isReply }) => {
14
+ const Comment = ({ pageContext, comment, authors, isReply }) => {
14
15
  const commentName = comment?.author_id ? authors?.[comment?.author_id]?.name : comment.name;
15
16
  const commentJobTitle = comment?.author_id ? authors?.[comment?.author_id]?.author_title : undefined;
16
17
  const date = new Date(comment.updated_at);
17
18
  const day = String(date.getUTCDate()).padStart(2, '0');
18
19
  const month = String(date.getUTCMonth() + 1).padStart(2, '0');
19
20
  const year = date.getUTCFullYear();
21
+ const [reply, setReply] = useState(false);
20
22
 
21
23
  const hours = String(date.getUTCHours()).padStart(2, '0');
22
24
  const minutes = String(date.getUTCMinutes()).padStart(2, '0');
23
25
  const commentDate = `${day}/${month}/${year} | ${hours}:${minutes}`;
24
26
 
25
27
  const handleVote = async (like = false, commentId) => {
26
- const data = like ? {"vote_up": "increase"} : {"vote_down": "increase"};
28
+ const data = like
29
+ ? {
30
+ "vote_up": "increase",
31
+ "commentID": commentId
32
+ }
33
+ : {
34
+ "vote_down": "increase",
35
+ "commentID": commentId
36
+ };
27
37
 
28
38
  const headers = {
29
39
  headers: {
30
- "X-ID": process.env.GATSBY_API_V2_X_ID,
31
- "X-Signature": process.env.GATSBY_API_V2_X_SIGNATURE,
32
40
  "Content-Type": "application/json",
33
41
  Accept: "application/json",
34
42
  },
35
43
  };
36
44
 
37
- const path = `${process.env.GATSBY_API_URL_V2}/v0.1/content/comments/votes/${commentId}`;
38
-
39
45
  return new Promise((resolve, reject) => {
40
46
  axios
41
- .post(path, data, headers)
42
- .then((response) => resolve(response.data.result))
47
+ .put('/api/put-vote', data, headers)
48
+ .then((response) => {
49
+ response.ok = response.status === 200;
50
+ resolve(response);
51
+ })
43
52
  .catch((error) => reject(error?.response?.data?.errors?.join() || error.message));
44
53
  });
45
54
  }
@@ -63,26 +72,32 @@ const Comment = ({ comment, authors, isReply }) => {
63
72
  <LazyImage className={styles.buttonGroupIcon} src='/images/dislike.svg' />
64
73
  {comment.votes_down}
65
74
  </button>
66
- <button aria-label='Reply Button' type='button' className={styles.replyButton}>
67
- {useTranslate('reply_button', 'Reply')}
68
- </button>
75
+ {!isReply && (
76
+ <button aria-label='Reply Button' onClick={() => setReply(!reply)} type='button' className={styles.replyButton}>
77
+ {reply ? useTranslate('cancel_reply_button', 'Cancel Reply') : useTranslate('reply_button', 'Reply')}
78
+ </button>
79
+ )}
69
80
  </div>
81
+ {reply && <LeaveCommentForm page={pageContext.page} isReply parentCommentID={comment.comment_id} />}
70
82
  </div>
71
83
  };
72
84
 
73
85
  Comment.propTypes = {
74
- comment: PropTypes.shape({
75
- comment_id: PropTypes.number,
76
- author_id: PropTypes.number,
77
- name: PropTypes.string,
78
- email: PropTypes.string,
79
- comment: PropTypes.string,
80
- updated_at: PropTypes.string,
81
- votes_up: PropTypes.number,
82
- votes_down: PropTypes.number,
83
- }),
84
- authors: PropTypes.shape({}),
85
- isReply: PropTypes.bool
86
+ pageContext: PropTypes.shape({
87
+ page: PropTypes.shape({})
88
+ }),
89
+ comment: PropTypes.shape({
90
+ comment_id: PropTypes.number,
91
+ author_id: PropTypes.number,
92
+ name: PropTypes.string,
93
+ email: PropTypes.string,
94
+ comment: PropTypes.string,
95
+ updated_at: PropTypes.string,
96
+ votes_up: PropTypes.number,
97
+ votes_down: PropTypes.number,
98
+ }),
99
+ authors: PropTypes.shape({}),
100
+ isReply: PropTypes.bool
86
101
  };
87
102
 
88
103
  export default Comment;
@@ -6,10 +6,12 @@ import axios from "axios";
6
6
  import Form from "gatsby-core-theme/src/components/organisms/form";
7
7
  import PropTypes from 'prop-types';
8
8
  import { FaArrowRight } from '@react-icons/all-files/fa/FaArrowRight';
9
- import { commentForm } from '../../../constants/forms';
9
+ import { commentForm, replyForm } from '../../../constants/forms';
10
10
 
11
11
  const LeaveCommentForm = ({
12
12
  page,
13
+ isReply = false,
14
+ parentCommentID = 0,
13
15
  showLabels = true,
14
16
  showButtonIcon = false,
15
17
  buttonLabel = 'Add Comment',
@@ -25,6 +27,7 @@ const LeaveCommentForm = ({
25
27
  const data = Object.fromEntries(formData.entries());
26
28
 
27
29
  if(data?.["g-recaptcha-response"] === '' || !data?.tnc) return;
30
+ if(parentCommentID) data.parent_id = parseInt(parentCommentID);
28
31
 
29
32
  data.reference_id = page?.id;
30
33
  data.site_id = parseInt(process.env.SITE_ID);
@@ -56,7 +59,7 @@ const LeaveCommentForm = ({
56
59
 
57
60
  return activeMarket &&
58
61
  <Form
59
- formOptions={commentForm[activeMarket] || commentForm.default}
62
+ formOptions={isReply ? (replyForm[activeMarket] || replyForm.default) : (commentForm[activeMarket] || commentForm.default)}
60
63
  showLabels={showLabels}
61
64
  hasButton
62
65
  showButtonIcon={showButtonIcon}
@@ -77,7 +80,8 @@ LeaveCommentForm.propTypes = {
77
80
  id: PropTypes.number,
78
81
  path: PropTypes.string,
79
82
  }).isRequired,
80
- // submitUrl: PropTypes.string,
83
+ isReply: PropTypes.bool,
84
+ parentCommentID: PropTypes.number,
81
85
  successMessage: PropTypes.string,
82
86
  failMessage: PropTypes.string,
83
87
  validationMessage: PropTypes.string,
@@ -4,21 +4,23 @@ import PropTypes, { arrayOf } from 'prop-types';
4
4
  import keygen from '~helpers/keygen';
5
5
  import Comment from "../../../molecules/comment";
6
6
 
7
- const CommentTree = React.memo(({ comment, authors, depth = 0 }) => (
7
+ const CommentTree = React.memo(({ pageContext, comment, authors, depth = 0 }) => (
8
8
  <div key={keygen()} style={{ marginLeft: depth * 56 }}>
9
- <Comment comment={comment} authors={authors} isReply={depth > 0} />
9
+ <Comment pageContext={pageContext} comment={comment} authors={authors} isReply={depth > 0} />
10
10
  {comment.replies?.map(reply => (
11
11
  <CommentTree
12
12
  key={keygen()}
13
13
  comment={reply}
14
14
  authors={authors}
15
- depth={depth + 1}
15
+ depth={depth + 1}
16
+ pageContext={pageContext}
16
17
  />
17
18
  ))}
18
19
  </div>
19
20
  ));
20
21
 
21
22
  CommentTree.propTypes = {
23
+ pageContext: PropTypes.shape({}),
22
24
  comment: PropTypes.shape({
23
25
  replies: arrayOf(PropTypes.shape({}))
24
26
  }),
@@ -10,7 +10,7 @@ const Comments = ({ pageContext }) => {
10
10
  return (
11
11
  <div>
12
12
  <LeaveCommentForm page={pageContext.page} />
13
- {comments.map((comment) => <CommentTree comment={comment} authors={authors?.authors} depth={0} />)}
13
+ {comments.map((comment) => <CommentTree pageContext={pageContext} comment={comment} authors={authors?.authors} depth={0} />)}
14
14
  </div>
15
15
  );
16
16
  };
@@ -232,6 +232,14 @@
232
232
  display: grid;
233
233
  grid-template-columns: 1fr 1fr;
234
234
 
235
+ input:user-invalid{
236
+ border: .15rem solid var(--comment-input-error, #DD4B39);
237
+ }
238
+
239
+ input:not(:placeholder-shown):invalid{
240
+ border: .15rem solid var(--comment-input-error, #DD4B39);
241
+ }
242
+
235
243
  > button{
236
244
  border: .2rem solid #161128;
237
245
  padding: 8px 16px;
@@ -184,6 +184,92 @@ export const commentForm = {
184
184
  },
185
185
  };
186
186
 
187
+ export const replyForm = {
188
+ default: {
189
+ hasReCAPTCHA: true,
190
+ reCaptcha: {
191
+ validations: {
192
+ label: 'Please confirm',
193
+ translationKey: 'valid_recaptcha'
194
+ }
195
+ },
196
+ fields: [
197
+ {
198
+ label: 'Name',
199
+ translationKey: 'name_label',
200
+ id: 'name',
201
+ type: 'text',
202
+ required: true,
203
+ placeholder: {
204
+ label: 'Name',
205
+ translationKey: 'name_placeholder',
206
+ },
207
+ twoCol: true,
208
+ },
209
+ {
210
+ label: 'Email Address',
211
+ id: 'email',
212
+ type: 'email',
213
+ required: true,
214
+ placeholder: {
215
+ label: 'Email@placeholder.com',
216
+ translationKey: 'email_placeholder',
217
+ },
218
+ translationKey: 'email_label',
219
+ twoCol: true,
220
+ },
221
+ {
222
+ label: 'Leave a comment',
223
+ id: 'comment',
224
+ type: 'textarea',
225
+ placeholder: {
226
+ label: 'Leave a comment',
227
+ translationKey: 'comment_placeholder',
228
+ },
229
+ translationKey: 'textarea_label',
230
+ twoCol: false,
231
+ required: true,
232
+ },
233
+ {
234
+ id: 'post_anonymously',
235
+ type: 'checkbox',
236
+ required: false,
237
+ switch: true,
238
+ translationKey: 'post_anonymously_label',
239
+ twoCol: false,
240
+ options: [
241
+ {
242
+ id: 'post_anonymously',
243
+ label:
244
+ 'Post comment anonymously.',
245
+ translationKey: 'post_anonymously_translation',
246
+ },
247
+ ],
248
+ },
249
+ {
250
+ id: 'tnc',
251
+ type: 'checkbox',
252
+ required: true,
253
+ translationKey: 'checkbox_label',
254
+ twoCol: false,
255
+ options: [
256
+ {
257
+ id: 'tnc',
258
+ label:
259
+ 'By checking this box, I agree to the Comments [Link] and Terms and Conditions.',
260
+ link: {
261
+ url: '/privacy-policy',
262
+ text: 'Link',
263
+ translationKey: 'contact_checkbox',
264
+ },
265
+ translationKey: 'option_one_translation',
266
+ },
267
+ ],
268
+ },
269
+ ],
270
+ },
271
+ };
272
+
187
273
  export const newsLetterForm = {
188
274
  default: {
189
275
  title: {