Created
June 3, 2016 18:04
-
-
Save brownish/db88066ce5a1145c17fa1e2a440bba10 to your computer and use it in GitHub Desktop.
mobx store
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class State { | |
id = null; | |
@observable name; | |
@observable abbreviation; | |
@observable smithsonianCode; | |
@observable fipsCode; | |
@observable gnisCode; | |
@observable _counties = asMap([]); | |
@observable _cities = asMap([]); | |
@observable _sites = asMap([]); | |
@observable createdAt; | |
@observable updatedAt; | |
@observable saved = false; | |
@observable saving = false; | |
@observable deleting = false; | |
@observable deleted = false; | |
@observable selected = false; | |
store = null; | |
_deleteHandler | |
_saveHandler = null; | |
get counties() { | |
return this._counties.values(); | |
} | |
@computed get asJson() { | |
return { | |
id: this.id, | |
name: this.name, | |
abbreviation: this.abbreviation, | |
smithsonianCode: this.smithsonianCode, | |
fipsCode: this.fipsCode, | |
gnisCode: this.gnisCode | |
}; | |
} | |
@computed get tableFormat() { | |
return { | |
id: this.id, | |
name: this.name, | |
abbreviation: this.abbreviation, | |
smithsonianCode: this.smithsonianCode, | |
fipsCode: this.fipsCode, | |
gnisCode: this.gnisCode | |
}; | |
} | |
@computed get dropdownFormat() { | |
return `${this.name}`; | |
} | |
@computed get detailsFormat() { | |
return { | |
id: this.id, | |
name: this.name, | |
abbreviation: this.abbreviation, | |
smithsonianCode: this.smithsonianCode, | |
fipsCode: this.fipsCode, | |
gnisCode: this.gnisCode | |
}; | |
} | |
constructor(store, state) { | |
this.store = store; | |
const { id, name, abbreviation, smithsonianCode, fipsCode, gnisCode, createdAt, updatedAt, deleted=true } = state; | |
if (id) this.saved = true; | |
this.id = id || uuid.v4(); | |
this.name = name; | |
this.abbreviation = abbreviation; | |
this.smithsonianCode = smithsonianCode; | |
this.fipsCode = fipsCode; | |
this.gnisCode = gnisCode; | |
this.createdAt = createdAt; | |
this.updatedAt = updatedAt; | |
this.deleted = deleted; | |
this._deleteHandler = autorun(() => { | |
if (this.deleted) { | |
this.store.removeItem(this); | |
} | |
}); | |
this._saveHandler = autorun(() => { | |
if (this.saving) { | |
this.store.saveItem(this); | |
} | |
}); | |
// makes sure the state has _counties, throws error without this check | |
if (this._counties) { | |
intercept(this, "_counties", change => { | |
console.log('_counties changed!', change); | |
return change; | |
}); | |
} | |
if (this.name) { | |
intercept(this, 'name', change => { | |
console.log('NAME CHANGED', change); | |
console.log(this.counties); | |
return change; | |
}) | |
} | |
} | |
@action select() { | |
this.selected = true; | |
} | |
@action deselect() { | |
this.selected = false; | |
} | |
@action save() { | |
this.saving = true; | |
this.store.saveItem(this.asJson); | |
} | |
@action delete() { | |
this.deleting = true; | |
this._saveHandler(); | |
this.store.deleteItem(this); | |
} | |
@action updateFromServer(update) { | |
console.log('UPDATED VERSION', update); | |
console.log('EXISTING VERSION', this.asJson); | |
console.log('EQUALITY TEST', update == this.asJson); | |
} | |
@action addCounty(county) { | |
county = this.store.stores.counties.findOrAddCounty(county); | |
this._counties.set(county.id, county); | |
} | |
} | |
export default class StateStore { | |
primus; | |
stores; | |
name = 'states'; | |
urlParam = 'states'; | |
label = 'States'; | |
columns = [ | |
{name: 'name'}, | |
{name: 'abbreviation'}, | |
{name: 'smithsonianCode'}, | |
{name: 'fipsCode'}, | |
{name: 'gnisCode'} | |
]; | |
@observable items = asMap([]); | |
@observable pendingRequestCount = 0; | |
@observable initialDataLoaded = false; | |
@observable error = null; | |
@observable selected = false; | |
@observable selectedId = null; | |
@computed get tableItems() { | |
return this.items.values().slice().filter(i => i.saved == true).map(i => i.tableFormat); | |
} | |
@computed get dropdownItems() { | |
// return this.items.values().slice().map(i => i.dropdownFormat); | |
return this.items.values(); | |
} | |
constructor(primus, stores, items) { | |
console.log('initializing StateStore!'); | |
this.primus = primus; | |
this.stores = stores; | |
this.primus.on('graphql', (error, response) => { | |
if (error) { | |
this.error = error; | |
} | |
if (response.states) { | |
this.handleResponse(response.states); | |
} | |
if (response.state) { | |
this.handleResponse(response.state); | |
} | |
if (response.addState) { | |
this.handleResponse(response.addState); | |
} | |
if (response.updateState) { | |
this.handleResponse(response.updateState); | |
} | |
if (response.deleteState) { | |
this.handleResponse(response.deleteState); | |
} | |
}); | |
if (typeof window !== 'undefined' && !this.items.length && !this.initialDataLoaded) { | |
this.getItems(); | |
this.initialDataLoaded = true; | |
} | |
} | |
@action newItem() { | |
const selected = this.selectedItem; | |
if (selected) { | |
selected.deselect(); | |
} | |
const newItem = new State(this, {}); | |
console.log('NEW ITEM', newItem); | |
this.items.set(newItem.id, newItem); | |
this.selectItem(newItem.id); | |
} | |
@computed get isLoading() { | |
return this.pendingRequestCount > 0; | |
} | |
@action getItems() { | |
console.log('getting items'); | |
const payload = { | |
query: `query { | |
states { | |
id, | |
name, | |
abbreviation, | |
smithsonianCode, | |
fipsCode, | |
gnisCode, | |
createdAt, | |
updatedAt | |
}}` | |
}; | |
this.primus.emit('graphql', prepareGraphQLParams(payload)); | |
this.pendingRequestCount++; | |
} | |
@action getItem(id) { | |
const payload = { | |
variables: {id}, | |
query: `query ($id: ID!) { | |
state (id: $id) { | |
id, | |
name, | |
abbreviation, | |
smithsonianCode, | |
fipsCode, | |
gnisCode, | |
counties {id, name}, | |
createdAt, | |
updatedAt | |
}}` | |
}; | |
this.primus.emit('graphql', prepareGraphQLParams(payload)); | |
this.pendingRequestCount++; | |
} | |
@action saveItem(item) { | |
console.log('SAVING ITEM', item); | |
const updateQuery = `mutation ($item: UpdatedState!) { | |
updateState (state: $item) { | |
id, | |
name, | |
abbreviation, | |
smithsonianCode, | |
fipsCode, | |
gnisCode, | |
createdAt, | |
updatedAt | |
}}`; | |
const newQuery = `mutation ($item: NewState!) { | |
addState (state: $item) { | |
id, | |
name, | |
abbreviation, | |
smithsonianCode, | |
fipsCode, | |
gnisCode, | |
createdAt, | |
updatedAt | |
}}`; | |
const payload = { | |
query: item.saved ? updateQuery : newQuery, | |
variables: {item: item.asJson} | |
}; | |
this.primus.emit('graphql', prepareGraphQLParams(payload)); | |
this.pendingRequestCount++; | |
} | |
@action deleteItem(item) { | |
const payload = { | |
query: `mutation ($id: ID!) {deleteState (id: $id){id,deleted}}`, | |
variables: {id: item.id} | |
}; | |
this.primus.emit('graphql', prepareGraphQLParams(payload)); | |
this.pendingRequestCount++; | |
} | |
@action removeItem(item) { | |
if (this.items.has(item.id)) { | |
this.items.delete(item.id); | |
} | |
} | |
@action select() { | |
this.selected = true; | |
} | |
@action deselect() { | |
this.selected = false; | |
} | |
@computed get selectedItem() { | |
if (this.items.has(this.selectedId)) { | |
return this.items.get(this.selectedId); | |
} else { | |
return null; | |
} | |
} | |
@action selectItem(id) { | |
this.selectedId = id; | |
} | |
@action handleResponse(response) { | |
if (!Array.isArray(response)) response = [response]; | |
response.forEach(item => { | |
if (this.items.has(item.id)) { | |
this.items.get(item.id).updateFromServer(item); | |
} else { | |
this.items.set(item.id, new State(this, item)); | |
} | |
}); | |
this.pendingRequestCount--; | |
} | |
@action findOrAddState(state) { | |
if (!this.items.has(state.id)) { | |
this.items.set(state.id, new State(this, state)); | |
} | |
return this.items.get(state.id); | |
} | |
@computed get form() { | |
return { | |
type: t.struct({ | |
id: t.maybe(UUID), | |
name: t.String, | |
abbreviation: t.String, | |
smithsonianCode: t.Number, | |
fipsCode: t.maybe(t.Number), | |
gnisCode: t.maybe(t.Number), | |
counties: t.list(this.stores.counties.form.type) | |
}), | |
options: { | |
fields: { | |
id: { | |
type: 'hidden' | |
}, | |
counties: { | |
item: this.stores.counties.form.options | |
} | |
} | |
} | |
}; | |
} | |
} | |
class County { | |
id = null; | |
@observable name; | |
@observable abbreviation; | |
@observable fipsCode; | |
@observable gnisCode; | |
@observable state; | |
@observable _cities = asMap([]); | |
@observable _sites = asMap([]); | |
@observable createdAt; | |
@observable updatedAt; | |
@observable saved = true; | |
@observable saving = false; | |
@observable deleting = false; | |
@observable deleted = false; | |
@observable selected = false; | |
store = null; | |
_deleteHandler = null; | |
_saveHandler = null; | |
@computed get asJson() { | |
return { | |
id: this.id, | |
name: this.name, | |
abbreviation: this.abbreviation, | |
state: this.state ? this.state.id : null, | |
createdAt: this.createdAt, | |
updatedAt: this.updatedAt | |
}; | |
} | |
@computed get tableFormat() { | |
return { | |
id: this.id, | |
name: this.name, | |
abbreviation: this.abbreviation, | |
state: this.state ? this.state.name : '' | |
}; | |
} | |
@computed get dropdownFormat() { | |
return `${this.name} (${this.state.name})`; | |
} | |
@computed get detailsFormat() { | |
return { | |
id: this.id, | |
name: this.name, | |
state: this.state ? this.state.name : null, | |
abbreviation: this.abbreviation, | |
fipsCode: this.fipsCode, | |
gnisCode: this.gnisCode | |
}; | |
} | |
constructor(store, county) { | |
this.store = store; | |
const { id, name, abbreviation, createdAt, updatedAt, state, deleted=false } = county; | |
if (!id) this.saved = false; | |
this.id = id || uuid.v4(); | |
this.name = name; | |
this.abbreviation = abbreviation; | |
this.createdAt = createdAt; | |
this.updatedAt = updatedAt; | |
this.deleted = deleted; | |
if (state) { | |
this.addState(state); | |
} | |
this._deleteHandler = autorun(() => { | |
if (this.deleted) { | |
this.store.removeItem(this); | |
} | |
}); | |
autorun(() => { | |
if (this.state && this.state.saving) { | |
console.log('STATE WAS SAVED, SHOULD I SAVE???'); | |
} | |
}) | |
this._saveHandler = autorun(() => { | |
const json = this.asJson; | |
if (this.saving) { | |
this.store.saveItem(json); | |
} | |
}); | |
if (this.state) { | |
intercept(this, "state", change => { | |
console.log('state changed!', change); | |
console.log('old state', this.state.name, change.newValue.name); | |
console.log('old state has this county', this.state._counties.has(this.id)); | |
this.state._counties.delete(this.id); | |
return change; | |
}); | |
} | |
if (this.name) { | |
intercept(this, 'name', change => { | |
console.log('COUNTY NAME CHANGE', this.name, change); | |
return change; | |
}); | |
} | |
} | |
@action select() { | |
this.selected = true; | |
} | |
@action deselect() { | |
this.selected = false; | |
} | |
@action save() { | |
this.store.saveItem(this.asJson); | |
} | |
@action delete() { | |
this.deleting = true; | |
this._saveHandler(); | |
this.store.deleteItem(this); | |
} | |
@action addState(state) { | |
this.state = this.store.stores.states.findOrAddState(state); | |
if (this.saved && !this.state._counties.has(this.id)) { | |
this.state._counties.set(this.id, this); | |
} | |
} | |
@action addSite(site) { | |
if (!this._sites.has(site.id)) { | |
site = this.store.stores.sites.findOrAddSite(site); | |
this._sites.set(site.id, site); | |
} | |
} | |
@action addCity(city) { | |
if (!this._cities.has(city.id)) { | |
city = this.store.stores.cities.findOrAddCity(city); | |
this._cities.set(city.id, city); | |
} | |
} | |
} | |
export default class CountyStore { | |
primus; | |
stores; | |
name = 'counties'; | |
urlParam = 'counties'; | |
label = 'Counties'; | |
columns = [ | |
{name: 'name'}, | |
{name: 'abbreviation'}, | |
{name: 'state'} | |
]; | |
@observable items = asMap([]); | |
@observable pendingRequestCount = 0; | |
@observable initialDataLoaded = false; | |
@observable error = null; | |
@observable selected = false; | |
@observable selectedId = null; | |
@computed get tableItems() { | |
return this.items.values() | |
.filter(i => i.saved) | |
.slice() | |
.map(i => i.tableFormat); | |
} | |
@computed get dropdownItems() { | |
return this.items.values().slice().map(i => i.dropdownFormat); | |
} | |
constructor(primus, stores, items) { | |
this.primus = primus; | |
this.stores = stores; | |
this.primus.on('graphql', (error, response) => { | |
if (error) { | |
this.error = error; | |
} | |
if (response.counties) { | |
this.handleResponse(response.counties); | |
} | |
if (response.county) { | |
this.handleResponse(response.county); | |
} | |
if (response.addCounty) { | |
this.handleResponse(response.addCounty); | |
} | |
if (response.updateCounty) { | |
this.handleResponse(response.updateCounty); | |
} | |
if (response.deleteCounty) { | |
this.handleResponse(response.deleteCounty); | |
} | |
}); | |
if (typeof window !== 'undefined' && !this.items.length && !this.initialDataLoaded) { | |
this.getItems(); | |
this.initialDataLoaded = true; | |
} | |
} | |
@action newItem() { | |
const selected = this.selectedItem; | |
if (selected) { | |
selected.deselect(); | |
} | |
const newItem = new County(this, {}); | |
console.log('NEW ITEM', newItem); | |
this.items.set(newItem.id, newItem); | |
this.selectItem(newItem.id); | |
} | |
@computed get isLoading() { | |
return this.pendingRequestCount > 0; | |
} | |
@action getItems() { | |
const payload = { | |
query: `query { | |
counties { | |
id, | |
name, | |
abbreviation, | |
state {id, name}, | |
createdAt, | |
updatedAt | |
}}` | |
}; | |
this.primus.emit('graphql', prepareGraphQLParams(payload)); | |
this.pendingRequestCount++; | |
} | |
@action getItem(id) { | |
const payload = { | |
variables: {id}, | |
query: `query ($id: ID!) { | |
county (id: $id) { | |
id, | |
name, | |
abbreviation, | |
fipsCode, | |
gnisCode, | |
state {id, name}, | |
createdAt, | |
updatedAt | |
}}` | |
}; | |
this.primus.emit('graphql', prepareGraphQLParams(payload)); | |
this.pendingRequestCount++; | |
} | |
saveItem(item) { | |
const updateQuery = `mutation ($item: updatedCounty!) { | |
updateCounty (county: $item) { | |
id, | |
name, | |
state {id, name}, | |
createdAt, | |
updatedAt | |
}}`; | |
const newQuery = `mutation ($item: NewCounty!) { | |
addCounty (county: $item) { | |
id, | |
name, | |
state {id, name}, | |
createdAt | |
}}` | |
const payload = { | |
query: this.saved ? updateQuery: newQuery, | |
variables: {item} | |
}; | |
this.primus.emit('graphql', prepareGraphQLParams(payload)); | |
this.pendingRequestCount++; | |
} | |
@action deleteItem(item) { | |
const payload = { | |
query: `mutation ($id: ID!) {deleteCounty (id: $id){id, deleted}}`, | |
variables: {id: item.id} | |
}; | |
this.primus.emit('graphql', prepareGraphQLParams(payload)); | |
this.pendingRequestCount++; | |
} | |
@action removeItem(item) { | |
if (this.items.has(item.id)) { | |
this.items.delete(item.id); | |
} | |
} | |
@action select() { | |
this.selected = true; | |
} | |
@action deselect() { | |
this.selected = false; | |
} | |
@computed get selectedItem() { | |
if (this.items.has(this.selectedId)) { | |
return this.items.get(this.selectedId); | |
} else { | |
return null; | |
} | |
} | |
@action selectItem(id) { | |
this.selectedId = id; | |
} | |
@action handleResponse(response) { | |
if (!Array.isArray(response)) response = [response]; | |
response.forEach(item => { | |
this.items.set(item.id, new County(this, item)); | |
}); | |
this.pendingRequestCount--; | |
} | |
@action findOrAddCounty(county) { | |
if (!this.items.has(county.id)) { | |
this.items.set(county.id, new County(this, county)); | |
} | |
return this.items.get(county.id); | |
} | |
@computed get form() { | |
const { states } = this.stores; | |
return { | |
type: t.struct({ | |
id: t.maybe(UUID), | |
name: t.maybe(t.String), | |
abbreviation: t.maybe(t.String), | |
gnisCode: t.maybe(t.Number), | |
fipsCode: t.maybe(t.Number), | |
state: UUID | |
}), | |
options: { | |
fields: { | |
id: { | |
type: 'hidden' | |
}, | |
state: { | |
factory: DropdownComponent(states.dropdownItems, states.pendingRequestCount > 0) | |
} | |
} | |
} | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment