Skip to content

Commit

Permalink
Merge pull request #111 from sqrl-planner/develop
Browse files Browse the repository at this point in the history
Bump version
  • Loading branch information
eamonma authored Jul 19, 2022
2 parents 41715a5 + 3d40db0 commit 550bea0
Show file tree
Hide file tree
Showing 19 changed files with 266 additions and 110 deletions.
34 changes: 19 additions & 15 deletions components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
Badge,
useToast,
} from "@chakra-ui/react"
import Head from "next/head"
import { EditIcon, Icon, InfoIcon, SettingsIcon } from "@chakra-ui/icons"
import { FaShareSquare } from "react-icons/fa"
import { useAppContext } from "../src/SqrlContext"
Expand All @@ -29,6 +28,8 @@ import useSections from "../src/useSections"
import { DUPLICATE_TIMETABLE } from "../operations/mutations/duplicateTimetable"
import { useMutation } from "@apollo/client"
import { useTranslation } from "next-i18next"
import TitleMeta from "./TitleMeta"
import useSharePrefix from "../src/useSharePrefix"

const HeaderComponent = styled(chakra.header)`
/* display: grid; */
Expand Down Expand Up @@ -78,7 +79,8 @@ const Header = ({ setSidebarOpen }: { setSidebarOpen: any }) => {
const [osModifier, setOsModifier] = useState("")

useEffect(() => {
if (navigator.userAgent.indexOf("Mac OS X") !== -1) return setOsModifier("⌘")
if (navigator.userAgent.indexOf("Mac OS X") !== -1)
return setOsModifier("⌘")
setOsModifier("Ctrl + ")
}, [])

Expand All @@ -90,6 +92,17 @@ const Header = ({ setSidebarOpen }: { setSidebarOpen: any }) => {

const { name, updateName } = useSections()

// Handles overriding the server-side title. When wget or discord embed searches for the title,
// it will find the one in [id].tsx, and never gives the client a chance to load. When the client loads
// in a browser, this <TitleMeta> overrides that one, making it react to name changes appropriately.
const [showReactiveTitle, setShowReactiveTitle] = useState<boolean>(false)

// The first time updateName is called, override the server-shown
// title with the client-side context-driven one.
useEffect(() => {
setShowReactiveTitle(true)
}, [setShowReactiveTitle])

const keydownListener = useCallback(
(e: KeyboardEvent) => {
if (!allowedToEdit) return
Expand Down Expand Up @@ -149,26 +162,17 @@ const Header = ({ setSidebarOpen }: { setSidebarOpen: any }) => {

const [duplicateTimetable] = useMutation(DUPLICATE_TIMETABLE)
const [loading, setLoading] = useState(false)
const [sharePrefix, setSharePrefix] = useState("")

useEffect(() => {
setSharePrefix(
`${window.location.protocol}//${window.location.host}/timetable/`
)
}, [])
const [sharePrefix] = useSharePrefix()

const id = router.query.id

const { t } = useTranslation("common")

return (
<HeaderComponent bg={useColorModeValue("gray.75", "gray.700")}>
<Head>
<title>Sqrl Planner | {name}</title>
<meta property="og:url" content={`${sharePrefix}${id}`} />
<meta property="og:type" content="website" />
<meta property="og:title" content={`Sqrl Planner | ${name}`} />
</Head>
{showReactiveTitle && (
<TitleMeta name={name} sharePrefix={sharePrefix} id={id} />
)}
<AboutModal isOpen={isAboutOpen} onClose={onCloseAbout} />
<ShareModal isOpen={isShareOpen} onClose={onCloseShare} />
<Flex flex="1" alignItems="center" pl="11rem">
Expand Down
12 changes: 3 additions & 9 deletions components/ShareModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { useMutation } from "@apollo/client"
import { DUPLICATE_TIMETABLE } from "../operations/mutations/duplicateTimetable"
import { CopyIcon, ExternalLinkIcon } from "@chakra-ui/icons"
import { useTranslation } from "next-i18next"
import useSharePrefix from "../src/useSharePrefix"

type props = {
isOpen: boolean
Expand All @@ -39,14 +40,7 @@ const ShareModal = ({ isOpen, onClose }: props) => {

const id = router.query.id

const [sharePrefix, setSharePrefix] = useState("")

useEffect(() => {
setSharePrefix(
`${window.location.protocol}//${window.location.host}/timetable/`
)
}, [])

const [sharePrefix] = useSharePrefix()
const shareUrl = `${sharePrefix}${id}`
const { onCopy, hasCopied } = useClipboard(shareUrl)

Expand All @@ -61,7 +55,7 @@ const ShareModal = ({ isOpen, onClose }: props) => {
duration: 9000,
isClosable: true,
})
}, [hasCopied])
}, [toast, hasCopied])

