Permalink
Browse files

Connected meeting creation and deletion.

  • Loading branch information...
dblock committed Jul 9, 2018
1 parent b79e65e commit f253e488b754f77df9ff050b7bd56ef7ed92a3b3
@@ -3,8 +3,9 @@ import { Alert, StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import moment from 'moment';
import twix from 'twix';
import Icon from 'react-native-vector-icons/Ionicons';
import { createFragmentContainer, graphql } from 'react-relay';

export default class Meeting extends React.Component {
class Meeting extends React.Component {
deleteItem() {
Alert.alert(
'Delete Meeting',
@@ -19,13 +20,17 @@ export default class Meeting extends React.Component {

render() {
return (
<View key={this.props.keyval} style={styles.meeting}>
<View key={this.props.meeting.id} style={styles.meeting}>
<Text style={styles.meetingText}>{
moment(this.props.val.startDateTime).format('dddd, MMMM Do, YYYY h:mm A')
this.props.meeting.title
}</Text>

<Text style={styles.meetingText}>{
moment(this.props.val.endDateTime).twix(this.props.val.startDateTime).humanizeLength()
moment(this.props.meeting.started).format('dddd, MMMM Do, YYYY h:mm A')
}</Text>

<Text style={styles.meetingText}>{
moment(this.props.meeting.finished).twix(this.props.meeting.started).humanizeLength()
}</Text>

<View style={ styles.deleteMeetingButton }>
@@ -63,3 +68,12 @@ const styles = StyleSheet.create({
color: 'white'
}
});

export default createFragmentContainer(Meeting, graphql`
fragment Meeting_meeting on Meeting {
id
title
started
finished
}
`)
@@ -1,19 +1,38 @@
import React from 'react';
import { View, Text, StyleSheet, ScrollView } from 'react-native';
import Meeting from './Meeting';
import { createFragmentContainer, graphql } from 'react-relay';
import DeleteMeetingMutation from '../mutations/DeleteMeetingMutation';
import environment from '../Environment'
import localStorage from 'react-native-sync-localstorage';

export default class Meetings extends React.Component {
state = {
meetings: []
class Meetings extends React.Component {
componentWillMount() {
localStorage.getAllFromLocalStorage().then(() => {
this.setState({
user: { id: localStorage.getItem('@33minutes:user/id') }
});
})
}

removeMeetingByKey(key) {

removeMeetingById(id) {
DeleteMeetingMutation.commit(this.state.user.id, {
environment,
input: {
id: id
}
}).then(response => {

}).catch(error => {
alert(error.message);
});
}

render() {
let meetings = this.state.meetings.map((val, key) => {
return <Meeting key={key} keyval={key} val={val} deleteMethod={ () => this.removeMeetingByKey(key) } />
let meetings = this.props.user.meetings.edges.map(({node}) => {
if (node) {
return <Meeting key={node.__id} meeting={node} deleteMethod={ () => this.removeMeetingById(node.__id) } />
}
})

if (meetings.length == 0) {
@@ -37,3 +56,15 @@ const styles = StyleSheet.create({
alignItems: 'center',
}
});

export default createFragmentContainer(Meetings, graphql`
fragment Meetings_user on User {
meetings(last: 10) @connection(key: "Meetings_meetings", filters: []) {
edges {
node {
...Meeting_meeting
}
}
}
}
`)
@@ -9,17 +9,31 @@ const mutation = graphql`
title
started
finished
},
meetingEdge {
node {
id
}
}
}
}
`

function commit({ environment, input }) {
function commit(userId, { environment, input }) {
const variables = { input }

return commitMutation(environment, {
mutation,
variables
variables,
configs: [{
type: 'RANGE_ADD',
parentID: userId,
connectionInfo: [{
key: 'Meetings_meetings',
rangeBehavior: 'append',
}],
edgeName: 'meetingEdge'
}]
})
}

@@ -0,0 +1,29 @@
import { graphql } from 'react-relay'
import commitMutation from 'relay-commit-mutation-promise'

const mutation = graphql`
mutation DeleteMeetingMutation($input: deleteMeetingInput!) {
deleteMeeting(input: $input) {
deletedId
}
}
`

function commit(userId, { environment, input }) {
const variables = { input }

return commitMutation(environment, {
mutation,
variables,
configs: [{
type: 'NODE_DELETE',
parentID: userId,
deletedIDFieldName: 'deletedId',
connectionName: 'Meetings_meetings'
}]
})
}

export default {
commit
}
@@ -11,6 +11,7 @@ momentDurationFormatSetup(moment);

import CreateMeetingMutation from '../mutations/CreateMeetingMutation';
import environment from '../Environment'
import localStorage from 'react-native-sync-localstorage';

export default class Record extends React.Component {
constructor(props) {
@@ -21,13 +22,21 @@ export default class Record extends React.Component {
}
}

componentWillMount() {
localStorage.getAllFromLocalStorage().then(() => {
this.setState({
user: { id: localStorage.getItem('@33minutes:user/id') }
});
})
}

startMeeting() {
this.setState({ isMeetingStarted: true, meetingStartedAt: new Date() })
}

stopMeeting() {
this.setState({ isMeetingStarted: false, meetingStartedAt: null })
CreateMeetingMutation.commit({
CreateMeetingMutation.commit(this.state.user.id, {
environment,
input: {
title: 'Untitled Meeting',
@@ -20,7 +20,8 @@ export default class SignIn extends Component {
componentWillMount() {
localStorage.getAllFromLocalStorage().then(() => {
this.setState({
email: localStorage.getItem('@33minutes:user/email')
email: localStorage.getItem('@33minutes:user/email'),
password: localStorage.getItem('@33minutes:user/password')
});
})
}
@@ -33,7 +34,9 @@ export default class SignIn extends Component {
password: this.state.password
}
}).then(response => {
localStorage.setItem('@33minutes:user/id', response.login.user.id);
localStorage.setItem('@33minutes:user/email', this.state.email);
localStorage.setItem('@33minutes:user/password', this.state.password);
this.props.navigation.navigate('SignedIn')
}).catch(error => {
this.setState({ message: error.message });
@@ -1,15 +1,41 @@
import React, { Component } from 'react';
import { SafeAreaView, StyleSheet } from 'react-native';
import { Text, View, SafeAreaView, StyleSheet } from 'react-native';
import Meetings from '../components/Meetings'
import Icon from 'react-native-vector-icons/Ionicons';
import Actions from '../components/Actions'
import Actions from '../components/Actions';
import environment from '../Environment';
import { graphql, QueryRenderer } from 'react-relay';

export default class You extends Component {
render() {
return (
<SafeAreaView style={styles.container}>
<Meetings />
<Actions />
<QueryRenderer
environment={environment}
query={graphql`
query YouQuery {
user {
id
...Meetings_user
}
}
`}
render={({error, props}) => {
if (error) {
return <Text>Error!</Text>;
}
if (!props) {
return <Text>Loading...</Text>;
}
return (
<View>
<Text>Meetings for user { props.user.id }</Text>
<Meetings user={ props.user } />
<Actions />
</View>
);
}}>
</QueryRenderer>
</SafeAreaView>
)
}
@@ -39,6 +39,7 @@ type MeetingEdge {
type Mutation {
createMeeting(input: createMeetingInput!): createMeetingPayload
createUser(input: createUserInput!): createUserPayload
deleteMeeting(input: deleteMeetingInput!): deleteMeetingPayload
login(input: loginInput!): loginPayload
logout(input: logoutInput!): logoutPayload
}
@@ -109,6 +110,8 @@ type createMeetingPayload {
# A unique identifier for the client performing the mutation.
clientMutationId: String
meeting: Meeting
meetingEdge: MeetingEdge
meetingsConnection: MeetingConnection
}

# Autogenerated input type of createUser
@@ -127,6 +130,20 @@ type createUserPayload {
user: User
}

# Autogenerated input type of deleteMeeting
input deleteMeetingInput {
# A unique identifier for the client performing the mutation.
clientMutationId: String
id: ID!
}

# Autogenerated return type of deleteMeeting
type deleteMeetingPayload {
# A unique identifier for the client performing the mutation.
clientMutationId: String
deletedId: ID!
}

# Autogenerated input type of login
input loginInput {
# A unique identifier for the client performing the mutation.

0 comments on commit f253e48

Please sign in to comment.