From 1f31a152d1faccf8cc9c78d873b38e7bef4b1ac4 Mon Sep 17 00:00:00 2001 From: Lee_D Date: Tue, 27 Aug 2024 11:31:09 +0300 Subject: [PATCH 01/21] firebasesrc --- .firebasesrc | 9 +++++++++ src/controllers/db/configKey.ts | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 .firebasesrc diff --git a/.firebasesrc b/.firebasesrc new file mode 100644 index 000000000..005161658 --- /dev/null +++ b/.firebasesrc @@ -0,0 +1,9 @@ +{ + "projects": { + "default": "delib-v3-dev", + "dev": "delib-v3-dev", + "prod": "synthesistalyaron" + }, + "targets": {}, + "etags": {} +} diff --git a/src/controllers/db/configKey.ts b/src/controllers/db/configKey.ts index 290d71d86..737413286 100644 --- a/src/controllers/db/configKey.ts +++ b/src/controllers/db/configKey.ts @@ -1,6 +1,6 @@ const mode = import.meta.env.VITE_APP_ENV as "development" | "production"; - +console.log("mode", mode); const firebaseConfig = { development: { apiKey: import.meta.env.VITE_FIREBASE_API_KEY_DEV, @@ -24,7 +24,6 @@ const firebaseConfig = { }, }; - const vapidKeys = { development: import.meta.env.VITE_FIREBASE_VAPID_KEY_DEV, production: import.meta.env.VITE_FIREBASE_VAPID_KEY_PROD, From 203fb29d059eba0af1c71e02b0818802729c72a7 Mon Sep 17 00:00:00 2001 From: Lee_D Date: Fri, 30 Aug 2024 15:52:56 +0300 Subject: [PATCH 02/21] non-voters-list --- .../settings/components/GetVoters.tsx | 60 ++- .../StatementSettingsForm.tsx | 30 +- .../settings/statementSettingsCont.ts | 510 +++++++++--------- 3 files changed, 336 insertions(+), 264 deletions(-) diff --git a/src/view/pages/statement/components/settings/components/GetVoters.tsx b/src/view/pages/statement/components/settings/components/GetVoters.tsx index 061be4ed0..8f1338700 100644 --- a/src/view/pages/statement/components/settings/components/GetVoters.tsx +++ b/src/view/pages/statement/components/settings/components/GetVoters.tsx @@ -1,28 +1,39 @@ +import { useLanguage } from "@/controllers/hooks/useLanguages"; import { User, Vote } from "delib-npm"; import React, { FC } from "react"; import { handleGetVoters } from "../statementSettingsCont"; -import { useLanguage } from "@/controllers/hooks/useLanguages"; import MembersChipsList from "./membership/membersChipsList/MembersChipList"; interface GetVotersProps { - statementId: string; + statementId: string; + joinedMembers: User[]; } -const GetVoters: FC = ({ statementId }) => { +const GetVoters: FC = ({ statementId, joinedMembers }) => { const { t } = useLanguage(); const [voters, setVoters] = React.useState([]); - const [clicked, setClicked] = React.useState(false); + const [nonVoters, setNonVoters] = React.useState([]); + const [clickedVoters, setClickedVoters] = React.useState(false); + const [clickedNonVoters, setClickedNonVoters] = React.useState(false); const getVoters = () => { - if (!clicked) { - handleGetVoters(statementId, setVoters, setClicked); + if (!clickedVoters) { + handleGetVoters(statementId, setVoters, setClickedVoters); } else { - setClicked(false); + setClickedVoters(false); } }; - const members = voters.flatMap((voter) => voter.voter as User); + React.useEffect(() => { + if (voters.length > 0) { + const voterIds = new Set(voters.map((voter) => voter.voter?.uid)); + const nonVotersList = joinedMembers.filter( + (member) => !voterIds.has(member.uid) + ); + setNonVoters(nonVotersList); + } + }, [voters, joinedMembers]); return ( <> @@ -35,17 +46,42 @@ const GetVoters: FC = ({ statementId }) => { {t("Get Voters")} - {clicked && ( + {clickedVoters && ( <> - {members.length > 0 && ( + {voters.length > 0 ? ( <> {voters.length} {t("Voted")} - + v.voter as User)} /> + + ) : ( +
{t("No voters found")}
+ )} + + )} + + + + {clickedNonVoters && ( + <> + {nonVoters.length > 0 ? ( + <> + + {nonVoters.length} {t("Did Not Vote")} + + + ) : ( +
{t("No non-voters found")}
)} - {members.length === 0 &&
{t("No voters found")}
} )} diff --git a/src/view/pages/statement/components/settings/components/statementSettingsForm/StatementSettingsForm.tsx b/src/view/pages/statement/components/settings/components/statementSettingsForm/StatementSettingsForm.tsx index c161582a8..a7f740559 100644 --- a/src/view/pages/statement/components/settings/components/statementSettingsForm/StatementSettingsForm.tsx +++ b/src/view/pages/statement/components/settings/components/statementSettingsForm/StatementSettingsForm.tsx @@ -2,7 +2,7 @@ import { Dispatch, FC } from 'react'; // Third party imports import { useNavigate, useParams } from 'react-router-dom'; -import { Statement } from 'delib-npm'; +import { Role, Statement, StatementSubscription } from 'delib-npm'; // Firestore functions @@ -26,6 +26,9 @@ import './StatementSettingsForm.scss'; // icons import SaveIcon from '@/assets/icons/save.svg?react'; import QuestionSettings from '../QuestionSettings/QuestionSettings'; +import { useAppSelector } from '@/controllers/hooks/reduxHooks'; +import { createSelector } from '@reduxjs/toolkit'; +import { RootState } from '@/model/store'; interface StatementSettingsFormProps { setIsLoading: (isLoading: boolean) => void; @@ -46,6 +49,24 @@ const StatementSettingsForm: FC = ({ const { statementId } = useParams(); const { t } = useLanguage(); + // Selector to get the statement memberships + const statementMembershipSelector = (statementId: string | undefined) => + createSelector( + (state: RootState) => state.statements.statementMembership, + (memberships) => + memberships.filter( + (membership: StatementSubscription) => + membership.statementId === statementId + ) + ); + + const members: StatementSubscription[] = useAppSelector( + statementMembershipSelector(statementId) + ); + + const joinedMembers = members.filter((member) => member.role !== Role.banned).map(m => m.user); + + // * Functions * // const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); @@ -77,7 +98,6 @@ const StatementSettingsForm: FC = ({
@@ -92,12 +112,12 @@ const StatementSettingsForm: FC = ({ - +
- +
- +
)} diff --git a/src/view/pages/statement/components/settings/statementSettingsCont.ts b/src/view/pages/statement/components/settings/statementSettingsCont.ts index 3e8d072b9..19832e51c 100644 --- a/src/view/pages/statement/components/settings/statementSettingsCont.ts +++ b/src/view/pages/statement/components/settings/statementSettingsCont.ts @@ -1,298 +1,314 @@ import { - Statement, - NavObject, - Vote, - Evaluation, - StatementType, - Screen, -} from 'delib-npm'; + Statement, + NavObject, + Vote, + Evaluation, + StatementType, + Screen, +} from "delib-npm"; // Helpers -import { getVoters } from '@/controllers/db/vote/getVotes'; -import { getEvaluations } from '@/controllers/db/evaluation/getEvaluation'; -import { navigateToStatementTab } from '@/controllers/general/helpers'; +import { getVoters } from "@/controllers/db/vote/getVotes"; +import { getEvaluations } from "@/controllers/db/evaluation/getEvaluation"; +import { navigateToStatementTab } from "@/controllers/general/helpers"; import { - createStatement, - setStatementToDB, - updateStatement, -} from '@/controllers/db/statements/setStatements'; + createStatement, + setStatementToDB, + updateStatement, +} from "@/controllers/db/statements/setStatements"; import { - defaultResultsSettings, - defaultStatementSettings, -} from './emptyStatementModel'; -import { NavigateFunction } from 'react-router-dom'; -import { store } from '@/model/store'; -import { setTempStatementsForPresentation } from '@/model/statements/statementsSlice'; + defaultResultsSettings, + defaultStatementSettings, +} from "./emptyStatementModel"; +import { NavigateFunction } from "react-router-dom"; +import { store } from "@/model/store"; +import { setTempStatementsForPresentation } from "@/model/statements/statementsSlice"; // Get users that voted on options in this statement export async function handleGetVoters( - parentId: string | undefined, - setVoters: React.Dispatch>, - setClicked: React.Dispatch> + parentId: string | undefined, + setVoters: React.Dispatch>, + setClicked: React.Dispatch> ) { - if (!parentId) return; - const voters = await getVoters(parentId); - setVoters(voters); - setClicked(true); + if (!parentId) return; + const voters = await getVoters(parentId); + setVoters(voters); + setClicked(true); +} + +//Get users that did not vote on options in this statement +export async function handleGetNonVoters( + parentId: string | undefined, + setNonVoters: React.Dispatch>, + setClicked: React.Dispatch> +) { + if (!parentId) return; + + try { + const voters = await getVoters(parentId); + + // Filter out users who haven't voted (those with no voter information) + const nonVoters = voters.filter((voter) => !voter.voter); + + setNonVoters(nonVoters); + + setClicked(true); + } catch (error) { + console.error("Error fetching non-voters:", error); + } } // Get users that evaluated on options in this statement export async function handleGetEvaluators( - parentId: string | undefined, - setEvaluators: React.Dispatch>, - setClicked: React.Dispatch> + parentId: string | undefined, + setEvaluators: React.Dispatch>, + setClicked: React.Dispatch> ) { - if (!parentId) return; - const evaluators = await getEvaluations(parentId); - setEvaluators(evaluators); - setClicked(true); + if (!parentId) return; + const evaluators = await getEvaluations(parentId); + setEvaluators(evaluators); + setClicked(true); } // Check if sub-page is checked in stored statement export function isSubPageChecked( - statement: Statement | undefined, - navObj: NavObject + statement: Statement | undefined, + navObj: NavObject ): boolean { - try { - //in case of a new statement - if (!statement) { - if (navObj.default === false) return false; - else return true; - } - - //in case of an existing statement - const { subScreens } = statement; - if (!subScreens) return true; - if (subScreens.includes(navObj.link)) return true; - - return false; - } catch (error) { - console.error(error); - - return true; - } + try { + //in case of a new statement + if (!statement) { + if (navObj.default === false) return false; + else return true; + } + + //in case of an existing statement + const { subScreens } = statement; + if (!subScreens) return true; + if (subScreens.includes(navObj.link)) return true; + + return false; + } catch (error) { + console.error(error); + + return true; + } } interface HandleSetStatementParams { - navigate: NavigateFunction; - statementId: string | undefined; - statement: Statement; - parentStatement?: Statement | 'top'; + navigate: NavigateFunction; + statementId: string | undefined; + statement: Statement; + parentStatement?: Statement | "top"; } export async function handleSetStatement({ - navigate, - statementId, - statement, - parentStatement, + navigate, + statementId, + statement, + parentStatement, }: HandleSetStatementParams) { - try { - - - - - // If statement title is empty, don't save - if(!statement.statement) return; - - const { - hasChildren, - resultsBy, - numberOfResults, - enableAddEvaluationOption, - enableAddVotingOption, - enhancedEvaluation, - showEvaluation, - subScreens, - membership, - } = getSetStatementData(statement); - - // If no statementId, user is on AddStatement page - if (!statementId) { - const newStatement = createStatement({ - text: statement.statement, - description: statement.description, - subScreens, - statementType: StatementType.question, - parentStatement: 'top', - resultsBy, - numberOfResults, - hasChildren, - enableAddEvaluationOption, - enableAddVotingOption, - enhancedEvaluation, - showEvaluation, - membership, - }); - if (!newStatement) throw new Error('newStatement had error in creating'); - - await setStatementToDB({ - parentStatement: 'top', - statement: newStatement, - addSubscription: true, - }); - navigateToStatementTab(newStatement, navigate); - - return; - } - - // If statementId, user is on Settings tab in statement page - else { - // update statement - if (!statement) throw new Error('statement is undefined'); - - const newStatement = updateStatement({ - statement, - text: statement.statement, - description: statement.description||'', - subScreens: subScreens, - statementType: StatementType.question, - resultsBy, - numberOfResults, - hasChildren, - enableAddEvaluationOption, - enableAddVotingOption, - enhancedEvaluation, - showEvaluation, - membership, - }); - if (!newStatement) throw new Error('newStatement had not been updated'); - - await setStatementToDB({ - parentStatement, - statement: newStatement, - addSubscription: true, - }); - navigateToStatementTab(newStatement, navigate); - - return; - } - } catch (error) { - console.error(error); - } + try { + // If statement title is empty, don't save + if (!statement.statement) return; + + const { + hasChildren, + resultsBy, + numberOfResults, + enableAddEvaluationOption, + enableAddVotingOption, + enhancedEvaluation, + showEvaluation, + subScreens, + membership, + } = getSetStatementData(statement); + + // If no statementId, user is on AddStatement page + if (!statementId) { + const newStatement = createStatement({ + text: statement.statement, + description: statement.description, + subScreens, + statementType: StatementType.question, + parentStatement: "top", + resultsBy, + numberOfResults, + hasChildren, + enableAddEvaluationOption, + enableAddVotingOption, + enhancedEvaluation, + showEvaluation, + membership, + }); + if (!newStatement) throw new Error("newStatement had error in creating"); + + await setStatementToDB({ + parentStatement: "top", + statement: newStatement, + addSubscription: true, + }); + navigateToStatementTab(newStatement, navigate); + + return; + } + + // If statementId, user is on Settings tab in statement page + else { + // update statement + if (!statement) throw new Error("statement is undefined"); + + const newStatement = updateStatement({ + statement, + text: statement.statement, + description: statement.description || "", + subScreens: subScreens, + statementType: StatementType.question, + resultsBy, + numberOfResults, + hasChildren, + enableAddEvaluationOption, + enableAddVotingOption, + enhancedEvaluation, + showEvaluation, + membership, + }); + if (!newStatement) throw new Error("newStatement had not been updated"); + + await setStatementToDB({ + parentStatement, + statement: newStatement, + addSubscription: true, + }); + navigateToStatementTab(newStatement, navigate); + + return; + } + } catch (error) { + console.error(error); + } } - - - - export const getStatementSettings = (statement: Statement) => { - const statementSettings = - statement.statementSettings ?? defaultStatementSettings; - - return { - enableAddEvaluationOption: Boolean( - statementSettings.enableAddEvaluationOption - ), - enableAddVotingOption: Boolean(statementSettings.enableAddVotingOption), - enhancedEvaluation: Boolean(statementSettings.enhancedEvaluation), - showEvaluation: Boolean(statementSettings.showEvaluation), - subScreens: statementSettings.subScreens ?? [], - inVotingGetOnlyResults: Boolean(statementSettings.inVotingGetOnlyResults), - enableSimilaritiesSearch: Boolean(statementSettings.enableSimilaritiesSearch), - enableNavigationalElements: Boolean(statementSettings.enableNavigationalElements), - }; + const statementSettings = + statement.statementSettings ?? defaultStatementSettings; + + return { + enableAddEvaluationOption: Boolean( + statementSettings.enableAddEvaluationOption + ), + enableAddVotingOption: Boolean(statementSettings.enableAddVotingOption), + enhancedEvaluation: Boolean(statementSettings.enhancedEvaluation), + showEvaluation: Boolean(statementSettings.showEvaluation), + subScreens: statementSettings.subScreens ?? [], + inVotingGetOnlyResults: Boolean(statementSettings.inVotingGetOnlyResults), + enableSimilaritiesSearch: Boolean( + statementSettings.enableSimilaritiesSearch + ), + enableNavigationalElements: Boolean( + statementSettings.enableNavigationalElements + ), + }; }; const getStatementSubScreens = (statement: Statement) => { - const defaultSubScreens = [Screen.CHAT, Screen.OPTIONS]; - const subScreens = statement.subScreens ?? defaultSubScreens; + const defaultSubScreens = [Screen.CHAT, Screen.OPTIONS]; + const subScreens = statement.subScreens ?? defaultSubScreens; - // don't allow setting sub-screens as an empty array - return subScreens.length === 0 ? defaultSubScreens : subScreens; + // don't allow setting sub-screens as an empty array + return subScreens.length === 0 ? defaultSubScreens : subScreens; }; const getSetStatementData = (statement: Statement) => { - const { resultsBy, numberOfResults } = - statement.resultsSettings ?? defaultResultsSettings; - const { - enableAddEvaluationOption, - enableAddVotingOption, - enhancedEvaluation, - showEvaluation, - } = getStatementSettings(statement); - - return { - hasChildren: Boolean(statement.hasChildren), - subScreens: getStatementSubScreens(statement), - resultsBy, - numberOfResults, - enableAddEvaluationOption, - enableAddVotingOption, - enhancedEvaluation, - showEvaluation, - membership: statement.membership, - }; + const { resultsBy, numberOfResults } = + statement.resultsSettings ?? defaultResultsSettings; + const { + enableAddEvaluationOption, + enableAddVotingOption, + enhancedEvaluation, + showEvaluation, + } = getStatementSettings(statement); + + return { + hasChildren: Boolean(statement.hasChildren), + subScreens: getStatementSubScreens(statement), + resultsBy, + numberOfResults, + enableAddEvaluationOption, + enableAddVotingOption, + enhancedEvaluation, + showEvaluation, + membership: statement.membership, + }; }; interface ToggleSubScreenParams { - subScreens: Screen[]; - screenLink: Screen; - statement: Statement; + subScreens: Screen[]; + screenLink: Screen; + statement: Statement; } export const toggleSubScreen = ({ - subScreens, - screenLink, - statement, + subScreens, + screenLink, + statement, }: ToggleSubScreenParams): Statement => { - const checked = subScreens.includes(screenLink) ?? false; - const newSubScreens = checked - ? subScreens.filter((subScreen) => subScreen !== screenLink) - : [...subScreens, screenLink]; - - return { - ...statement, - subScreens: newSubScreens, - }; + const checked = subScreens.includes(screenLink) ?? false; + const newSubScreens = checked + ? subScreens.filter((subScreen) => subScreen !== screenLink) + : [...subScreens, screenLink]; + + return { + ...statement, + subScreens: newSubScreens, + }; }; interface CreateStatementFromModalParams { - title: string; - description: string; - isOptionSelected: boolean; - parentStatement: Statement | 'top'; - toggleAskNotifications?: VoidFunction; - isSendToStoreTemp?: boolean; + title: string; + description: string; + isOptionSelected: boolean; + parentStatement: Statement | "top"; + toggleAskNotifications?: VoidFunction; + isSendToStoreTemp?: boolean; } export async function createStatementFromModal({ - title, - description, - isOptionSelected, - toggleAskNotifications, - parentStatement, - isSendToStoreTemp, + title, + description, + isOptionSelected, + toggleAskNotifications, + parentStatement, + isSendToStoreTemp, }: CreateStatementFromModalParams) { - try { - if (!title) throw new Error('title is undefined'); - - - - const newStatement = createStatement({ - ...defaultStatementSettings, - hasChildren: true, - toggleAskNotifications, - text:title, - description, - parentStatement, - statementType: isOptionSelected - ? StatementType.option - : StatementType.question, - }); - - if (!newStatement) throw new Error('newStatement was not created'); - - await setStatementToDB({ - statement: newStatement, - parentStatement: parentStatement === 'top' ? undefined : parentStatement, - addSubscription: true, - }); - - if (isSendToStoreTemp) { - //dispatch to the store - store.dispatch(setTempStatementsForPresentation([newStatement])); - } - } catch (error) { - console.error(error); - } + try { + if (!title) throw new Error("title is undefined"); + + const newStatement = createStatement({ + ...defaultStatementSettings, + hasChildren: true, + toggleAskNotifications, + text: title, + description, + parentStatement, + statementType: isOptionSelected + ? StatementType.option + : StatementType.question, + }); + + if (!newStatement) throw new Error("newStatement was not created"); + + await setStatementToDB({ + statement: newStatement, + parentStatement: parentStatement === "top" ? undefined : parentStatement, + addSubscription: true, + }); + + if (isSendToStoreTemp) { + //dispatch to the store + store.dispatch(setTempStatementsForPresentation([newStatement])); + } + } catch (error) { + console.error(error); + } } From 57c1ba8aefb1e3979f315310030ec9d4bfa8b8db Mon Sep 17 00:00:00 2001 From: Lee_D Date: Fri, 30 Aug 2024 15:58:48 +0300 Subject: [PATCH 03/21] code-refinement --- .../statement/components/settings/components/GetVoters.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/view/pages/statement/components/settings/components/GetVoters.tsx b/src/view/pages/statement/components/settings/components/GetVoters.tsx index 8f1338700..3c2a7dac5 100644 --- a/src/view/pages/statement/components/settings/components/GetVoters.tsx +++ b/src/view/pages/statement/components/settings/components/GetVoters.tsx @@ -1,6 +1,6 @@ import { useLanguage } from "@/controllers/hooks/useLanguages"; import { User, Vote } from "delib-npm"; -import React, { FC } from "react"; +import React, { FC, useEffect } from "react"; import { handleGetVoters } from "../statementSettingsCont"; import MembersChipsList from "./membership/membersChipsList/MembersChipList"; @@ -25,7 +25,8 @@ const GetVoters: FC = ({ statementId, joinedMembers }) => { } }; - React.useEffect(() => { + //filter out users who haven't vote/those with no voter information + useEffect(() => { if (voters.length > 0) { const voterIds = new Set(voters.map((voter) => voter.voter?.uid)); const nonVotersList = joinedMembers.filter( From c84979713eb8cd7e5803dbe06ee40ef729b39d19 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Mon, 2 Sep 2024 19:47:59 +0300 Subject: [PATCH 04/21] classpuzle --- .../getMultiStageStatements.ts | 44 ++ src/model/statements/statementsSlice.ts | 16 +- .../solutions/StatementSolutionsPage.tsx | 610 +++++++++--------- .../solutions/statementSolutionsHooks.ts | 65 ++ 4 files changed, 437 insertions(+), 298 deletions(-) create mode 100644 src/view/pages/statement/components/solutions/statementSolutionsHooks.ts diff --git a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts index 34bceeafa..c18798083 100644 --- a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts +++ b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts @@ -55,4 +55,48 @@ export async function getMultiStageOptions( console.error(error); dispatch(setTempStatementsForPresentation([])); } +} + +export async function getFirstEvaluationOptions( + statement: Statement, + +): Promise { + const dispatch: Dispatch = store.dispatch; + try { + const urlBase = isProduction() ? "qeesi7aziq-uc.a.run.app" : "http://localhost:5001/synthesistalyaron/us-central1"; + + const url = isProduction() ? `https://getRandomStatements-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getRandomStatements"; + + const response = await fetch( + `${url}?parentId=${statement.statementId}&limit=6` + ); + const { randomStatements, error } = await response.json(); + if (error) throw new Error(error); + dispatch(setTempStatementsForPresentation(randomStatements)); + return randomStatements as Statement[]; + } catch (error) { + console.error(error); + dispatch(setTempStatementsForPresentation([])); + return []; + } +} + +export async function getSecondEvaluationOptions(statement: Statement): Promise { + const dispatch: Dispatch = store.dispatch; + try { + const urlBase = isProduction() ? "qeesi7aziq-uc.a.run.app" : "http://localhost:5001/synthesistalyaron/us-central1"; + + const url = isProduction() ? `https://getTopStatements-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getTopStatements"; + const response = await fetch( + `${url}?parentId=${statement.statementId}&limit=10` + ); + const { topSolutions, error } = await response.json(); + if (error) throw new Error(error); + dispatch(setTempStatementsForPresentation(topSolutions)); + return topSolutions as Statement[]; + } catch (error) { + console.error(error); + dispatch(setTempStatementsForPresentation([])); + return []; + } } \ No newline at end of file diff --git a/src/model/statements/statementsSlice.ts b/src/model/statements/statementsSlice.ts index dd5889884..bf3315336 100644 --- a/src/model/statements/statementsSlice.ts +++ b/src/model/statements/statementsSlice.ts @@ -1,6 +1,6 @@ /* eslint-disable indent */ import { createSlice, PayloadAction, createSelector } from "@reduxjs/toolkit"; -import { RootState } from "../store"; +import { RootState, store } from "../store"; // Third party imports @@ -241,7 +241,7 @@ export const statementsSlicer = createSlice({ action: PayloadAction<{ statement: Statement; screen: Screen }>, ) => { try { - + const { statement, screen } = action.payload; const _statement = state.statements.find( (st) => st.statementId === statement.statementId, @@ -434,7 +434,7 @@ export const hasTokenSelector = return statement?.token?.includes(token) || false; }; - + export const subscriptionParentStatementSelector = (parentId: string) => createSelector( (state: RootState) => state.statements.statementSubscription, @@ -442,4 +442,14 @@ export const subscriptionParentStatementSelector = (parentId: string) => statementSubscription.filter((sub) => sub.statement.topParentId === parentId) ); + +export const myStatementsByStatementIdSelector = (statementId: string) =>{ + const user = store.getState().user.user; + return createSelector( + (state: RootState) => state.statements.statements, + (statements) => + statements.filter((st) => st.parentId === statementId && st.creatorId === user?.uid) + ); +} + export default statementsSlicer.reducer; diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index 3877e00ec..77c282705 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -1,18 +1,18 @@ -import { FC, useEffect, useState } from 'react'; +import { FC, useEffect, useState } from "react"; // Third party imports import { - QuestionStage, - QuestionType, - Statement, - StatementType, - User, - isOptionFn, -} from 'delib-npm'; -import { useParams, useNavigate } from 'react-router'; + QuestionStage, + QuestionType, + Statement, + StatementType, + User, + isOptionFn, +} from "delib-npm"; +import { useParams, useNavigate } from "react-router"; // Utils & Helpers -import { sortSubStatements } from './statementSolutionsCont'; +import { sortSubStatements } from "./statementSolutionsCont"; // Custom Components import StatementEvaluationCard from "./components/StatementSolutionCard"; @@ -32,311 +32,331 @@ import styles from "./statementSolutinsPage.module.scss"; import ideaImage from "@/assets/images/manWithIdeaLamp.png"; import WhitePlusIcon from "@/view/components/icons/WhitePlusIcon"; import useWindowDimensions from "@/controllers/hooks/useWindowDimentions"; - +import { useMultiStage } from "./statementSolutionsHooks"; +import { set } from "node_modules/cypress/types/lodash"; interface StatementEvaluationPageProps { - statement: Statement; - subStatements: Statement[]; - handleShowTalker: (talker: User | null) => void; - showNav?: boolean; - questions?: boolean; - toggleAskNotifications: () => void; - currentPage?: string; + statement: Statement; + subStatements: Statement[]; + handleShowTalker: (talker: User | null) => void; + showNav?: boolean; + questions?: boolean; + toggleAskNotifications: () => void; + currentPage?: string; } const StatementEvaluationPage: FC = ({ - statement, - subStatements, - handleShowTalker, - questions = false, - toggleAskNotifications, - currentPage = `suggestion`, + statement, + subStatements, + handleShowTalker, + questions = false, + toggleAskNotifications, + currentPage = `suggestion`, }) => { - try { - // Hooks - const { sort } = useParams(); - const navigate = useNavigate(); - const { t } = useLanguage(); - const isMuliStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - const currentStage = statement.questionSettings?.currentStage; - const stageInfo = getStagesInfo(currentStage); - const useSearchForSimilarStatements = - statement.statementSettings?.enableSimilaritiesSearch || false; + try { + // Hooks + const { sort } = useParams(); + const navigate = useNavigate(); + const { t } = useLanguage(); + const isMuliStage = + statement.questionSettings?.questionType === QuestionType.multipleSteps; + const currentStage = statement.questionSettings?.currentStage; + const stageInfo = getStagesInfo(currentStage); + const useSearchForSimilarStatements = + statement.statementSettings?.enableSimilaritiesSearch || false; + + //hooks + const { subStatements: multiStageOptions, isLoading } = useMultiStage({ + statement, + }); + + // Use States + const [showModal, setShowModal] = useState(false); + const [showToast, setShowToast] = useState(false); + const [showExplanation, setShowExplanation] = useState( + currentStage === QuestionStage.explanation && isMuliStage && !questions + ); + const [sortedSubStatements, setSortedSubStatements] = useState( + [...subStatements] + ); - // Use States - const [showModal, setShowModal] = useState(false); - const [showToast, setShowToast] = useState(false); - const [showExplanation, setShowExplanation] = useState( - currentStage === QuestionStage.explanation && isMuliStage && !questions); - const [sortedSubStatements, setSortedSubStatements] = useState( - [...subStatements] - ); + useEffect(() => { + if (isMuliStage) { + setSortedSubStatements(multiStageOptions); + } else { + const _sortedSubStatements = sortSubStatements( + subStatements, + sort + ).filter((subStatement) => { + //if questions is true, only show questions + if (questions) { + return subStatement.statementType === StatementType.question; + } - useEffect(() => { - const _sortedSubStatements = sortSubStatements( - subStatements, - sort - ).filter((subStatement) => { - //if questions is true, only show questions - if (questions) { - return subStatement.statementType === StatementType.question; - } + if (isMuliStage) { + //filter the temp presentation designed for this stage + return subStatement.isPartOfTempPresentation; + } - if (isMuliStage) { - //filter the temp presentation designed for this stage - return subStatement.isPartOfTempPresentation; - } + //if options is true, only show options + return isOptionFn(subStatement); + }); - //if options is true, only show options - return isOptionFn(subStatement); - }); + setSortedSubStatements(_sortedSubStatements); + } + }, [sort, subStatements, questions, isMuliStage, multiStageOptions]); - setSortedSubStatements(_sortedSubStatements); - }, [sort, subStatements, questions]); + useEffect(() => { + if (questions) { + setShowToast(false); + } + }, [questions]); - useEffect(() => { - if (questions) { - setShowToast(false); - } - }, [questions]); + useEffect(() => { + if (!showToast && !questions) { + setShowToast(true); + } + if ( + currentStage === QuestionStage.explanation && + isMuliStage && + !questions + ) { + setShowExplanation(true); + } + if (currentStage === QuestionStage.voting && !questions) { + //redirect us react router dom to voting page + navigate(`/statement/${statement.statementId}/vote`); + } + }, [statement.questionSettings?.currentStage, questions]); - useEffect(() => { - if (isMuliStage) { - getMultiStageOptions(statement); - } - }, [currentStage]); + // Variables + let topSum = 30; + const tops: number[] = [topSum]; + const message = stageInfo ? stageInfo.message : false; - useEffect(() => { - if (!showToast && !questions) { - setShowToast(true); - } - if ( - currentStage === QuestionStage.explanation && - isMuliStage && - !questions - ) { - setShowExplanation(true); - } - if (currentStage === QuestionStage.voting && !questions) { - //redirect us react router dom to voting page - navigate(`/statement/${statement.statementId}/vote`); - } - }, [statement.questionSettings?.currentStage, questions]); + const handlePlusIconClick = () => { + setShowModal(true); + }; - // Variables - let topSum = 30; - const tops: number[] = [topSum]; - const message = stageInfo ? stageInfo.message : false; + const { width } = useWindowDimensions(); + const smallScreen = width < 1024; - const handlePlusIconClick = () => { - setShowModal(true); - }; + const renderCommonContent = () => ( + <> +
+
+
+

+ {isLoading &&

Loading...

} + {smallScreen ? ( + <> + {t(`Click on`)}{" "} + {t(`”+”`)}{" "} + {t(`to add your ${currentPage}`)} + + ) : ( + <> +

+ {`Click on `} + + {`” ${t(`Add ${currentPage} button`)} ”`} + +
+ {` to add your ${t(`${currentPage}`)}`} +

+ + )} + +
+
+ {smallScreen ? ( + + ) : ( +

+ {" "} + {t(`Add ${currentPage}`)} {" "} +

+ )} +
+
+ +
+ {isMuliStage && stageInfo?.message && ( + + {getToastButtons(currentStage)} + + )} + {showExplanation && ( + + + + )} + {showModal && ( + + )} + + ); - const { width } = useWindowDimensions(); - const smallScreen = width < 1024; + if (sortedSubStatements.length === 0) { + return renderCommonContent(); + } - const renderCommonContent = () => ( - <> -
-
-
-

- {smallScreen ? ( - <> - {t(`Click on`)} {t(`”+”`)} {t(`to add your ${currentPage}`)} - - ) : ( - <> -

- {`Click on `} - - {`” ${t(`Add ${currentPage} button`)} ”`} -
- {` to add your ${t(`${currentPage}`)}`} -

- - )} - -
-
- {smallScreen ? ( - ) : (

{t(`Add ${currentPage}`)}

- )} -
-
- -
- {isMuliStage && stageInfo?.message && ( - - {getToastButtons(currentStage)} - - )} - {showExplanation && ( - - - - )} - {showModal && ( - - )} - - ); + return ( + <> +
+
+ {isMuliStage && message && ( + + {getToastButtons(currentStage)} + + )} + {sortedSubStatements?.map((statementSub: Statement, i: number) => { + //get the top of the element + if (statementSub.elementHight) { + topSum += statementSub.elementHight + 30; + tops.push(topSum); + } - if (sortedSubStatements.length === 0) { - return renderCommonContent(); - } - - return ( - <> -
-
- {isMuliStage && message && ( - - {getToastButtons(currentStage)} - - )} - {sortedSubStatements?.map((statementSub: Statement, i: number) => { - //get the top of the element - if (statementSub.elementHight) { - topSum += statementSub.elementHight + 30; - tops.push(topSum); + return ( + + ); + })} +
+
+
+
+ +
+ {showExplanation && ( + + + + )} + {showModal && ( + + )} + + ); + function getToastButtons(questionStage: QuestionStage | undefined) { + try { + switch (questionStage) { + case QuestionStage.voting: + case QuestionStage.firstEvaluation: + case QuestionStage.secondEvaluation: + case QuestionStage.finished: + case QuestionStage.explanation: + return ( +
-
-
- -
- {showExplanation && ( - - - - )} - {showModal && ( - - )} - - ); - function getToastButtons(questionStage: QuestionStage | undefined) { - try { - switch (questionStage) { - case QuestionStage.voting: - case QuestionStage.firstEvaluation: - case QuestionStage.secondEvaluation: - case QuestionStage.finished: - case QuestionStage.explanation: - return ( -
- {navItems.map((navItem) => ( -
+ {navItems.map((navItem, i) => ( +
void; currentPage?: string; } - +let counter = 0; const StatementEvaluationPage: FC = ({ statement, subStatements, @@ -58,53 +55,39 @@ const StatementEvaluationPage: FC = ({ const { sort } = useParams(); const navigate = useNavigate(); const { t } = useLanguage(); - const isMuliStage = + const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - const currentStage = statement.questionSettings?.currentStage; + + const myStatements = useSelector(myStatementsByStatementIdSelector(statement.statementId)); + + const currentStage = statement.questionSettings?.currentStage; const stageInfo = getStagesInfo(currentStage); const useSearchForSimilarStatements = statement.statementSettings?.enableSimilaritiesSearch || false; - //hooks - const { subStatements: multiStageOptions, isLoading } = useMultiStage({ - statement, - }); // Use States const [showModal, setShowModal] = useState(false); const [showToast, setShowToast] = useState(false); const [showExplanation, setShowExplanation] = useState( - currentStage === QuestionStage.explanation && isMuliStage && !questions + currentStage === QuestionStage.explanation && isMultiStage && !questions ); const [sortedSubStatements, setSortedSubStatements] = useState( [...subStatements] ); useEffect(() => { - if (isMuliStage) { - setSortedSubStatements(multiStageOptions); - } else { - const _sortedSubStatements = sortSubStatements( - subStatements, - sort - ).filter((subStatement) => { - //if questions is true, only show questions - if (questions) { - return subStatement.statementType === StatementType.question; - } - - if (isMuliStage) { - //filter the temp presentation designed for this stage - return subStatement.isPartOfTempPresentation; - } - - //if options is true, only show options - return isOptionFn(subStatement); - }); - - setSortedSubStatements(_sortedSubStatements); - } - }, [sort, subStatements, questions, isMuliStage, multiStageOptions]); + + getSubStatements({ + statement, + subStatements, + sort, + questions, + myStatements, + setSortedSubStatements, + }); + + }, [sort, subStatements, questions, isMultiStage]); useEffect(() => { if (questions) { @@ -118,7 +101,7 @@ const StatementEvaluationPage: FC = ({ } if ( currentStage === QuestionStage.explanation && - isMuliStage && + isMultiStage && !questions ) { setShowExplanation(true); @@ -134,100 +117,20 @@ const StatementEvaluationPage: FC = ({ const tops: number[] = [topSum]; const message = stageInfo ? stageInfo.message : false; - const handlePlusIconClick = () => { - setShowModal(true); - }; + - const { width } = useWindowDimensions(); - const smallScreen = width < 1024; - - const renderCommonContent = () => ( - <> -
-
-
-

- {isLoading &&

Loading...

} - {smallScreen ? ( - <> - {t(`Click on`)}{" "} - {t(`”+”`)}{" "} - {t(`to add your ${currentPage}`)} - - ) : ( - <> -

- {`Click on `} - - {`” ${t(`Add ${currentPage} button`)} ”`} - -
- {` to add your ${t(`${currentPage}`)}`} -

- - )} - -
-
- {smallScreen ? ( - - ) : ( -

- {" "} - {t(`Add ${currentPage}`)} {" "} -

- )} -
-
- -
- {isMuliStage && stageInfo?.message && ( - - {getToastButtons(currentStage)} - - )} - {showExplanation && ( - - - - )} - {showModal && ( - - )} - - ); + + if (sortedSubStatements.length === 0) { - return renderCommonContent(); + return } return ( <>
- {isMuliStage && message && ( + {isMultiStage && message && ( = ({ toggleAskNotifications={toggleAskNotifications} parentStatement={statement} isQuestion={questions} - isMuliStage={isMuliStage} + isMultiStage={isMultiStage} setShowModal={setShowModal} useSimilarStatements={useSearchForSimilarStatements} /> )} ); + + function getToastButtons(questionStage: QuestionStage | undefined) { try { switch (questionStage) { diff --git a/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx b/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx new file mode 100644 index 000000000..f75101f27 --- /dev/null +++ b/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx @@ -0,0 +1,104 @@ +import { Dispatch, FC } from "react"; +import styles from "../../StatementSolutionsPage.module.scss"; +import useWindowDimensions from "@/controllers/hooks/useWindowDimentions"; + +// /graphics +import ideaImage from "@/assets/images/manWithIdeaLamp.png"; +import WhitePlusIcon from "@/view/components/icons/WhitePlusIcon"; +import { useLanguage } from "@/controllers/hooks/useLanguages"; +import { StageInfo } from "../../../settings/components/QuestionSettings/QuestionStageRadioBtn/QuestionStageRadioBtn"; + +interface Props { + currentPage: string; + stageInfo: StageInfo | undefined; + setShowModal: Dispatch; +} + +const EmptyScreen: FC = ({ currentPage, stageInfo,setShowModal }) => { + const {t} = useLanguage(); + const { width } = useWindowDimensions(); + const smallScreen = width < 1024; + + const handlePlusIconClick = () => { + setShowModal(true); + }; + + return ( + <> +
+
+
+

+ {smallScreen ? ( + <> + {t(`Click on`)}{" "} + {t(`”+”`)}{" "} + {t(`to add your ${currentPage}`)} + + ) : ( + <> +

+ {`Click on `} + + {`” ${t(`Add ${currentPage} button`)} ”`} + +
+ {` to add your ${t(`${currentPage}`)}`} +

+ + )} + +
+
+ {smallScreen ? ( + + ) : ( +

+ {" "} + {t(`Add ${currentPage}`)} {" "} +

+ )} +
+
+ +
+ {isMultiStage && stageInfo?.message && ( + + {getToastButtons(currentStage)} + + )} + {showExplanation && ( + + + + )} + {showModal && ( + + )} + + ); +}; + +export default EmptyScreen; diff --git a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts index 6777764e2..4c120a9ec 100644 --- a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts +++ b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts @@ -1,9 +1,10 @@ -import { Statement, Screen } from "delib-npm"; +import { Statement, Screen, isOptionFn, QuestionType, StatementType, QuestionStage } from "delib-npm"; import { EnhancedEvaluationThumb, enhancedEvaluationsThumbs, } from "./components/evaluation/enhancedEvaluation/EnhancedEvaluationModel"; +import { getFirstEvaluationOptions, getSecondEvaluationOptions } from "@/controllers/db/multiStageQuestion/getMultiStageStatements"; @@ -12,32 +13,30 @@ export function sortSubStatements( sort: string | undefined, ): Statement[] { try { - let _subStatements = subStatements.map( - (statement: Statement) => statement, - ); + let _subStatements = [...subStatements]; switch (sort) { - case Screen.OPTIONS_CONSENSUS: - case Screen.QUESTIONS_CONSENSUS: - _subStatements = subStatements.sort( - (a: Statement, b: Statement) => b.consensus - a.consensus, - ); - break; - case Screen.OPTIONS_NEW: - case Screen.QUESTIONS_NEW: - _subStatements = subStatements.sort( - (a: Statement, b: Statement) => b.createdAt - a.createdAt, - ); - break; - case Screen.OPTIONS_RANDOM: - case Screen.QUESTIONS_RANDOM: - _subStatements = subStatements.sort(() => Math.random() - 0.5); - break; - case Screen.OPTIONS_UPDATED: - case Screen.QUESTIONS_UPDATED: - _subStatements = subStatements.sort( - (a: Statement, b: Statement) => b.lastUpdate - a.lastUpdate, - ); - break; + case Screen.OPTIONS_CONSENSUS: + case Screen.QUESTIONS_CONSENSUS: + _subStatements = subStatements.sort( + (a: Statement, b: Statement) => b.consensus - a.consensus, + ); + break; + case Screen.OPTIONS_NEW: + case Screen.QUESTIONS_NEW: + _subStatements = subStatements.sort( + (a: Statement, b: Statement) => b.createdAt - a.createdAt, + ); + break; + case Screen.OPTIONS_RANDOM: + case Screen.QUESTIONS_RANDOM: + _subStatements = subStatements.sort(() => Math.random() - 0.5); + break; + case Screen.OPTIONS_UPDATED: + case Screen.QUESTIONS_UPDATED: + _subStatements = subStatements.sort( + (a: Statement, b: Statement) => b.lastUpdate - a.lastUpdate, + ); + break; } const __subStatements = _subStatements.map( (statement: Statement, i: number) => { @@ -106,4 +105,78 @@ export const getEvaluationThumbsToDisplay = ({ ); return [selectedThumb || defaultThumb]; -}; \ No newline at end of file +}; + +interface GetSubStatementsProps { + statement: Statement; + subStatements: Statement[]; + sort: string | undefined; + questions: boolean; + myStatements: Statement[]; + setSortedSubStatements: React.Dispatch; +} +export async function getSubStatements({ statement, subStatements, sort, questions, myStatements, setSortedSubStatements }: GetSubStatementsProps): Promise { + try { + console.log("getSubStatements") + if (!statement) return; + if (!subStatements) return; + const _subStatements = [...subStatements]; + + const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; + + if (!isMultiStage) { + const st = getSortedStatements(_subStatements, sort, questions); + console.log("single stage"); + setSortedSubStatements(st); + } else { + console.log("multi steps") + switch (statement.questionSettings?.currentStage) { + case QuestionStage.explanation: + setSortedSubStatements([]); + return; + case QuestionStage.suggestion: + setSortedSubStatements(myStatements); + return; + case QuestionStage.firstEvaluation: + getFirstEvaluationOptions(statement).then((subStatements) => { + // const st = getSortedStatements(subStatements, sort, questions); + setSortedSubStatements(subStatements); + }) + + return; + case QuestionStage.secondEvaluation: + getSecondEvaluationOptions(statement).then((subStatements) => { + const st = getSortedStatements(subStatements, sort, questions); + setSortedSubStatements(st); + }) + return; + case QuestionStage.voting: + setSortedSubStatements([]); + return; + default: + console.log("default ") + setSortedSubStatements([]); + return; + } + } + return; + + } catch (error) { + console.error(error); + + } +} + +function getSortedStatements(_subStatements:Statement[], sort: string | undefined, questions: boolean) { + return sortSubStatements( + _subStatements, + sort + ).filter((subStatement) => { + //if questions is true, only show questions + if (questions) { + return subStatement.statementType === StatementType.question; + } + //if options is true, only show options + return isOptionFn(subStatement); + }); +} diff --git a/src/view/pages/statement/components/solutions/statementSolutionsHooks.ts b/src/view/pages/statement/components/solutions/statementSolutionsHooks.ts index 5b50e8869..941ad3c74 100644 --- a/src/view/pages/statement/components/solutions/statementSolutionsHooks.ts +++ b/src/view/pages/statement/components/solutions/statementSolutionsHooks.ts @@ -3,6 +3,7 @@ import { Statement, QuestionStage, QuestionType } from "delib-npm"; import { useSelector } from "react-redux"; import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; import { getFirstEvaluationOptions, getSecondEvaluationOptions } from "@/controllers/db/multiStageQuestion/getMultiStageStatements"; +import { set } from "node_modules/cypress/types/lodash"; interface Props { @@ -16,6 +17,7 @@ export function useMultiStage({ statement }: Props): Output { try { const [isLoading, setIsLoading] = useState(false); const [subStatements, setSubStatements] = useState([]); + const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; const questionStage = statement.questionSettings?.currentStage || QuestionStage.finished; const questionType = statement.questionSettings?.questionType; @@ -25,36 +27,7 @@ export function useMultiStage({ statement }: Props): Output { const myStatements = useSelector(myStatementsByStatementIdSelector(statement.statementId)); - useEffect(() => { - setIsLoading(true); - switch (questionStage) { - case QuestionStage.explanation: - setSubStatements([]); - setIsLoading(false); - break; - case QuestionStage.suggestion: - setSubStatements(myStatements); - break; - case QuestionStage.firstEvaluation: - getFirstEvaluationOptions(statement).then((statements) => { - setSubStatements(statements); - setIsLoading(false); - }); - break; - case QuestionStage.secondEvaluation: - getSecondEvaluationOptions(statement).then((statements) => { - setSubStatements(statements); - setIsLoading(false); - }); - break; - case QuestionStage.voting: - //do something - break; - default: - //do something - break; - } - }, [questionStage]); + // useEffect(, [questionStage]); return { subStatements, isLoading }; } catch (error) { From 9e50b14cb30a4889322ee1c8f39196edda46d7ea Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Tue, 3 Sep 2024 09:23:25 +0300 Subject: [PATCH 06/21] refactor --- .../getMultiStageStatements.ts | 6 - .../solutions/StatementSolutionsPage.tsx | 118 +++++++++--------- .../components/emptyScreen/EmptyScreen.tsx | 34 +---- 3 files changed, 60 insertions(+), 98 deletions(-) diff --git a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts index fc889db2c..9bfb39ece 100644 --- a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts +++ b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts @@ -73,9 +73,6 @@ export async function getFirstEvaluationOptions( const { randomStatements, error } = await response.json(); if (error) throw new Error(error); - randomStatements.forEach((s: Statement, i) => { - s.order = i - }) return randomStatements as Statement[]; } catch (error) { @@ -97,9 +94,6 @@ export async function getSecondEvaluationOptions(statement: Statement): Promise< const { topSolutions, error } = await response.json(); if (error) throw new Error(error); - topSolutions.forEach((s: Statement, i) => { - s.order = i - }) return topSolutions as Statement[]; } catch (error) { diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index 95cdd6090..ba8e7f603 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -1,12 +1,7 @@ import { FC, useEffect, useState } from "react"; // Third party imports -import { - QuestionStage, - QuestionType, - Statement, - User -} from "delib-npm"; +import { QuestionStage, QuestionType, Statement, User } from "delib-npm"; import { useParams, useNavigate } from "react-router"; // Utils & Helpers @@ -31,7 +26,6 @@ import { useSelector } from "react-redux"; import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; import EmptyScreen from "./components/emptyScreen/EmptyScreen"; - interface StatementEvaluationPageProps { statement: Statement; subStatements: Statement[]; @@ -57,15 +51,16 @@ const StatementEvaluationPage: FC = ({ const { t } = useLanguage(); const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - - const myStatements = useSelector(myStatementsByStatementIdSelector(statement.statementId)); - - const currentStage = statement.questionSettings?.currentStage; + + const myStatements = useSelector( + myStatementsByStatementIdSelector(statement.statementId) + ); + + const currentStage = statement.questionSettings?.currentStage; const stageInfo = getStagesInfo(currentStage); const useSearchForSimilarStatements = statement.statementSettings?.enableSimilaritiesSearch || false; - // Use States const [showModal, setShowModal] = useState(false); const [showToast, setShowToast] = useState(false); @@ -77,16 +72,14 @@ const StatementEvaluationPage: FC = ({ ); useEffect(() => { - - getSubStatements({ - statement, - subStatements, - sort, - questions, - myStatements, - setSortedSubStatements, - }); - + getSubStatements({ + statement, + subStatements, + sort, + questions, + myStatements, + setSortedSubStatements, + }); }, [sort, subStatements, questions, isMultiStage]); useEffect(() => { @@ -117,51 +110,55 @@ const StatementEvaluationPage: FC = ({ const tops: number[] = [topSum]; const message = stageInfo ? stageInfo.message : false; - - - - - if (sortedSubStatements.length === 0) { - return + return; } return ( <>
-
- {isMultiStage && message && ( - - {getToastButtons(currentStage)} - - )} - {sortedSubStatements?.map((statementSub: Statement, i: number) => { - //get the top of the element - if (statementSub.elementHight) { - topSum += statementSub.elementHight + 30; - tops.push(topSum); - } + {sortedSubStatements.length === 0 ? ( + + ) : ( +
+ {isMultiStage && message && ( + + {getToastButtons(currentStage)} + + )} + {sortedSubStatements?.map( + (statementSub: Statement, i: number) => { + //get the top of the element + if (statementSub.elementHight) { + topSum += statementSub.elementHight + 30; + tops.push(topSum); + } - return ( - - ); - })} -
-
+ return ( + + ); + } + )} +
+
+ )}
= ({ ); - function getToastButtons(questionStage: QuestionStage | undefined) { try { switch (questionStage) { diff --git a/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx b/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx index f75101f27..ab95ee8d6 100644 --- a/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx +++ b/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx @@ -6,15 +6,14 @@ import useWindowDimensions from "@/controllers/hooks/useWindowDimentions"; import ideaImage from "@/assets/images/manWithIdeaLamp.png"; import WhitePlusIcon from "@/view/components/icons/WhitePlusIcon"; import { useLanguage } from "@/controllers/hooks/useLanguages"; -import { StageInfo } from "../../../settings/components/QuestionSettings/QuestionStageRadioBtn/QuestionStageRadioBtn"; + interface Props { currentPage: string; - stageInfo: StageInfo | undefined; setShowModal: Dispatch; } -const EmptyScreen: FC = ({ currentPage, stageInfo,setShowModal }) => { +const EmptyScreen: FC = ({ currentPage, setShowModal }) => { const {t} = useLanguage(); const { width } = useWindowDimensions(); const smallScreen = width < 1024; @@ -69,34 +68,7 @@ const EmptyScreen: FC = ({ currentPage, stageInfo,setShowModal }) => {
- {isMultiStage && stageInfo?.message && ( - - {getToastButtons(currentStage)} - - )} - {showExplanation && ( - - - - )} - {showModal && ( - - )} + ); }; From 27e317f1835e60d21f7a2f8af6dfc1ddb24fcdd3 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Tue, 3 Sep 2024 10:30:11 +0300 Subject: [PATCH 07/21] before change of architecture --- .../solutions/StatementSolutionsPage.tsx | 6 ++---- .../solutions/statementSolutionsCont.ts | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index ba8e7f603..97c833795 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -35,7 +35,7 @@ interface StatementEvaluationPageProps { toggleAskNotifications: () => void; currentPage?: string; } -let counter = 0; + const StatementEvaluationPage: FC = ({ statement, subStatements, @@ -110,9 +110,7 @@ const StatementEvaluationPage: FC = ({ const tops: number[] = [topSum]; const message = stageInfo ? stageInfo.message : false; - if (sortedSubStatements.length === 0) { - return; - } + console.log(sortedSubStatements.map((subStatement:Statement) => subStatement.statement).join(',')); return ( <> diff --git a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts index 4c120a9ec..5a8f24673 100644 --- a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts +++ b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts @@ -138,17 +138,23 @@ export async function getSubStatements({ statement, subStatements, sort, questio setSortedSubStatements(myStatements); return; case QuestionStage.firstEvaluation: - getFirstEvaluationOptions(statement).then((subStatements) => { - // const st = getSortedStatements(subStatements, sort, questions); - setSortedSubStatements(subStatements); - }) + try { + const subStatements = await getFirstEvaluationOptions(statement); + const st = getSortedStatements(subStatements, sort, questions); + setSortedSubStatements(st); + } catch (error) { + console.error(error); + } return; case QuestionStage.secondEvaluation: - getSecondEvaluationOptions(statement).then((subStatements) => { + try { + const subStatements = await getSecondEvaluationOptions(statement); const st = getSortedStatements(subStatements, sort, questions); setSortedSubStatements(st); - }) + } catch (error) { + console.error(error); + } return; case QuestionStage.voting: setSortedSubStatements([]); From 383b2165f4804a13932058b912a2eeefab777a46 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Tue, 3 Sep 2024 13:14:30 +0300 Subject: [PATCH 08/21] before refactorting --- .../solutions/StatementSolutionsPage.tsx | 11 ++-- .../suggestionCards/SuggestionCards.tsx | 9 +++ .../solutions/statementSolutionsCont.ts | 56 ++++++------------- 3 files changed, 33 insertions(+), 43 deletions(-) create mode 100644 src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index 97c833795..4ad68e497 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -67,9 +67,7 @@ const StatementEvaluationPage: FC = ({ const [showExplanation, setShowExplanation] = useState( currentStage === QuestionStage.explanation && isMultiStage && !questions ); - const [sortedSubStatements, setSortedSubStatements] = useState( - [...subStatements] - ); + const [sortedSubStatements, setSortedSubStatements] = useState([]); useEffect(() => { getSubStatements({ @@ -78,7 +76,9 @@ const StatementEvaluationPage: FC = ({ sort, questions, myStatements, - setSortedSubStatements, + }).then((_subStatements) => { + console.log("new st..............", _subStatements.length) + setSortedSubStatements(_subStatements); }); }, [sort, subStatements, questions, isMultiStage]); @@ -109,8 +109,9 @@ const StatementEvaluationPage: FC = ({ let topSum = 30; const tops: number[] = [topSum]; const message = stageInfo ? stageInfo.message : false; + console.log(topSum, tops) - console.log(sortedSubStatements.map((subStatement:Statement) => subStatement.statement).join(',')); + return ( <> diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx new file mode 100644 index 000000000..7d1e7cc67 --- /dev/null +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +const SuggestionCards = () => { + return ( +
SuggestionCards
+ ) +} + +export default SuggestionCards \ No newline at end of file diff --git a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts index 5a8f24673..b4a725860 100644 --- a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts +++ b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts @@ -113,67 +113,47 @@ interface GetSubStatementsProps { sort: string | undefined; questions: boolean; myStatements: Statement[]; - setSortedSubStatements: React.Dispatch; } -export async function getSubStatements({ statement, subStatements, sort, questions, myStatements, setSortedSubStatements }: GetSubStatementsProps): Promise { +export async function getSubStatements({ statement, subStatements, sort, questions, myStatements }: GetSubStatementsProps): Promise { try { - console.log("getSubStatements") - if (!statement) return; - if (!subStatements) return; + + if (!statement) return []; + if (!subStatements) return []; const _subStatements = [...subStatements]; const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; if (!isMultiStage) { - const st = getSortedStatements(_subStatements, sort, questions); - console.log("single stage"); - setSortedSubStatements(st); + return getSortedStatements(_subStatements, sort, questions); } else { - console.log("multi steps") + switch (statement.questionSettings?.currentStage) { case QuestionStage.explanation: - setSortedSubStatements([]); - return; + return ([]); case QuestionStage.suggestion: - setSortedSubStatements(myStatements); - return; + return myStatements; case QuestionStage.firstEvaluation: - try { - const subStatements = await getFirstEvaluationOptions(statement); - const st = getSortedStatements(subStatements, sort, questions); - setSortedSubStatements(st); - } catch (error) { - console.error(error); - } - - return; + const firstSt = await getFirstEvaluationOptions(statement); + return getSortedStatements(firstSt, sort, questions); case QuestionStage.secondEvaluation: - try { - const subStatements = await getSecondEvaluationOptions(statement); - const st = getSortedStatements(subStatements, sort, questions); - setSortedSubStatements(st); - } catch (error) { - console.error(error); - } - return; + const secondSt = await getSecondEvaluationOptions(statement); + return getSortedStatements(secondSt, sort, questions); case QuestionStage.voting: - setSortedSubStatements([]); - return; + + return ([]); default: - console.log("default ") - setSortedSubStatements([]); - return; + return ([]); } } - return; + } catch (error) { console.error(error); - + return []; } } -function getSortedStatements(_subStatements:Statement[], sort: string | undefined, questions: boolean) { +function getSortedStatements(_subStatements: Statement[], sort: string | undefined, questions: boolean) { return sortSubStatements( _subStatements, sort From 6504e9682c429d83ced01e318db6a7a73f6ddeee Mon Sep 17 00:00:00 2001 From: Lee_D Date: Tue, 3 Sep 2024 21:55:09 +0300 Subject: [PATCH 09/21] He-translation --- src/assets/Languages/he.json | 337 ++++++++++++++-------------- src/controllers/db/vote/getVotes.ts | 86 ++++--- 2 files changed, 211 insertions(+), 212 deletions(-) diff --git a/src/assets/Languages/he.json b/src/assets/Languages/he.json index 0362ceeec..ff4227c63 100644 --- a/src/assets/Languages/he.json +++ b/src/assets/Languages/he.json @@ -1,168 +1,171 @@ { - "Add": "הוספה", - "Add New Group": "הוספת קבוצה חדשה", - "Add Option": "הוספת פתרון", - "Add a solution": "הוספת פתרון", - "Add Question": "הוספת שאלה", - "Admin": "מנהל", - "Advanced": "מתקדם", - "Agree": "אני מסכים/ה", - "Agreement": "הסכמה", - "Agreement Description": "אנא אשר/י שאת/ה יודע/ת שזאת תוכנת ניסוי, וכל מידע שתכניס/י למערכת עלול להיות ציבורי וחשוף לקהל רחב. אנא המנע/י מהכנסת מידע רגיש. כל הכנסת מידע נמצא באחריותך בלבד, ואין לך תביעה מבעלי המערכת", - "Agreements": "הסכמות", - "All": "הכל", - "Allow participants to contribute options to the evaluation page": "לאפשר למשתתפים לתרום אפשרויות לדף ההערכות", - "Allow participants to contribute options to the voting page": "לאפשר למשתתפים לתרום אפשרויות לדף ההצבעה", - "Answer": "תשובה", - "Blocked": "חסום", - "Couldn't find the invitation. Please check the PIN and try again.": "לא נמצאה ההזמנה. אנא בדקו את הקוד ונסו שוב.", - "Cancel": "ביטול", - "Cancellation of division": "ביטול חלוקה", - "Chat": "שיחה", - "Close": "סגירה", - "Sign up with": "הרשם עם", - "Conversations": "שיחות", - "Creating Agreements": "יוצרים הסכמות", - "Delib": "המועצה", - "Delib: We create agreements together": "דליב: אנחנו יוצרים הסכמות ביחד", - "Description": "תיאור", - "Disconnect": "התנתקות", - "Display Results": "הצגת תוצאות", - "Display Results According To": "הצגת תוצאות לפי", - "Discussion Results": "תוצאות הדיון", - "Discussion Topic": "נושא הדיון", - "Divide into rooms": "חלק/י לחדרים", - "Division into rooms": "חלוקה לחדרים", - "Dont agree": "אני לא מסכים/ה", - "Edit Text": "עריכת טקסט", - "Enable Sub-Conversations": "לאפשר תת-שיחות", - "Evaluated": "העריכו", - "Enhanced Evaluation": "הערכה מגוונת", - "Evaluations": "פתרונות", - "Explain how to open the notifications": "הסבר כיצד לפתוח את ההתראות", - "Favorite Option": "אופציה מועדפת", - "Follow Me": "עקוב אחרי", - "Follow Mode Active": "מצב עקיבה פעיל", - "Follow Instructor": "עקוב אחרי המדריך/ה", - "Fostering Collaborations": "מקדמים שיתופי פעולה", - "From the Institute for Deliberative Democracy": "מבית המכון לדמוקרטיה דיונית", - "General": "כללי", - "Get Voters": "הבא מצביעים/ות", - "Get Evaluators": "הבא מעריכים/ות", - "Got it": "הבנתי", - "Guest": "אורח", - "Group": "קבוצה", - "Group Description": "תיאור הקבוצה", - "Group Title": "כותרת הקבוצה", - "Join with PIN number": "הצטרפות עם מספר קוד", - "Join": "הצטרף/י", - "Invite with PIN number": "הזמנה עם מספר קוד", - "Install the App": "התקנת האפליקציה", - "Info": "מידע", - "In conversation:": "בשיחה:", - "In Voting page, show only the results of the top options": "בדף ההצבעה, הצג רק את תוצאות האופציות המובילות", - "In Zoom": "בזום", - "Invited:": "מוזמנים:", - "It is necessary to receive notifications": "יש צורך לקבל התראות", - "Login with a temporary name": "התחברות עם שם זמני", - "Map": "מפה", - "Main": "ראשי", - "Main Page": "דף ראשי", - "Mass Questions": "שאלות המונים", - "Member": "חבר", - "Members in Group": "חברים בקבוצה", - "Management board": "לוח ניהול", - "Maximum number of participants in the room": "מספר מקסימלי של משתתפים בחדר", - "New": "חדש", - "New message": "הודעה חדשה", - "New Messages": "הודעות חדשות", - "Nickname": "כינוי", - "No": "לא", - "No Options Selected Yet": "לא נבחרו עדיין אפשרויות", - "No Topic Chosen by You": "לא נבחר נושא על ידך", - "No evaluators found": "לא נמצאו הערכות של משתתפים", - "No voters found": "לא נמצאו מצביעים", - "Number of Results to Display": "כמה תוצאות להציג", - "Number of Solutions in Each Level": "כמות פתרונות בכל רמה", - "Please suggest a solution to the question": "אנא הצע/י פתרון לשאלה", - "Option": "אפשרות", - "Options": "אפשרויות", - "Parent Admin": "מנהל על", - "Participants": "משתתפים", - "Participants choose rooms": "המשתתפים בוחרים חדרים", - "Please confirm alerts for Delib": "אנא אשרו התראות עבור דליב", - "Please confirm notifications to receive updates on new comments\nYou can disable notifications at any time": "אנא אשר/י התראות, כדי לקבל עדכונים על תגובות חדשות\nתוכל/י לבטל את ההתראות בכל זמן", - "Please evaluate each solution in the next set of solutions. For each solution, indicate your rating using the smiley (positive) or frown (negative) icons": "אנא העריכו כל פתרון בסט הפתרונות הבא. עבור כל פתרון, ציינו את הדירוג שלכם באמצעות האייקונים של החיוך (חיובי) או הפרצוף העצוב (שלילי)", - "Please evaluate the top solutions": "אנא העריכו את הפתרונות המובילים", - "Please chose your preferred solution": "אנא בחר/י את הפתרון המועדף עליך", - "Question": "שאלה", - "Questions": "שאלות", - "Random": "אקראי", - "Remove Option": "הסרת אפשרות", - "Results": "תוצאות", - "Results By": "תוצאות לפי", - "Room": "חדר", - "Rooms": "חדרים", - "Selected": "נבחר", - "Room Allocation": "חלוקה לחדרים", - "Room's Topic": "נושא החדר", - "Send a link to anonymous users": "שליחת קישור למשתמשים אנונימיים", - "Settings": "הגדרות", - "Share": "שתף/י", - "Show division into rooms": "הצג/י חלוקה לחדרים", - "Show Evaluations results": "הצגת תוצאות הערכות", - "Show": "הצג ", - "So you can communicate": "כדי שתוכלו לתקשר", - "Solutions": "פתרונות", - "Start": "התחלה", - "Sorry, Page not found": "מצטערים, הדף לא נמצא", - "Take me home": "הביאו אותי הביתה", - "Tabs to display": "לשוניות", - "General Settings": "הגדרות כלליות", - "Members": "חברים", - "Joined members": "חברים שהצטרפו", - "terms of use": "תנאי שימוש", - "Title": "כותרת", - "Turn off": "כיבוי התראות", - "Turn on": "הפעלת התראות", - "Update": "עדכון", - "Updating": "מעדכן", - "Voted": "הצביעו", - "Votes": "הצבעות", - "Voting": "הצבעה", - "Voting Results": "תוצאות ההצבעה", - "Vote": "הצבעה", - "Welcome to Room Number": "מוזמן/ת לחדר מספר", - "Yes": "כן", - "Would you like to receive notifications in this group?": "האם תרצה לקבל הודעות בקבוצה הזאת?", - "Save": "שמירה", - "description": "תיאור", - "Unmark as a Solution": "ביטול סימון כפתרון", - "Mark as a Solution": "סימון כפתרון", - "Mark as a Question": "סימון כשאלה", - "Unmark as a Question": "ביטול סימון כשאלה", - "Welcome to room": "ברוך/ה הבא/ה לחדר", - "Current stage": "שלב נוכחי", - "Suggestions": "הצעות", - "First Evaluation": "הערכה ראשונה", - "Second Evaluation": "הערכה שנייה", - "Finished": "סיום", - "single-step": "שלב אחד", - "multiple-steps": "מספר שלבים", - "There are no rooms yet": "אין עדיין חדרים", - "Enter your 4-digit passcode to unlock group access": "הזן את קוד הסיסמה בן 4 הספרות שלך כדי לבטל את נעילת הגישה לקבוצה", - "Bravo! Your passcode is correct. Welcome aboard!": "בראבו! קוד הגישה שלך נכון. ברוכים הבאים!", - "Something went wrong. Please try again!": "משהו השתבש. בבקשה נסה שוב!", - "Submit": "שלח", - "Click on": "תלחץ על", - "Add suggestion button": "הוסף פתרון", - "to add your suggestion": "כדי להוסיף את הפתרון שלך", - "Add suggestion":"הוסף פתרון", - "Add question button": "הוסף שאלה", - "to add your question": "כדי להוסיף את השאלה שלך", - "Add question":"הוסף שאלה", - "Sort questions": "מיין שאלות", - "Sort suggestions": "מיין פתרונות", - "Allow similarity search": "אפשר חיפוש דמיון", - "Allow removal of navigational elements": "אפשר הסרת רכיבי ניווט" -} \ No newline at end of file + "Add": "הוספה", + "Add New Group": "הוספת קבוצה חדשה", + "Add Option": "הוספת פתרון", + "Add a solution": "הוספת פתרון", + "Add Question": "הוספת שאלה", + "Admin": "מנהל", + "Advanced": "מתקדם", + "Agree": "אני מסכים/ה", + "Agreement": "הסכמה", + "Agreement Description": "אנא אשר/י שאת/ה יודע/ת שזאת תוכנת ניסוי, וכל מידע שתכניס/י למערכת עלול להיות ציבורי וחשוף לקהל רחב. אנא המנע/י מהכנסת מידע רגיש. כל הכנסת מידע נמצא באחריותך בלבד, ואין לך תביעה מבעלי המערכת", + "Agreements": "הסכמות", + "All": "הכל", + "Allow participants to contribute options to the evaluation page": "לאפשר למשתתפים לתרום אפשרויות לדף ההערכות", + "Allow participants to contribute options to the voting page": "לאפשר למשתתפים לתרום אפשרויות לדף ההצבעה", + "Answer": "תשובה", + "Blocked": "חסום", + "Couldn't find the invitation. Please check the PIN and try again.": "לא נמצאה ההזמנה. אנא בדקו את הקוד ונסו שוב.", + "Cancel": "ביטול", + "Cancellation of division": "ביטול חלוקה", + "Chat": "שיחה", + "Close": "סגירה", + "Sign up with": "הרשם עם", + "Conversations": "שיחות", + "Creating Agreements": "יוצרים הסכמות", + "Delib": "המועצה", + "Delib: We create agreements together": "דליב: אנחנו יוצרים הסכמות ביחד", + "Description": "תיאור", + "Disconnect": "התנתקות", + "Display Results": "הצגת תוצאות", + "Display Results According To": "הצגת תוצאות לפי", + "Discussion Results": "תוצאות הדיון", + "Discussion Topic": "נושא הדיון", + "Divide into rooms": "חלק/י לחדרים", + "Division into rooms": "חלוקה לחדרים", + "Dont agree": "אני לא מסכים/ה", + "Edit Text": "עריכת טקסט", + "Enable Sub-Conversations": "לאפשר תת-שיחות", + "Evaluated": "העריכו", + "Enhanced Evaluation": "הערכה מגוונת", + "Evaluations": "פתרונות", + "Explain how to open the notifications": "הסבר כיצד לפתוח את ההתראות", + "Favorite Option": "אופציה מועדפת", + "Follow Me": "עקוב אחרי", + "Follow Mode Active": "מצב עקיבה פעיל", + "Follow Instructor": "עקוב אחרי המדריך/ה", + "Fostering Collaborations": "מקדמים שיתופי פעולה", + "From the Institute for Deliberative Democracy": "מבית המכון לדמוקרטיה דיונית", + "General": "כללי", + "Get Voters": "הבא מצביעים/ות", + "Get Non Voters": "הבא משתתפים/ות שלא הצביעו", + "Get Evaluators": "הבא מעריכים/ות", + "Got it": "הבנתי", + "Guest": "אורח", + "Group": "קבוצה", + "Group Description": "תיאור הקבוצה", + "Group Title": "כותרת הקבוצה", + "Join with PIN number": "הצטרפות עם מספר קוד", + "Join": "הצטרף/י", + "Invite with PIN number": "הזמנה עם מספר קוד", + "Install the App": "התקנת האפליקציה", + "Info": "מידע", + "In conversation:": "בשיחה:", + "In Voting page, show only the results of the top options": "בדף ההצבעה, הצג רק את תוצאות האופציות המובילות", + "In Zoom": "בזום", + "Invited:": "מוזמנים:", + "It is necessary to receive notifications": "יש צורך לקבל התראות", + "Login with a temporary name": "התחברות עם שם זמני", + "Map": "מפה", + "Main": "ראשי", + "Main Page": "דף ראשי", + "Mass Questions": "שאלות המונים", + "Member": "חבר", + "Members in Group": "חברים בקבוצה", + "Management board": "לוח ניהול", + "Maximum number of participants in the room": "מספר מקסימלי של משתתפים בחדר", + "New": "חדש", + "New message": "הודעה חדשה", + "New Messages": "הודעות חדשות", + "Nickname": "כינוי", + "No": "לא", + "No Options Selected Yet": "לא נבחרו עדיין אפשרויות", + "No Topic Chosen by You": "לא נבחר נושא על ידך", + "No evaluators found": "לא נמצאו הערכות של משתתפים", + "No voters found": "לא נמצאו מצביעים", + "No non-voters found": "לא נמצאו משתתפים/ות שלא הצביעו", + "Number of Results to Display": "כמה תוצאות להציג", + "Number of Solutions in Each Level": "כמות פתרונות בכל רמה", + "Please suggest a solution to the question": "אנא הצע/י פתרון לשאלה", + "Option": "אפשרות", + "Options": "אפשרויות", + "Parent Admin": "מנהל על", + "Participants": "משתתפים", + "Participants choose rooms": "המשתתפים בוחרים חדרים", + "Please confirm alerts for Delib": "אנא אשרו התראות עבור דליב", + "Please confirm notifications to receive updates on new comments\nYou can disable notifications at any time": "אנא אשר/י התראות, כדי לקבל עדכונים על תגובות חדשות\nתוכל/י לבטל את ההתראות בכל זמן", + "Please evaluate each solution in the next set of solutions. For each solution, indicate your rating using the smiley (positive) or frown (negative) icons": "אנא העריכו כל פתרון בסט הפתרונות הבא. עבור כל פתרון, ציינו את הדירוג שלכם באמצעות האייקונים של החיוך (חיובי) או הפרצוף העצוב (שלילי)", + "Please evaluate the top solutions": "אנא העריכו את הפתרונות המובילים", + "Please chose your preferred solution": "אנא בחר/י את הפתרון המועדף עליך", + "Question": "שאלה", + "Questions": "שאלות", + "Random": "אקראי", + "Remove Option": "הסרת אפשרות", + "Results": "תוצאות", + "Results By": "תוצאות לפי", + "Room": "חדר", + "Rooms": "חדרים", + "Selected": "נבחר", + "Room Allocation": "חלוקה לחדרים", + "Room's Topic": "נושא החדר", + "Send a link to anonymous users": "שליחת קישור למשתמשים אנונימיים", + "Settings": "הגדרות", + "Share": "שתף/י", + "Show division into rooms": "הצג/י חלוקה לחדרים", + "Show Evaluations results": "הצגת תוצאות הערכות", + "Show": "הצג ", + "So you can communicate": "כדי שתוכלו לתקשר", + "Solutions": "פתרונות", + "Start": "התחלה", + "Sorry, Page not found": "מצטערים, הדף לא נמצא", + "Take me home": "הביאו אותי הביתה", + "Tabs to display": "לשוניות", + "General Settings": "הגדרות כלליות", + "Members": "חברים", + "Joined members": "חברים שהצטרפו", + "terms of use": "תנאי שימוש", + "Title": "כותרת", + "Turn off": "כיבוי התראות", + "Turn on": "הפעלת התראות", + "Update": "עדכון", + "Updating": "מעדכן", + "Voted": "הצביעו", + "Votes": "הצבעות", + "Voting": "הצבעה", + "Did Not Vote": "לא הצביעו", + "Voting Results": "תוצאות ההצבעה", + "Vote": "הצבעה", + "Welcome to Room Number": "מוזמן/ת לחדר מספר", + "Yes": "כן", + "Would you like to receive notifications in this group?": "האם תרצה לקבל הודעות בקבוצה הזאת?", + "Save": "שמירה", + "description": "תיאור", + "Unmark as a Solution": "ביטול סימון כפתרון", + "Mark as a Solution": "סימון כפתרון", + "Mark as a Question": "סימון כשאלה", + "Unmark as a Question": "ביטול סימון כשאלה", + "Welcome to room": "ברוך/ה הבא/ה לחדר", + "Current stage": "שלב נוכחי", + "Suggestions": "הצעות", + "First Evaluation": "הערכה ראשונה", + "Second Evaluation": "הערכה שנייה", + "Finished": "סיום", + "single-step": "שלב אחד", + "multiple-steps": "מספר שלבים", + "There are no rooms yet": "אין עדיין חדרים", + "Enter your 4-digit passcode to unlock group access": "הזן את קוד הסיסמה בן 4 הספרות שלך כדי לבטל את נעילת הגישה לקבוצה", + "Bravo! Your passcode is correct. Welcome aboard!": "בראבו! קוד הגישה שלך נכון. ברוכים הבאים!", + "Something went wrong. Please try again!": "משהו השתבש. בבקשה נסה שוב!", + "Submit": "שלח", + "Click on": "תלחץ על", + "Add suggestion button": "הוסף פתרון", + "to add your suggestion": "כדי להוסיף את הפתרון שלך", + "Add suggestion": "הוסף פתרון", + "Add question button": "הוסף שאלה", + "to add your question": "כדי להוסיף את השאלה שלך", + "Add question": "הוסף שאלה", + "Sort questions": "מיין שאלות", + "Sort suggestions": "מיין פתרונות", + "Allow similarity search": "אפשר חיפוש דמיון", + "Allow removal of navigational elements": "אפשר הסרת רכיבי ניווט" +} diff --git a/src/controllers/db/vote/getVotes.ts b/src/controllers/db/vote/getVotes.ts index 376efeeae..164211eec 100644 --- a/src/controllers/db/vote/getVotes.ts +++ b/src/controllers/db/vote/getVotes.ts @@ -1,10 +1,10 @@ import { - collection, - doc, - getDoc, - getDocs, - query, - where, + collection, + doc, + getDoc, + getDocs, + query, + where, } from "firebase/firestore"; import { Collections, Statement, StatementSchema, Vote } from "delib-npm"; import { DB } from "../config"; @@ -14,56 +14,52 @@ import { store } from "@/model/store"; // Why get user from firebase when we can pass it as a parameter? export async function getToVoteOnParent( - parentId: string, - updateStoreWithVoteCB: (statement: Statement) => void, + parentId: string, + updateStoreWithVoteCB: (statement: Statement) => void ): Promise { - try { - const user = getUserFromFirebase(); - if (!user) throw new Error("User not logged in"); - if(!parentId) throw new Error("ParentId not provided"); - const voteId = getVoteId(user.uid, parentId); - if (!voteId) throw new Error("VoteId not found"); + try { + const user = getUserFromFirebase(); + if (!user) throw new Error("User not logged in"); + if (!parentId) throw new Error("ParentId not provided"); + const voteId = getVoteId(user.uid, parentId); + if (!voteId) throw new Error("VoteId not found"); - const parentVoteRef = doc( - DB, - Collections.votes, - voteId - ); + const parentVoteRef = doc(DB, Collections.votes, voteId); - const voteDB = await getDoc(parentVoteRef); + const voteDB = await getDoc(parentVoteRef); - const vote = voteDB.data(); - if (!vote) return; // the user has not voted on this statement - VoteSchema.parse(vote); + const vote = voteDB.data(); + if (!vote) return; + VoteSchema.parse(vote); - //get statemtn to update to store - const statementRef = doc(DB, Collections.statements, vote.statementId); - const statementDB = await getDoc(statementRef); + //get statemtn to update to store + const statementRef = doc(DB, Collections.statements, vote.statementId); + const statementDB = await getDoc(statementRef); - const statement = statementDB.data() as Statement; - if (!statement) throw new Error("Parent not found"); - StatementSchema.parse(statement); + const statement = statementDB.data() as Statement; + if (!statement) throw new Error("Parent not found"); + StatementSchema.parse(statement); - updateStoreWithVoteCB(statement); - } catch (error) { - console.error(error); - } + updateStoreWithVoteCB(statement); + } catch (error) { + console.error(error); + } } export async function getVoters(parentId: string): Promise { - try { - const user = store.getState().user.user; - if (!user) throw new Error("User not logged in"); - const votesRef = collection(DB, Collections.votes); - const q = query(votesRef, where("parentId", "==", parentId)); + try { + const user = store.getState().user.user; + if (!user) throw new Error("User not logged in"); + const votesRef = collection(DB, Collections.votes); + const q = query(votesRef, where("parentId", "==", parentId)); - const votersDB = await getDocs(q); - const voters = votersDB.docs.map((vote) => vote.data()) as Vote[]; + const votersDB = await getDocs(q); + const voters = votersDB.docs.map((vote) => vote.data()) as Vote[]; - return voters; - } catch (error) { - console.error(error); + return voters; + } catch (error) { + console.error(error); - return [] as Vote[]; - } + return [] as Vote[]; + } } From 0fcb459a24622144d4b19a1d4bc3d87481f6a55b Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 08:17:03 +0300 Subject: [PATCH 10/21] regualr sorting works --- .../solutions/StatementSolutionsPage.tsx | 41 +-- .../components/StatementSolutionCard.tsx | 304 +++++++++--------- .../SuggestionCards.module.scss | 4 + .../suggestionCards/SuggestionCards.tsx | 53 ++- 4 files changed, 214 insertions(+), 188 deletions(-) create mode 100644 src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.module.scss diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index 4ad68e497..20cc35258 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -25,6 +25,7 @@ import styles from "./statementSolutinsPage.module.scss"; import { useSelector } from "react-redux"; import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; import EmptyScreen from "./components/emptyScreen/EmptyScreen"; +import SuggestionCards from "./components/suggestionCards/SuggestionCards"; interface StatementEvaluationPageProps { statement: Statement; @@ -67,7 +68,9 @@ const StatementEvaluationPage: FC = ({ const [showExplanation, setShowExplanation] = useState( currentStage === QuestionStage.explanation && isMultiStage && !questions ); - const [sortedSubStatements, setSortedSubStatements] = useState([]); + const [sortedSubStatements, setSortedSubStatements] = useState( + [] + ); useEffect(() => { getSubStatements({ @@ -77,7 +80,7 @@ const StatementEvaluationPage: FC = ({ questions, myStatements, }).then((_subStatements) => { - console.log("new st..............", _subStatements.length) + console.log("new st..............", _subStatements.length); setSortedSubStatements(_subStatements); }); }, [sort, subStatements, questions, isMultiStage]); @@ -105,13 +108,7 @@ const StatementEvaluationPage: FC = ({ } }, [statement.questionSettings?.currentStage, questions]); - // Variables - let topSum = 30; - const tops: number[] = [topSum]; const message = stageInfo ? stageInfo.message : false; - console.log(topSum, tops) - - return ( <> @@ -133,29 +130,11 @@ const StatementEvaluationPage: FC = ({ {getToastButtons(currentStage)} )} - {sortedSubStatements?.map( - (statementSub: Statement, i: number) => { - //get the top of the element - if (statementSub.elementHight) { - topSum += statementSub.elementHight + 30; - tops.push(topSum); - } - - return ( - - ); - } - )} -
+
)}
diff --git a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx b/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx index 5adddffee..c78d33c17 100644 --- a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx +++ b/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx @@ -6,8 +6,8 @@ import { Statement, StatementType, User } from "delib-npm"; // Redux Store import { useAppDispatch, useAppSelector } from "@/controllers/hooks/reduxHooks"; import { - setStatementElementHight, - statementSubscriptionSelector, + setStatementElementHight, + statementSubscriptionSelector, } from "@/model/statements/statementsSlice"; // Helpers @@ -15,7 +15,7 @@ import { isAuthorized, linkToChildren } from "@/controllers/general/helpers"; // Hooks import useStatementColor, { - StyleProps, + StyleProps, } from "@/controllers/hooks/useStatementColor"; // Custom Components @@ -33,6 +33,7 @@ import "./StatementSolutionCard.scss"; import SolutionMenu from "./solutionMenu/SolutionMenu"; interface Props { + statement: Statement; parentStatement: Statement; showImage: (talker: User | null) => void; @@ -40,156 +41,157 @@ interface Props { } const StatementSolutionCard: FC = ({ - parentStatement, - statement, - top, + + parentStatement, + statement, + top, }) => { - // Hooks - - const { t, dir } = useLanguage(); - - // Redux Store - const dispatch = useAppDispatch(); - const statementColor: StyleProps = useStatementColor( - statement.statementType || StatementType.statement - ); - const statementSubscription = useAppSelector( - statementSubscriptionSelector(statement.statementId) - ); - - // Use Refs - const elementRef = useRef(null); - - // Use States - const [newTop, setNewTop] = useState(top); - const [isEdit, setIsEdit] = useState(false); - const [shouldShowAddSubQuestionModal, setShouldShowAddSubQuestionModal] = + // Hooks + + const { t, dir } = useLanguage(); + + // Redux Store + const dispatch = useAppDispatch(); + const statementColor: StyleProps = useStatementColor( + statement.statementType || StatementType.statement + ); + const statementSubscription = useAppSelector( + statementSubscriptionSelector(statement.statementId) + ); + + // Use Refs + const elementRef = useRef(null); + + // Use States + const [newTop, setNewTop] = useState(top); + const [isEdit, setIsEdit] = useState(false); + const [shouldShowAddSubQuestionModal, setShouldShowAddSubQuestionModal] = useState(false); - const [isCardMenuOpen, setIsCardMenuOpen] = useState(false); - - const _isAuthorized = isAuthorized( - statement, - statementSubscription, - parentStatement.creatorId - ); - - useEffect(() => { - setNewTop(top); - }, [top]); - - useEffect(() => { - dispatch( - setStatementElementHight({ - statementId: statement.statementId, - height: elementRef.current?.clientHeight, - }) - ); - }, [statement.statement]); - - function handleSetOption() { - try { - if (statement.statementType === "option") { - const cancelOption = window.confirm( - "Are you sure you want to cancel this option?" - ); - if (cancelOption) { - setStatementIsOption(statement); - } - } else { - setStatementIsOption(statement); - } - } catch (error) { - console.error(error); - } - } - - const shouldLinkToChildStatements = linkToChildren( - statement, - parentStatement - ); - - const statementAge = new Date().getTime() - statement.createdAt; - - return ( -
-
-
- {t("Selected")} -
-
-
-
-
- -
-
- -
-
- {shouldLinkToChildStatements && ( -
- -
- )} -
- - {parentStatement.hasChildren && ( - setShouldShowAddSubQuestionModal(true)} - > - - - )} -
- {shouldShowAddSubQuestionModal && ( - - )} -
-
- ); + const [isCardMenuOpen, setIsCardMenuOpen] = useState(false); + + const _isAuthorized = isAuthorized( + statement, + statementSubscription, + parentStatement.creatorId + ); + + useEffect(() => { + setNewTop(top); + }, [top]); + + useEffect(() => { + dispatch( + setStatementElementHight({ + statementId: statement.statementId, + height: elementRef.current?.clientHeight, + }) + ); + }, [statement.statement, parentStatement.questionSettings?.currentStage]); + + function handleSetOption() { + try { + if (statement.statementType === "option") { + const cancelOption = window.confirm( + "Are you sure you want to cancel this option?" + ); + if (cancelOption) { + setStatementIsOption(statement); + } + } else { + setStatementIsOption(statement); + } + } catch (error) { + console.error(error); + } + } + + const shouldLinkToChildStatements = linkToChildren( + statement, + parentStatement + ); + + const statementAge = new Date().getTime() - statement.createdAt; + + return ( +
+
+
+ {t("Selected")} +
+
+
+
+
+ +
+
+ +
+
+ {shouldLinkToChildStatements && ( +
+ +
+ )} +
+ + {parentStatement.hasChildren && ( + setShouldShowAddSubQuestionModal(true)} + > + + + )} +
+ {shouldShowAddSubQuestionModal && ( + + )} +
+
+ ); }; export default StatementSolutionCard; diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.module.scss b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.module.scss new file mode 100644 index 000000000..0320f56be --- /dev/null +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.module.scss @@ -0,0 +1,4 @@ +.suggestions-wrapper{ + position: relative; + width: 100%; +} \ No newline at end of file diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 7d1e7cc67..40354b9ca 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,9 +1,50 @@ -import React from 'react' +import { Statement, User } from "delib-npm"; +import { FC } from "react"; +import StatementEvaluationCard from "../StatementSolutionCard"; +import styles from "./SuggestionCards.module.scss"; -const SuggestionCards = () => { - return ( -
SuggestionCards
- ) +interface Props { + statement: Statement; + sortedSubStatements: Statement[]; + handleShowTalker: (talker: User | null) => void; } -export default SuggestionCards \ No newline at end of file +const SuggestionCards: FC = ({ + statement, + sortedSubStatements, + handleShowTalker, +}) => { + // Variables + let topSum = 30; + const tops: number[] = [topSum]; + + console.log(topSum, tops); + + return ( +
+ {sortedSubStatements?.map((statementSub: Statement, i: number) => { + //get the top of the element + if (statementSub.elementHight) { + topSum += statementSub.elementHight + 30; + tops.push(topSum); + } + + return ( + + ); + })} +
+
+ ); +}; + +export default SuggestionCards; From d15ee273f9bd1a609e8c884b8db6900d1097687f Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 08:58:22 +0300 Subject: [PATCH 11/21] refactoring to use context --- .../solutions/StatementSolutionsPage.tsx | 124 ++++++++---------- .../suggestionCards/SuggestionCards.tsx | 41 +++++- .../suggestionCards/suggestionCardsCont.ts | 16 +++ .../statementSolutionPageContext.tsx | 26 ++++ 4 files changed, 134 insertions(+), 73 deletions(-) create mode 100644 src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts create mode 100644 src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index 20cc35258..3a1ac213e 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -4,11 +4,8 @@ import { FC, useEffect, useState } from "react"; import { QuestionStage, QuestionType, Statement, User } from "delib-npm"; import { useParams, useNavigate } from "react-router"; -// Utils & Helpers -import { getSubStatements } from "./statementSolutionsCont"; - // Custom Components -import StatementEvaluationCard from "./components/StatementSolutionCard"; + import StatementBottomNav from "../nav/bottom/StatementBottomNav"; import Toast from "@/view/components/toast/Toast"; import Modal from "@/view/components/modal/Modal"; @@ -26,6 +23,7 @@ import { useSelector } from "react-redux"; import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; import EmptyScreen from "./components/emptyScreen/EmptyScreen"; import SuggestionCards from "./components/suggestionCards/SuggestionCards"; +import { SubStatementsProvider } from "./statementSolutionPageContext"; interface StatementEvaluationPageProps { statement: Statement; @@ -47,15 +45,13 @@ const StatementEvaluationPage: FC = ({ }) => { try { // Hooks - const { sort } = useParams(); + const navigate = useNavigate(); const { t } = useLanguage(); const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - const myStatements = useSelector( - myStatementsByStatementIdSelector(statement.statementId) - ); + const currentStage = statement.questionSettings?.currentStage; const stageInfo = getStagesInfo(currentStage); @@ -68,22 +64,9 @@ const StatementEvaluationPage: FC = ({ const [showExplanation, setShowExplanation] = useState( currentStage === QuestionStage.explanation && isMultiStage && !questions ); - const [sortedSubStatements, setSortedSubStatements] = useState( - [] - ); + - useEffect(() => { - getSubStatements({ - statement, - subStatements, - sort, - questions, - myStatements, - }).then((_subStatements) => { - console.log("new st..............", _subStatements.length); - setSortedSubStatements(_subStatements); - }); - }, [sort, subStatements, questions, isMultiStage]); + useEffect(() => { if (questions) { @@ -111,58 +94,61 @@ const StatementEvaluationPage: FC = ({ const message = stageInfo ? stageInfo.message : false; return ( - <> -
- {sortedSubStatements.length === 0 ? ( - + <> +
+ {subStatements.length === 0 ? ( + + ) : ( +
+ {isMultiStage && message && ( + + {getToastButtons(currentStage)} + + )} + +
+ )} +
+
+ - ) : ( -
- {isMultiStage && message && ( - - {getToastButtons(currentStage)} - - )} - + {showExplanation && ( + + -
+ )} -
-
- -
- {showExplanation && ( - - - - )} - {showModal && ( - - )} - + )} + + ); function getToastButtons(questionStage: QuestionStage | undefined) { diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 40354b9ca..7fe7b40b0 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,19 +1,52 @@ -import { Statement, User } from "delib-npm"; -import { FC } from "react"; +import { QuestionType, Statement, User } from "delib-npm"; +import { FC, useContext, useEffect } from "react"; import StatementEvaluationCard from "../StatementSolutionCard"; import styles from "./SuggestionCards.module.scss"; +import { getSubStatements } from "../../statementSolutionsCont"; +import { useParams } from "react-router-dom"; +import { useSelector } from "react-redux"; +import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; +import { SubStatementsContext } from "../../statementSolutionPageContext"; interface Props { statement: Statement; - sortedSubStatements: Statement[]; + subStatements: Statement[]; + questions: boolean; handleShowTalker: (talker: User | null) => void; } const SuggestionCards: FC = ({ statement, - sortedSubStatements, + subStatements, handleShowTalker, + questions, }) => { + const { sort } = useParams(); + const isMultiStage = + statement.questionSettings?.questionType === QuestionType.multipleSteps; + const myStatements = useSelector( + myStatementsByStatementIdSelector(statement.statementId) + ); + + const { sortedSubStatements, setSortedSubStatements } = + useContext(SubStatementsContext); + + useEffect(() => { + setSortedSubStatements(subStatements); + }, []); + + useEffect(() => { + getSubStatements({ + statement, + subStatements, + sort, + questions, + myStatements, + }).then((_subStatements) => { + setSortedSubStatements(_subStatements); + }); + }, [sort, subStatements, questions, isMultiStage]); + // Variables let topSum = 30; const tops: number[] = [topSum]; diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts new file mode 100644 index 000000000..35c5d626d --- /dev/null +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts @@ -0,0 +1,16 @@ +import { Statement } from "delib-npm"; + +export function getTops(sortedSubStatements: Statement[]): {statementId: string, top: number}[] { + let topSum = 30; + const tops: number[] = [topSum]; + + sortedSubStatements.forEach((statementSub: Statement, i: number) => { + //get the top of the element + if (statementSub.elementHight) { + topSum += statementSub.elementHight + 30; + tops.push(topSum); + } + }); + + return tops; +} \ No newline at end of file diff --git a/src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx b/src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx new file mode 100644 index 000000000..8d0acef39 --- /dev/null +++ b/src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx @@ -0,0 +1,26 @@ +import React, { createContext, useState, ReactNode } from "react"; +import { Statement } from "delib-npm"; + +interface SubStatementsContextType { + sortedSubStatements: Statement[]; + setSortedSubStatements: React.Dispatch>; +} + +export const SubStatementsContext = createContext({ + sortedSubStatements: [], + setSortedSubStatements: () => {}, +}); + +interface SubStatementsProviderProps { + children: ReactNode; +} + +export const SubStatementsProvider: React.FC = ({ children }): ReactNode => { + const [sortedSubStatements, setSortedSubStatements] = useState([]); + + return ( + + {children} + + ); +}; \ No newline at end of file From cd69ec141167b21a4fa8e3e363549e425b7c6ce2 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 10:15:25 +0300 Subject: [PATCH 12/21] cont --- .../solutions/StatementSolutionsPage.tsx | 2 -- .../components/StatementSolutionCard.tsx | 36 +++++++++++++------ .../suggestionCards/SuggestionCards.tsx | 10 +++--- .../suggestionCards/suggestionCardsCont.ts | 16 --------- 4 files changed, 32 insertions(+), 32 deletions(-) delete mode 100644 src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index 3a1ac213e..fba66aba2 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -19,8 +19,6 @@ import { getTitle } from "@/controllers/general/helpers"; import CreateStatementModalSwitch from "../createStatementModalSwitch/CreateStatementModalSwitch"; import styles from "./statementSolutinsPage.module.scss"; -import { useSelector } from "react-redux"; -import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; import EmptyScreen from "./components/emptyScreen/EmptyScreen"; import SuggestionCards from "./components/suggestionCards/SuggestionCards"; import { SubStatementsProvider } from "./statementSolutionPageContext"; diff --git a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx b/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx index c78d33c17..8dc7c0760 100644 --- a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx +++ b/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx @@ -1,4 +1,4 @@ -import { FC, useEffect, useRef, useState } from "react"; +import { FC, useContext, useEffect, useRef, useState } from "react"; // Third Party import { Statement, StatementType, User } from "delib-npm"; @@ -31,9 +31,9 @@ import CreateStatementModal from "../../createStatementModal/CreateStatementModa import Evaluation from "./evaluation/Evaluation"; import "./StatementSolutionCard.scss"; import SolutionMenu from "./solutionMenu/SolutionMenu"; +import { SubStatementsContext } from "../statementSolutionPageContext"; interface Props { - statement: Statement; parentStatement: Statement; showImage: (talker: User | null) => void; @@ -41,7 +41,6 @@ interface Props { } const StatementSolutionCard: FC = ({ - parentStatement, statement, top, @@ -63,6 +62,8 @@ const StatementSolutionCard: FC = ({ const elementRef = useRef(null); // Use States + const { sortedSubStatements, setSortedSubStatements } = + useContext(SubStatementsContext); const [newTop, setNewTop] = useState(top); const [isEdit, setIsEdit] = useState(false); const [shouldShowAddSubQuestionModal, setShouldShowAddSubQuestionModal] = @@ -80,13 +81,27 @@ const StatementSolutionCard: FC = ({ }, [top]); useEffect(() => { - dispatch( - setStatementElementHight({ - statementId: statement.statementId, - height: elementRef.current?.clientHeight, - }) - ); - }, [statement.statement, parentStatement.questionSettings?.currentStage]); + const element = elementRef.current; + if (element) { + setTimeout(() => { + dispatch( + setStatementElementHight({ + statementId: statement.statementId, + height: elementRef.current?.clientHeight, + }) + ); + }, 0); + } + }, [elementRef.current?.clientHeight]); + + // useEffect(() => { + // dispatch( + // setStatementElementHight({ + // statementId: statement.statementId, + // height: elementRef.current?.clientHeight, + // }) + // ); + // }, [statement.statement, parentStatement.questionSettings?.currentStage]); function handleSetOption() { try { @@ -145,6 +160,7 @@ const StatementSolutionCard: FC = ({
+

{statement.elementHight || 0}

= ({ const { sortedSubStatements, setSortedSubStatements } = useContext(SubStatementsContext); - useEffect(() => { - setSortedSubStatements(subStatements); - }, []); + useEffect(() => { + setSortedSubStatements(subStatements); + }, []); + + useEffect(() => { getSubStatements({ @@ -45,7 +47,7 @@ const SuggestionCards: FC = ({ }).then((_subStatements) => { setSortedSubStatements(_subStatements); }); - }, [sort, subStatements, questions, isMultiStage]); + }, [sort,subStatements]); // Variables let topSum = 30; diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts deleted file mode 100644 index 35c5d626d..000000000 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Statement } from "delib-npm"; - -export function getTops(sortedSubStatements: Statement[]): {statementId: string, top: number}[] { - let topSum = 30; - const tops: number[] = [topSum]; - - sortedSubStatements.forEach((statementSub: Statement, i: number) => { - //get the top of the element - if (statementSub.elementHight) { - topSum += statementSub.elementHight + 30; - tops.push(topSum); - } - }); - - return tops; -} \ No newline at end of file From 57427a22ff1860db1a4407e310bfb8a0c0763fcf Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 12:51:21 +0300 Subject: [PATCH 13/21] we now have more clear sorting and animations + no update on random --- package-lock.json | 8 +- package.json | 2 +- src/model/statements/statementsSlice.ts | 26 ++++- .../solutions/StatementSolutionsPage.tsx | 105 ++++++++---------- .../suggestionCards/SuggestionCards.tsx | 74 +++++------- .../suggestionCard/SuggestionCard.scss} | 0 .../suggestionCard/SuggestionCard.tsx} | 49 ++++---- .../statementSolutionPageContext.tsx | 26 ----- .../solutions/statementSolutionsCont.ts | 36 ++++-- 9 files changed, 145 insertions(+), 181 deletions(-) rename src/view/pages/statement/components/solutions/components/{StatementSolutionCard.scss => suggestionCards/suggestionCard/SuggestionCard.scss} (100%) rename src/view/pages/statement/components/solutions/components/{StatementSolutionCard.tsx => suggestionCards/suggestionCard/SuggestionCard.tsx} (82%) delete mode 100644 src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx diff --git a/package-lock.json b/package-lock.json index df19d7431..4da32a9b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@dagrejs/dagre": "^1.0.4", "@reduxjs/toolkit": "^1.9.5", - "delib-npm": "^1.3.44", + "delib-npm": "^1.3.45", "eslint-plugin-import": "^2.29.1", "eslint-plugin-sonarjs": "^1.0.3", "firebase": "^10.0.0", @@ -5486,9 +5486,9 @@ } }, "node_modules/delib-npm": { - "version": "1.3.44", - "resolved": "https://registry.npmjs.org/delib-npm/-/delib-npm-1.3.44.tgz", - "integrity": "sha512-6/5LMhuJ4lekGRVc4sChA6SRgEOxaXUySdswrkENlBMi1htrL8+6aM9zlX/ExJgjfzpOo8cgpibKKyKpENipOQ==", + "version": "1.3.45", + "resolved": "https://registry.npmjs.org/delib-npm/-/delib-npm-1.3.45.tgz", + "integrity": "sha512-yV6KfkizLAldGPehKRCtw1ozad3PeVcuC3dzqDBflTcYvqaQOE/dAcy6Jbxny4EotgbROxG0jIiUndmgEpa+Qw==", "dependencies": { "react": "^18.3.1", "sass": "^1.77.6", diff --git a/package.json b/package.json index 476edb640..a53e6eb0e 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@dagrejs/dagre": "^1.0.4", "@reduxjs/toolkit": "^1.9.5", - "delib-npm": "^1.3.44", + "delib-npm": "^1.3.45", "eslint-plugin-import": "^2.29.1", "eslint-plugin-sonarjs": "^1.0.3", "firebase": "^10.0.0", diff --git a/src/model/statements/statementsSlice.ts b/src/model/statements/statementsSlice.ts index bf3315336..8448a76bb 100644 --- a/src/model/statements/statementsSlice.ts +++ b/src/model/statements/statementsSlice.ts @@ -16,6 +16,7 @@ import { // Helpers import { updateArray } from "../../controllers/general/helpers"; import { sortSubStatements } from "../../view/pages/statement/components/solutions/statementSolutionsCont"; +import { updateStatement } from "@/controllers/db/statements/setStatements"; enum StatementScreen { chat = "chat", @@ -206,6 +207,28 @@ export const statementsSlicer = createSlice({ console.error(error); } }, + updateStatementTop: ( + state, + action: PayloadAction<{ statementId: string; top: number }[]>, + ) => { + try { + const updates = action.payload; + updates.forEach((update) => { + try { + const statement = state.statements.find( + (statement) => statement.statementId === update.statementId, + ); + if (statement) statement.top = update.top; + else throw new Error("statement not found"); + } catch (error) { + console.error("On updateStatementTop loop: ",error); + } + + }); + } catch (error) { + console.error(error); + } + }, setTempStatementsForPresentation: (state, action: PayloadAction) => { try { const statements = action.payload; @@ -307,6 +330,7 @@ export const { setStatementsSubscription, setTempStatementsForPresentation, deleteStatement, + updateStatementTop, deleteSubscribedStatement, setStatementOrder, setScreen, @@ -443,7 +467,7 @@ export const subscriptionParentStatementSelector = (parentId: string) => ); -export const myStatementsByStatementIdSelector = (statementId: string) =>{ +export const myStatementsByStatementIdSelector = (statementId: string) => { const user = store.getState().user.user; return createSelector( (state: RootState) => state.statements.statements, diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index fba66aba2..39b3f9d03 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -18,14 +18,11 @@ import { getStagesInfo } from "../settings/components/QuestionSettings/QuestionS import { getTitle } from "@/controllers/general/helpers"; import CreateStatementModalSwitch from "../createStatementModalSwitch/CreateStatementModalSwitch"; import styles from "./statementSolutinsPage.module.scss"; - -import EmptyScreen from "./components/emptyScreen/EmptyScreen"; import SuggestionCards from "./components/suggestionCards/SuggestionCards"; -import { SubStatementsProvider } from "./statementSolutionPageContext"; interface StatementEvaluationPageProps { statement: Statement; - subStatements: Statement[]; + handleShowTalker: (talker: User | null) => void; showNav?: boolean; questions?: boolean; @@ -35,7 +32,6 @@ interface StatementEvaluationPageProps { const StatementEvaluationPage: FC = ({ statement, - subStatements, handleShowTalker, questions = false, toggleAskNotifications, @@ -43,14 +39,12 @@ const StatementEvaluationPage: FC = ({ }) => { try { // Hooks - + const navigate = useNavigate(); const { t } = useLanguage(); const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - - const currentStage = statement.questionSettings?.currentStage; const stageInfo = getStagesInfo(currentStage); const useSearchForSimilarStatements = @@ -62,9 +56,6 @@ const StatementEvaluationPage: FC = ({ const [showExplanation, setShowExplanation] = useState( currentStage === QuestionStage.explanation && isMultiStage && !questions ); - - - useEffect(() => { if (questions) { @@ -92,61 +83,53 @@ const StatementEvaluationPage: FC = ({ const message = stageInfo ? stageInfo.message : false; return ( - - <> -
- {subStatements.length === 0 ? ( - - ) : ( -
- {isMultiStage && message && ( - - {getToastButtons(currentStage)} - - )} - -
+ <> +
+
+ {isMultiStage && message && ( + + {getToastButtons(currentStage)} + )} -
-
-
- {showExplanation && ( - - - - )} - {showModal && ( - +
+ +
+ {showExplanation && ( + + - )} - - + + )} + {showModal && ( + + )} + ); function getToastButtons(questionStage: QuestionStage | undefined) { diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 47144a475..051a5c101 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,83 +1,61 @@ import { QuestionType, Statement, User } from "delib-npm"; -import { FC, useContext, useEffect } from "react"; -import StatementEvaluationCard from "../StatementSolutionCard"; +import { FC, useEffect } from "react"; +import StatementEvaluationCard from "./suggestionCard/SuggestionCard"; import styles from "./SuggestionCards.module.scss"; -import { getSubStatements } from "../../statementSolutionsCont"; +import { getSubStatements, sortSubStatements } from "../../statementSolutionsCont"; import { useParams } from "react-router-dom"; import { useSelector } from "react-redux"; -import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; -import { SubStatementsContext } from "../../statementSolutionPageContext"; +import { + myStatementsByStatementIdSelector, + statementSubsSelector, +} from "@/model/statements/statementsSlice"; +import EmptyScreen from "../emptyScreen/EmptyScreen"; interface Props { statement: Statement; - subStatements: Statement[]; questions: boolean; handleShowTalker: (talker: User | null) => void; + currentPage?: string; + setShowModal: (show: boolean) => void; } const SuggestionCards: FC = ({ statement, - subStatements, handleShowTalker, questions, + currentPage = `suggestion`, + setShowModal, }) => { const { sort } = useParams(); - const isMultiStage = - statement.questionSettings?.questionType === QuestionType.multipleSteps; - const myStatements = useSelector( - myStatementsByStatementIdSelector(statement.statementId) + const subStatements = useSelector( + statementSubsSelector(statement.statementId) ); - const { sortedSubStatements, setSortedSubStatements } = - useContext(SubStatementsContext); + + useEffect(() => { + sortSubStatements(subStatements, sort, 30); + },[sort]); - useEffect(() => { - setSortedSubStatements(subStatements); - }, []); - - - - useEffect(() => { - getSubStatements({ - statement, - subStatements, - sort, - questions, - myStatements, - }).then((_subStatements) => { - setSortedSubStatements(_subStatements); - }); - }, [sort,subStatements]); - - // Variables - let topSum = 30; - const tops: number[] = [topSum]; - - console.log(topSum, tops); + if (!subStatements) { + return ( + + ); + } return (
- {sortedSubStatements?.map((statementSub: Statement, i: number) => { - //get the top of the element - if (statementSub.elementHight) { - topSum += statementSub.elementHight + 30; - tops.push(topSum); - } - + {subStatements?.map((statementSub: Statement) => { return ( ); })} -
+
); }; diff --git a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.scss b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.scss similarity index 100% rename from src/view/pages/statement/components/solutions/components/StatementSolutionCard.scss rename to src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.scss diff --git a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx similarity index 82% rename from src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx rename to src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx index 8dc7c0760..8343d5b02 100644 --- a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx @@ -1,7 +1,7 @@ -import { FC, useContext, useEffect, useRef, useState } from "react"; +import { FC, useEffect, useRef, useState } from "react"; // Third Party -import { Statement, StatementType, User } from "delib-npm"; +import { Screen, Statement, StatementType, User } from "delib-npm"; // Redux Store import { useAppDispatch, useAppSelector } from "@/controllers/hooks/reduxHooks"; @@ -25,29 +25,31 @@ import { useLanguage } from "@/controllers/hooks/useLanguages"; import EditTitle from "@/view/components/edit/EditTitle"; import IconButton from "@/view/components/iconButton/IconButton"; -import StatementChatMore from "../../chat/components/StatementChatMore"; +import StatementChatMore from "../../../../chat/components/StatementChatMore"; import AddQuestionIcon from "@/assets/icons/addQuestion.svg?react"; -import CreateStatementModal from "../../createStatementModal/CreateStatementModal"; -import Evaluation from "./evaluation/Evaluation"; -import "./StatementSolutionCard.scss"; -import SolutionMenu from "./solutionMenu/SolutionMenu"; -import { SubStatementsContext } from "../statementSolutionPageContext"; +import CreateStatementModal from "../../../../createStatementModal/CreateStatementModal"; +import Evaluation from "../../evaluation/Evaluation"; +import "./SuggestionCard.scss"; +import SolutionMenu from "../../solutionMenu/SolutionMenu"; +import { sortSubStatements } from "../../../statementSolutionsCont"; +import { useParams } from "react-router-dom"; interface Props { statement: Statement; + siblingStatements: Statement[]; parentStatement: Statement; showImage: (talker: User | null) => void; - top: number; } -const StatementSolutionCard: FC = ({ +const SuggestionCard: FC = ({ parentStatement, + siblingStatements, statement, - top, }) => { // Hooks const { t, dir } = useLanguage(); + const { sort } = useParams(); // Redux Store const dispatch = useAppDispatch(); @@ -62,9 +64,7 @@ const StatementSolutionCard: FC = ({ const elementRef = useRef(null); // Use States - const { sortedSubStatements, setSortedSubStatements } = - useContext(SubStatementsContext); - const [newTop, setNewTop] = useState(top); + const [isEdit, setIsEdit] = useState(false); const [shouldShowAddSubQuestionModal, setShouldShowAddSubQuestionModal] = useState(false); @@ -76,10 +76,6 @@ const StatementSolutionCard: FC = ({ parentStatement.creatorId ); - useEffect(() => { - setNewTop(top); - }, [top]); - useEffect(() => { const element = elementRef.current; if (element) { @@ -94,14 +90,11 @@ const StatementSolutionCard: FC = ({ } }, [elementRef.current?.clientHeight]); - // useEffect(() => { - // dispatch( - // setStatementElementHight({ - // statementId: statement.statementId, - // height: elementRef.current?.clientHeight, - // }) - // ); - // }, [statement.statement, parentStatement.questionSettings?.currentStage]); + useEffect(() => { + if (sort !== Screen.OPTIONS_RANDOM && sort !== Screen.QUESTIONS_RANDOM) { + sortSubStatements(siblingStatements, sort, 30); + } + }, [statement.consensus]); function handleSetOption() { try { @@ -135,7 +128,7 @@ const StatementSolutionCard: FC = ({ : "statement-evaluation-card" } style={{ - top: `${newTop}px`, + top: `${statement.top || 0}px`, borderLeft: `8px solid ${statementColor.backgroundColor || "wheat"}`, color: statementColor.color, flexDirection: dir === "ltr" ? "row" : "row-reverse", @@ -210,4 +203,4 @@ const StatementSolutionCard: FC = ({ ); }; -export default StatementSolutionCard; +export default SuggestionCard; diff --git a/src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx b/src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx deleted file mode 100644 index 8d0acef39..000000000 --- a/src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React, { createContext, useState, ReactNode } from "react"; -import { Statement } from "delib-npm"; - -interface SubStatementsContextType { - sortedSubStatements: Statement[]; - setSortedSubStatements: React.Dispatch>; -} - -export const SubStatementsContext = createContext({ - sortedSubStatements: [], - setSortedSubStatements: () => {}, -}); - -interface SubStatementsProviderProps { - children: ReactNode; -} - -export const SubStatementsProvider: React.FC = ({ children }): ReactNode => { - const [sortedSubStatements, setSortedSubStatements] = useState([]); - - return ( - - {children} - - ); -}; \ No newline at end of file diff --git a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts index b4a725860..4a3fa6377 100644 --- a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts +++ b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts @@ -5,14 +5,18 @@ import { enhancedEvaluationsThumbs, } from "./components/evaluation/enhancedEvaluation/EnhancedEvaluationModel"; import { getFirstEvaluationOptions, getSecondEvaluationOptions } from "@/controllers/db/multiStageQuestion/getMultiStageStatements"; +import { store } from "@/model/store"; +import { updateStatementTop } from "@/model/statements/statementsSlice"; export function sortSubStatements( subStatements: Statement[], sort: string | undefined, -): Statement[] { + gap:number = 30 +): void { try { + const dispatch = store.dispatch; let _subStatements = [...subStatements]; switch (sort) { case Screen.OPTIONS_CONSENSUS: @@ -38,20 +42,28 @@ export function sortSubStatements( ); break; } - const __subStatements = _subStatements.map( - (statement: Statement, i: number) => { - const updatedStatement = Object.assign({}, statement); - updatedStatement.order = i; + + let totalHeight = gap; + const updates: { statementId: string; top: number }[] = _subStatements.map((subStatement) => { + try { + const update = { + statementId: subStatement.statementId, + top: totalHeight, + }; + totalHeight += (subStatement.elementHight || 0) + gap; + return update; + + } catch (error) { + console.error(error); + } + }).filter((update) => update !== undefined) as { statementId: string; top: number }[]; + dispatch(updateStatementTop(updates)); - return updatedStatement; - }, - ); - return __subStatements; } catch (error) { console.error(error); - return subStatements; + } } @@ -116,7 +128,7 @@ interface GetSubStatementsProps { } export async function getSubStatements({ statement, subStatements, sort, questions, myStatements }: GetSubStatementsProps): Promise { try { - + if (!statement) return []; if (!subStatements) return []; const _subStatements = [...subStatements]; @@ -126,7 +138,7 @@ export async function getSubStatements({ statement, subStatements, sort, questio if (!isMultiStage) { return getSortedStatements(_subStatements, sort, questions); } else { - + switch (statement.questionSettings?.currentStage) { case QuestionStage.explanation: return ([]); From 698fbb0355eb0672a1a27694f99234b56f9a5091 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 13:35:47 +0300 Subject: [PATCH 14/21] adjust height to new size --- .../components/suggestionCards/SuggestionCards.tsx | 11 ++++++++++- .../suggestionCards/suggestionCard/SuggestionCard.tsx | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 051a5c101..25d559e64 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,5 +1,5 @@ import { QuestionType, Statement, User } from "delib-npm"; -import { FC, useEffect } from "react"; +import { FC, useEffect, useState } from "react"; import StatementEvaluationCard from "./suggestionCard/SuggestionCard"; import styles from "./SuggestionCards.module.scss"; import { getSubStatements, sortSubStatements } from "../../statementSolutionsCont"; @@ -31,11 +31,20 @@ const SuggestionCards: FC = ({ statementSubsSelector(statement.statementId) ); + const [wrapperHeight, setWrapperHeight] = useState(0); + useEffect(() => { sortSubStatements(subStatements, sort, 30); },[sort]); + useEffect(() => { + if (subStatements) { + const height = subStatements.reduce((acc, statement:Statement) => acc + (statement.top ||0), 0); + setWrapperHeight(height); + } + }, [subStatements]); + if (!subStatements) { return ( diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx index 8343d5b02..8c9a02cc4 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx @@ -96,6 +96,10 @@ const SuggestionCard: FC = ({ } }, [statement.consensus]); + useEffect(() => { + sortSubStatements(siblingStatements, sort, 30); + }, [statement.elementHight]); + function handleSetOption() { try { if (statement.statementType === "option") { @@ -153,7 +157,6 @@ const SuggestionCard: FC = ({
-

{statement.elementHight || 0}

Date: Wed, 4 Sep 2024 14:01:26 +0300 Subject: [PATCH 15/21] created a new reducer for optins from multisteps --- package-lock.json | 8 +-- package.json | 2 +- src/model/statements/statementsSlice.ts | 48 +++++++-------- .../suggestionCards/SuggestionCards.tsx | 16 +---- .../solutions/statementSolutionsCont.ts | 60 +------------------ 5 files changed, 32 insertions(+), 102 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4da32a9b6..8f4b59db0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@dagrejs/dagre": "^1.0.4", "@reduxjs/toolkit": "^1.9.5", - "delib-npm": "^1.3.45", + "delib-npm": "^1.3.46", "eslint-plugin-import": "^2.29.1", "eslint-plugin-sonarjs": "^1.0.3", "firebase": "^10.0.0", @@ -5486,9 +5486,9 @@ } }, "node_modules/delib-npm": { - "version": "1.3.45", - "resolved": "https://registry.npmjs.org/delib-npm/-/delib-npm-1.3.45.tgz", - "integrity": "sha512-yV6KfkizLAldGPehKRCtw1ozad3PeVcuC3dzqDBflTcYvqaQOE/dAcy6Jbxny4EotgbROxG0jIiUndmgEpa+Qw==", + "version": "1.3.46", + "resolved": "https://registry.npmjs.org/delib-npm/-/delib-npm-1.3.46.tgz", + "integrity": "sha512-zOaIOguKki8p1mNbtSRjDRk0zNZrTVNCxRnPTEd3S3eoAmYrLljEJy3aIw2xrQceYfEwy+SQWPHG3KQTOJd31w==", "dependencies": { "react": "^18.3.1", "sass": "^1.77.6", diff --git a/package.json b/package.json index a53e6eb0e..93e5ad434 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@dagrejs/dagre": "^1.0.4", "@reduxjs/toolkit": "^1.9.5", - "delib-npm": "^1.3.45", + "delib-npm": "^1.3.46", "eslint-plugin-import": "^2.29.1", "eslint-plugin-sonarjs": "^1.0.3", "firebase": "^10.0.0", diff --git a/src/model/statements/statementsSlice.ts b/src/model/statements/statementsSlice.ts index 8448a76bb..db7198684 100644 --- a/src/model/statements/statementsSlice.ts +++ b/src/model/statements/statementsSlice.ts @@ -221,7 +221,7 @@ export const statementsSlicer = createSlice({ if (statement) statement.top = update.top; else throw new Error("statement not found"); } catch (error) { - console.error("On updateStatementTop loop: ",error); + console.error("On updateStatementTop loop: ", error); } }); @@ -229,29 +229,6 @@ export const statementsSlicer = createSlice({ console.error(error); } }, - setTempStatementsForPresentation: (state, action: PayloadAction) => { - try { - const statements = action.payload; - - - //clear all temp statements - state.statements.forEach((statement) => { - statement.isPartOfTempPresentation = false; - }); - - //set new temp statements - statements.forEach((statement) => { - statement.isPartOfTempPresentation = true; - state.statements = updateArray( - state.statements, - statement, - "statementId", - ); - }); - } catch (error) { - console.error(error); - } - }, setScreen: (state, action: PayloadAction) => { try { state.screen = action.payload; @@ -272,7 +249,7 @@ export const statementsSlicer = createSlice({ if (!_statement) throw new Error("statement not found"); const subScreens = _statement?.subScreens; if (subScreens?.length === 0 || subScreens === undefined) - throw new Error("no subscreens"); + throw new Error("no sub screens"); if (subScreens.includes(screen)) { _statement.subScreens = subScreens.filter( (subScreen) => subScreen !== screen, @@ -320,6 +297,27 @@ export const statementsSlicer = createSlice({ state.statementMembership = []; state.screen = StatementScreen.chat; }, + setCurrentMultiStepOptions: (state, action: PayloadAction) => { + try { + + const previousInMultiStageOptions = state.statements.filter(statement => statement.isInMultiStage); + previousInMultiStageOptions.forEach((statement) => { + statement.isInMultiStage = false; + }); + + const newStatements = action.payload; + newStatements.forEach((statement) => { + statement.isInMultiStage = true; + state.statements = updateArray( + state.statements, + statement, + "statementId", + ); + }); + } catch (error) { + console.error(error); + } + }, }, }); diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 25d559e64..600c9f678 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,15 +1,14 @@ -import { QuestionType, Statement, User } from "delib-npm"; -import { FC, useEffect, useState } from "react"; +import { Statement, User } from "delib-npm"; +import { FC, useEffect } from "react"; import StatementEvaluationCard from "./suggestionCard/SuggestionCard"; import styles from "./SuggestionCards.module.scss"; -import { getSubStatements, sortSubStatements } from "../../statementSolutionsCont"; import { useParams } from "react-router-dom"; import { useSelector } from "react-redux"; import { - myStatementsByStatementIdSelector, statementSubsSelector, } from "@/model/statements/statementsSlice"; import EmptyScreen from "../emptyScreen/EmptyScreen"; +import { sortSubStatements } from "../../statementSolutionsCont"; interface Props { statement: Statement; @@ -22,7 +21,6 @@ interface Props { const SuggestionCards: FC = ({ statement, handleShowTalker, - questions, currentPage = `suggestion`, setShowModal, }) => { @@ -31,19 +29,11 @@ const SuggestionCards: FC = ({ statementSubsSelector(statement.statementId) ); - const [wrapperHeight, setWrapperHeight] = useState(0); - useEffect(() => { sortSubStatements(subStatements, sort, 30); },[sort]); - useEffect(() => { - if (subStatements) { - const height = subStatements.reduce((acc, statement:Statement) => acc + (statement.top ||0), 0); - setWrapperHeight(height); - } - }, [subStatements]); if (!subStatements) { return ( diff --git a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts index 4a3fa6377..562a6db5f 100644 --- a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts +++ b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts @@ -1,10 +1,9 @@ -import { Statement, Screen, isOptionFn, QuestionType, StatementType, QuestionStage } from "delib-npm"; +import { Statement, Screen } from "delib-npm"; import { EnhancedEvaluationThumb, enhancedEvaluationsThumbs, } from "./components/evaluation/enhancedEvaluation/EnhancedEvaluationModel"; -import { getFirstEvaluationOptions, getSecondEvaluationOptions } from "@/controllers/db/multiStageQuestion/getMultiStageStatements"; import { store } from "@/model/store"; import { updateStatementTop } from "@/model/statements/statementsSlice"; @@ -119,62 +118,5 @@ export const getEvaluationThumbsToDisplay = ({ return [selectedThumb || defaultThumb]; }; -interface GetSubStatementsProps { - statement: Statement; - subStatements: Statement[]; - sort: string | undefined; - questions: boolean; - myStatements: Statement[]; -} -export async function getSubStatements({ statement, subStatements, sort, questions, myStatements }: GetSubStatementsProps): Promise { - try { - if (!statement) return []; - if (!subStatements) return []; - const _subStatements = [...subStatements]; - - const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - - if (!isMultiStage) { - return getSortedStatements(_subStatements, sort, questions); - } else { - - switch (statement.questionSettings?.currentStage) { - case QuestionStage.explanation: - return ([]); - case QuestionStage.suggestion: - return myStatements; - case QuestionStage.firstEvaluation: - const firstSt = await getFirstEvaluationOptions(statement); - return getSortedStatements(firstSt, sort, questions); - case QuestionStage.secondEvaluation: - const secondSt = await getSecondEvaluationOptions(statement); - return getSortedStatements(secondSt, sort, questions); - case QuestionStage.voting: - - return ([]); - default: - return ([]); - } - } - - } catch (error) { - console.error(error); - return []; - } -} - -function getSortedStatements(_subStatements: Statement[], sort: string | undefined, questions: boolean) { - return sortSubStatements( - _subStatements, - sort - ).filter((subStatement) => { - //if questions is true, only show questions - if (questions) { - return subStatement.statementType === StatementType.question; - } - //if options is true, only show options - return isOptionFn(subStatement); - }); -} From 5360ea31e49090e471f7d2e2689d60c0d3bfd769 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 15:23:47 +0300 Subject: [PATCH 16/21] freedi brings first evaluation and second evaluation --- .../getMultiStageStatements.ts | 83 ++++--------------- src/model/statements/statementsSlice.ts | 11 ++- .../settings/statementSettingsCont.ts | 8 +- .../suggestionCards/SuggestionCards.tsx | 30 +++++-- 4 files changed, 53 insertions(+), 79 deletions(-) diff --git a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts index 9bfb39ece..03c2c273a 100644 --- a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts +++ b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts @@ -1,68 +1,18 @@ -import { QuestionStage, Statement } from "delib-npm"; -import { Dispatch } from "react"; +import { Statement, StatementSchema } from "delib-npm"; +import { z } from "zod"; import { isProduction } from "@/controllers/general/helpers"; -import { setTempStatementsForPresentation } from "@/model/statements/statementsSlice"; +import { setCurrentMultiStepOptions } from "@/model/statements/statementsSlice"; import { store } from "@/model/store"; -// export async function getMultiStageOptions( -// statement: Statement, - -// ): Promise { -// const dispatch: Dispatch = store.dispatch; -// try { - -// const urlBase = isProduction() ? "qeesi7aziq-uc.a.run.app" : "http://localhost:5001/synthesistalyaron/us-central1"; - -// if (statement.questionSettings?.currentStage === QuestionStage.suggestion) { -// const userId = store.getState().user.user?.uid; -// if (!userId) throw new Error("User not found"); - -// const url = isProduction() ? `https://getUserOptions-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getUserOptions"; - -// const response = await fetch( -// `${url}?parentId=${statement.statementId}&userId=${userId}` -// ); -// const { statements, error } = await response.json(); -// if (error) throw new Error(error); - -// dispatch(setTempStatementsForPresentation(statements)); -// } else if ( -// statement.questionSettings?.currentStage === QuestionStage.firstEvaluation -// ) { -// const url = isProduction() ? `https://getRandomStatements-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getRandomStatements"; - -// const response = await fetch( -// `${url}?parentId=${statement.statementId}&limit=6` -// ); -// const { randomStatements, error } = await response.json(); -// if (error) throw new Error(error); -// dispatch(setTempStatementsForPresentation(randomStatements)); -// } else if ( -// statement.questionSettings?.currentStage === -// QuestionStage.secondEvaluation -// ) { -// const url = isProduction() ? `https://getTopStatements-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getTopStatements"; -// const response = await fetch( -// `${url}?parentId=${statement.statementId}&limit=6` -// ); -// const { topSolutions, error } = await response.json(); -// if (error) throw new Error(error); -// dispatch(setTempStatementsForPresentation(topSolutions)); -// } else { -// dispatch(setTempStatementsForPresentation([])); -// } -// } catch (error) { -// console.error(error); -// dispatch(setTempStatementsForPresentation([])); -// } -// } export async function getFirstEvaluationOptions( statement: Statement, -): Promise { +): Promise { try { + console.log("getFirstEvaluationOptions") + const dispatch = store.dispatch; const urlBase = isProduction() ? "qeesi7aziq-uc.a.run.app" : "http://localhost:5001/synthesistalyaron/us-central1"; const url = isProduction() ? `https://getRandomStatements-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getRandomStatements"; @@ -72,19 +22,23 @@ export async function getFirstEvaluationOptions( ); const { randomStatements, error } = await response.json(); if (error) throw new Error(error); + z.array(StatementSchema).parse(randomStatements); + console.log(randomStatements) + + dispatch(setCurrentMultiStepOptions(randomStatements)); + - - return randomStatements as Statement[]; } catch (error) { console.error(error); - - return []; + + } } -export async function getSecondEvaluationOptions(statement: Statement): Promise { +export async function getSecondEvaluationOptions(statement: Statement): Promise { try { + const dispatch = store.dispatch; const urlBase = isProduction() ? "qeesi7aziq-uc.a.run.app" : "http://localhost:5001/synthesistalyaron/us-central1"; const url = isProduction() ? `https://getTopStatements-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getTopStatements"; @@ -94,11 +48,10 @@ export async function getSecondEvaluationOptions(statement: Statement): Promise< const { topSolutions, error } = await response.json(); if (error) throw new Error(error); - - return topSolutions as Statement[]; + z.array(StatementSchema).parse(topSolutions); + dispatch(setCurrentMultiStepOptions(topSolutions)); } catch (error) { console.error(error); - - return []; + } } \ No newline at end of file diff --git a/src/model/statements/statementsSlice.ts b/src/model/statements/statementsSlice.ts index db7198684..15a14d4c6 100644 --- a/src/model/statements/statementsSlice.ts +++ b/src/model/statements/statementsSlice.ts @@ -16,7 +16,7 @@ import { // Helpers import { updateArray } from "../../controllers/general/helpers"; import { sortSubStatements } from "../../view/pages/statement/components/solutions/statementSolutionsCont"; -import { updateStatement } from "@/controllers/db/statements/setStatements"; + enum StatementScreen { chat = "chat", @@ -326,7 +326,6 @@ export const { setStatements, setStatementSubscription, setStatementsSubscription, - setTempStatementsForPresentation, deleteStatement, updateStatementTop, deleteSubscribedStatement, @@ -337,6 +336,7 @@ export const { setMembership, removeMembership, resetStatements, + setCurrentMultiStepOptions } = statementsSlicer.actions; // statements @@ -474,4 +474,11 @@ export const myStatementsByStatementIdSelector = (statementId: string) => { ); } +export const statementsOfMultiStepSelectorByStatementId =(statementId: string) => createSelector( + (state: RootState) => state.statements.statements, + (statements) => statements.filter((st) => st.isInMultiStage && st.parentId === statementId) +); + + + export default statementsSlicer.reducer; diff --git a/src/view/pages/statement/components/settings/statementSettingsCont.ts b/src/view/pages/statement/components/settings/statementSettingsCont.ts index 3e8d072b9..9cc1e5ac9 100644 --- a/src/view/pages/statement/components/settings/statementSettingsCont.ts +++ b/src/view/pages/statement/components/settings/statementSettingsCont.ts @@ -21,8 +21,7 @@ import { defaultStatementSettings, } from './emptyStatementModel'; import { NavigateFunction } from 'react-router-dom'; -import { store } from '@/model/store'; -import { setTempStatementsForPresentation } from '@/model/statements/statementsSlice'; + // Get users that voted on options in this statement export async function handleGetVoters( @@ -288,10 +287,7 @@ export async function createStatementFromModal({ addSubscription: true, }); - if (isSendToStoreTemp) { - //dispatch to the store - store.dispatch(setTempStatementsForPresentation([newStatement])); - } + } catch (error) { console.error(error); } diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 600c9f678..828a8a7fd 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,14 +1,16 @@ -import { Statement, User } from "delib-npm"; +import { QuestionStage, QuestionType, Statement, User } from "delib-npm"; import { FC, useEffect } from "react"; -import StatementEvaluationCard from "./suggestionCard/SuggestionCard"; +import SuggestionCard from "./suggestionCard/SuggestionCard"; import styles from "./SuggestionCards.module.scss"; import { useParams } from "react-router-dom"; import { useSelector } from "react-redux"; import { + statementsOfMultiStepSelectorByStatementId, statementSubsSelector, } from "@/model/statements/statementsSlice"; import EmptyScreen from "../emptyScreen/EmptyScreen"; import { sortSubStatements } from "../../statementSolutionsCont"; +import { getFirstEvaluationOptions, getSecondEvaluationOptions } from "@/controllers/db/multiStageQuestion/getMultiStageStatements"; interface Props { statement: Statement; @@ -25,14 +27,30 @@ const SuggestionCards: FC = ({ setShowModal, }) => { const { sort } = useParams(); - const subStatements = useSelector( - statementSubsSelector(statement.statementId) - ); + const {questionType ,currentStage} = statement.questionSettings || {questionType: QuestionType.singleStep, currentStage: QuestionStage.suggestion}; + const subStatements = switchSubStatements() ; + + function switchSubStatements(){ + if(questionType === QuestionType.singleStep) return useSelector( + statementSubsSelector(statement.statementId) + ) + else if(questionType === QuestionType.multipleSteps && currentStage !== QuestionStage.suggestion) return useSelector(statementsOfMultiStepSelectorByStatementId(statement.statementId)); + else return []; + } useEffect(() => { sortSubStatements(subStatements, sort, 30); },[sort]); + useEffect(() => { + if(questionType == QuestionType.multipleSteps){ + if(currentStage === QuestionStage.firstEvaluation) + getFirstEvaluationOptions(statement); + else if(currentStage === QuestionStage.secondEvaluation) + getSecondEvaluationOptions(statement); + + } + }, [currentStage, questionType]); if (!subStatements) { @@ -45,7 +63,7 @@ const SuggestionCards: FC = ({
{subStatements?.map((statementSub: Statement) => { return ( - Date: Wed, 4 Sep 2024 15:27:31 +0300 Subject: [PATCH 17/21] Bring my personal suggestions on suggestions --- .../solutions/components/suggestionCards/SuggestionCards.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 828a8a7fd..9e45d5991 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -5,6 +5,7 @@ import styles from "./SuggestionCards.module.scss"; import { useParams } from "react-router-dom"; import { useSelector } from "react-redux"; import { + myStatementsByStatementIdSelector, statementsOfMultiStepSelectorByStatementId, statementSubsSelector, } from "@/model/statements/statementsSlice"; @@ -36,6 +37,7 @@ const SuggestionCards: FC = ({ statementSubsSelector(statement.statementId) ) else if(questionType === QuestionType.multipleSteps && currentStage !== QuestionStage.suggestion) return useSelector(statementsOfMultiStepSelectorByStatementId(statement.statementId)); + else if(questionType === QuestionType.multipleSteps && currentStage === QuestionStage.suggestion) return useSelector(myStatementsByStatementIdSelector(statement.statementId)); else return []; } From 5551b66fc32b48ba1a8ce3a8c1cfcd0a781b85f6 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 15:34:25 +0300 Subject: [PATCH 18/21] Basic steps are working --- .../solutions/components/suggestionCards/SuggestionCards.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 9e45d5991..af7850ec1 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -2,7 +2,7 @@ import { QuestionStage, QuestionType, Statement, User } from "delib-npm"; import { FC, useEffect } from "react"; import SuggestionCard from "./suggestionCard/SuggestionCard"; import styles from "./SuggestionCards.module.scss"; -import { useParams } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import { useSelector } from "react-redux"; import { myStatementsByStatementIdSelector, @@ -28,6 +28,7 @@ const SuggestionCards: FC = ({ setShowModal, }) => { const { sort } = useParams(); + const navigate = useNavigate(); const {questionType ,currentStage} = statement.questionSettings || {questionType: QuestionType.singleStep, currentStage: QuestionStage.suggestion}; const subStatements = switchSubStatements() ; @@ -50,6 +51,8 @@ const SuggestionCards: FC = ({ getFirstEvaluationOptions(statement); else if(currentStage === QuestionStage.secondEvaluation) getSecondEvaluationOptions(statement); + else if(currentStage === QuestionStage.voting) navigate(`statement/${statement.statementId}/vote`); + else if(currentStage === QuestionStage.finished) getSecondEvaluationOptions(statement); } }, [currentStage, questionType]); From 46bb012e17c5b23d090e0ec9e43f73ecafeee4a0 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Thu, 5 Sep 2024 09:22:25 +0300 Subject: [PATCH 19/21] multi-steps working --- .../components/suggestionCards/SuggestionCards.tsx | 12 ++++++++---- .../suggestionCard/SuggestionCard.scss | 1 - .../components/solutions/statementSolutionsCont.ts | 6 +++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index af7850ec1..853cbd3b7 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,5 +1,5 @@ import { QuestionStage, QuestionType, Statement, User } from "delib-npm"; -import { FC, useEffect } from "react"; +import { FC, useEffect, useState } from "react"; import SuggestionCard from "./suggestionCard/SuggestionCard"; import styles from "./SuggestionCards.module.scss"; import { useNavigate, useParams } from "react-router-dom"; @@ -30,9 +30,12 @@ const SuggestionCards: FC = ({ const { sort } = useParams(); const navigate = useNavigate(); + const [totalHeight, setTotalHeight] = useState(0); + const {questionType ,currentStage} = statement.questionSettings || {questionType: QuestionType.singleStep, currentStage: QuestionStage.suggestion}; const subStatements = switchSubStatements() ; + //change the source of options from the store based on the question type function switchSubStatements(){ if(questionType === QuestionType.singleStep) return useSelector( statementSubsSelector(statement.statementId) @@ -43,7 +46,8 @@ const SuggestionCards: FC = ({ } useEffect(() => { - sortSubStatements(subStatements, sort, 30); + const {totalHeight:_totalHeight} = sortSubStatements(subStatements, sort, 30); + setTotalHeight(_totalHeight); },[sort]); useEffect(() => { if(questionType == QuestionType.multipleSteps){ @@ -65,12 +69,12 @@ const SuggestionCards: FC = ({ } return ( -
+
{subStatements?.map((statementSub: Statement) => { return ( update !== undefined) as { statementId: string; top: number }[]; dispatch(updateStatementTop(updates)); - + return {totalHeight} } catch (error) { console.error(error); - + return {totalHeight:0}; } } From d441391cdc7d313b826c5b4e2163d9cdba13d829 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Thu, 5 Sep 2024 10:19:42 +0300 Subject: [PATCH 20/21] linting and type check --- .../getMultiStageStatements.ts | 4 +- src/model/statements/statementsSlice.ts | 9 +- src/view/components/triangle/Triangle.tsx | 8 +- .../statement/components/SwitchScreens.tsx | 2 - .../settings/statementSettingsCont.ts | 3 +- .../solutions/StatementSolutionsPage.tsx | 331 +++++++++--------- .../components/emptyScreen/EmptyScreen.tsx | 108 +++--- .../suggestionCards/SuggestionCards.tsx | 110 +++--- .../suggestionCard/SuggestionCard.tsx | 316 ++++++++--------- .../solutions/statementSolutionsCont.ts | 48 +-- .../solutions/statementSolutionsHooks.ts | 38 -- .../components/vote/StatementVote.tsx | 2 +- 12 files changed, 468 insertions(+), 511 deletions(-) delete mode 100644 src/view/pages/statement/components/solutions/statementSolutionsHooks.ts diff --git a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts index 03c2c273a..51c606c4d 100644 --- a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts +++ b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts @@ -11,7 +11,7 @@ export async function getFirstEvaluationOptions( ): Promise { try { - console.log("getFirstEvaluationOptions") + const dispatch = store.dispatch; const urlBase = isProduction() ? "qeesi7aziq-uc.a.run.app" : "http://localhost:5001/synthesistalyaron/us-central1"; @@ -23,7 +23,7 @@ export async function getFirstEvaluationOptions( const { randomStatements, error } = await response.json(); if (error) throw new Error(error); z.array(StatementSchema).parse(randomStatements); - console.log(randomStatements) + dispatch(setCurrentMultiStepOptions(randomStatements)); diff --git a/src/model/statements/statementsSlice.ts b/src/model/statements/statementsSlice.ts index 15a14d4c6..4300da962 100644 --- a/src/model/statements/statementsSlice.ts +++ b/src/model/statements/statementsSlice.ts @@ -15,8 +15,6 @@ import { // Helpers import { updateArray } from "../../controllers/general/helpers"; -import { sortSubStatements } from "../../view/pages/statement/components/solutions/statementSolutionsCont"; - enum StatementScreen { chat = "chat", @@ -393,9 +391,7 @@ export const statementOptionsSelector = .sort((a, b) => a.createdAt - b.createdAt) .map((statement) => ({ ...statement })); - const sortedSubStatements = sortSubStatements(subStatements, state.statements.screen); - - return sortedSubStatements; + return subStatements; }; export const questionsSelector = (statementId: string | undefined) => (state: RootState) => state.statements.statements.filter((statement) => statement.parentId === statementId && statement.statementType === StatementType.question).sort((a, b) => a.createdAt - b.createdAt); @@ -467,7 +463,8 @@ export const subscriptionParentStatementSelector = (parentId: string) => export const myStatementsByStatementIdSelector = (statementId: string) => { const user = store.getState().user.user; - return createSelector( + +return createSelector( (state: RootState) => state.statements.statements, (statements) => statements.filter((st) => st.parentId === statementId && st.creatorId === user?.uid) diff --git a/src/view/components/triangle/Triangle.tsx b/src/view/components/triangle/Triangle.tsx index 514214674..89e03c5c9 100644 --- a/src/view/components/triangle/Triangle.tsx +++ b/src/view/components/triangle/Triangle.tsx @@ -14,12 +14,12 @@ interface Props { const Triangle: FC = ({ statement }) => { const {t} = useLanguage(); - const subStatements = useSelector( + const subStatements:Statement[] = useSelector( statementOptionsSelector(statement.statementId) - ).filter((s) => s.evaluation?.sumCon !== undefined); + ).filter((s:Statement) => s.evaluation?.sumCon !== undefined); let maxEvaluators = 0; - subStatements.forEach((subStatement) => { + subStatements.forEach((subStatement:Statement) => { if (subStatement.evaluation?.numberOfEvaluators !== undefined && subStatement.evaluation?.numberOfEvaluators > maxEvaluators) maxEvaluators = subStatement.evaluation.numberOfEvaluators; }); @@ -29,7 +29,7 @@ const Triangle: FC = ({ statement }) => {
- {subStatements.map((subStatement) => { + {subStatements.map((subStatement:Statement) => { return ( ); diff --git a/src/view/pages/statement/components/SwitchScreens.tsx b/src/view/pages/statement/components/SwitchScreens.tsx index b34271f82..18e6a355c 100644 --- a/src/view/pages/statement/components/SwitchScreens.tsx +++ b/src/view/pages/statement/components/SwitchScreens.tsx @@ -53,7 +53,6 @@ export default function SwitchScreens({ return ( @@ -83,7 +82,6 @@ export default function SwitchScreens({ return ( void; showNav?: boolean; questions?: boolean; @@ -31,178 +30,178 @@ interface StatementEvaluationPageProps { } const StatementEvaluationPage: FC = ({ - statement, - handleShowTalker, - questions = false, - toggleAskNotifications, - currentPage = `suggestion`, + statement, + handleShowTalker, + questions = false, + toggleAskNotifications, + currentPage = `suggestion`, }) => { - try { - // Hooks + try { + // Hooks - const navigate = useNavigate(); - const { t } = useLanguage(); - const isMultiStage = + const navigate = useNavigate(); + const { t } = useLanguage(); + const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - const currentStage = statement.questionSettings?.currentStage; - const stageInfo = getStagesInfo(currentStage); - const useSearchForSimilarStatements = + const currentStage = statement.questionSettings?.currentStage; + const stageInfo = getStagesInfo(currentStage); + const useSearchForSimilarStatements = statement.statementSettings?.enableSimilaritiesSearch || false; - // Use States - const [showModal, setShowModal] = useState(false); - const [showToast, setShowToast] = useState(false); - const [showExplanation, setShowExplanation] = useState( - currentStage === QuestionStage.explanation && isMultiStage && !questions - ); - - useEffect(() => { - if (questions) { - setShowToast(false); - } - }, [questions]); - - useEffect(() => { - if (!showToast && !questions) { - setShowToast(true); - } - if ( - currentStage === QuestionStage.explanation && + // Use States + const [showModal, setShowModal] = useState(false); + const [showToast, setShowToast] = useState(false); + const [showExplanation, setShowExplanation] = useState( + currentStage === QuestionStage.explanation && isMultiStage && !questions + ); + + useEffect(() => { + if (questions) { + setShowToast(false); + } + }, [questions]); + + useEffect(() => { + if (!showToast && !questions) { + setShowToast(true); + } + if ( + currentStage === QuestionStage.explanation && isMultiStage && !questions - ) { - setShowExplanation(true); - } - if (currentStage === QuestionStage.voting && !questions) { - //redirect us react router dom to voting page - navigate(`/statement/${statement.statementId}/vote`); - } - }, [statement.questionSettings?.currentStage, questions]); - - const message = stageInfo ? stageInfo.message : false; - - return ( - <> -
-
- {isMultiStage && message && ( - - {getToastButtons(currentStage)} - - )} - -
-
-
- -
- {showExplanation && ( - - - - )} - {showModal && ( - - )} - - ); - - function getToastButtons(questionStage: QuestionStage | undefined) { - try { - switch (questionStage) { - case QuestionStage.voting: - case QuestionStage.firstEvaluation: - case QuestionStage.secondEvaluation: - case QuestionStage.finished: - case QuestionStage.explanation: - return ( -