// License: LGPL-3.0-or-later const R = require('ramda') const h = require('snabbdom/h') const flyd = require('flyd') const url$ = require('flyd-url') const render = require('ff-core/render') const filter = require('flyd/module/filter') const snabbdom = require('snabbdom') const mergeAll = require('flyd/module/mergeall') const sampleOn = require('flyd/module/sampleon') const queryString = require('query-string') const notification = require('ff-core/notification') const request = require('../../../../common/request') const confirm = require('../../../../components/confirmation-modal') const actions = require('./supporter-actions') const activities = require('./supporter-activities') const offsiteDonationForm = require('./offsite-donation-form') const supporterNoteForm = require('./supporter-note-form') const flatMap = R.curry(require('flyd/module/flatmap')) const init = _ => { var state = { clickComposing$: flyd.stream() , threadId$: flyd.stream() , newNote$: flyd.stream() , editNote$: flyd.stream() , deleteNote$: flyd.stream() , newDonation$: flyd.stream() } const supporterID$ = R.compose( filter(Boolean ) , flyd.map(url => queryString.parse(url.search).sid) )(url$) state.pathPrefix$ = flyd.map(constructPathPrefix, supporterID$) const supporterPath$ = flyd.map(id => `/nonprofits/${app.nonprofit_id}/supporters/${id}`, supporterID$) const supporterResp$ = R.compose( flyd.map(x => x.body.data) , filter(x => x.status === 200) , flatMap(path => request({method: 'get', path}).load) )(supporterPath$) state.supporter$ = flyd.merge(supporterResp$, flyd.stream({})) state.offsiteDonationForm = offsiteDonationForm.init(state) state.editNoteData$ = flyd.merge( flyd.map(R.always({}), state.newNote$) , flyd.map(d => ({id: d.attachment_id, content: d.json_data.content}), state.editNote$)) const deleteNoteId$ = flyd.map(d => d.attachment_id, state.deleteNote$) state.noteAjaxMethod$ = mergeAll([ flyd.map(R.always('post'), state.newNote$) , flyd.map(R.always('put'), state.editNote$) ]) state.supporterNoteForm = supporterNoteForm.init(state) state.confirmDelete = confirm.init(deleteNoteId$) const deleteNoteResp$ = flatMap(ajaxDeleteNote(supporterPath$, deleteNoteId$), state.confirmDelete.confirm$) // All streams that we want to trigger a refresh of the supporter timeline const fetchActivitiesWith$ = mergeAll([ state.pathPrefix$ , state.offsiteDonationForm.saved$ , state.supporterNoteForm.saved$ , deleteNoteResp$ ]) // Stream of activities data, using the pathPrefix$ stream, triggered by fetchActivitiesWith$ state.activities$ = R.compose( R.curryN(2, flatMap)(getActivities) , sampleOn(R.__, state.pathPrefix$) )(fetchActivitiesWith$) state.activities = activities.init(state) state.modalID$ = mergeAll([ , flyd.map(()=> 'newSupporterNoteModal', state.editNoteData$) , flyd.map(()=> null, state.supporterNoteForm.saved$) ]) const message$ = mergeAll([ , flyd.map(()=> 'Successfully created a new offsite contribution', state.offsiteDonationForm.saved$) , flyd.map(()=> `Successfully ${noteMsg(state.noteAjaxMethod$)} supporter note`, state.supporterNoteForm.saved$) , flyd.map(()=> 'Successfully deleted supporter note', deleteNoteResp$) ]) state.notification = notification.init({message$}) window.state = state return state } const ajaxDeleteNote = (pathPrefix$, id$) => () => { const path = `${pathPrefix$()}/supporter_notes/${id$()}` return request({ method: 'delete' , path }).load } const noteMsg = method$ => { if(method$() === 'put') return 'edited' if(method$() === 'post') return 'created a new' } const getActivities = path => flyd.map(req => req.body, request({path: path + 'activities', method: 'get'}).load) const constructPathPrefix = sid => `/nonprofits/${app.nonprofit_id}/supporters/${sid}/` const view = state => { return h('div', [ actions.view(state) , activities.view(state) , notification.view(state.notification) , offsiteDonationForm.view(R.merge(state.offsiteDonationForm)) , supporterNoteForm.view(R.merge(state.supporterNoteForm, {modalID$: state.modalID$})) , confirm.view(state.confirmDelete, 'Are you sure you want to delete this note?') ]) } var container = document.querySelector('#js-sidePanel') // -- Render to the page // render takes state, view function, patch function, and DOM container const patch = snabbdom.init([ require('snabbdom/modules/eventlisteners') , require('snabbdom/modules/class') , require('snabbdom/modules/props') , require('snabbdom/modules/attributes') , require('snabbdom/modules/style') ]) render({ patch, container , view, state: init() })