Subscriptions are now working and updating some parts of the view.
This commit is contained in:
parent
8687355932
commit
14ce6df7af
10 changed files with 430 additions and 127 deletions
|
@ -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">
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
13
src/containers/CompleteAchievement.js
Normal file
13
src/containers/CompleteAchievement.js
Normal 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
|
||||
}
|
||||
}
|
||||
`)
|
|
@ -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
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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})
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue