{
+ const [open, setOpen] = React.useState(false);
+ return (
+ <>
+
+ {
+ setOpen(true);
+ setTimeout(() => {
+ setOpen(false);
+ }, 1000);
+ }}
+ >
+ {children}
+
+ >
+ );
+};
+
+export default InfoSnackBar;
diff --git a/src/components/TutorialPage/components/PostDetails.jsx b/src/components/TutorialPage/components/PostDetails.jsx
index 1eb94dbe..1a9b8ced 100644
--- a/src/components/TutorialPage/components/PostDetails.jsx
+++ b/src/components/TutorialPage/components/PostDetails.jsx
@@ -15,6 +15,7 @@ import { getUserProfileData } from "../../../store/actions";
import { HashLink } from "react-router-hash-link";
import { useParams } from "react-router-dom";
import TutorialLikesDislikes from "../../ui-helpers/TutorialLikesDislikes";
+import InfoSnackBar from "./InfoSnackBar";
const useStyles = makeStyles(() => ({
container: {
padding: "20px",
@@ -48,18 +49,6 @@ const PostDetails = ({ details }) => {
getUserProfileData(details.user)(firebase, firestore, dispatch);
}, [details]);
- const user = useSelector(
- ({
- profile: {
- user: { data }
- }
- }) => data
- );
-
- const getTime = timestamp => {
- return timestamp.toDate().toDateString();
- };
-
const classes = useStyles();
return (
<>
@@ -94,12 +83,17 @@ const PostDetails = ({ details }) => {
-
-
-
+
+ {
+ navigator.clipboard.writeText(window.location.href);
+ }}
+ >
+
+
+
diff --git a/src/components/TutorialPage/components/UserDetails.jsx b/src/components/TutorialPage/components/UserDetails.jsx
index 2310956f..071a964e 100644
--- a/src/components/TutorialPage/components/UserDetails.jsx
+++ b/src/components/TutorialPage/components/UserDetails.jsx
@@ -34,7 +34,9 @@ const User = ({ id, timestamp, size }) => {
const profileData = useSelector(({ firebase: { profile } }) => profile);
- const user = useSelector(
+ const [user, setUser] = useState(null);
+
+ const userData = useSelector(
({
profile: {
user: { data }
@@ -62,11 +64,17 @@ const User = ({ id, timestamp, size }) => {
};
const getTime = timestamp => {
- return timestamp.toDate().toDateString();
+ return timestamp.toDate().toLocaleString();
};
const showFollowButton = profileData?.uid !== user?.uid;
+ useEffect(() => {
+ if (userData && userData.handle === id) {
+ setUser(userData);
+ }
+ }, [userData]);
+
return (
<>
steps
);
- if ((!loading && !tutorial) || (!loading && !tutorial?.isPublished)) {
- console.log(loading, tutorial);
- history.push("/not-found");
- }
+ const userHandle = useSelector(
+ ({
+ firebase: {
+ profile: { handle }
+ }
+ }) => handle
+ );
const handleAddComment = async comment => {
const commentData = {
@@ -87,7 +90,7 @@ function TutorialPage({ background = "white", textColor = "black" }) {
replyTo: id,
tutorial_id: id,
createdAt: firestore.FieldValue.serverTimestamp(),
- userId: "codelabzuser"
+ userId: userHandle
};
const commentId = await addComment(commentData)(
firebase,
@@ -102,6 +105,19 @@ function TutorialPage({ background = "white", textColor = "black" }) {
}
};
+ useEffect(() => {
+ let timeoutId = null;
+ if ((!loading && !tutorial) || (!loading && !tutorial?.isPublished)) {
+ console.log(loading, tutorial);
+ timeoutId = setTimeout(() => {
+ history.push("/not-found");
+ }, 2000);
+ }
+ return () => {
+ if (timeoutId) clearTimeout(timeoutId);
+ };
+ }, [loading, tutorial]);
+
return (
{
}));
}, [tags]);
- const organizations = useSelector(
- ({
- profile: {
- data: { organizations }
- }
- }) => organizations
- );
- // console.log("organizations", organizations);
+ const profileState = useSelector(state => state.profile.data);
+
+ const { organizations, isEmpty } = profileState || {
+ organizations: null,
+ isEmpty: false
+ };
useEffect(() => {
- if (!organizations) {
+ const isFetchProfile = organizations === null && !isEmpty;
+
+ if (isFetchProfile) {
getProfileData()(firebase, firestore, dispatch);
}
- }, [firestore, firebase, dispatch, organizations]);
+ }, [firestore, firebase, dispatch, organizations, isEmpty]);
const userHandle = useSelector(
({
@@ -119,14 +119,6 @@ const NewTutorial = ({ viewModal, onSidebarClick, viewCallback, active }) => {
}) => handle
);
- const displayName = useSelector(
- ({
- firebase: {
- profile: { displayName }
- }
- }) => displayName
- );
-
//This name should be replaced by displayName when implementing backend
const sampleName = "User Name Here";
const allowOrgs = organizations && organizations.length > 0;
@@ -158,6 +150,7 @@ const NewTutorial = ({ viewModal, onSidebarClick, viewCallback, active }) => {
const onSubmit = formData => {
formData.preventDefault();
+ setError(false);
const tutorialData = {
...formValue,
created_by: userHandle,
diff --git a/src/components/ui-helpers/CommentLikesDislikes.jsx b/src/components/ui-helpers/CommentLikesDislikes.jsx
index 916a7659..36a2159e 100644
--- a/src/components/ui-helpers/CommentLikesDislikes.jsx
+++ b/src/components/ui-helpers/CommentLikesDislikes.jsx
@@ -106,11 +106,25 @@ const CommentLikesDislikes = ({ comment_id }) => {
onChange={handleUserChoice}
aria-label="like dislike"
>
-
+
{upVotes}
-
+
{downVotes}
diff --git a/src/components/ui-helpers/TutorialLikesDislikes.jsx b/src/components/ui-helpers/TutorialLikesDislikes.jsx
index 5c016342..9e24a005 100644
--- a/src/components/ui-helpers/TutorialLikesDislikes.jsx
+++ b/src/components/ui-helpers/TutorialLikesDislikes.jsx
@@ -106,11 +106,25 @@ const TutorialLikesDislikes = ({ tutorial_id }) => {
onChange={handleUserChoice}
aria-label="like dislike"
>
-
+
{upVotes}
-
+
{downVotes}
diff --git a/src/store/actions/actionTypes.js b/src/store/actions/actionTypes.js
index 1de49e90..6ce8a244 100644
--- a/src/store/actions/actionTypes.js
+++ b/src/store/actions/actionTypes.js
@@ -148,6 +148,10 @@ export const ADD_COMMENT_START = "ADD_COMMENT_START";
export const ADD_COMMENT_SUCCESS = "ADD_COMMENT_SUCCESS";
export const ADD_COMMENT_FAILED = "ADD_COMMENT_FAILED";
+export const INC_COMMENT_COUNT = "INC_COMMENT_COUNT";
+
+export const ADD_REPLIES_SUCCESS = "ADD_REPLIES_SUCCESS";
+
export const GET_STEPS_DATA_START = "GET_STEPS_DETAILS_START";
export const GET_STEPS_DATA_SUCCESS = "GET_STEPS_DETAILS_SUCCESS";
export const GET_STEPS_DATA_FAIL = "GET_STEPS_DETAILS_FAILED";
diff --git a/src/store/actions/tutorialPageActions.js b/src/store/actions/tutorialPageActions.js
index 1aa92c3a..421d5e23 100644
--- a/src/store/actions/tutorialPageActions.js
+++ b/src/store/actions/tutorialPageActions.js
@@ -103,7 +103,7 @@ export const getTutorialFeedData =
featured_image: tutorial?.featured_image,
tut_tags: tutorial?.tut_tags,
upVotes: tutorial?.upVotes || 0,
- downVotes: tutorial?.downVotes || 0,
+ downVotes: tutorial?.downVotes || 0
};
return tutorialData;
});
@@ -126,6 +126,15 @@ export const getTutorialData =
if (tutorial.comments && Array.isArray(tutorial.comments)) {
tutorial.comments.reverse();
}
+ const no_of_comments = await firestore
+ .collection("cl_comments")
+ .where("tutorial_id", "==", tutorialID)
+ .get()
+ .then(querySnapshot => {
+ return querySnapshot.size;
+ });
+ tutorial.no_of_comments = no_of_comments;
+ console.log("fetched", tutorial);
dispatch({ type: actions.GET_POST_DATA_SUCCESS, payload: tutorial });
} catch (e) {
dispatch({ type: actions.GET_POST_DATA_FAIL });
@@ -165,6 +174,14 @@ export const getCommentData =
.doc(commentId)
.get();
const comment = data.data();
+ const no_of_replies = await firestore
+ .collection("cl_comments")
+ .where("replyTo", "==", commentId)
+ .get()
+ .then(querySnapshot => {
+ return querySnapshot.size;
+ });
+ comment.no_of_replies = no_of_replies;
dispatch({ type: actions.GET_COMMENT_DATA_SUCCESS, payload: comment });
} catch (e) {
dispatch({ type: actions.GET_COMMENT_DATA_FAIL });
@@ -218,41 +235,46 @@ export const addComment = comment => async (firebase, firestore, dispatch) => {
}
dispatch({ type: actions.ADD_COMMENT_SUCCESS });
+ dispatch({ type: actions.INC_COMMENT_COUNT });
+ return docref.id;
} catch (e) {
dispatch({ type: actions.ADD_COMMENT_FAILED, payload: e.message });
}
};
-export const getRecommendedTutorials = currentTutorialTags => async (firebase, firestore) => {
- try {
- const tutorialsRef = firestore.collection("tutorials");
+export const getRecommendedTutorials =
+ currentTutorialTags => async (firebase, firestore) => {
+ try {
+ const tutorialsRef = firestore.collection("tutorials");
- // Fetch tutorials with matching tags
- const querySnapshot = await tutorialsRef
- .where("tut_tags", "array-contains-any", currentTutorialTags)
- .get();
+ // Fetch tutorials with matching tags
+ const querySnapshot = await tutorialsRef
+ .where("tut_tags", "array-contains-any", currentTutorialTags)
+ .get();
- // Calculate relevance score based on matching tags
- const recommendedTutorials = querySnapshot.docs
- .map(doc => {
- const tutorial = doc.data();
+ // Calculate relevance score based on matching tags
+ const recommendedTutorials = querySnapshot.docs
+ .map(doc => {
+ const tutorial = doc.data();
- // Skip unpublished tutorials
- if (!tutorial.isPublished) return null;
+ // Skip unpublished tutorials
+ if (!tutorial.isPublished) return null;
- const matchingTags = tutorial.tut_tags.filter(tag => currentTutorialTags.includes(tag));
- return {
- ...tutorial,
- relevanceScore: matchingTags.length
- };
- })
- .filter(tutorial => tutorial !== null); // Remove null values from the array
+ const matchingTags = tutorial.tut_tags.filter(tag =>
+ currentTutorialTags.includes(tag)
+ );
+ return {
+ ...tutorial,
+ relevanceScore: matchingTags.length
+ };
+ })
+ .filter(tutorial => tutorial !== null); // Remove null values from the array
- recommendedTutorials.sort((a, b) => b.relevanceScore - a.relevanceScore);
+ recommendedTutorials.sort((a, b) => b.relevanceScore - a.relevanceScore);
- return recommendedTutorials;
- } catch (error) {
- console.error("Error fetching recommended tutorials:", error);
- return [];
- }
-};
\ No newline at end of file
+ return recommendedTutorials;
+ } catch (error) {
+ console.error("Error fetching recommended tutorials:", error);
+ return [];
+ }
+ };
diff --git a/src/store/reducers/tutorialPageReducers/commentReducer.js b/src/store/reducers/tutorialPageReducers/commentReducer.js
index 7d1780ac..5ef687cc 100644
--- a/src/store/reducers/tutorialPageReducers/commentReducer.js
+++ b/src/store/reducers/tutorialPageReducers/commentReducer.js
@@ -62,6 +62,13 @@ const CommentReducer = (state = initialState, { type, payload }) => {
error: payload
};
+ case actions.ADD_REPLIES_SUCCESS:
+ return {
+ ...state,
+ loading: false,
+ replies: payload
+ };
+
default:
return state;
}
diff --git a/src/store/reducers/tutorialPageReducers/postReducer.js b/src/store/reducers/tutorialPageReducers/postReducer.js
index a681c1b6..3dd25d8c 100644
--- a/src/store/reducers/tutorialPageReducers/postReducer.js
+++ b/src/store/reducers/tutorialPageReducers/postReducer.js
@@ -54,6 +54,16 @@ const PostReducer = (state = initialState, { type, payload }) => {
error: payload
};
+ case actions.INC_COMMENT_COUNT:
+ return {
+ ...state,
+ data: {
+ ...(state.data || {}),
+ no_of_comments:
+ (state.data || { no_of_comments: 0 }).no_of_comments + 1
+ }
+ };
+
default:
return state;
}