nextcloud-contacts/src/store/circles.js

236 lines
6.6 KiB
JavaScript

/**
* @copyright Copyright (c) 2021 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import { showError } from '@nextcloud/dialogs'
import Vue from 'vue'
import { createCircle, deleteCircle, deleteMember, getCircleMembers, getCircles, leaveCircle, addMembers } from '../services/circles.ts'
import Member from '../models/member.ts'
import Circle from '../models/circle.ts'
const state = {
/** @type {Object.<string>} Circle */
circles: {},
}
const mutations = {
/**
* Add a circle into state
*
* @param {Object} state the store data
* @param {Circle} circle the circle to add
*/
addCircle(state, circle) {
if (circle.constructor.name !== Circle.name) {
throw new Error('circle must be a Circle type')
}
Vue.set(state.circles, circle.id, circle)
},
/**
* Delete circle
*
* @param {Object} state the store data
* @param {Circle} circle the circle to delete
*/
deleteCircle(state, circle) {
if (!(circle.id in state.circles)) {
console.warn('Skipping deletion of unknown circle', circle)
}
Vue.delete(state.circles, circle.id)
},
/**
* Append a list of members to a circle
* and remove duplicates
*
* @param {Object} state the store data
* @param {Members[]} members array of members to append
*/
appendMembersToCircle(state, members) {
members.forEach(member => member.circle.addMember(member))
},
/**
* Add a member to a circle and overwrite if duplicate uid
*
* @param {Object} state the store data
* @param {Object} data destructuring object
* @param {string} data.circleId the circle to add the members to
* @param {Member} data.member array of contacts to append
*/
addMemberToCircle(state, { circleId, member }) {
const circle = state.circles[circleId]
circle.addmember(member)
},
/**
* Delete a contact in a specified circle
*
* @param {Object} state the store data
* @param {Member} member the member to add
*/
deleteMemberFromCircle(state, member) {
// Circles dependencies are managed directly from the model
member.delete()
},
}
const getters = {
getCircles: state => Object.values(state.circles),
getCircle: state => (id) => state.circles[id],
}
const actions = {
/**
* Retrieve and commit circles
*
* @param {Object} context the store mutations
* @returns {Object[]} the circles
*/
async getCircles(context) {
const circles = await getCircles()
console.debug(`Retrieved ${circles.length} circle(s)`, circles)
let failure = false
circles.forEach(circle => {
try {
const newCircle = new Circle(circle)
context.commit('addCircle', newCircle)
} catch (error) {
failure = true
console.error('This circle failed to be processed', circle, error)
}
})
if (failure) {
showError(t('contacts', 'Some circle(s) errored, check the console for more details'))
}
return circles
},
/**
* Retrieve and commit circle members
*
* @param {Object} context the store mutations
* @param {string} circleId the circle id
*/
async getCircleMembers(context, circleId) {
const circle = context.getters.getCircle(circleId)
const members = await getCircleMembers(circleId)
console.debug(`${circleId} have ${members.length} member(s)`, members)
context.commit('appendMembersToCircle', members.map(member => new Member(member, circle)))
},
/**
* Create circle
*
* @param {Object} context the store mutations Current context
* @param {string} circleName the circle name
* @returns {Circle} the new circle
*/
async createCircle(context, circleName) {
try {
const response = await createCircle(circleName)
const circle = new Circle(response)
context.commit('addCircle', circle)
console.debug('Created circle', circleName, circle)
return circle
} catch (error) {
console.error(error)
showError(t('contacts', 'Unable to create circle {circleName}', { circleName }))
}
},
/**
* Delete circle
*
* @param {Object} context the store mutations Current context
* @param {Circle} circle the circle to delete
*/
async deleteCircle(context, circle) {
try {
await deleteCircle(circle.id)
console.debug('Created circle', circle.displayName, circle)
} catch (error) {
console.error(error)
showError(t('contacts', 'Unable to create circle {displayName}', circle))
}
},
/**
* Add members to a circle
*
* @param {Object} context the store mutations Current context
* @param {Object} data destructuring object
* @param {string} data.circleId the circle to manage
* @param {Array} data.selection the members to add, see addMembers service
* @returns {Member[]}
*/
async addMembersToCircle(context, { circleId, selection }) {
const circle = context.getters.getCircle(circleId)
const results = await addMembers(circleId, selection)
const members = results.map(member => new Member(member, circle))
console.debug('Added members to circle', circle, members)
context.commit('appendMembersToCircle', members)
return members
},
/**
* Delete a member from a circle
*
* @param {Object} context the store mutations Current context
* @param {Member} member the member to remove
* @param {boolean} [leave=false] leave the circle instead of removing the member
*/
async deleteMemberFromCircle(context, { member, leave = false }) {
const circleId = member.circle.id
const memberId = member.id
if (leave) {
const circle = await leaveCircle(circleId)
member.circle.updateData(circle)
// If the circle is not visible, we remove it from the list
if (!member.circle.isVisible && !member.circle.isMember) {
await context.commit('deleteCircle', circle)
console.debug('Deleted circle', circleId, memberId)
}
} else {
await deleteMember(circleId, memberId)
}
// success, let's remove from store
context.commit('deleteMemberFromCircle', member)
console.debug('Deleted member', circleId, memberId)
},
}
export default { state, mutations, getters, actions }