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

Modal folder structure #36

Open
wants to merge 10 commits into
base: main
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
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ export MVC_FIREBASE_DOMAIN="<domain>"

We use [Cypress](https://www.cypress.io/) to run end to end tests on our code.

In order to run tests locally, you'll currently need service account access to firebase. (We're looking to get rid of this dependency)

tl;dr:
- Go to the [Firebase console](https://console.firebase.google.com/)
- Select the `minimum-viable-ceremonies-test` project
- Select Project Configuration -> Service Accounts -> Generate new private key
- Save the resulting file as `serviceAccount.json` in the root of this project (make sure it's `.gitignored`!)

Still lost? [Detailed instructions here](https://github.com/prescottprue/cypress-firebase)

```shell
npm run test
```
Expand Down
2 changes: 1 addition & 1 deletion cypress/integration/createRoom.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('Create room', () => {
cy.get('.copy-link').invoke('val').should('match', /http:\/\/localhost:8000\/room/)
cy.contains('Create room').click()

cy.get('.setup-user-name h1', {timeout: 10_000}).invoke('text').should('match', /What\'s your name/)
cy.get('.setup-input-subpanel h1', {timeout: 10_000}).invoke('text').should('match', /What\'s your name/)
cy.url().should('include', 'http://localhost:8000/room')
})
})
9 changes: 5 additions & 4 deletions cypress/integration/editCeremony.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ describe('Edit ceremony', () => {
})

it('Can make a placement via the modal', () => {
cy.get('.mvc-input__cadence').click().find('input').focus()
cy.focused().type('{downarrow}{enter}', {force:true})
cy.get('.mvc-input__cadence').click()
cy.get('.mvc-input__cadence input').type('{downarrow}{enter}', {force:true})
cy.contains('Back').click()
cy.get('.cadence.daily').contains('Personal Check-in')

cy.wait(500)
cy.fetchRoom('test-room-uuid').then(room => {
assert.equal(room.ceremonies.checkin.placement, 'daily')
})
Expand Down Expand Up @@ -40,8 +41,8 @@ describe('Edit ceremony', () => {

it('Can add a time for synchronous meetings', () => {
cy.get('.mvc-input__async').contains('Yes (Synchronous)').click()
cy.get('.mvc-input__cadence').click().find('input').focus()
cy.focused().type('{downarrow}{enter}', {force:true})
cy.get('.mvc-input__cadence').click().find('input')
cy.get('.mvc-input__cadence input').type('{downarrow}{enter}', {force:true})

cy.get('.mvc-input__start-time').click().find('input').focus()
cy.focused().type('{downarrow}{enter}', {force:true})
Expand Down
14 changes: 14 additions & 0 deletions gatsby-config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const path = require('path')

const apiKey = process.env.CYPRESS
? process.env.CYPRESS_API_KEY
: process.env.MVC_FIREBASE_API_KEY
Expand Down Expand Up @@ -49,6 +51,18 @@ module.exports = {
`gatsby-plugin-react-svg`,
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-root-import`,
options: {
components: path.join(__dirname, 'src/components'),
contexts: path.join(__dirname, 'src/contexts'),
images: path.join(__dirname, 'src/images'),
styles: path.join(__dirname, 'src/styles'),
data: path.join(__dirname, 'src/data'),
hooks: path.join(__dirname, 'src/hooks'),
firebaseLocal: path.join(__dirname, 'src/firebase'),
}
},
{
resolve: `gatsby-plugin-manifest`,
options: {
Expand Down
5 changes: 5 additions & 0 deletions 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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"gatsby-plugin-offline": "^3.1.4",
"gatsby-plugin-react-helmet": "^3.2.4",
"gatsby-plugin-react-svg": "^3.0.0",
"gatsby-plugin-root-import": "^2.0.6",
"gatsby-plugin-sass": "^2.2.4",
"gatsby-plugin-sharp": "^2.5.6",
"gatsby-plugin-web-font-loader": "^1.0.4",
Expand Down
20 changes: 10 additions & 10 deletions src/components/board.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import React, { useContext } from "react"
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { DragDropContext } from "react-beautiful-dnd"
import Confetti from "react-dom-confetti"
import { DragDropContext } from 'react-beautiful-dnd'
import Confetti from 'react-dom-confetti'

import Cadence from "./cadence"
import Dropdown from "./dropdown"
import Sidebar from "./sidebar"
import Toast from "./toast"
import Context from "../contexts/room"
import confettiData from "../data/confetti"
import "../styles/board.scss"
import Sidebar from 'components/sidebar'
import Cadence from 'components/shared/cadence'
import Dropdown from 'components/shared/dropdown'
import Toast from 'components/shared/toast'
import Context from 'contexts/room'
import confettiData from 'data/confetti'
import 'styles/board.scss'

const Board = () => {
const { t } = useTranslation()
Expand Down
31 changes: 9 additions & 22 deletions src/components/intro.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import React, { useEffect } from "react"
import phrase from "random-words"
import { useMatomo } from "@datapunt/matomo-tracker-react"
import React, { useEffect } from 'react'
import phrase from 'random-words'
import { useMatomo } from '@datapunt/matomo-tracker-react'

import SetupRoom from "./setupRoom"
import Board from "./board"
import Modal from "./modal"
import useRoomContext from "../hooks/useRoomContext"
import Context from "../contexts/room"
import roomTable from "../firebase/db/room"
import SetupRoom from 'components/modals/room'
import Board from 'components/board'
import Modal from 'components/modals/index'
import useRoomContext from 'hooks/useRoomContext'
import Context from 'contexts/room'

const Intro = () => {
const draft = useRoomContext(phrase({exactly: 3, join: '-'}), true)
Expand All @@ -18,21 +17,9 @@ const Intro = () => {
return (
<Context.Provider value={draft}>
<Modal
Content={SetupRoom}
content={SetupRoom}
open={true}
initialModel={draft}
submit={roomTable.create}
steps={[{
next: "setup.controls.okGotIt",
back: null,
}, {
next: "setup.controls.next",
back: "setup.controls.back",
canProceed: ({ name }) => name.length > 3,
}, {
next: "setup.controls.createRoom",
back: "setup.controls.back",
}]}
/>
<Board />
</Context.Provider>
Expand Down
8 changes: 4 additions & 4 deletions src/components/layout.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from "react"
import FreshChat from "react-freshchat"
import { MatomoProvider, createInstance } from "@datapunt/matomo-tracker-react"
import React from 'react'
import FreshChat from 'react-freshchat'
import { MatomoProvider, createInstance } from '@datapunt/matomo-tracker-react'

import "../styles/layout.scss"
import 'styles/layout.scss'

const Layout = ({ children }) => (
<MatomoProvider value={process.env.MATOMO_SITE_ID ? createInstance({
Expand Down
33 changes: 33 additions & 0 deletions src/components/modals/ceremony/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { useEffect, useContext } from "react"

import CustomCard from 'components/shared/card/custom'
import Context from "contexts/modal"
import RoomContext from 'contexts/room'

const Ceremony = () => {
const { model, setModel, submitting, setSubmitted } = useContext(Context)
const { modifyCeremony, setEditingCeremonyId } = useContext(RoomContext)

/* eslint-disable react-hooks/exhaustive-deps */
useEffect(() => {
if (!submitting) { return }

modifyCeremony(model.id, model).then(() => {
setSubmitted(true)
setEditingCeremonyId(model.id)
})
}, [submitting])

return (
<div className="setup-ceremony flex-grow">
<CustomCard model={model} setModel={attrs => (
setModel(current => ({ ...current, ...attrs }))
)} />
</div>
)
}

Ceremony.next = "common.save"
Ceremony.canProceed = ({ title }) => !!title

export default Ceremony
18 changes: 18 additions & 0 deletions src/components/modals/closeButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React, { useContext } from 'react'
import { useTranslation } from "react-i18next"
import Context from "contexts/modal"

const CloseButton = () => {
const { steps, close } = useContext(Context)
const { t } = useTranslation()

if (steps.length > 1) { return null }

return (
<div className="flex items-start">
<button className="close-modal" onClick={close}>{t("setup.controls.back")}</button>
</div>
)
}

export default CloseButton
25 changes: 25 additions & 0 deletions src/components/modals/content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { useContext } from 'react'
import Context from "contexts/modal"
import 'styles/setup.scss'

const Content = () => {
const { steps, currentStep } = useContext(Context)

if (!steps) { return null }

return (
<div className="setup">
<div className="setup-slides" style={{ marginLeft: `-${100 * currentStep.index}%`}}>
{steps.map((Step, index) => (
<div key={index} className={`setup-slide ${currentStep.index === index ? 'active' : ''}`}>
<div className="setup-panel">
<Step current={index === currentStep.index} />
</div>
</div>
))}
</div>
</div>
)
}

export default Content
14 changes: 7 additions & 7 deletions src/components/controls.js → src/components/modals/controls.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import React, { useContext } from "react"
import { useTranslation } from "react-i18next"

import Loading from "./loading"
import Context from "../contexts/modal"
import "../styles/controls.scss"
import Loading from 'components/shared/loading'
import Context from 'contexts/modal'
import 'styles/controls.scss'

const Controls = ({ single }) => {
const Controls = () => {
const { t } = useTranslation()
const { model, currentStep, nextStep, prevStep, submitting } = useContext(Context)
const { next, back, canProceed } = currentStep

return (
<div className="controls">
{back && !single && <button onClick={prevStep} className="mvc-btn btn-secondary">{t(back)}</button>}
{!single && <div className="controls-divider" />}
{next && <button disabled={!canProceed(model)} className={`mvc-btn btn-primary ${single ? 'flex-grow' : ''}`} onClick={nextStep}>
{back && <button onClick={prevStep} className="mvc-btn btn-secondary">{t(back)}</button>}
<div className="controls-divider" />
{next && <button disabled={!canProceed(model)} className="mvc-btn btn-primary" onClick={nextStep}>
{submitting && <Loading size={25} />}
<span style={{ visibility: submitting ? 'hidden' : 'visible' }}>{t(next)}</span>
</button>}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import React, { useMemo, useContext } from "react"
import Select from "react-select"
import { useTranslation } from "react-i18next"
import Check from "../images/check-mark.svg"
import React, { useMemo, useContext } from 'react'
import Select from 'react-select'
import { useTranslation } from 'react-i18next'

import Card from "./card"
import CustomCard from "./customCard"
import ParticipantOption from "./participantOption"
import Context from "../contexts/room"
import "../styles/setup.scss"
import cadenceData from "../data/cadences"
import hourData from "../data/hours"
import Check from 'images/check-mark.svg'
import ContentCard from 'components/shared/card/content'
import CustomCard from 'components/shared/card/custom'
import ParticipantOption from 'components/shared/participant/option'
import Context from 'contexts/room'
import 'styles/setup.scss'
import cadenceData from 'data/cadences'
import hourData from 'data/hours'

const withOption = (value, option) => {
switch (option) {
Expand All @@ -28,7 +28,7 @@ const withOption = (value, option) => {
}
}

const EditCeremony = ({ onSubmit }) => {
const EditCeremony = () => {
const { t } = useTranslation()
const { weekCount, editingCeremony, participants, modifyCeremony } = useContext(Context)
const { id, placement, async, notes, startTime, endTime } = editingCeremony || {}
Expand Down Expand Up @@ -63,7 +63,7 @@ const EditCeremony = ({ onSubmit }) => {
modifyCeremony(editingCeremony.id, attrs)
)} />
) : (
<Card id={id} namespace="ceremonies" theme={true} />
<ContentCard id={id} namespace="ceremonies" theme={true} />
)}
</div>
<div className="overflow-auto pr-4">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React, { useState, useContext, useMemo } from "react"
import { useTranslation } from "react-i18next"

import Card from "./card"
import RoleBadge from "./roleBadge"
import Context from "../contexts/room"
import "../styles/editUser.scss"
import roleData from "../data/roles"
import ContentCard from "components/shared/card/content"
import RoleBadge from "components/shared/role/badge"
import RoomContext from "contexts/room"
import "styles/editUser.scss"
import roleData from "data/roles"

const EditUser = ({ onSubmit }) => {
const { editingUser, modifyParticipant } = useContext(Context)
const EditUser = () => {
const { editingUser, modifyParticipant } = useContext(RoomContext)
const { t } = useTranslation()
const [currentRole, setCurrentRole] = useState()

Expand All @@ -22,7 +22,7 @@ const EditUser = ({ onSubmit }) => {
<div className="edit-user flex flex-col">
<div className="setup-panel split">
<div>
<Card namespace="roles" id={currentRole || roles[0]} />
<ContentCard namespace="roles" id={currentRole || roles[0]} />
</div>
<div>
<h3 className="mvc-subtitle">{t("participant.name")}</h3>
Expand Down
Loading