Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Compare whys#200 #266

Merged
merged 25 commits into from
Dec 14, 2024
Merged
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
refactoring in progresss
  • Loading branch information
ddfridley committed Nov 25, 2024
commit 699a492340068d6ab609cf60524adbe7684fd7b8
48 changes: 25 additions & 23 deletions app/components/ranking.jsx
Original file line number Diff line number Diff line change
@@ -13,6 +13,27 @@ const selectedOption = (

const unselectedOption = <rect x="1" y="1" width="22" height="22" rx="11" stroke="#06335C" strokeWidth="2" />

// table to map from data model properties, to the Rank Strings shown in the UI
const toRankString = {
undefined: '',
most: 'Most',
least: 'Least',
neutral: 'Neutral',
}

// table to map from UI's Rank Strings to the data model prpoerty names
const rankStringToCategory = Object.entries(toRankString).reduce((rS2C, [key, value]) => {
if (key === 'undefined') return rS2C // rankStringToCategory[''] will be undefined
rS2C[value] = key
return rS2C
}, {})

function Rank(props) {
const { onDone, rank, ...otherProps } = props
const handleOnDone = result => ({ valid: result.valid, value: rankStringToCategory[result.value] })
return <Ranking onDone={handleOnDone} rank={toRankString[rank]} {...otherProps}></Ranking>
}

export default function Ranking(props) {
//Isolate props and set initial state
const { disabled, defaultValue, className, onDone, ...otherProps } = props
@@ -38,36 +59,17 @@ export default function Ranking(props) {
}
setResponse(e.target.value)
if (!onDone) {
return console.warn(
`Unhandled rank selection: ${e.target.value}. Please pass a handler function via the onDone prop.`
)
return console.warn(`Unhandled rank selection: ${e.target.value}. Please pass a handler function via the onDone prop.`)
} else onDone({ valid: true, value: e.target.value })
}
return (
<div
data-value={response}
className={cx(className, styleClasses.group, disabled && styleClasses.disabled)}
onChange={onSelectionChange}
{...otherProps}
>
<div data-value={response} className={cx(className, styleClasses.group, disabled && styleClasses.disabled)} onChange={onSelectionChange} {...otherProps}>
{responseOptions.map(option => {
return (
<label>
<input
disabled={disabled || false}
checked={response === option}
type="radio"
value={option}
name={`importance-${option}`}
className={cx(styleClasses.hideDefaultRadio, `ranking${option}`)}
></input>
<input disabled={disabled || false} checked={response === option} type="radio" value={option} name={`importance-${option}`} className={cx(styleClasses.hideDefaultRadio, `ranking${option}`)}></input>
<span className={cx(styleClasses.option)}>
<svg
className={cx(styleClasses.optionIcon)}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<svg className={cx(styleClasses.optionIcon)} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
{response === option ? selectedOption : unselectedOption}
</svg>
{option}
42 changes: 39 additions & 3 deletions app/components/steps/compare-whys.js
Original file line number Diff line number Diff line change
@@ -7,8 +7,46 @@ import { createUseStyles } from 'react-jss'
import PairCompare from '../pair-compare'
import { H, Level } from 'react-accessible-headings'

import DeliberationContext from '../deliberation-context'
import { isEqual } from 'lodash'
import ObjectId from 'bson-objectid'

export default function CompareWhysStep(props) {
const { onDone, category } = props
const { data, upsert } = useContext(DeliberationContext)
const args = { ...derivePointWithWhyRankListLisyByCategory(data, category) }
const handleOnDone = ({ valid, value, delta }) => {
if (delta) {
upsert({ whyRankByParentId: { [delta.parentId]: delta } })
window.socket.emit('upsert-rank', delta)
}
onDone({ valid, value })
}
// fetch previous data
if (typeof window !== 'undefined')
useState(() => {
// on the browser, do this once and only once when this component is first rendered
const { discussionId, round, reducedPointList } = data
window.socket.emit(
'get-user-post-ranks-and-top-ranked-whys',
discussionId,
round,
reducedPointList.map(point_group => point_group.point._id),
result => {
if (!result) return // there was an error
const [ranks, whys] = result
//if (!ranks.length && !whys.length) return // nothing to do
const postRankByParentId = ranks.reduce((postRankByParentId, rank) => ((postRankByParentId[rank.parentId] = rank), postRankByParentId), {})
const topWhyById = whys.reduce((topWhyById, point) => ((topWhyById[point._id] = point), topWhyById), {})
upsert({ postRankByParentId, topWhyById })
}
)
})
return <CompareWhys {...props} {...args} round={data.round} discussionId={data.discussionId} onDone={handleOnDone} />
}

// pointWithWhyRankListList = [{point: {}, whyRankList: [why:{}, rank:{}]]
function CompareReasons(props) {
export function CompareWhys(props) {
const { pointWithWhyRankListList = [], side = '', onDone = () => {}, className, ...otherProps } = props
const classes = useStyles()
const [completedPoints, setCompletedPoints] = useState(new Set())
@@ -83,8 +121,6 @@ const useStyles = createUseStyles(theme => ({
},
}))

export default CompareReasons

// pointWithWhyRankByWhyIdByPointId={id: {point, whyRankByWhyId: {id: {why, rank}}}}

export function derivePointWithWhyRankListLisyByCategory(data, category) {
4 changes: 2 additions & 2 deletions stories/compare-reasons.stories.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// https://github.com/EnCiv/civil-pursuit/issues/200

import CompareReasons from '../app/components/steps/compare-whys'
import CompareWhysStep, { CompareReasons as CompareWhys } from '../app/components/steps/compare-whys'
import { asyncSleep, onDoneDecorator, onDoneResult } from './common'
import { within, userEvent, waitFor } from '@storybook/test'
import expect from 'expect'

export default { component: CompareReasons, args: {}, decorators: [onDoneDecorator] }
export default { component: CompareWhys, args: {}, decorators: [onDoneDecorator] }

const pointWithWhyRankListList = [
{