const [duplicateTimetable] = useMutation(DUPLICATE_TIMETABLE)

Expand Down
23 changes: 23 additions & 0 deletions components/TitleMeta.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react"
import Head from "next/head"

type Props = {
name: string
sharePrefix: string
id: string | string[] | undefined
}

function TitleMeta(props: Props) {
const { name, sharePrefix, id } = props

return (
<Head>
<title>Sqrl Planner | {name}</title>
<meta property="og:url" content={`${sharePrefix}${id}`} />
<meta property="og:type" content="website" />
<meta property="og:title" content={`Sqrl Planner | ${name}`} />
</Head>
)
}

export default TitleMeta
2 changes: 1 addition & 1 deletion components/preferences/PreferencesMeeting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ const PreferencesMeeting = () => {
fontSize="sm"
fontWeight={500}
>
{t("cosmic ")}
{t("cosmic")}
</SliderMark>
<SliderTrack>
<SliderFilledTrack />
Expand Down
169 changes: 117 additions & 52 deletions components/sidebar/CourseView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,9 @@ import {
Tooltip,
useClipboard,
useToast,
VStack,
} from "@chakra-ui/react"
import React, {
Fragment,
useEffect,
useRef,
useState,
} from "react"
import React, { Dispatch, Fragment, useEffect, useRef, useState } from "react"
import reactStringReplace from "react-string-replace"
import { useAppContext } from "../../src/SqrlContext"
import { MeetingCategoryType } from "../timetable/Meeting"
Expand All @@ -44,8 +40,18 @@ import useSections from "../../src/useSections"
import { motion } from "framer-motion"
import useTimetable from "../../src/useTimetable"
import { SearchIcon } from "@chakra-ui/icons"
import {
getCourseLetterFromTerm,
computeSiblingCourseId,
} from "../../src/utils/course"
import { useLazyQuery } from "@apollo/client"
import { CHECK_COURSE_EXISTS } from "../../operations/queries/checkCourseExists"

type Props = {
setSearchQuery: Dispatch<React.SetStateAction<string>>
}

const CourseView = ({ setSearchQuery }: { setSearchQuery: Function }) => {
const CourseView = ({ setSearchQuery }: Props) => {
const {
state: {
// courses,
Expand All @@ -61,9 +67,42 @@ const CourseView = ({ setSearchQuery }: { setSearchQuery: Function }) => {
sections,
})
const { allowedToEdit } = useTimetable({ id: router.query.id as string })
const [siblingCourseId, setSiblingCourseId] = useState<string | null>(null)

const course = courses[identifier]

const [checkCourseExists] = useLazyQuery(CHECK_COURSE_EXISTS, {
errorPolicy: "all",
})

useEffect(() => {
// Cannot put async callback to useEffect, so wrap
// Check for the sibling course if it exists, and if it does,
// add the ID of that course to the state. If not, it's null

// Run the query
;(async () => {
if (!course) return

const siblingCourseId = computeSiblingCourseId(course)
if (siblingCourseId === null) return

const result = await checkCourseExists({
variables: {
id: siblingCourseId,
},
})

// I don't know how to show errors in sqrl :/ so return for now
if (result.error) return

if (result.data.courseById) {
// courseById is null when there is course with matching id
setSiblingCourseId(result.data.courseById.id)
}
})()
}, [course, checkCourseExists])

// TODO: meetings out of the timetable's display bounds are hidden without warning. Warn them.

const boxRef = useRef<HTMLHeadingElement | null>(null)
Expand Down Expand Up @@ -97,7 +136,7 @@ const CourseView = ({ setSearchQuery }: { setSearchQuery: Function }) => {
if (missing.length !== 0) return

toast.close("warn-missing-section")
}, [course, userMeetings, identifier])
}, [toast, course, userMeetings, identifier])

useEffect(() => {
if (!hasCopied) return
Expand All @@ -108,7 +147,7 @@ const CourseView = ({ setSearchQuery }: { setSearchQuery: Function }) => {
duration: 9000,
isClosable: true,
})
}, [hasCopied])
}, [toast, hasCopied])

