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

stateless refactor #811

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 4 additions & 2 deletions packages/quizzes-dashboard/components/StatelessEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ const Wrapper = styled.div`
`

interface StatelessEditorProps {
onHeightChange: (newHeight: number) => void
onHeightChange: (newHeight: number, port: MessagePort) => void
port: MessagePort
}

const StatelessEditor: React.FC<StatelessEditorProps> = ({
onHeightChange,
port,
}) => {
const contentRef = useRef<HTMLDivElement>(null)
const store = useTypedSelector(state => state)
Expand All @@ -25,7 +27,7 @@ const StatelessEditor: React.FC<StatelessEditorProps> = ({
if (!ref) {
return
}
onHeightChange(ref.getBoundingClientRect().height)
onHeightChange(ref.getBoundingClientRect().height, port)
}, [store])

return (
Expand Down
5 changes: 5 additions & 0 deletions packages/quizzes-dashboard/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/quizzes-dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"timezone-support": "^2.0.2",
"tmc-client-js": "0.0.9",
"typesafe-actions": "^5.1.0",
"use-memo-one": "^1.1.2",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove

"uuid": "^8.3.2",
"yup": "^0.32.8"
},
Expand Down
177 changes: 109 additions & 68 deletions packages/quizzes-dashboard/pages/stateless/index.tsx
Original file line number Diff line number Diff line change
@@ -1,92 +1,89 @@
import { denormalize, normalize } from "normalizr"
import React, { useEffect } from "react"
import React, { useEffect, useState } from "react"
import { useDispatch } from "react-redux"
import { v4 } from "uuid"
import StatelessEditor from "../../components/StatelessEditor"
import { normalizedQuiz } from "../../schemas"
import { initializedEditor } from "../../store/editor/editorActions"
import { storeState, useTypedSelector } from "../../store/store"
import { Quiz } from "../../types/Quiz"
import {
Item,
PrivateSpecItem,
PrivateSpecOption,
PublicSpecItem,
PublicSpecOption,
Quiz,
} from "../../types/Quiz"

const Stateless: React.FC = () => {
const dispatch = useDispatch()
// const [state, _setState] = useState()

// const stateRef = useRef(state)
// const setState = (data: any) => {
// stateRef.current = data
// _setState(data)
// console.log("Posting current state to parent")
// window.parent.postMessage(
// { message: "current-state2", message_type: "moocfi/editor-message", data: data },
// "*",
// )
// }
const store = useTypedSelector(state => state)
const [port, setPort] = useState<MessagePort | null>(null)

useEffect(() => {
if (typeof window === undefined) {
console.log("Not adding a event listener because window is undefined.")
if (!port) {
return
}
const handleMessage = handleMessageCreator()
console.log("Adding event listener...")
window.addEventListener("message", handleMessage)
if (window.parent === window) {
console.warn(
"Cannot inform the parent we're ready since there is no parent. Please make sure you're using this from an iframe.",
)
} else {
console.log("Telling the parent we're ready")
window.parent.postMessage(
{ message: "ready", message_type: "moocfi/editor-message" },
"*",
)
}
const removeListener = () => {
console.log("Removing event listener")
window.removeEventListener("message", handleMessage)
}
return removeListener
}, [])
port.postMessage({
message: "current-state",
data: convertStoreToSpecs(store),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implement the changes in rage/secret-project-331#264

})
}, [store])

const handleMessageCreator = () => {
return function handleMessage(event: WindowEventMap["message"]) {
if (event.data.message_type !== "moocfi/editor-message") {
useEffect(() => {
const handler = (message: WindowEventMap["message"]) => {
if (message.source !== parent) {
return
}
console.log("Frame received an event: ", JSON.stringify(event.data))
if (event.data.message === "content") {
dispatch(
initializedEditor(normalizeData(event.data.data), event.data.data),
)
// setState(event.data.data || [])
}
if (event.data.message === "give-state") {
const data = denormalizeData(useTypedSelector(state => state))
window.parent.postMessage(
{
message: "current-state",
message_type: "moocfi/editor-message",
data: data,
},
"*",
)
const port = message.ports[0]
if (port) {
console.log("Frame received a port:", port)
setPort(port)
port.onmessage = (message: WindowEventMap["message"]) => {
console.log(
"Frame received a message from port",
JSON.stringify(message.data),
)
const data = message.data
if (data.message === "set-state") {
console.log("Frame: setting state from message")
console.log(data)
dispatch(initializedEditor(normalizeData(data.data), data.data))
} else {
console.error("Frame received an unknown message from message port")
}
}
}
}
console.log("frame adding event listener")
addEventListener("message", handler)
// target origin is *, beacause this is a sandboxed iframe without the
// allow-same-origin permission
parent.postMessage("ready", "*")

// cleanup function
return () => {
console.log("removing event listener")
removeEventListener("message", handler)
}
}, [store])

if (!store) {
return <>Waiting for content...</>
}

if (!port) {
return <>Waiting for port...</>
}

return <StatelessEditor onHeightChange={onHeightChange} />
return <StatelessEditor onHeightChange={onHeightChange} port={port} />
}

const onHeightChange = (newHeight: number) => {
window.parent.postMessage(
{
message: "height-changed",
data: newHeight,
message_type: "moocfi/editor-message",
},
"*",
)
const onHeightChange = (newHeight: number, port: MessagePort) => {
port.postMessage({
message: "height-changed",
data: newHeight,
})
}

const normalizeData = (data: any) => {
Expand All @@ -104,8 +101,53 @@ const normalizeData = (data: any) => {
questions: normalizedInputData.entities.questions ?? {},
}
}
interface QuizzesSpecs {
private_spec: Quiz
public_spec: { id: string; items: PublicSpecItem[] }
}

const convertStoreToSpecs = (store: storeState): QuizzesSpecs => {
const denormalizedData = denormalizeData(store)

const specs: QuizzesSpecs = {
private_spec: denormalizeData(store),
public_spec: {
id: v4(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

items: denormalizedData.items.map(i => {
const publicItem: PublicSpecItem = {
formatRegex: i.formatRegex,
multi: i.multi,
id: i.id,
body: i.body,
direction: i.direction,
maxLabel: i.maxLabel,
maxValue: i.maxValue,
maxWords: i.maxWords,
minLabel: i.minLabel,
minValue: i.minValue,
minWords: i.minWords,
order: i.order,
title: i.title,
type: i.type,
options: i.options.map(o => {
const publicOption: PublicSpecOption = {
id: o.id,
body: o.body,
order: o.order,
title: o.title,
quizItemId: o.quizItemId,
}
return publicOption
}),
}
return publicItem
}),
},
}
return specs
}

const denormalizeData = (store: storeState) => {
const denormalizeData = (store: storeState): Quiz => {
let quizData = {
quizzes: store.editor.quizzes,
items: store.editor.items,
Expand All @@ -117,7 +159,6 @@ const denormalizeData = (store: storeState) => {
return denormalize(quizData.quizId, normalizedQuiz, quizData)
}

//From parent?
const emptyQuiz: Quiz = {
id: v4(),
autoConfirm: true,
Expand Down
28 changes: 27 additions & 1 deletion packages/quizzes-dashboard/types/Quiz.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,27 @@ export interface Item {
| "DisplayFeedbackOnAllOptions"
}

export interface PublicSpecItem {
id: string
type: string
order: number
formatRegex: null
multi: boolean
minWords: number | null
maxWords: number | null
maxValue: number | null
minValue: number | null
maxLabel: string | null
minLabel: string | null
options: PublicSpecOption[]
title: null
body: null
direction: "row" | "column"
}

export interface Option {
id: string
quizItemId?: string
quizItemId: string
order: number
correct: boolean
createdAt: Date
Expand All @@ -65,6 +83,14 @@ export interface Option {
failureMessage: null | string
}

export interface PublicSpecOption {
id: string
quizItemId: string
order: number
title: string
body: string | null
}

export interface PeerReviewCollection {
id: string
quizId: string
Expand Down