181 lines
3.9 KiB
JavaScript
181 lines
3.9 KiB
JavaScript
const moment = require("moment")
|
||
|
||
const {postApi} = require("../../../../../rpdata/api/Post")
|
||
const {logsApi} = require("../../../../../rpdata/api/Log")
|
||
|
||
module.exports = class {
|
||
onCreate(input) {
|
||
this.state = {
|
||
log: input.log,
|
||
modal: null,
|
||
removed: false,
|
||
highlights: [],
|
||
}
|
||
}
|
||
|
||
onMount() {
|
||
this.sub = logsApi.subscribeChanges(this.state.log.id)
|
||
|
||
this.sub.on("data", data => {
|
||
this.handleChange(data.changes)
|
||
})
|
||
|
||
this.sub.connect()
|
||
}
|
||
|
||
onUnmount() {
|
||
if (this.sub != null) {
|
||
this.sub.disconnect()
|
||
}
|
||
}
|
||
|
||
open(modal) {
|
||
this.state.modal = modal
|
||
}
|
||
|
||
close() {
|
||
this.state.modal = null
|
||
}
|
||
|
||
/**
|
||
* Patch the posts
|
||
*
|
||
* @param {{id:string, [x:string]: any}[]} patches
|
||
*/
|
||
patch(patches) {
|
||
const posts = this.state.log.posts.slice()
|
||
|
||
for (const patch of patches) {
|
||
const index = posts.findIndex(p => p.id === patch.id)
|
||
if (index == -1) {
|
||
continue
|
||
}
|
||
|
||
posts[index] = Object.assign(Object.assign({}, posts[index]), patch)
|
||
}
|
||
|
||
// Sort posts and look for continuity issues (duplicate or skipped positions)
|
||
posts.sort((a, b) => a.position - b.position)
|
||
for (let i = 1; i < posts.length; ++i) {
|
||
if (posts[i].position !== posts[i - 1].position + 1) {
|
||
console.warn("Discontinuity detected:", i, posts)
|
||
}
|
||
}
|
||
|
||
this.state.log.posts = posts
|
||
this.state.log = Object.assign({}, this.state.log)
|
||
}
|
||
|
||
movePost(post, toPosition, relative) {
|
||
if (relative) {
|
||
toPosition = post.position + toPosition
|
||
}
|
||
|
||
postApi.move({id: post.id, toPosition}).then(patches => {
|
||
this.patch(patches)
|
||
}).catch(err => {
|
||
console.warn(err)
|
||
})
|
||
}
|
||
|
||
removePost(post) {
|
||
postApi.remove({id: post.id}).then(() => {
|
||
this.postRemoved(post)
|
||
}).catch(errs => {
|
||
console.warn("Failed to delete:", errs)
|
||
this.state.error = "Failed to delete: " + (errs.message || errs[0].message)
|
||
})
|
||
}
|
||
|
||
postEdited(patch) {
|
||
this.patch([patch])
|
||
}
|
||
|
||
logEdited(patch) {
|
||
this.state.log = Object.assign(Object.assign({}, this.state.log), patch)
|
||
}
|
||
|
||
postRemoved(post) {
|
||
if (this.state.log.posts.find(p => p.id === post.id) == null) {
|
||
return
|
||
}
|
||
|
||
const posts = this.state.log.posts.filter(p => p.id !== post.id).map(p => {
|
||
if (p.position > post.position) {
|
||
return Object.assign({}, p, {position: p.position - 1})
|
||
}
|
||
|
||
return p
|
||
})
|
||
|
||
this.state.log = Object.assign({}, this.state.log, {posts: posts})
|
||
}
|
||
|
||
postAdded(post) {
|
||
// Stop duplicates in case of race condition.
|
||
if (this.state.log.posts.find(p => p.id === post.id)) {
|
||
return
|
||
}
|
||
|
||
this.state.log.posts = this.state.log.posts.concat([post])
|
||
this.state.log = Object.assign({}, this.state.log)
|
||
}
|
||
|
||
handleChange(change) {
|
||
switch (`${change.model}.${change.op}`) {
|
||
case "Post.add": {
|
||
for (const post of change.objects.filter(o => o.type === "Post")) {
|
||
this.postAdded(post)
|
||
}
|
||
|
||
break
|
||
}
|
||
|
||
case "Post.move":
|
||
case "Post.edit": {
|
||
this.patch(change.objects.filter(o => o.type === "Post"))
|
||
|
||
break
|
||
}
|
||
|
||
case "Post.remove": {
|
||
for (const post of change.objects.filter(o => o.type === "Post")) {
|
||
this.postRemoved(post)
|
||
}
|
||
}
|
||
|
||
case "Log.edit": {
|
||
const patch = change.objects.find(o => o.type === "Log")
|
||
if (patch == null) {
|
||
break
|
||
}
|
||
|
||
this.logEdited(patch)
|
||
|
||
break
|
||
}
|
||
|
||
case "Log.remove": {
|
||
this.logRemoved()
|
||
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
logRemoved() {
|
||
this.state.removed = true
|
||
}
|
||
|
||
highlightsChanged(highlights) {
|
||
this.state.highlights = highlights.slice();
|
||
}
|
||
|
||
get title() {
|
||
if (this.state.log.title) {
|
||
return this.state.log.title
|
||
}
|
||
|
||
return `${this.state.log.channel.name} – ${moment(this.state.log.date).format("MMMM D, YYYY")}`
|
||
}
|
||
} |