diff --git a/api/BanditAPI.js b/api/BanditAPI.js
index ad630b6e5..bf9749676 100644
--- a/api/BanditAPI.js
+++ b/api/BanditAPI.js
@@ -6,11 +6,11 @@ export default class ChatAPI extends BaseAPI {
return ret.variant
}
- shown({ uid, variant, score }) {
- return this.$post('/abtest', { uid, variant, score, shown: true })
+ shown({ uid, variant }) {
+ return this.$post('/abtest', { uid, variant, shown: true })
}
- chosen({ uid, variant }) {
- return this.$post('/abtest', { uid, variant, action: true })
+ chosen({ uid, variant, score }) {
+ return this.$post('/abtest', { uid, variant, action: true, score })
}
}
diff --git a/api/ChatAPI.js b/api/ChatAPI.js
index a7fe45bbb..c70bf51ff 100644
--- a/api/ChatAPI.js
+++ b/api/ChatAPI.js
@@ -2,7 +2,9 @@ import BaseAPI from '@/api/BaseAPI'
export default class ChatAPI extends BaseAPI {
fetch(chatid, { limit, context }) {
- return this.$get(`/chat/rooms/${chatid}/messages`, { limit, context })
+ return chatid
+ ? this.$get(`/chat/rooms/${chatid}/messages`, { limit, context })
+ : this.$get(`/chatmessages`, { limit, context })
}
async listChats(params) {
@@ -33,9 +35,9 @@ export default class ChatAPI extends BaseAPI {
})
}
- nudge(roomid) {
+ nudge(chatid) {
return this.$post('/chatrooms', {
- id: roomid,
+ id: chatid,
action: 'Nudge'
})
}
@@ -52,9 +54,32 @@ export default class ChatAPI extends BaseAPI {
return this.$get('/chatrooms', { count: true })
}
- rsvp(roomid, id, value) {
+ hold(msgid) {
+ return this.$post('/chatmessages', { id: msgid, action: 'Hold' })
+ }
+
+ release(msgid) {
+ return this.$post('/chatmessages', { id: msgid, action: 'Release' })
+ }
+
+ reject(msgid) {
+ return this.$post('/chatmessages', { id: msgid, action: 'Reject' })
+ }
+
+ approve(msgid) {
+ return this.$post('/chatmessages', { id: msgid, action: 'Approve' })
+ }
+
+ whitelist(msgid) {
+ return this.$post('/chatmessages', {
+ id: msgid,
+ action: 'ApproveAllFuture'
+ })
+ }
+
+ rsvp(chatid, id, value) {
return this.$patch('/chatmessages', {
- roomid: roomid,
+ roomid: chatid,
id: id,
replyexpected: value
})
diff --git a/api/MembershipsAPI.js b/api/MembershipsAPI.js
index d29f9cb07..8a85818f7 100644
--- a/api/MembershipsAPI.js
+++ b/api/MembershipsAPI.js
@@ -12,4 +12,72 @@ export default class MembershipsAPI extends BaseAPI {
leaveGroup(data) {
return this.$del('/memberships', data)
}
+
+ fetch(params, logError = true) {
+ return this.$get('/memberships', params, logError)
+ }
+
+ fetchMembers(params) {
+ return this.$get('/memberships', params)
+ }
+
+ del(id) {
+ return this.$del('/memberships', { id })
+ }
+
+ put(data) {
+ return this.$put('/memberships', data)
+ }
+
+ approve(id, groupid, subject = null, stdmsgid = null, body = null) {
+ return this.$post('/memberships', {
+ action: 'Approve',
+ id: id,
+ groupid: groupid,
+ subject: subject,
+ stdmsgid: stdmsgid,
+ body: body
+ })
+ }
+
+ reply(id, groupid, subject = null, stdmsgid = null, body = null) {
+ return this.$post('/memberships', {
+ action: 'Reply',
+ id: id,
+ groupid: groupid,
+ subject: subject,
+ stdmsgid: stdmsgid,
+ body: body
+ })
+ }
+
+ reject(id, groupid, subject = null, stdmsgid = null, body = null) {
+ return this.$post('/memberships', {
+ action: 'Reject',
+ id: id,
+ groupid: groupid,
+ subject: subject,
+ stdmsgid: stdmsgid,
+ body: body
+ })
+ }
+
+ delete(id, groupid, subject = null, stdmsgid = null, body = null) {
+ return this.$post('/memberships', {
+ action: 'Delete',
+ id: id,
+ groupid: groupid,
+ subject: subject,
+ stdmsgid: stdmsgid,
+ body: body
+ })
+ }
+
+ spam(id, groupid) {
+ return this.$post('/memberships', {
+ action: 'Spam',
+ id: id,
+ groupid: groupid
+ })
+ }
}
diff --git a/api/MessageAPI.js b/api/MessageAPI.js
index d4c85659e..2c5018bdb 100644
--- a/api/MessageAPI.js
+++ b/api/MessageAPI.js
@@ -95,4 +95,26 @@ export default class MessageAPI extends BaseAPI {
groupid: groupid
})
}
+
+ notspam(id, groupid) {
+ return this.$post('/message', {
+ action: 'NotSpam',
+ id: id,
+ groupid: groupid
+ })
+ }
+
+ hold(id) {
+ return this.$post('/message', {
+ action: 'Hold',
+ id: id
+ })
+ }
+
+ release(id) {
+ return this.$post('/message', {
+ action: 'Release',
+ id: id
+ })
+ }
}
diff --git a/components/ChatPane.vue b/components/ChatPane.vue
index dcf9205da..17696b83c 100644
--- a/components/ChatPane.vue
+++ b/components/ChatPane.vue
@@ -138,6 +138,11 @@
Nudge
+
+
+ Info
+
+
Send
@@ -209,6 +214,7 @@ import ChatBlockModal from './ChatBlockModal'
import ChatHideModal from './ChatHideModal'
import twem from '~/assets/js/twem'
import chatCollate from '@/mixins/chatCollate.js'
+import WaitForRef from '@/mixins/waitForRef'
// Don't use dynamic imports because it stops us being able to scroll to the bottom after render.
import ChatMessage from '~/components/ChatMessage.vue'
@@ -239,7 +245,7 @@ export default {
ChatReportModal,
ChatRSVPModal
},
- mixins: [chatCollate],
+ mixins: [chatCollate, WaitForRef],
props: {
id: {
type: Number,
@@ -320,18 +326,22 @@ export default {
otheruser() {
// The user who isn't us.
let ret = null
+ const me = this.$store.getters['auth/user']
- if (
- this.chat &&
- this.chat.chattype === 'User2User' &&
- this.chat.user1 &&
- this.$store.getters['auth/user']
- ) {
- ret =
+ if (this.chat && me) {
+ if (this.chat.chattype === 'User2User' && this.chat.user1 && me) {
+ ret =
+ this.chat.user1 && this.chat.user1.id === me.id
+ ? this.chat.user2
+ : this.chat.user1
+ } else if (
+ this.chat.chattype === 'User2Mod' &&
this.chat.user1 &&
- this.chat.user1.id === this.$store.getters['auth/user'].id
- ? this.chat.user2
- : this.chat.user1
+ me.id !== this.chat.user1.id
+ ) {
+ // We are a mod.
+ ret = this.chat.user1
+ }
}
return ret
@@ -419,7 +429,9 @@ export default {
methods: {
showInfo() {
- this.$refs.profile.show()
+ this.waitForRef('profile', () => {
+ this.$refs.profile.show()
+ })
},
availability() {
this.$refs.availabilitymodal.show()
diff --git a/components/ChatPopup.vue b/components/ChatPopup.vue
index e9beccc93..5b6202931 100644
--- a/components/ChatPopup.vue
+++ b/components/ChatPopup.vue
@@ -17,102 +17,88 @@
@resizing="onResize"
>
-
-
-
-
-
-
-
- {{ chat.name }}
-
-
-
- {{ chat.name }}
-
-
-
- {{ chat.unseen }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ {{ chat.name }}
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ -
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -215,6 +201,8 @@ const ProfileModal = () => import('./ProfileModal')
const AvailabilityModal = () => import('~/components/AvailabilityModal')
const AddressModal = () => import('~/components/AddressModal')
+const HEIGHT = 400
+
export default {
components: {
InfiniteLoading,
@@ -259,7 +247,7 @@ export default {
},
minheight() {
- return Math.min(this.maxheight, 400)
+ return Math.min(this.maxheight, HEIGHT)
},
maxheight() {
@@ -326,7 +314,7 @@ export default {
height() {
return this.chat && this.chat.remember && this.chat.remember.height
? this.chat.remember.height
- : 400
+ : HEIGHT
},
right() {
let right = 0
diff --git a/components/ComposeGroup.vue b/components/ComposeGroup.vue
index 9cffd8a51..9563754b4 100644
--- a/components/ComposeGroup.vue
+++ b/components/ComposeGroup.vue
@@ -29,7 +29,7 @@ export default {
if (this.postcode) {
for (const group of this.postcode.groupsnear) {
- if (group.type === 'Freegle') {
+ if (group.type === 'Freegle' && group.onhere) {
ret.push({
value: group.id,
text: group.namedisplay ? group.namedisplay : group.nameshort
diff --git a/components/DonationAskModal.vue b/components/DonationAskModal.vue
index 7d1486d1e..f18ce8236 100644
--- a/components/DonationAskModal.vue
+++ b/components/DonationAskModal.vue
@@ -154,7 +154,6 @@ export default {
},
score(value) {
- console.log('Score', value)
this.$api.bandit.chosen({
uid: 'donation',
variant: this.variant,
diff --git a/components/LoginModal.vue b/components/LoginModal.vue
index b739fa52f..2320605b3 100644
--- a/components/LoginModal.vue
+++ b/components/LoginModal.vue
@@ -346,12 +346,10 @@ export default {
console.log('Current path', this.$nuxt, this.$router, this.$route)
// Pick up the new user
- console.log('Fetch user')
await this.$store.dispatch('auth/fetchUser', {
components: ['me'],
force: true
})
- console.log('Fetched')
if (this.$route.path === '/' || !this.$route.path) {
// We've signed up from the home page. Send them to the explore page to find a group.
diff --git a/components/Message.vue b/components/Message.vue
index d62e33f0e..df7bb8589 100644
--- a/components/Message.vue
+++ b/components/Message.vue
@@ -504,11 +504,9 @@ export default {
// Have to get the message back, because as a non-member we couldn't see who sent it, and therefore
// who to reply to.
- console.log('Fetch message back')
await this.$store.dispatch('messages/fetch', {
id: this.id
})
- console.log('Fetched')
}
// Now create the chat and send the first message.
diff --git a/components/MessageUserInfo.vue b/components/MessageUserInfo.vue
index 232057c91..1db481a1c 100644
--- a/components/MessageUserInfo.vue
+++ b/components/MessageUserInfo.vue
@@ -32,7 +32,7 @@
- {{ user.id }}
+ {{ user.id }}
@@ -56,7 +56,8 @@ export default {
},
message: {
type: Object,
- required: false
+ required: false,
+ default: null
},
milesaway: {
type: Number,
diff --git a/components/ModChatReview.vue b/components/ModChatReview.vue
new file mode 100644
index 000000000..f491d8fb7
--- /dev/null
+++ b/components/ModChatReview.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ You held this {{ message.held.timestamp | timeago }}. Other people will see a warning to check with
+ you before releasing it.
+
+
+ Held by {{ message.held.name }}
+ {{ message.held.timestamp | timeago }}. Please check with them before releasing it.
+
+
+
+ {{ message.message }}
+
+
+
+ {{ message.date | timeago }}
+
+
+ {{ message.touser.displayname }} is on {{ message.group.namedisplay }}, which you mod.
+
+
+ {{ message.id }}
+
+
+
+
+
+
+ View Chat
+
+
+ Release
+
+
+ Add Mod Message
+
+
+ Approve - Not Spam
+
+
+ Approve and whitelist
+
+
+ Hold
+
+
+ Delete
+
+
+ Spam
+
+
+
+
+
+
+
diff --git a/components/ModChatReviewUser.vue b/components/ModChatReviewUser.vue
new file mode 100644
index 000000000..552cfbde8
--- /dev/null
+++ b/components/ModChatReviewUser.vue
@@ -0,0 +1,29 @@
+
+
+
+ {{ tag }}
{{ user.displayname }}
+
+ {{ user.id }}
+
+
+
+
+
+
+
diff --git a/components/ModImage.vue b/components/ModImage.vue
deleted file mode 100644
index be83e0b93..000000000
--- a/components/ModImage.vue
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/components/ModMember.vue b/components/ModMember.vue
new file mode 100644
index 000000000..824058864
--- /dev/null
+++ b/components/ModMember.vue
@@ -0,0 +1,183 @@
+
+
+
+
+
+ {{ member.email }}
+
+
+
+ {{ member.displayname }}
+
+
+ {{ member.joined | datetimeshort }}
+
+
+ {{ member.id }}
+
+
+
+
+ This freegler is active on groups {{ member.activedistance }} miles apart.
+
+
+
+
+
+
+
+ {{ offers | pluralize([ 'OFFER', 'OFFERs' ], { includeNumber: true }) }}
+
+
+ {{ wanteds | pluralize([ 'WANTED', 'WANTEDs' ], { includeNumber: true }) }}
+
+
+ {{ member.modmails | pluralize([ 'Modmail', 'Modmails' ], { includeNumber: true }) }}
+
+
+
+
+
+ Remove
+
+
+ Ban
+
+
+ Scammer
+
+
+ Whitelist
+
+
+ Add note
+
+
+ Purge
+
+
+
+
+
+
+ Hide
+
+
+ Show {{ member.emails.length | pluralize('email', { includeNumber: true }) }}
+
+
+
+
+ {{ member.emails.length }}
+
+
+ Show {{ member.emails.length | pluralize('email', { includeNumber: true }) }}
+
+
+
+
+
+ View posts
+
+
+
+ View logs
+
+
+
+
+
+
+ {{ email.email }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/ModMenuItemLeft.vue b/components/ModMenuItemLeft.vue
new file mode 100644
index 000000000..079202397
--- /dev/null
+++ b/components/ModMenuItemLeft.vue
@@ -0,0 +1,76 @@
+
+
+
+ {{ name }}
+
+ {{ getCount(count) }}
+
+
+ {{ getCount(othercount) }}
+
+
+
+
+
diff --git a/components/ModMenuItemNav.vue b/components/ModMenuItemNav.vue
new file mode 100644
index 000000000..5648caf5e
--- /dev/null
+++ b/components/ModMenuItemNav.vue
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+ {{ name }}
+
+
+ {{ name }}
+
+
+
+ {{ getCount(count) }}
+
+
+ {{ getCount(othercount) }}
+
+
+
+
diff --git a/components/ModMessage.vue b/components/ModMessage.vue
index d63a66aa9..36ef32cf9 100644
--- a/components/ModMessage.vue
+++ b/components/ModMessage.vue
@@ -43,12 +43,28 @@
-
+
+
+ You held this {{ message.heldby.timestamp | timeago }}. Other people will see a warning to check with
+ you before releasing it.
+
+
+ Held by {{ message.heldby.name }}
+ {{ message.heldby.timestamp | timeago }}. Please check with them before releasing it.
+
+
This freegler is active on groups {{ message.fromuser.activedistance }} miles apart.
+
+ {{ spamreason }}
+
+
+ We think this message might be spam.
+
+
{{ eBody }}
-
+
@@ -130,6 +146,7 @@
+
Purge
-
@@ -181,17 +197,19 @@ import MessageHistory from './MessageHistory'
import MessageUserInfo from './MessageUserInfo'
import MessageReplyInfo from './MessageReplyInfo'
import SettingsGroup from './SettingsGroup'
-import ModImage from './ModImage'
+import ModPhoto from './ModPhoto'
import NoticeMessage from './NoticeMessage'
import ModMessageButtons from './ModMessageButtons'
+import ModMessageWorry from './ModMessageWorry'
import twem from '~/assets/js/twem'
export default {
name: 'ModMessage',
components: {
+ ModMessageWorry,
ModMessageButtons,
NoticeMessage,
- ModImage,
+ ModPhoto,
SettingsGroup,
MessageReplyInfo,
MessageUserInfo,
@@ -214,19 +232,19 @@ export default {
}
},
computed: {
+ me() {
+ return this.$store.getters['auth/user']
+ },
pending() {
- let ret = false
-
- if (this.message.groups) {
- this.message.groups.forEach(group => {
- if (group.collection === 'Pending') {
- ret = true
- }
- })
- }
-
- return ret
+ return this.hasCollection('Pending')
},
+ approved() {
+ return this.hasCollection('Approved')
+ },
+ spam() {
+ return this.hasCollection('Spam')
+ },
+
typeOptions() {
// TODO Per group keywords
return [
@@ -290,7 +308,21 @@ export default {
return ret
}
},
- methods: {}
+ methods: {
+ hasCollection(coll) {
+ let ret = false
+
+ if (this.message.groups) {
+ this.message.groups.forEach(group => {
+ if (group.collection === coll) {
+ ret = true
+ }
+ })
+ }
+
+ return ret
+ }
+ }
}
diff --git a/components/ModStdMessageModal.vue b/components/ModStdMessageModal.vue
index c9eacb6e2..9c470872a 100644
--- a/components/ModStdMessageModal.vue
+++ b/components/ModStdMessageModal.vue
@@ -16,7 +16,10 @@
{{ fromName }}
- {{ message.fromuser.displayname }} <{{ toEmail }}>
+ {{ message.fromuser.displayname }}
+
+ <{{ toEmail }}>
+
@@ -75,7 +78,8 @@ export default {
this.message.fromuser.emails.forEach(email => {
if (
email.email &&
- email.email.indexOf('users.ilovefreegle.org') === -1
+ email.email.indexOf('users.ilovefreegle.org') === -1 &&
+ (ret === null || email.preferred)
) {
ret = email.email
}
@@ -93,7 +97,6 @@ export default {
return ret
},
-
processLabel() {
if (this.stdmsg) {
switch (this.stdmsg.action) {
@@ -118,10 +121,9 @@ export default {
return 'Unknown Action - Bug'
}
} else {
- return null
+ return 'Send'
}
},
-
modstatus() {
if (this.stdmsg) {
switch (this.stdmsg.newmodstatus) {
@@ -138,7 +140,6 @@ export default {
return null
},
-
emailfrequency() {
if (this.stdmsg) {
switch (this.stdmsg.newdelstatus) {
@@ -155,7 +156,6 @@ export default {
return 0
},
-
delstatus() {
if (this.stdmsg) {
switch (this.emailfrequency) {
@@ -380,12 +380,6 @@ export default {
console.error('Unknown stdmsg action', this.action)
}
}
-
- // Ensure the counts are updated.
- await this.$store.dispatch('auth/fetchUser', {
- components: ['work'],
- force: true
- })
}
}
}
diff --git a/components/ModUserComment.vue b/components/ModUserComment.vue
new file mode 100644
index 000000000..e512f9850
--- /dev/null
+++ b/components/ModUserComment.vue
@@ -0,0 +1,33 @@
+
+
+ {{ comment.user1 }}
+ {{ comment.user2 }}
+ {{ comment.user3 }}
+ {{ comment.user4 }}
+ {{ comment.user5 }}
+ {{ comment.user6 }}
+ {{ comment.user7 }}
+ {{ comment.user8 }}
+ {{ comment.user9 }}
+ {{ comment.user10 }}
+ {{ comment.user11 }}
+
+ by {{ comment.byuser.displayname }}
+
+ #{{ comment.byuser.id }}
+
+
+
+
+
diff --git a/components/MyMessage.vue b/components/MyMessage.vue
index 4d01d5df7..1a7037f92 100644
--- a/components/MyMessage.vue
+++ b/components/MyMessage.vue
@@ -416,6 +416,14 @@ export default {
type: this.message.type
})
+ // Set the current location and nearby groups, too, since we're about to use them
+ const loc = await this.$axios.get(process.env.API + '/locations', {
+ params: {
+ typeahead: this.message.location.name
+ }
+ })
+ await this.$store.dispatch('compose/setPostcode', loc.data.locations[0])
+
await this.$store.dispatch('compose/setAttachmentsForMessage', {
id: this.message.id,
attachments: this.message.attachments
diff --git a/components/NewsThread.vue b/components/NewsThread.vue
index 5052b44aa..df83b58a1 100644
--- a/components/NewsThread.vue
+++ b/components/NewsThread.vue
@@ -65,7 +65,7 @@
/>
-
+
-
+
diff --git a/mobile/freegle/android/config.xml b/mobile/freegle/android/config.xml
index ddbf66294..184ab4817 100644
--- a/mobile/freegle/android/config.xml
+++ b/mobile/freegle/android/config.xml
@@ -1,5 +1,5 @@
-
+
Freegle
Offer and request free items on your local Freegle reuse group
diff --git a/mobile/freegle/ios/config.xml b/mobile/freegle/ios/config.xml
index 4726b88d6..35c8d677e 100644
--- a/mobile/freegle/ios/config.xml
+++ b/mobile/freegle/ios/config.xml
@@ -1,5 +1,5 @@
-
+
Freegle
Offer and request free items on your local Freegle reuse group
diff --git a/nuxt.config.js b/nuxt.config.js
index 0b10bd780..133ebeb8b 100644
--- a/nuxt.config.js
+++ b/nuxt.config.js
@@ -5,7 +5,7 @@ const FACEBOOK_APPID = '134980666550322'
const SENTRY_DSN = 'https://4de62393d60a4d2aae4ccc3519e94878@sentry.io/1868170'
const YAHOO_CLIENTID =
'dj0yJmk9N245WTRqaDd2dnA4JmQ9WVdrOWIzTlZNMU01TjJjbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmc3Y9MCZ4PWRh'
-const MOBILE_VERSION = '2.0.16'
+const MOBILE_VERSION = '2.0.17'
require('dotenv').config()
diff --git a/pages/find/whoami.vue b/pages/find/whoami.vue
index 345d62741..4934cbcfd 100644
--- a/pages/find/whoami.vue
+++ b/pages/find/whoami.vue
@@ -79,7 +79,7 @@ export default {
},
mounted() {
if (!this.valid) {
- this.$router.push('/find/whatisit')
+ //this.$router.push('/find/whatisit')
}
},
methods: {
diff --git a/pages/give/whoami.vue b/pages/give/whoami.vue
index 184a80ab9..a5698db4a 100644
--- a/pages/give/whoami.vue
+++ b/pages/give/whoami.vue
@@ -78,7 +78,7 @@ export default {
},
mounted() {
if (!this.valid) {
- this.$router.push('/give/whatisit')
+ //this.$router.push('/give/whatisit')
}
},
methods: {
diff --git a/pages/message/_id.vue b/pages/message/_id.vue
index 71170be6d..b11ffeb9e 100644
--- a/pages/message/_id.vue
+++ b/pages/message/_id.vue
@@ -124,7 +124,7 @@ export default {
if (message) {
if (message.snippet) {
- snip = twem.twem(this.$emoji, message.snippet)
+ snip = twem.twem(this.$emoji, message.snippet) + '...'
} else {
snip = 'Click for more details'
}
diff --git a/pages/modtools/chats/review.vue b/pages/modtools/chats/review.vue
new file mode 100644
index 000000000..0cfab89e9
--- /dev/null
+++ b/pages/modtools/chats/review.vue
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+ There are no chat messages to review at the moment.
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/modtools/members/approved/_id.vue b/pages/modtools/members/approved/_id.vue
new file mode 100644
index 000000000..d98615ca4
--- /dev/null
+++ b/pages/modtools/members/approved/_id.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+ There are no members at the moment.
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/modtools/messages/spam/_id.vue b/pages/modtools/messages/spam/_id.vue
new file mode 100644
index 000000000..50f5e1322
--- /dev/null
+++ b/pages/modtools/messages/spam/_id.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+ There are no messages at the moment. This will refresh automatically.
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/filters.js b/plugins/filters.js
index a14a3908e..9e59aeeb8 100644
--- a/plugins/filters.js
+++ b/plugins/filters.js
@@ -4,6 +4,7 @@ import dayjs from 'dayjs'
// These are various formatting utilities which we use in templates.
Vue.filter('dateonly', val => dayjs(val).format('Do MMMM, YYYY'))
Vue.filter('datetime', val => dayjs(val).format('Do MMMM, YYYY HH:mm:ss'))
+Vue.filter('datetimeshort', val => dayjs(val).format('Do MMM, YYYY HH:mm'))
Vue.filter('dateshort', val => dayjs(val).format('MMM DD, YYYY'))
// dayjs pluralises wrongly in some cases - we've seen 1 hours ago.
diff --git a/plugins/vue-awesome.js b/plugins/vue-awesome.js
index 430a2b378..f35c4d625 100644
--- a/plugins/vue-awesome.js
+++ b/plugins/vue-awesome.js
@@ -3,6 +3,7 @@ import Icon from 'vue-awesome/components/Icon.vue'
// We list the icons we use explicitly because this reduces our bundle size.
require('vue-awesome/icons/address-book')
+require('vue-awesome/icons/arrow-circle-right')
require('vue-awesome/icons/angle-double-right')
require('vue-awesome/icons/baby-carriage')
require('vue-awesome/icons/balance-scale-left')
@@ -58,7 +59,9 @@ require('vue-awesome/icons/meh')
require('vue-awesome/icons/map-marker-alt')
require('vue-awesome/icons/map-marked-alt')
require('vue-awesome/icons/mobile-alt')
+require('vue-awesome/icons/pause')
require('vue-awesome/icons/pen')
+require('vue-awesome/icons/play')
require('vue-awesome/icons/plus')
require('vue-awesome/icons/print')
require('vue-awesome/icons/question-circle')
@@ -87,6 +90,7 @@ require('vue-awesome/icons/utensils')
require('vue-awesome/icons/window-maximize')
require('vue-awesome/icons/window-restore')
+require('vue-awesome/icons/brands/discourse')
require('vue-awesome/icons/brands/facebook')
require('vue-awesome/icons/brands/google-plus')
require('vue-awesome/icons/brands/pinterest')
diff --git a/store/chatmessages.js b/store/chatmessages.js
index 35d2eaf2a..e1865f9da 100644
--- a/store/chatmessages.js
+++ b/store/chatmessages.js
@@ -13,6 +13,10 @@ export const mutations = {
Object.assign(state.messages, {})
},
+ clearMessage(state, payload) {
+ Vue.set(state.messages[payload.chatid], payload.id, null)
+ },
+
mergeMessages(state, payload) {
const chatid = payload.id + ''
const messages =
@@ -102,15 +106,19 @@ export const actions = {
}
)
- commit('mergeMessages', {
- id: chatid,
- messages: chatmessages
- })
+ if (chatmessages) {
+ commit('mergeMessages', {
+ id: chatid,
+ messages: chatmessages
+ })
+ }
- commit('mergeUsers', {
- id: chatid,
- users: chatusers
- })
+ if (chatusers) {
+ commit('mergeUsers', {
+ id: chatid,
+ users: chatusers
+ })
+ }
if (!noContext) {
commit('setContext', {
@@ -141,5 +149,45 @@ export const actions = {
async rsvp({ commit, dispatch }, { id, roomid, value }) {
await this.$api.chat.rsvp(roomid, id, value)
+ },
+
+ async hold({ commit, dispatch, rootGetters }, { id, chatid }) {
+ await this.$api.chat.hold(id)
+ await dispatch('fetch', {
+ chatid: chatid,
+ noContext: true
+ })
+ },
+
+ async release({ commit, dispatch }, { id, chatid }) {
+ await this.$api.chat.release(id)
+ await dispatch('fetch', {
+ chatid: chatid,
+ noContext: true
+ })
+ },
+
+ async reject({ commit, dispatch }, { id, chatid }) {
+ await this.$api.chat.reject(id)
+ commit('clearMessage', {
+ id,
+ chatid
+ })
+ },
+
+ async approve({ commit, dispatch }, { id, chatid }) {
+ await this.$api.chat.approve(id)
+ commit('clearMessage', {
+ id,
+ chatid
+ })
+ },
+
+ async whitelist({ commit, dispatch }, { id, chatid }) {
+ await this.$api.chat.whitelist(id)
+ commit('clearMessage', {
+ id,
+ chatid
+ })
}
}
diff --git a/store/compose.js b/store/compose.js
index 462dbf8f4..70f2dd052 100644
--- a/store/compose.js
+++ b/store/compose.js
@@ -281,24 +281,33 @@ export const actions = {
})
})
} else {
- // This is one of our messages which we are reposting. We need to edit it (to update it from our client
- // copy), convert it back to draft, and then submit.
+ // This is one of our existing messages which we are reposting. We need to convert it back to a draft,
+ // edit it (to update it from our client data), and then submit.
promise = new Promise(function(resolve, reject) {
- dispatch('messages/patch', message, {
- root: true
- }).then(() => {
+ dispatch(
+ 'messages/update',
+ {
+ id: message.id,
+ action: 'RejectToDraft'
+ },
+ {
+ root: true
+ }
+ ).then(() => {
commit('incProgress')
- dispatch(
- 'messages/update',
- {
- id: message.id,
- action: 'RejectToDraft'
- },
- {
- root: true
- }
- ).then(() => {
+ const data = {
+ id: message.id,
+ locationid: state.postcode.id,
+ messagetype: message.type,
+ item: message.item,
+ textbody: message.description,
+ groupid: state.group
+ }
+
+ dispatch('messages/patch', data, {
+ root: true
+ }).then(() => {
commit('incProgress')
self.$api.message
diff --git a/store/members.js b/store/members.js
new file mode 100644
index 000000000..35d22ad87
--- /dev/null
+++ b/store/members.js
@@ -0,0 +1,249 @@
+import Vue from 'vue'
+import cloneDeep from 'lodash.clonedeep'
+
+export const state = () => ({
+ // Use array because we need to store them in the order returned by the server.
+ list: [],
+
+ // The context from the last fetch, used for fetchMore.
+ context: null
+})
+
+export const mutations = {
+ add(state, item) {
+ // Overwrite any existing entry.
+ const existing = state.list.findIndex(obj => {
+ return parseInt(obj.id) === parseInt(item.id)
+ })
+
+ if (existing !== -1) {
+ Vue.set(state.list, existing, item)
+ } else {
+ state.list.push(item)
+ }
+ },
+ addAll(state, items) {
+ items.forEach(item => {
+ const existing = state.list.findIndex(obj => {
+ return parseInt(obj.id) === parseInt(item.id)
+ })
+
+ if (existing !== -1) {
+ Vue.set(state.list, existing, item)
+ } else {
+ state.list.push(item)
+ }
+ })
+ },
+ remove(state, item) {
+ state.list = state.list.filter(obj => {
+ return parseInt(obj.id) !== parseInt(item.id)
+ })
+ },
+ clear(state) {
+ state.list = []
+ },
+ setContext(state, ctx) {
+ state.context = ctx
+ }
+}
+
+export const getters = {
+ get: state => id => {
+ let ret = null
+
+ Object.keys(state.list).forEach(key => {
+ if (parseInt(state.list[key].id) === parseInt(id)) {
+ ret = state.list[key]
+ }
+ })
+
+ return ret
+ },
+ getContext: state => {
+ let ret = null
+
+ if (state.context && state.context.id) {
+ ret = state.context
+ }
+
+ return ret
+ },
+ getByGroup: state => groupid => {
+ const ret = state.list.filter(member => {
+ return parseInt(member.groupid) === parseInt(groupid)
+ })
+
+ return ret
+ },
+ getAll: state => {
+ return state.list
+ }
+}
+
+export const actions = {
+ async fetchMembers({ commit, state }, params) {
+ if (params.context) {
+ // Ensure the context is a real object, in case it has been in the store.
+ const ctx = cloneDeep(params.context)
+ params.context = ctx
+ } else if (state.context) {
+ params.context = state.context
+ }
+
+ const { members, context } = await this.$api.memberships.fetchMembers(
+ params
+ )
+
+ for (let i = 0; i < members.length; i++) {
+ // The server doesn't return the collection but this is useful to have in the store.
+ members[i].collection = params.collection
+ }
+
+ commit('addAll', members)
+ commit('setContext', context)
+ },
+
+ async fetch({ commit }, params) {
+ // Don't log errors on fetches of individual members
+ const { member } = await this.$api.memberships.fetch(params, data => {
+ return data.ret !== 3
+ })
+
+ commit('add', member)
+ },
+
+ async update({ commit, dispatch }, params) {
+ const data = await this.$api.memberships.update(params)
+
+ if (!data.deleted) {
+ // Fetch back the updated version.
+ await dispatch('fetch', { id: params.id })
+ }
+
+ return data
+ },
+
+ async patch({ commit, dispatch }, params) {
+ const data = await this.$api.memberships.save(params)
+ await dispatch('fetch', { id: params.id })
+ return data
+ },
+
+ async updateChat({ dispatch }, userid) {
+ // Find the chat to this user and refetch the members, so that if we have a chat window open or other data
+ // that depends on it, we update that.
+ const chatid = await dispatch(
+ 'chats/openChatToUser',
+ {
+ userid: userid
+ },
+ {
+ root: true
+ }
+ )
+
+ await dispatch(
+ 'chatmembers/clearContext',
+ {
+ chatid: chatid
+ },
+ {
+ root: true
+ }
+ )
+
+ await dispatch(
+ 'chatmembers/fetch',
+ {
+ chatid: chatid
+ },
+ {
+ root: true
+ }
+ )
+ },
+
+ async promise({ dispatch }, params) {
+ await dispatch(
+ 'update',
+ Object.assign(params, {
+ action: 'Promise'
+ })
+ )
+
+ await dispatch('updateChat', params.userid)
+ },
+
+ async renege({ dispatch }, params) {
+ await dispatch(
+ 'update',
+ Object.assign(params, {
+ action: 'Renege'
+ })
+ )
+
+ await dispatch('updateChat', params.userid)
+ },
+
+ clear({ commit }) {
+ commit('clear')
+ commit('setContext', null)
+ },
+
+ async approve({ commit }, params) {
+ await this.$api.memberships.approve(
+ params.id,
+ params.groupid,
+ params.subject,
+ params.stdmsgid,
+ params.body
+ )
+ commit('remove', {
+ id: params.id
+ })
+ },
+
+ async spam({ commit }, params) {
+ await this.$api.memberships.spam(params.id, params.groupid)
+ commit('remove', {
+ id: params.id
+ })
+ },
+
+ async reject({ commit }, params) {
+ await this.$api.memberships.reject(
+ params.id,
+ params.groupid,
+ params.subject,
+ params.stdmsgid,
+ params.body
+ )
+ commit('remove', {
+ id: params.id
+ })
+ },
+
+ async reply({ commit }, params) {
+ await this.$api.memberships.reply(
+ params.id,
+ params.groupid,
+ params.subject,
+ params.stdmsgid,
+ params.body
+ )
+ },
+
+ async delete({ commit }, params) {
+ await this.$api.memberships.delete(
+ params.id,
+ params.groupid,
+ params.subject,
+ params.stdmsgid,
+ params.body
+ )
+ commit('remove', {
+ id: params.id
+ })
+ }
+}
diff --git a/store/messages.js b/store/messages.js
index 1a77b5c97..c3699401e 100644
--- a/store/messages.js
+++ b/store/messages.js
@@ -215,7 +215,7 @@ export const actions = {
}
},
- async approve({ commit }, params) {
+ async approve({ commit, dispatch }, params) {
await this.$api.message.approve(
params.id,
params.groupid,
@@ -223,19 +223,62 @@ export const actions = {
params.stdmsgid,
params.body
)
+
commit('remove', {
id: params.id
})
+
+ dispatch(
+ 'auth/fetchUser',
+ {
+ components: ['work'],
+ force: true
+ },
+ {
+ root: true
+ }
+ )
},
- async spam({ commit }, params) {
+ async spam({ commit, dispatch }, params) {
await this.$api.message.spam(params.id, params.groupid)
+
+ commit('remove', {
+ id: params.id
+ })
+
+ dispatch(
+ 'auth/fetchUser',
+ {
+ components: ['work'],
+ force: true
+ },
+ {
+ root: true
+ }
+ )
+ },
+
+ async notspam({ commit, dispatch }, params) {
+ await this.$api.message.notspam(params.id, params.groupid)
+
commit('remove', {
id: params.id
})
+
+ dispatch(
+ 'auth/fetchUser',
+ {
+ components: ['work'],
+ force: true
+ },
+ {
+ root: true
+ }
+ )
},
- async reject({ commit }, params) {
+ async reject({ commit, dispatch }, params) {
await this.$api.message.reject(
params.id,
params.groupid,
@@ -243,12 +286,24 @@ export const actions = {
params.stdmsgid,
params.body
)
+
commit('remove', {
id: params.id
})
+
+ dispatch(
+ 'auth/fetchUser',
+ {
+ components: ['work'],
+ force: true
+ },
+ {
+ root: true
+ }
+ )
},
- async reply({ commit }, params) {
+ async reply({ commit, dispatch }, params) {
await this.$api.message.reply(
params.id,
params.groupid,
@@ -256,9 +311,20 @@ export const actions = {
params.stdmsgid,
params.body
)
+
+ dispatch(
+ 'auth/fetchUser',
+ {
+ components: ['work'],
+ force: true
+ },
+ {
+ root: true
+ }
+ )
},
- async delete({ commit }, params) {
+ async delete({ commit, dispatch }, params) {
await this.$api.message.delete(
params.id,
params.groupid,
@@ -266,8 +332,38 @@ export const actions = {
params.stdmsgid,
params.body
)
+
commit('remove', {
id: params.id
})
+
+ dispatch(
+ 'auth/fetchUser',
+ {
+ components: ['work'],
+ force: true
+ },
+ {
+ root: true
+ }
+ )
+ },
+
+ async hold({ dispatch, commit }, params) {
+ await this.$api.message.hold(params.id)
+ const { message } = await this.$api.message.fetch({
+ id: params.id,
+ messagehistory: true
+ })
+ commit('add', message)
+ },
+
+ async release({ dispatch, commit }, params) {
+ await this.$api.message.release(params.id)
+ const { message } = await this.$api.message.fetch({
+ id: params.id,
+ messagehistory: true
+ })
+ commit('add', message)
}
}
diff --git a/store/stdmsgs.js b/store/stdmsgs.js
index a3cace9ad..612758e7d 100644
--- a/store/stdmsgs.js
+++ b/store/stdmsgs.js
@@ -23,7 +23,6 @@ export const getters = {
export const actions = {
async fetch({ state, commit }, params) {
const { stdmsg } = await this.$api.modconfigs.fetchStdMsg(params.id)
- console.log('Fetched', stdmsg)
commit('set', stdmsg)
return stdmsg
}