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 ScoutOverview from './components/ScoutOverview.js';
const ScoutView = ScoutOverviewCont(ScoutOverview);
class App extends Component {
render() {
const scoutID = getQueryParamByName("id", this.props.slug);
const ScoutView = ScoutOverviewCont(ScoutOverview);
return (
<div className="App">

View File

@ -1,5 +1,30 @@
import React from 'react';
import { gql, graphql } from 'react-apollo';
export default({id, number, description, additionalText}) => {
return <div>{number}</div>;
export default({
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}) => {
console.log("completed: ", completed);
if(!achievements) {
return <div>Loading...</div>
export default class AchievementList extends React.Component {
componentWillMount() {
this.unsubscribe = this.props.subscribeToAchievements({
scoutID: this.props.scoutID,
adventureID: this.props.adventureID
});
}
const list = [...achievements].sort((a, b) => {
if (a.number === b.number)
return a.letter > b.letter;
return a.number > b.number;
}).map(achievement => (
<Achievement key={achievement.id} {...achievement} />
));
return <div>
{list}
</div>
render() {
const {
allAchievements,
completedAchievements,
scoutID
} = 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();
}
}

View File

@ -1,15 +1,28 @@
import React from 'react'
import GetAchievements from "../containers/GetAchievementsForAdventure.js";
import AchievementList from "./AchievementList.js";
import GetAchievements from '../containers/GetAchievementsForAdventure.js';
import AchievementList from './AchievementList.js';
import {Card, CardHeader} from 'material-ui/Card';
export default ({id, name, number, isRequired, achievements,
completedAdventures, completedAchievements}) => {
const AchievementListComp = GetAchievements(AchievementList);
const AchievementListComp = GetAchievements(AchievementList);
return <div>
<div>{name}</div>
<AchievementListComp adventureID={id} completed={completedAchievements}/>
</div>
export default ({
id,
name,
number,
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 Adventure from './Adventure.js';
export default ({
allAdventures,
completedAdventures
}) => {
if(!allAdventures) {
return <div> Loading... </div>
export default class AdventureList extends React.Component {
componentWillMount() {
this.unsubscribe = this.props.subscribeToAdventures({
scoutID: this.props.scoutID
});
}
const sortedAdventures = [...allAdventures].sort((a,b) => (a.number > b.number));
render() {
const {
scoutID,
allAdventures,
completedAdventures
} = this.props;
console.log("completed!: ", completedAdventures);
const [
requiredAdventures,
optionalAdventures
] = splitFilter(sortedAdventures, a => a.required);
if(!allAdventures || !allAdventures.length) {
return <div> Loading... </div>
}
const requiredAdventureList = requiredAdventures.map(adventure => {
return <Adventure key={adventure.id} {...adventure} />;
});
const completedMap = completedAdventures.reduce((map, adv) => {
map[adv.adventure.id] = adv;
return map;
}, {});
const sortedAdventures = [...allAdventures].sort((a,b) => (a.number > b.number));
const optionalAdventureList = optionalAdventures.map(adventure => {
return <Adventure key={adventure.id} {...adventure} />;
});
const [
requiredAdventures,
optionalAdventures
] = splitFilter(sortedAdventures, a => a.required);
return <div>
<div>
{requiredAdventureList}
</div>
<div>
{
//optionalAdventureList
const requiredAdventureList = requiredAdventures.map(adventure => {
const props = {
key: adventure.id,
scoutID: scoutID,
completed: completedMap[adventure.id],
...adventure
}
</div>
</div>;
return <Adventure {...props} />;
});
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 AppBar from 'material-ui/AppBar';
export default ({
scoutID,
displayName,
advancementDeadline,
completedAdventures,
completedAchievements
}) => {
const appBarProps = {
title: displayName,
showMenuIconButton: false
const AdventureListComp = AllAdventures(AdventureList);
export default class ScoutOverview extends React.Component {
componentWillMount() {
this.unsubscribe = this.props.subscribeToData({
scoutID: this.props.scoutID
});
}
const AdventureListComp = AllAdventures(AdventureList);
console.log(displayName)
return (
<div>
<AppBar {...appBarProps} />
<AdventureListComp
{...{scoutID, completedAdventures, completedAchievements}}
/>
</div>
);
render() {
const {
scoutID,
displayName,
advancementDeadline,
} = this.props;
const appBarProps = {
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';
export default graphql(gql`
query GetAchievementsForAdventure($adventureID:ID!){
allAchievements(filter: {
adventure: {
id: $adventureID
query GetAchievementsForAdventure($adventureID:ID! $scoutID:ID!){
all: allAchievements(filter: {
adventure: {id: $adventureID}
}) {
id
number
letter
description
additionalText
}
completed: allCompletedAchievements(filter:{
scout: {id: $scoutID}
achievement: {
adventure: {id: $adventureID}
}
}) {
id,
number,
letter,
description,
additionalText
id
completedAt
achievement {
id
}
}
}
`,{
options: ({adventureID}) => {
return {
variables: {
adventureID
}
};
},
options: ({adventureID, scoutID}) => ({variables: { adventureID, scoutID }}),
props: ({ownProps, data}) => {
return data.allAchievements ? {
achievements: data.allAchievements,
...ownProps
} : {...ownProps}
const {
subscribeToMore,
all,
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';
export default graphql(gql`
query GetAllAdventures{
allAdventures {
name,
number,
required,
query GetAllAdventures($scoutID:ID!){
allAdventures: allAdventures {
name
number
required
id
}
completedAdventures: allCompletedAdventures(filter:{
scout: { id: $scoutID }
}) {
id
signer { id }
adventure { id }
}
}
`,{
props: ({ownProps, data}) => (
data.allAdventures ? {
allAdventures: data.allAdventures,
options: ({scoutID}) => ({variables: {scoutID}}),
props: ({ownProps, data}) => {
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})
};
}
});

View File

@ -5,29 +5,57 @@ export default graphql(gql`
Scout(id: $scoutID) {
displayName
advancementDeadline
completedAdventures {
id
name
}
completedAchievements {
id
number
letter
}
}
}
`,{
options : ({scoutID}) => ({variables: {scoutID}}),
props: ({ ownProps, data }) => (
data.Scout ? {
name: 'scoutData',
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,
displayName: data.Scout.displayName,
advancementDeadline: data.Scout.advancementDeadline,
completedAdventures: data.Scout.completedAdventures,
completedAchievements: data.Scout.completedAchievements
displayName: scoutData.Scout.displayName,
advancementDeadline: scoutData.Scout.advancementDeadline,
subscribeToData,
...ownProps
} : {
scoutID: ownProps.scoutID
scoutID: ownProps.scoutID,
subscribeToData,
...ownProps
}
)
}
});