Skip to content

Commit

Permalink
Merge pull request #2116 from gdg-x/realtime
Browse files Browse the repository at this point in the history
Update data in realtime
  • Loading branch information
abraham authored Jan 4, 2022
2 parents 70c157c + a5e9caa commit 1a249b5
Show file tree
Hide file tree
Showing 26 changed files with 419 additions and 237 deletions.
25 changes: 24 additions & 1 deletion firestore.indexes.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
{
"indexes": [],
"fieldOverrides": []
"fieldOverrides": [
{
"collectionGroup": "members",
"fieldPath": "name",
"indexes": [
{
"order": "ASCENDING",
"queryScope": "COLLECTION"
},
{
"order": "DESCENDING",
"queryScope": "COLLECTION"
},
{
"arrayConfig": "CONTAINS",
"queryScope": "COLLECTION"
},
{
"order": "ASCENDING",
"queryScope": "COLLECTION_GROUP"
}
]
}
]
}
12 changes: 12 additions & 0 deletions firestore.rules
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ service cloud.firestore {
// Disallow writes
allow write: if false;

// TODO: remove
match /members/{memberId} {
// Applies to single document read requests
allow get;
Expand All @@ -198,6 +199,17 @@ service cloud.firestore {
}
}

match /{path=**}/members/{memberId} {
// Applies to single document read requests
allow get;

// Applies to queries and collection read requests
allow list;

// Disallow writes
allow write: if false;
}

match /tickets/{ticket} {
// Applies to single document read requests
allow get;
Expand Down
4 changes: 2 additions & 2 deletions src/models/member.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Social } from './social';
import { Id } from './types';
import { ParentId } from './types';

export interface MemberData {
name: string;
Expand All @@ -10,4 +10,4 @@ export interface MemberData {
title: string;
}

export type Member = Id & MemberData;
export type Member = ParentId & MemberData;
4 changes: 4 additions & 0 deletions src/models/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export interface Id {
id: string;
}

export type ParentId = Id & {
parentId: string;
};
43 changes: 18 additions & 25 deletions src/pages/team-page.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Failure, Initialized, Pending } from '@abraham/remotedata';
import { Failure, Pending } from '@abraham/remotedata';
import { computed, customElement, property } from '@polymer/decorators';
import '@polymer/iron-icon';
import '@polymer/marked-element';
Expand All @@ -7,25 +7,12 @@ import { html, PolymerElement } from '@polymer/polymer';
import 'plastic-image';
import '../elements/shared-styles';
import { ReduxMixin } from '../mixins/redux-mixin';
import { RootState, store } from '../store';
import { fetchTeams } from '../store/teams/actions';
import { initialTeamsState } from '../store/teams/state';
import { RootState } from '../store';
import { selectTeamsAndMembers } from '../store/teams-members/selectors';
import { initialTeamsMembersState } from '../store/teams-members/state';

@customElement('team-page')
export class TeamPage extends ReduxMixin(PolymerElement) {
@property({ type: Object })
teams = initialTeamsState;

@computed('teams')
get pending() {
return this.teams instanceof Pending;
}

@computed('teams')
get failure() {
return this.teams instanceof Failure;
}

static get template() {
return html`
<style include="shared-styles flex flex-alignment">
Expand Down Expand Up @@ -158,7 +145,7 @@ export class TeamPage extends ReduxMixin(PolymerElement) {
<p>Error loading teams.</p>
</template>
<template is="dom-repeat" items="[[teams.data]]" as="team">
<template is="dom-repeat" items="[[teamsMembers.data]]" as="team">
<div class="team-title">[[team.title]]</div>
<div class="team-block">
Expand Down Expand Up @@ -198,14 +185,20 @@ export class TeamPage extends ReduxMixin(PolymerElement) {
`;
}

override stateChanged(state: RootState) {
this.teams = state.teams;
@property({ type: Object })
teamsMembers = initialTeamsMembersState;

@computed('teamsMembers')
get pending() {
return this.teamsMembers instanceof Pending;
}

override connectedCallback() {
super.connectedCallback();
if (this.teams instanceof Initialized) {
store.dispatch(fetchTeams);
}
@computed('teamsMembers')
get failure() {
return this.teamsMembers instanceof Failure;
}

override stateChanged(state: RootState) {
this.teamsMembers = selectTeamsAndMembers(state);
}
}
36 changes: 16 additions & 20 deletions src/store/blog/actions.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,31 @@
import { collection, getDocs, orderBy, query } from 'firebase/firestore';
import { Initialized, Success } from '@abraham/remotedata';
import { orderBy } from 'firebase/firestore';
import { Dispatch } from 'redux';
import { db } from '../../firebase';
import { Post } from '../../models/post';
import { mergeDataAndId } from '../../utils/firestore';
import { subscribeToCollection, Subscription } from '../../utils/firestore';
import {
BlogActions,
FETCH_BLOG_LIST,
FETCH_BLOG_LIST_FAILURE,
FETCH_BLOG_LIST_SUCCESS,
} from './types';

const getPosts = async (): Promise<Post[]> => {
const { docs } = await getDocs(query(collection(db, 'blog'), orderBy('published', 'desc')));
let subscription: Subscription = new Initialized();

return docs.map<Post>(mergeDataAndId);
export const unsubscribe = () => {
if (subscription instanceof Success) {
subscription.data();
}
};

export const fetchBlogPosts = async (dispatch: Dispatch<BlogActions>) => {
dispatch({
type: FETCH_BLOG_LIST,
});

try {
dispatch({
type: FETCH_BLOG_LIST_SUCCESS,
payload: await getPosts(),
});
} catch (error) {
dispatch({
type: FETCH_BLOG_LIST_FAILURE,
payload: error,
});
if (subscription instanceof Initialized) {
subscription = subscribeToCollection(
'blog',
() => dispatch({ type: FETCH_BLOG_LIST }),
(payload: Post[]) => dispatch({ type: FETCH_BLOG_LIST_SUCCESS, payload }),
(payload: Error) => dispatch({ type: FETCH_BLOG_LIST_FAILURE, payload }),
orderBy('published', 'desc')
);
}
};
36 changes: 16 additions & 20 deletions src/store/gallery/actions.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,31 @@
import { collection, getDocs, query } from 'firebase/firestore';
import { Initialized, Success } from '@abraham/remotedata';
import { orderBy } from 'firebase/firestore';
import { Dispatch } from 'redux';
import { db } from '../../firebase';
import { Photo } from '../../models/photo';
import { mergeDataAndId } from '../../utils/firestore';
import { subscribeToCollection, Subscription } from '../../utils/firestore';
import {
FETCH_GALLERY,
FETCH_GALLERY_FAILURE,
FETCH_GALLERY_SUCCESS,
GalleryActions,
} from './types';

const getGalleries = async (): Promise<Photo[]> => {
const { docs } = await getDocs(query(collection(db, 'gallery')));
let subscription: Subscription = new Initialized();

return docs.map<Photo>(mergeDataAndId);
export const unsubscribe = () => {
if (subscription instanceof Success) {
subscription.data();
}
};

export const fetchGallery = async (dispatch: Dispatch<GalleryActions>) => {
dispatch({
type: FETCH_GALLERY,
});

try {
dispatch({
type: FETCH_GALLERY_SUCCESS,
payload: await getGalleries(),
});
} catch (error) {
dispatch({
type: FETCH_GALLERY_FAILURE,
payload: error,
});
if (subscription instanceof Initialized) {
subscription = subscribeToCollection(
'gallery',
() => dispatch({ type: FETCH_GALLERY }),
(payload: Photo[]) => dispatch({ type: FETCH_GALLERY_SUCCESS, payload }),
(payload: Error) => dispatch({ type: FETCH_GALLERY_FAILURE, payload }),
orderBy('order')
);
}
};
4 changes: 3 additions & 1 deletion src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { featuredSessionsReducer } from './featured-sessions/reducers';
import { feedbackReducer } from './feedback/reducers';
import { filtersReducer } from './filters/reducers';
import { galleryReducer } from './gallery/reducers';
import { membersReducer } from './members/reducers';
import { notificationsReducer } from './notifications/reducers';
import { partnersReducer } from './partners/reducers';
import { potentialPartnersReducer } from './potential-partners/reducers';
Expand All @@ -32,8 +33,9 @@ export const store = configureStore({
dialogs: dialogsReducer,
featuredSessions: featuredSessionsReducer,
feedback: feedbackReducer,
gallery: galleryReducer,
filters: filtersReducer,
gallery: galleryReducer,
members: membersReducer,
notifications: notificationsReducer,
partners: partnersReducer,
potentialPartners: potentialPartnersReducer,
Expand Down
29 changes: 29 additions & 0 deletions src/store/members/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Initialized, Success } from '@abraham/remotedata';
import { Dispatch } from 'redux';
import { Member } from '../../models/member';
import { subscribeToCollectionGroup, Subscription } from '../../utils/firestore';
import {
FETCH_MEMBERS,
FETCH_MEMBERS_FAILURE,
FETCH_MEMBERS_SUCCESS,
MembersActions,
} from './types';

let subscription: Subscription = new Initialized();

export const unsubscribe = () => {
if (subscription instanceof Success) {
subscription.data();
}
};

export const fetchMembers = async (dispatch: Dispatch<MembersActions>) => {
if (subscription instanceof Initialized) {
subscription = subscribeToCollectionGroup(
'members',
() => dispatch({ type: FETCH_MEMBERS }),
(payload: Member[]) => dispatch({ type: FETCH_MEMBERS_SUCCESS, payload }),
(payload: Error) => dispatch({ type: FETCH_MEMBERS_FAILURE, payload })
);
}
};
27 changes: 27 additions & 0 deletions src/store/members/reducers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Failure, Pending, Success } from '@abraham/remotedata';
import { initialMembersState, MembersState } from './state';
import {
FETCH_MEMBERS,
FETCH_MEMBERS_FAILURE,
FETCH_MEMBERS_SUCCESS,
MembersActions,
} from './types';

export const membersReducer = (
state = initialMembersState,
action: MembersActions
): MembersState => {
switch (action.type) {
case FETCH_MEMBERS:
return new Pending();

case FETCH_MEMBERS_FAILURE:
return new Failure(action.payload);

case FETCH_MEMBERS_SUCCESS:
return new Success(action.payload);

default:
return state;
}
};
13 changes: 13 additions & 0 deletions src/store/members/selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Initialized, Pending } from '@abraham/remotedata';
import { RootState, store } from '..';
import { fetchMembers } from './actions';
import { MembersState } from './state';

export const selectMembers = (state: RootState): MembersState => {
if (state.members instanceof Initialized) {
store.dispatch(fetchMembers);
return new Pending();
} else {
return state.members;
}
};
5 changes: 5 additions & 0 deletions src/store/members/state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Initialized, RemoteData } from '@abraham/remotedata';
import { Member } from '../../models/member';

export type MembersState = RemoteData<Error, Member[]>;
export const initialMembersState: MembersState = new Initialized();
24 changes: 24 additions & 0 deletions src/store/members/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Member } from '../../models/member';

export const FETCH_MEMBERS = 'FETCH_MEMBERS';
export const FETCH_MEMBERS_FAILURE = 'FETCH_MEMBERS_FAILURE';
export const FETCH_MEMBERS_SUCCESS = 'FETCH_MEMBERS_SUCCESS';

interface FetchMembersAction {
type: typeof FETCH_MEMBERS;
}

interface FetchMembersFailureAction {
type: typeof FETCH_MEMBERS_FAILURE;
payload: Error;
}

interface FetchMembersSuccessAction {
type: typeof FETCH_MEMBERS_SUCCESS;
payload: Member[];
}

export type MembersActions =
| FetchMembersAction
| FetchMembersFailureAction
| FetchMembersSuccessAction;
Loading

0 comments on commit 1a249b5

Please sign in to comment.