Subscriptions are now working and updating some parts of the view.

This commit is contained in:
John Shaver 2017-07-20 15:32:17 -07:00
parent 8687355932
commit 14ce6df7af
10 changed files with 430 additions and 127 deletions

View file

@ -3,10 +3,11 @@ import { getQueryParamByName } from './utils.js';
import ScoutOverviewCont from './containers/GetScoutData.js'; import ScoutOverviewCont from './containers/GetScoutData.js';
import ScoutOverview from './components/ScoutOverview.js'; import ScoutOverview from './components/ScoutOverview.js';
const ScoutView = ScoutOverviewCont(ScoutOverview);
class App extends Component { class App extends Component {
render() { render() {
const scoutID = getQueryParamByName("id", this.props.slug); const scoutID = getQueryParamByName("id", this.props.slug);
const ScoutView = ScoutOverviewCont(ScoutOverview);
return ( return (
<div className="App"> <div className="App">

View file

@ -1,5 +1,30 @@
import React from 'react'; import React from 'react';
import { gql, graphql } from 'react-apollo';
export default({id, number, description, additionalText}) => { export default({
return <div>{number}</div>; id,
number,
completed,
letter,
description,
additionalText,
scoutID,
mutate
}) => {
if(completed) {
return <div className='completed-achievement'>
{number}{letter}
</div>;
} else {
const variables = {
scoutID,
id,
date: (new Date(Date.now())).toISOString()
};
return <button onClick={() => mutate({variables})} className='achievement'>
{number}{letter}
</button>;
}
}; };

View file

@ -1,22 +1,55 @@
import React from 'react' import React from 'react';
import Achievement from './Achievement.js';
import CompleteAchievement from '../containers/CompleteAchievement.js';
import Achievement from "./Achievement.js"; const AchievementButton = CompleteAchievement(Achievement);
export default ({achievements, id, completed}) => { export default class AchievementList extends React.Component {
console.log("completed: ", completed);
if(!achievements) { componentWillMount() {
return <div>Loading...</div> this.unsubscribe = this.props.subscribeToAchievements({
scoutID: this.props.scoutID,
adventureID: this.props.adventureID
});
} }
const list = [...achievements].sort((a, b) => { render() {
if (a.number === b.number) const {
return a.letter > b.letter; allAchievements,
return a.number > b.number; completedAchievements,
}).map(achievement => ( scoutID
<Achievement key={achievement.id} {...achievement} /> } = this.props;
));
const completedMap = completedAchievements.reduce((map, ach) => {
map[ach.achievement.id] = ach;
return map
}, {});
if(!allAchievements || !allAchievements.length) {
return <div>Loading...</div>
}
const list = [...allAchievements].sort((a, b) => {
if (a.number === b.number)
return a.letter > b.letter;
return a.number > b.number;
}).map(achievement => {
const props = {
key: achievement.id,
completed: completedMap[achievement.id],
scoutID,
...achievement
};
return <AchievementButton {...props} />
});
return <div>
{list}
</div>
}
componentWillUnmount() {
this.unsubscribe();
}
return <div>
{list}
</div>
} }

View file

@ -1,15 +1,28 @@
import React from 'react' import React from 'react'
import GetAchievements from "../containers/GetAchievementsForAdventure.js"; import GetAchievements from '../containers/GetAchievementsForAdventure.js';
import AchievementList from "./AchievementList.js"; import AchievementList from './AchievementList.js';
import {Card, CardHeader} from 'material-ui/Card';
export default ({id, name, number, isRequired, achievements, const AchievementListComp = GetAchievements(AchievementList);
completedAdventures, completedAchievements}) => {
const AchievementListComp = GetAchievements(AchievementList); export default ({
return <div> id,
<div>{name}</div> name,
<AchievementListComp adventureID={id} completed={completedAchievements}/> number,
</div> isRequired,
achievements,
completed,
scoutID
}) => {
const className = `adventure ${completed ? 'completed-adventure' :''}`;
return <Card className={className}>
<CardHeader title={name} />
<AchievementListComp
scoutID = {scoutID}
adventureID={id}
/>
</Card>
} }

View file

@ -1,39 +1,74 @@
import React from "react" import React from 'react';
import { splitFilter } from '../utils.js'; import { splitFilter } from '../utils.js';
import Adventure from './Adventure.js'; import Adventure from './Adventure.js';
export default ({ export default class AdventureList extends React.Component {
allAdventures,
completedAdventures componentWillMount() {
}) => { this.unsubscribe = this.props.subscribeToAdventures({
if(!allAdventures) { scoutID: this.props.scoutID
return <div> Loading... </div> });
} }
const sortedAdventures = [...allAdventures].sort((a,b) => (a.number > b.number)); render() {
const {
scoutID,
allAdventures,
completedAdventures
} = this.props;
console.log("completed!: ", completedAdventures);
const [ if(!allAdventures || !allAdventures.length) {
requiredAdventures, return <div> Loading... </div>
optionalAdventures }
] = splitFilter(sortedAdventures, a => a.required);
const requiredAdventureList = requiredAdventures.map(adventure => { const completedMap = completedAdventures.reduce((map, adv) => {
return <Adventure key={adventure.id} {...adventure} />; map[adv.adventure.id] = adv;
}); return map;
}, {});
const optionalAdventureList = optionalAdventures.map(adventure => { const sortedAdventures = [...allAdventures].sort((a,b) => (a.number > b.number));
return <Adventure key={adventure.id} {...adventure} />;
});
return <div> const [
<div> requiredAdventures,
{requiredAdventureList} optionalAdventures
</div> ] = splitFilter(sortedAdventures, a => a.required);
<div>
{ const requiredAdventureList = requiredAdventures.map(adventure => {
//optionalAdventureList const props = {
key: adventure.id,
scoutID: scoutID,
completed: completedMap[adventure.id],
...adventure
} }
</div> return <Adventure {...props} />;
</div>; });
const optionalAdventureList = optionalAdventures.map(adventure => {
console.log("ADVENTURE!: ", adventure);
const props = {
key: adventure.id,
scoutID: scoutID,
completed: completedMap[adventure.id],
...adventure
}
return <Adventure {...props} />;
});
return <div className="adventure-list" >
<div >
{requiredAdventureList}
</div>
<div>
{
//optionalAdventureList
}
</div>
</div>;
}
componentWillUnmount() {
this.unsubscribe();
}
} }

View file

@ -3,25 +3,38 @@ import AllAdventures from '../containers/GetAllAdventures.js'
import AdventureList from './AdventureList.js'; import AdventureList from './AdventureList.js';
import AppBar from 'material-ui/AppBar'; import AppBar from 'material-ui/AppBar';
export default ({ const AdventureListComp = AllAdventures(AdventureList);
scoutID,
displayName, export default class ScoutOverview extends React.Component {
advancementDeadline,
completedAdventures, componentWillMount() {
completedAchievements this.unsubscribe = this.props.subscribeToData({
}) => { scoutID: this.props.scoutID
const appBarProps = { });
title: displayName,
showMenuIconButton: false
} }
const AdventureListComp = AllAdventures(AdventureList);
console.log(displayName) render() {
return ( const {
<div> scoutID,
<AppBar {...appBarProps} /> displayName,
<AdventureListComp advancementDeadline,
{...{scoutID, completedAdventures, completedAchievements}} } = this.props;
/> const appBarProps = {
</div> title: displayName,
); showMenuIconButton: false
}
return (
<div>
<AppBar {...appBarProps} />
<AdventureListComp
scoutID = {scoutID}
/>
</div>
);
}
componentWillUnmount() {
this.unsubscribe();
}
} }

View file

@ -0,0 +1,13 @@
import { gql, graphql } from 'react-apollo';
export default graphql(gql`
mutation MarkAchievementComplete($id:ID!, $scoutID:ID!, $date:DateTime!){
createCompletedAchievement(
completedAt: $date
achievementId: $id
scoutId: $scoutID
) {
id
}
}
`)

View file

@ -1,32 +1,106 @@
import { gql, graphql } from 'react-apollo'; import { gql, graphql } from 'react-apollo';
export default graphql(gql` export default graphql(gql`
query GetAchievementsForAdventure($adventureID:ID!){ query GetAchievementsForAdventure($adventureID:ID! $scoutID:ID!){
allAchievements(filter: { all: allAchievements(filter: {
adventure: { adventure: {id: $adventureID}
id: $adventureID }) {
id
number
letter
description
additionalText
}
completed: allCompletedAchievements(filter:{
scout: {id: $scoutID}
achievement: {
adventure: {id: $adventureID}
} }
}) { }) {
id, id
number, completedAt
letter, achievement {
description, id
additionalText }
} }
} }
`,{ `,{
options: ({adventureID}) => { options: ({adventureID, scoutID}) => ({variables: { adventureID, scoutID }}),
return {
variables: {
adventureID
}
};
},
props: ({ownProps, data}) => { props: ({ownProps, data}) => {
return data.allAchievements ? { const {
achievements: data.allAchievements, subscribeToMore,
...ownProps all,
} : {...ownProps} completed
} = data;
const subscribeToAchievements = params => {
return subscribeToMore({
document: gql`
subscription subscribeToCompAch($scoutID:ID!, $adventureID:ID!){
CompletedAchievement(filter: {
mutation_in: [UPDATED, CREATED, DELETED]
node: {
scout: {
id: $scoutID
}
achievement: {
adventure: {
id: $adventureID
}
}
}
}){
mutation
node {
id
completedAt
achievement {
id
}
}
previousValues {
id
}
}
}
`,
variables: {
scoutID: params.scoutID,
adventureID: params.adventureID
},
updateQuery: (prev, response) => {
const subscriptionData = response.subscriptionData.data.CompletedAchievement;
console.log("UPDATE! :", response);
let updatedAchievements;
const oldAchievements = prev.completed
if(subscriptionData.mutation === 'DELETED') {
updatedAchievements = oldAchievements.filter(ach => (
ach.id !== subscriptionData.previousValues.id
));
} else {
const updatedID = subscriptionData.node.id;
updatedAchievements = [...oldAchievements];
let index = oldAchievements.findIndex(adventure => (
adventure.id === updatedID
));
if(index === -1) index = updatedAchievements.length;
updatedAchievements[index] = subscriptionData.node;
}
return Object.assign({}, prev, {
completed: updatedAchievements
});
}
});
};
return {
allAchievements: all || [],
completedAchievements: completed || [],
subscribeToAchievements,
...ownProps
};
} }
}); });

View file

@ -1,22 +1,90 @@
import { gql, graphql } from 'react-apollo'; import { gql, graphql } from 'react-apollo';
export default graphql(gql` export default graphql(gql`
query GetAllAdventures{ query GetAllAdventures($scoutID:ID!){
allAdventures { allAdventures: allAdventures {
name, name
number, number
required, required
id id
} }
completedAdventures: allCompletedAdventures(filter:{
scout: { id: $scoutID }
}) {
id
signer { id }
adventure { id }
}
} }
`,{ `,{
props: ({ownProps, data}) => ( options: ({scoutID}) => ({variables: {scoutID}}),
data.allAdventures ? { props: ({ownProps, data}) => {
allAdventures: data.allAdventures, const {
subscribeToMore,
completedAdventures,
allAdventures
} = data;
const subscribeToAdventures = params => {
return subscribeToMore({
document: gql`
subscription subscribeToCompletedAdventures($scoutID:ID!){
CompletedAdventure(filter: {
mutation_in: [UPDATED, CREATED, DELETED]
node: {
scout: {
id: $scoutID
}
}
}){
mutation
node {
id
signer { id }
adventure { id }
}
}
}
`,
variables: {
scoutID: params.scoutID
},
updateQuery: (prev, {subscriptionData}) => {
console.log("SubscriptionData: ", subscriptionData);
if(!subscriptionData.data) {
return prev;
}
let updatedAdventures;
const updatedID = subscriptionData.node.id;
const oldAdventures = prev.completedAdventures;
if(subscriptionData.mutation === "DELETE") {
updatedAdventures = oldAdventures.filter(adventure => (
adventure.id !== updatedID
));
} else {
updatedAdventures = [...oldAdventures];
let index = oldAdventures.findIndex(adventure => (
adventure.id === updatedID
));
if(index === -1) index = updatedAdventures.length;
updatedAdventures[index] = subscriptionData;
}
return Object.assign({}, prev, {
completedAdventures: updatedAdventures
});
}
});
};
return {
allAdventures: allAdventures || [],
completedAdventures: completedAdventures || [],
subscribeToAdventures,
...ownProps ...ownProps
} : {...ownProps}) };
}
}); });

View file

@ -5,29 +5,57 @@ export default graphql(gql`
Scout(id: $scoutID) { Scout(id: $scoutID) {
displayName displayName
advancementDeadline advancementDeadline
completedAdventures {
id
name
}
completedAchievements {
id
number
letter
}
} }
} }
`,{ `,{
options : ({scoutID}) => ({variables: {scoutID}}), options : ({scoutID}) => ({variables: {scoutID}}),
props: ({ ownProps, data }) => ( name: 'scoutData',
data.Scout ? { props: ({ ownProps, data, scoutData }) => {
const subscribeToData = params => {
return scoutData.subscribeToMore({
document: gql`
subscription subscribeToScoutData($scoutID:ID!){
Scout(filter: {
mutation_in: [UPDATED]
node: {
id: $scoutID
}
}) {
mutation
node {
displayName
advancementDeadline
}
}
}
`,
variables: {
scoutID: params.scoutID
},
updateQuery: (prev, {subscriptionData}) => {
if(!subscriptionData.data) {
console.log('no data!');
return prev;
}
console.log('data! : ', prev, ':', subscriptionData);
return Object.assign({}, prev, {
Scout: subscriptionData.data.Scout.node
});
}
});
};
return scoutData.Scout ? {
scoutID: ownProps.scoutID, scoutID: ownProps.scoutID,
displayName: data.Scout.displayName, displayName: scoutData.Scout.displayName,
advancementDeadline: data.Scout.advancementDeadline, advancementDeadline: scoutData.Scout.advancementDeadline,
completedAdventures: data.Scout.completedAdventures, subscribeToData,
completedAchievements: data.Scout.completedAchievements ...ownProps
} : { } : {
scoutID: ownProps.scoutID scoutID: ownProps.scoutID,
subscribeToData,
...ownProps
} }
) }
}); });