Compare commits

...

18 Commits

Author SHA1 Message Date
Harmony
e158b5ccd6 switching between sprints 2020-03-30 15:41:10 -04:00
Harmony
aafba656c8 Bit o stylin' 2020-03-30 10:21:16 -04:00
Harmony
17de3426e2 can login with google to view boxes 2020-03-02 10:13:01 -05:00
Harmony
f58d607c5d Able to switch sprints 2019-11-25 13:27:34 -05:00
Harmony
ddaf3df1a3 added ability to cross items off 2019-11-25 10:24:32 -05:00
Harmony
4398ee2d45 Can delete any item from db except last one in list 2019-11-25 10:04:50 -05:00
Harmony
3b9ee304db writing to each box 2019-11-15 14:27:56 -05:00
Harmony
f5c8edd74c Reading from each box and writing to one 2019-11-15 11:43:03 -05:00
tparnell
de22b649a2 unlisten when component unmounts 2019-10-25 15:31:15 -04:00
Harmony
7bc236e7e7 read from firebase 2019-10-25 14:54:02 -04:00
Harmony
db72085762 delete items 2019-10-25 13:46:11 -04:00
Harmony
406a89db39 handle when no one has redux devtools 2019-10-25 13:07:41 -04:00
tparnell
3f01282bcc redux should work 2019-10-25 13:03:31 -04:00
Harmony
998cf45a97 it works 2019-10-25 12:55:56 -04:00
Harmony
c474fe3792 merge card UI 2019-10-25 12:54:35 -04:00
Harmony
64a9420b01 stop 2019-10-25 12:53:46 -04:00
Harmony
90d633ed23 merging master 2019-10-25 12:46:30 -04:00
Harmony
5d3c81a650 Box set up 2019-10-25 10:59:41 -04:00
21 changed files with 15803 additions and 334 deletions

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
registry=https://registry.npmjs.org

14647
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3,13 +3,17 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@reach/router": "^1.2.1",
"firebase": "^7.2.2",
"node-sass": "^4.13.0", "node-sass": "^4.13.0",
"react": "^16.11.0", "react": "^16.11.0",
"react-dom": "^16.11.0", "react-dom": "^16.11.0",
"react-firebaseui": "^4.1.0",
"react-redux": "^7.1.1", "react-redux": "^7.1.1",
"react-scripts": "3.2.0", "react-scripts": "3.2.0",
"redux": "^4.0.4", "redux": "^4.0.4",
"redux-thunk": "^2.3.0" "redux-thunk": "^2.3.0",
"uuid": "^3.3.3"
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start",

View File

@@ -1,22 +0,0 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #09d3ac;
}

View File

@@ -1,11 +1,49 @@
import React from "react"; import React, {useState, useEffect} from "react";
import StyledFirebaseAuth from 'react-firebaseui/StyledFirebaseAuth';
import firebase from'firebase'
import { Provider } from "react-redux"; import { Provider } from "react-redux";
import { Router } from "@reach/router";
import Boxes from "./boxes/Boxes";
import SignedIn from "./SignedIn/SignedIn.js";
import setupStore from "./store/setupStore.js"; import setupStore from "./store/setupStore.js";
const config = {
apiKey: "AIzaSyC5krz4RBiT87RK7cEidh3n-A4H63uGcyM",
authDomain: "retrod-7e2cd.firebaseapp.com",
};
const uiConfig = {
signInFlow: 'popup',
signInSuccessUrl: '/',
signInOptions: [
firebase.auth.GoogleAuthProvider.PROVIDER_ID,
]
};
function App() { function App() {
const [sprint, setSprint] = useState(1);
const [isSignedIn, setSignIn] = useState(false)
useEffect(() => {
firebase.auth().onAuthStateChanged(user => {
setSignIn(!!user)
})
})
return ( return (
<Provider store={setupStore()}> <Provider store={setupStore()}>
<div>Yoooooo</div> <Router>
<Boxes exact path={`/` + sprint} />
</Router>
<div>
{isSignedIn ? (
<>
<SignedIn/>
</>
) : (
<>
<h1>You're Not Signed In</h1>
<StyledFirebaseAuth uiConfig={uiConfig} firebaseAuth={firebase.auth()}/>
</>
)
}
</div>
</Provider> </Provider>
); );
} }

25
src/Items/Items.js Normal file
View File

@@ -0,0 +1,25 @@
import React from 'react';
import { databaseRef } from '../store/firebase.js'
import styles from "./items.module.css";
export default function Item({ item, boxId, sprint }) {
const handleClick = e => {
let url;
if(boxId === "1"){
url = `retros/` + sprint + `/www/`
} else if(boxId === "2"){
url = `retros/` + sprint + `/!www/`
} else if(boxId === "3"){
url = `retros/` + sprint + `/questions/`
} else {
url = 'retros/1/a/'
}
databaseRef.ref(url + item.id + `/completed`).set(item.completed === false ? true : false)
}
return (
<div className={styles.flexItem}>
<p style={{ textDecoration: item.completed ? "line-through" : "" }}>{item.title}</p>
<button onClick={handleClick}>{item.completed === false ? <p className={styles.checkmark}></p> : <p className={styles.redx}>x</p>}</button>
</div>
)
}

