"Mark Prayed" works

This commit is contained in:
Daniel J. Summers 2017-09-22 22:30:00 -05:00
parent c703d717d8
commit 181dc5ea63
9 changed files with 127 additions and 87 deletions

View File

@ -32,59 +32,16 @@ const requestNotFound = {
export default function (pool) { export default function (pool) {
return { return {
/** /**
* Get the current requests for a user (i.e., their complete current journal) * Add a history entry for this request
* @param {string} userId The Id of the user * @param {string} requestId The Id of the request
* @return The requests that make up the current journal * @param {string} status The status for this history entry
* @param {string} updateText The updated text for the request (pass blank if no update)
*/ */
journal: async userId => (await pool.query(`${journalSql} ORDER BY "asOf" DESC`, [ userId ])).rows, addHistory: async (requestId, status, updateText) => {
const asOf = Date.now()
/** await pool.query(`
* Get the least-recently-updated prayer request for the given user INSERT INTO mpj.history ("requestId", "asOf", "status", "text") VALUES ($1, $2, $3, NULLIF($4, ''))`,
* @param {string} userId The Id of the current user [ requestId, asOf, status, updateText ])
* @return The least-recently-updated request for the given user
*/
oldest: async userId => (await pool.query(`${journalSql} ORDER BY "asOf" LIMIT 1`, [ userId ])).rows[0],
/**
* Get the "current" version of a request by its Id
* @param {string} requestId The Id of the request to retrieve
* @param {string} userId The Id of the user to which the request belongs
* @return The request, or a request-like object indicating that the request was not found
*/
byId: async (userId, requestId) => {
const reqs = await pool.query(`${currentRequestSql}
WHERE "requestId" = $1
AND "userId" = $2
GROUP BY request."requestId"`,
[ requestId, userId ])
return (0 < req.rowCount) ? reqs.rows[0] : requestNotFound
},
/**
* Get a prayer request, including its full history, by its Id
* @param {string} userId The Id of the user to which the request belongs
* @param {string} requestId The Id of the request to retrieve
* @return The request, or a request-like object indicating that the request was not found
*/
fullById: async (userId, requestId) => {
const reqResults = await pool.query(`
SELECT "requestId", "enteredOn"
FROM mpj.request
WHERE "requestId" = $1
AND "userId" = $2`,
[ requestId, userId ])
if (0 === reqResults.rowCount) {
return requestNotFound
}
const req = reqResults.rows[0]
const history = await pool.query(`
SELECT "asOf", "status", COALESCE("text", '') AS "text"
FROM mpj.history
WHERE "requestId" = $1
ORDER BY "asOf"`,
[ requestId ])
req.history = history.rows
return req
}, },
/** /**
@ -121,17 +78,61 @@ export default function (pool) {
}, },
/** /**
* Add a history entry for this request * Get the "current" version of a request by its Id
* @param {string} requestId The Id of the request * @param {string} requestId The Id of the request to retrieve
* @param {string} status The status for this history entry * @param {string} userId The Id of the user to which the request belongs
* @param {string} updateText The updated text for the request (pass blank if no update) * @return The request, or a request-like object indicating that the request was not found
*/ */
addHistory: async (requestId, status, updateText) => { byId: async (userId, requestId) => {
const asOf = Date.now() const reqs = await pool.query(`${currentRequestSql}
await pool.query(` WHERE "requestId" = $1
INSERT INTO mpj.history ("requestId", "asOf", "status", "text") VALUES ($1, $2, $3, NULLIF($4, ''))`, AND "userId" = $2
[ requestId, asOf, status, updateText ]) GROUP BY request."requestId"`,
} [ requestId, userId ])
return (0 < reqs.rowCount) ? reqs.rows[0] : requestNotFound
},
/**
* Get a prayer request, including its full history, by its Id
* @param {string} userId The Id of the user to which the request belongs
* @param {string} requestId The Id of the request to retrieve
* @return The request, or a request-like object indicating that the request was not found
*/
fullById: async (userId, requestId) => {
const reqResults = await pool.query(`
SELECT "requestId", "enteredOn"
FROM mpj.request
WHERE "requestId" = $1
AND "userId" = $2`,
[ requestId, userId ])
if (0 === reqResults.rowCount) {
return requestNotFound
}
const req = reqResults.rows[0]
const history = await pool.query(`
SELECT "asOf", "status", COALESCE("text", '') AS "text"
FROM mpj.history
WHERE "requestId" = $1
ORDER BY "asOf"`,
[ requestId ])
req.history = history.rows
return req
},
/**
* Get the current requests for a user (i.e., their complete current journal)
* @param {string} userId The Id of the user
* @return The requests that make up the current journal
*/
journal: async userId => (await pool.query(`${journalSql} ORDER BY "asOf" DESC`, [ userId ])).rows,
/**
* Get the least-recently-updated prayer request for the given user
* @param {string} userId The Id of the current user
* @return The least-recently-updated request for the given user
*/
oldest: async userId => (await pool.query(`${journalSql} ORDER BY "asOf" LIMIT 1`, [ userId ])).rows[0]
} }
} }

View File

@ -16,15 +16,15 @@ export default function (checkJwt) {
// Add a request history entry (prayed, updated, answered, etc.) // Add a request history entry (prayed, updated, answered, etc.)
.post('/:id/history', checkJwt, async (ctx, next) => { .post('/:id/history', checkJwt, async (ctx, next) => {
const body = ctx.request.body const body = ctx.request.body
const result = await db.request.addHistory(ctx.params.id, body.status, body.updateText) await db.request.addHistory(ctx.params.id, body.status, body.updateText)
ctx.status(('Not Found' === result.text) ? 404 : 204) ctx.response.status = 204
await next() await next()
}) })
// Get a journal-style request by its Id // Get a journal-style request by its Id
.get('/:id', checkJwt, async (ctx, next) => { .get('/:id', checkJwt, async (ctx, next) => {
const req = await db.request.byId(ctx.state.user.sub, ctx.params.id) const req = await db.request.byId(ctx.state.user.sub, ctx.params.id)
if ('Not Found' === req.text) { if ('Not Found' === req.text) {
ctx.status(404) ctx.response.status = 404
} else { } else {
ctx.body = req ctx.body = req
} }
@ -34,7 +34,7 @@ export default function (checkJwt) {
.get('/:id/full', checkJwt, async (ctx, next) => { .get('/:id/full', checkJwt, async (ctx, next) => {
const req = await db.request.fullById(ctx.state.user.sub, ctx.params.id) const req = await db.request.fullById(ctx.state.user.sub, ctx.params.id)
if ('Not Found' === req.text) { if ('Not Found' === req.text) {
ctx.status(404) ctx.response.status = 404
} else { } else {
ctx.body = req ctx.body = req
} }

View File

@ -35,6 +35,11 @@ export default {
* Mark a prayer request as having been prayed * Mark a prayer request as having been prayed
* @param {string} requestId The Id of the request * @param {string} requestId The Id of the request
*/ */
markPrayed: requestId => http.post('request/${requestId}/history', { status: 'Prayed', updateText: '' }) markPrayed: requestId => http.post(`request/${requestId}/history`, { status: 'Prayed', updateText: '' }),
/**
* Get a prayer request
*/
getPrayerRequest: requestId => http.get(`request/${requestId}`)
} }

View File

@ -9,7 +9,7 @@
el-col(:span='4'): strong Actions el-col(:span='4'): strong Actions
el-col(:span='16'): strong Request el-col(:span='16'): strong Request
el-col(:span='4'): strong As Of el-col(:span='4'): strong As Of
request-list-item(v-for="request in journal" v-bind:request="request" v-bind:key="request.requestId") request-list-item(v-for="request in journal" :request="request" :key="request.requestId")
</template> </template>
<script> <script>

View File

@ -28,7 +28,10 @@ export default {
}, },
methods: { methods: {
saveRequest: async function () { saveRequest: async function () {
await this.$store.dispatch(actions.ADD_REQUEST, this.form.requestText) await this.$store.dispatch(actions.ADD_REQUEST, {
progress: this.$Progress,
requestText: this.form.requestText
})
this.showNewVisible = false this.showNewVisible = false
} }
} }

View File

@ -10,8 +10,12 @@
</template> </template>
<script> <script>
'use strict'
import moment from 'moment' import moment from 'moment'
import actions from '@/store/action-types'
export default { export default {
name: 'request-list-item', name: 'request-list-item',
props: ['request'], props: ['request'],
@ -20,8 +24,10 @@ export default {
}, },
methods: { methods: {
markPrayed () { markPrayed () {
alert(`Marking ${this.request.requestId} prayed`) this.$store.dispatch(actions.MARK_PRAYED, {
// TODO: write function progress: this.$Progress,
requestId: this.request.requestId
})
} }
}, },
computed: { computed: {

View File

@ -4,5 +4,7 @@ export default {
/** Action to add a prayer request (pass request text) */ /** Action to add a prayer request (pass request text) */
ADD_REQUEST: 'add-request', ADD_REQUEST: 'add-request',
/** Action to load the user's prayer journal */ /** Action to load the user's prayer journal */
LOAD_JOURNAL: 'load-journal' LOAD_JOURNAL: 'load-journal',
/** Action to mark a request as prayed */
MARK_PRAYED: 'mark-prayed'
} }

View File

@ -38,17 +38,6 @@ export default new Vuex.Store({
isLoadingJournal: false isLoadingJournal: false
}, },
mutations: { mutations: {
[mutations.USER_LOGGED_ON] (state, user) {
localStorage.setItem('user_profile', JSON.stringify(user))
state.user = user
api.setBearer(localStorage.getItem('id_token'))
state.isAuthenticated = true
},
[mutations.USER_LOGGED_OFF] (state) {
state.user = {}
api.removeBearer()
state.isAuthenticated = false
},
[mutations.LOADING_JOURNAL] (state, flag) { [mutations.LOADING_JOURNAL] (state, flag) {
state.isLoadingJournal = flag state.isLoadingJournal = flag
}, },
@ -57,9 +46,36 @@ export default new Vuex.Store({
}, },
[mutations.REQUEST_ADDED] (state, newRequest) { [mutations.REQUEST_ADDED] (state, newRequest) {
state.journal.unshift(newRequest) state.journal.unshift(newRequest)
},
[mutations.REQUEST_UPDATED] (state, request) {
let jrnl = state.journal.filter(it => it.requestId !== request.requestId)
jrnl.unshift(request)
state.journal = jrnl
},
[mutations.USER_LOGGED_OFF] (state) {
state.user = {}
api.removeBearer()
state.isAuthenticated = false
},
[mutations.USER_LOGGED_ON] (state, user) {
localStorage.setItem('user_profile', JSON.stringify(user))
state.user = user
api.setBearer(localStorage.getItem('id_token'))
state.isAuthenticated = true
} }
}, },
actions: { actions: {
async [actions.ADD_REQUEST] ({ commit }, { progress, requestText }) {
progress.start()
try {
const newRequest = await api.addRequest(requestText)
commit(mutations.REQUEST_ADDED, newRequest.data)
progress.finish()
} catch (err) {
logError(err)
progress.fail()
}
},
async [actions.LOAD_JOURNAL] ({ commit }, progress) { async [actions.LOAD_JOURNAL] ({ commit }, progress) {
commit(mutations.LOADED_JOURNAL, {}) commit(mutations.LOADED_JOURNAL, {})
progress.start() progress.start()
@ -68,19 +84,24 @@ export default new Vuex.Store({
try { try {
const jrnl = await api.journal() const jrnl = await api.journal()
commit(mutations.LOADED_JOURNAL, jrnl.data) commit(mutations.LOADED_JOURNAL, jrnl.data)
progress.finish()
} catch (err) { } catch (err) {
logError(err) logError(err)
progress.fail()
} finally { } finally {
commit(mutations.LOADING_JOURNAL, false) commit(mutations.LOADING_JOURNAL, false)
progress.finish()
} }
}, },
async [actions.ADD_REQUEST] ({ commit }, requestText) { async [actions.MARK_PRAYED] ({ commit }, { progress, requestId }) {
try { try {
const newRequest = await api.addRequest(requestText) progress.start()
commit(mutations.REQUEST_ADDED, newRequest.data) await api.markPrayed(requestId)
const request = await api.getPrayerRequest(requestId)
commit(mutations.REQUEST_UPDATED, request.data)
progress.finish()
} catch (err) { } catch (err) {
logError(err) logError(err)
progress.fail()
} }
} }
}, },

View File

@ -7,6 +7,8 @@ export default {
LOADED_JOURNAL: 'journal-loaded', LOADED_JOURNAL: 'journal-loaded',
/** Mutation for adding a new prayer request (pass text) */ /** Mutation for adding a new prayer request (pass text) */
REQUEST_ADDED: 'request-added', REQUEST_ADDED: 'request-added',
/** Mutation to replace a prayer request at the top of the current journal */
REQUEST_UPDATED: 'request-updated',
/** Mutation for logging a user off */ /** Mutation for logging a user off */
USER_LOGGED_OFF: 'user-logged-off', USER_LOGGED_OFF: 'user-logged-off',
/** Mutation for logging a user on (pass user) */ /** Mutation for logging a user on (pass user) */