if (!identifier) {
return (
Expand Down Expand Up @@ -225,11 +264,7 @@ const CourseView = ({ setSearchQuery }: { setSearchQuery: Function }) => {
{suffix}
</Text>
<Text as="span" fontSize="0.8em" ml={2}>
{(() => {
if (course.term === "FIRST_SEMESTER") return "F"
if (course.term === "SECOND_SEMESTER") return "S"
return "Y"
})()}
{getCourseLetterFromTerm(course)}
</Text>
</Box>
<Box>
Expand Down Expand Up @@ -316,46 +351,76 @@ const CourseView = ({ setSearchQuery }: { setSearchQuery: Function }) => {
</Fragment>
)}
</Popover>
<ButtonGroup
isAttached
display="flex"
width="100%"
variant="outline"
colorScheme="gray"
>
<Button
alignItems="center"
gap={2}
onClick={() => {
if (!removePopoverTriggerRef.current) return
removePopoverTriggerRef.current.click()
}}
disabled={
!allowedToEdit ||
!Object.keys(userMeetings).some((courseCode) => {
return courseCode === course.id
})
}
<VStack>
{siblingCourseId && (
<ButtonGroup
isAttached
display="flex"
width="100%"
variant="outline"
colorScheme="gray"
>
<Button
alignItems="center"
gap={2}
onClick={() => {
dispatch({
type: "SET_SIDEBAR",
payload: 1,
})
dispatch({
type: "SET_SIDEBAR_COURSE",
payload: siblingCourseId,
})
}}
>
{course.term === "FIRST_SEMESTER"
? t("sidebar:see-in-second-semester")
: t("sidebar:see-in-first-semester")}
</Button>
</ButtonGroup>
)}
<ButtonGroup
isAttached
display="flex"
width="100%"
variant="outline"
colorScheme="gray"
>
<Icon as={FaTrashAlt} />
{t("sidebar:remove")}
</Button>
<Button
alignItems="center"
gap={2}
onClick={() => {
if (!removePopoverTriggerRef.current) return
removePopoverTriggerRef.current.click()
}}
disabled={
!allowedToEdit ||
!Object.keys(userMeetings).some((courseCode) => {
return courseCode === course.id
})
}
>
<Icon as={FaTrashAlt} />
{t("sidebar:remove")}
</Button>

<Button
alignItems="center"
gap={2}
disabled={
true ||
!Object.keys(userMeetings).some((courseCode) => {
return courseCode === course.id
})
}
onClick={onCopy}
>
<Icon as={FaShareSquare} />
Share with selections
</Button>
</ButtonGroup>
<Button
alignItems="center"
gap={2}
disabled={
true ||
!Object.keys(userMeetings).some((courseCode) => {
return courseCode === course.id
})
}
onClick={onCopy}
>
<Icon as={FaShareSquare} />
Share with selections
</Button>
</ButtonGroup>
</VStack>
</Flex>
{Object.values(MeetingCategoryType).map((method) => (
<MeetingPicker
Expand Down
8 changes: 2 additions & 6 deletions components/sidebar/SearchView/SearchResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,18 @@ import {
VStack,
} from "@chakra-ui/react"
import { motion } from "framer-motion"
import React, { SetStateAction } from "react"
import { Dispatch } from "react"
import React from "react"
import { Course } from "../../../src/Course"
import { useAppContext } from "../../../src/SqrlContext"
import { breakdownCourseCode } from "../../../src/utils/course"

type Props = {
courses: Array<Course>
setChosenCourse: Dispatch<SetStateAction<string>>
chosenCourse: string
}

const MotionFlex = motion<FlexProps>(Flex)

const SearchResults = ({ courses, setChosenCourse, chosenCourse }: Props) => {
const SearchResults = ({ courses }: Props) => {
const { dispatch } = useAppContext()
const hoverBackground = useColorModeValue("gray.100", "gray.600")

Expand Down Expand Up @@ -65,7 +62,6 @@ const SearchResults = ({ courses, setChosenCourse, chosenCourse }: Props) => {
}}
tabIndex={0}
onClick={() => {
setChosenCourse(course.id)
dispatch({
type: "SET_SIDEBAR",
payload: 1,
Expand Down
Loading

0 comments on commit 550bea0

Please sign in to comment.