View File

@@ -0,0 +1,15 @@
.flexItem{
display: flex;
justify-content: space-between;
}
button{
background: none;
border: none;
}
.checkmark{
color: green;
cursor: pointer;
}
.redx{
color: red;
}

45
src/NewItem/NewItem.js Normal file
View File

@@ -0,0 +1,45 @@
import React, {useState} from 'react';
import { databaseRef } from '../store/firebase.js'
import uuid from "uuid";
export default function NewItem({ addItem, boxId, sprint }) {
const [value, setValue ] = useState("");
const handleSubmit = e => {
e.preventDefault();
let retroRef;
let url;
if(boxId === "1"){
url = `retros/` + sprint + `/www`;
retroRef = databaseRef.ref(url);
} else if(boxId === "2"){
url = `retros/` + sprint + `/!www`;
retroRef = databaseRef.ref(url);
} else if(boxId === "3"){
url = `retros/` + sprint + `/questions`;
retroRef = databaseRef.ref(url);
} else {
url = 'retros/1/a';
retroRef = databaseRef.ref(url);
}
const item = {
completed: false,
id: uuid.v4(),
title: value,
}
let objectId = retroRef.push(item);
databaseRef.ref(url + `/` + objectId.key + `/id`).set(objectId.key)
setValue("")
}
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
value={value}
placeholder="stuff"
onChange={e => setValue(e.target.value)}
/>
</form>
</div>
)
}

21
src/SignedIn/SignedIn.js Normal file
View File

@@ -0,0 +1,21 @@
import React from "react";
import firebase from'firebase';
import SprintSelect from "../sprintSelect/SprintSelect"
import styles from "./signedIn.module.css";
export default function SignedIn() {
return (
<div>
<div className={styles.alignRight}>
<div className={styles.marginRight}>
<p>{firebase.auth().currentUser.displayName}</p>
<div>
<img align="right" className={styles.profilePicture} alt='user profile' src={firebase.auth().currentUser.photoURL} />
</div>
<button className={styles.signOutButton} onClick={() => firebase.auth().signOut()}>Sign Out</button>
</div>
</div>
<SprintSelect />
</div>
)
}

View File

@@ -0,0 +1,25 @@
body{
background: lightseagreen;
}
.alignRight{
width: 100%;
display: flex;
flex-direction: column;
align-items: flex-end;
}
.marginRight{
margin-right: 1rem;
}
.signOutButton{
background: none;
border: none;
text-decoration: underline;
cursor: pointer;
width: 100%;
text-align: right;
padding: 0;
margin-top: 1rem;
}
.alignRight .profilePicture{
max-width: 50px;
}

13
src/boxes/Boxes.js Normal file
View File

@@ -0,0 +1,13 @@
import React from 'react';
import styles from './Boxes.module.css'
import Cards from '../cards/Cards.js'
export default function Boxes({ sectionName, boxId, sprint }) {
return (
<div>
<div className={styles.box}>
<Cards sectionName={sectionName} boxId={boxId} sprint={sprint} />
</div>
</div>
)
}

View File

@@ -0,0 +1,4 @@
.box{
border: .15rem solid black;
background: lightgrey;
}

55
src/cards/Cards.js Normal file
View File

@@ -0,0 +1,55 @@
import React, { useState, useEffect, useMemo } from 'react';
import { databaseRef } from '../store/firebase.js'
import Item from '../Items/Items.js';
import NewItem from '../NewItem/NewItem.js'
import DeleteItem from '../deleteItem/DeleteItem.js'
import styles from "./cards.module.css";
export function Cards({item, setItem, boxId, sprint, sectionName, sprint_id}) {
return (
<>
<h3>{sectionName}</h3>
{item.map((i, index) => (
<div className={i.sprint_id === sprint ? styles.cardBackground : styles.hide} key={i.id}>
<Item
item={i}
index={index}
boxId={boxId}
sprint={sprint}
/>
<DeleteItem item={i} boxId={boxId} sprint={sprint}/>
</div>
))}
<NewItem sprint={sprint} boxId={boxId}/>
</>
)
}
export default function FirebaseWrapper({sectionName, boxId, sprint}) {
const [cards, setCards] = useState(null)
let retro;
if(boxId === "1"){
retro = databaseRef.ref(`retros/` + sprint + `/www`);
} else if(boxId === "2"){
retro = databaseRef.ref(`retros/` + sprint + `/!www`);
} else if(boxId === "3"){
retro = databaseRef.ref(`retros/` + sprint + `/questions`);
} else {
retro = databaseRef.ref('retros/1/a');
}
const retroRef = useMemo(() => databaseRef.ref(retro), []);
useEffect(() => {
retroRef.on('value', function(snapshot) {
const values = Object.values(snapshot.val())
setCards(values)
});
// this will be called when our component unmounts
return () => {
retroRef.off();
}
}, [retroRef]);
if(!cards) {
return <div>loading...</div>;
};
return <Cards sectionName={sectionName} item={cards} boxId={boxId} sprint={sprint} setItem={()=> {}}/>
}

View File

@@ -0,0 +1,8 @@
.cardBackground{
background: white;
margin: .5em;
padding: 1em;
}
.hide{
display: none;
}

View File

@@ -0,0 +1,31 @@
import React from 'react';
import { databaseRef } from '../store/firebase.js'
import styles from "./deleteItem.module.css";
export default function DeleteItem({ item, boxId, objectId, sprint }) {
// const [value, setValue ] = useState("");
const handleClick = e => {
let retroRef;
if(boxId === "1"){
retroRef = databaseRef.ref(`retros/` + sprint + `/www/` + item.id);
} else if(boxId === "2"){
retroRef = databaseRef.ref(`retros/` + sprint + `/!www/` + item.id);
} else if(boxId === "3"){
retroRef = databaseRef.ref(`retros/` + sprint + `/questions/` + item.id);
} else {
retroRef = databaseRef.ref(`retros/1/a/` + item.id);
}
// const item = {
// completed: false,
// id: uuid.v4(),
// title: value,
// }
// databaseRef.ref.remove(retroRef);
// setValue("")
retroRef.remove()
}
return (
<button className={styles.deleteButton} onClick={handleClick}>DELETE</button>
)
}

View File

@@ -0,0 +1,10 @@
.deleteButton{
color: darkred;
width: 100%;
display: flex;
justify-content: flex-end;
font-size: .5em;
font-weight: bolder;
letter-spacing: 1px;
cursor: pointer;
}

View File

@@ -0,0 +1,54 @@
import React, { useState, useEffect, useMemo } from 'react';
import Boxes from "../boxes/Boxes";
import { databaseRef } from '../store/firebase.js'
import styles from "../sprintSelect/sprintSelect.module.css";
export function SprintSelect({item}) {
const [sprint, setSprint] = useState(1);
let sprintArray = [];
let sortedSprint;
sortedSprint = item.map((i, index) => (
sprintArray.push(i.sprint_id)
))
.reduce((unique, item) => {
return unique.includes(item) ? unique : [...unique, item]
}, [])
.sort();
let dropdownSprint;
dropdownSprint = sortedSprint.map((i, index) => (
<option onClick={() => setSprint(i)}>{i}</option>
));
return (
<div>
<label>Choose Sprint:</label>
<select>
{dropdownSprint}
</select>
<h3>Sprint {sprint}</h3>
<div className={styles.grid}>
<Boxes sectionName={"What Went Well"} sprint={sprint} boxId={'1'} />
<Boxes sectionName={"What Could Be Better"} sprint={sprint} boxId={'2'}/>
<Boxes sectionName={"Questions"} sprint={sprint} boxId={'3'}/>
</div>
</div>
)
}
export default function FirebaseWrapper() {
const [cards, setCards] = useState(null)
let retro = databaseRef.ref(`retros/1/www`);
const retroRef = useMemo(() => databaseRef.ref(retro), []);
useEffect(() => {
retroRef.on('value', function(snapshot) {
const values = Object.values(snapshot.val())
setCards(values)
});
return () => {
retroRef.off();
}
}, [retroRef]);
if(!cards) {
return <div>loading...</div>;
};
return <SprintSelect item={cards} setItem={()=> {}}/>
}

View File

@@ -0,0 +1,6 @@
.grid{
display: grid;
grid-template-columns: auto auto auto;
grid-column-gap: 1em;
margin: 1rem;
}

7
src/store/firebase.js Normal file
View File

@@ -0,0 +1,7 @@
import * as firebase from 'firebase';const config = {
apiKey: "AIzaSyC5krz4RBiT87RK7cEidh3n-A4H63uGcyM",
authDomain: "retrod-7e2cd.firebaseapp.com",
databaseURL: "https://retrod-7e2cd.firebaseio.com/",
}
firebase.initializeApp(config);
export const databaseRef = firebase.database();

View File

@@ -1,13 +1,14 @@
import { createStore, applyMiddleware, compose } from "redux"; import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk"; import thunk from "redux-thunk";
import rootReducer from "../reducers/main.js"; import rootReducer from "../reducers/main.js";
const devTools = window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__();
export default function setupStore() { export default function setupStore() {
return createStore( return createStore(
rootReducer, rootReducer,
compose( compose(
applyMiddleware(thunk), applyMiddleware(thunk),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() (devTools || function(f) { return f; })
) )
); );
} }

1097
yarn.lock

File diff suppressed because it is too large Load Diff