nextcloud-contacts/src/models/circle.ts

269 lines
5.2 KiB
TypeScript

/**
* @copyright Copyright (c) 2018 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 Vue from 'vue'
import Member from './member'
import { CircleConfigs, MemberLevels } from './constants'
type MemberList = Record<string, Member>
export default class Circle {
_data: any = {}
_members: MemberList = {}
_owner: Member
_initiator: Member
/**
* Creates an instance of Circle
*/
constructor(data: Object) {
this.updateData(data)
}
/**
* Update inner circle data, owner and initiator
*/
updateData(data: any) {
if (typeof data !== 'object') {
throw new Error('Invalid circle')
}
// if no uid set, fail
if (!data.id) {
throw new Error('This circle do not have a proper uid')
}
this._data = data
this._owner = new Member(data.owner, this)
if (data.initiator) {
this._initiator = new Member(data.initiator, this)
}
}
// METADATA -----------------------------------------
/**
* Circle id
*/
get id(): string {
return this._data.id
}
/**
* Formatted display name
*/
get displayName(): string {
return this._data.displayName
}
/**
* Circle creation date
*/
get creation(): number {
return this._data.creation
}
/**
* Circle description
*/
get description(): string {
return this._data.description
}
/**
* Circle description
*/
set description(text: string) {
this._data.description = text
}
// MEMBERSHIP -----------------------------------------
/**
* Circle ini_initiator the current
* user info for this circle
*/
get initiator(): Member {
return this._initiator
}
/**
* Circle ownership
*/
get owner(): Member {
return this._owner
}
/**
* Set new circle owner
*/
set owner(owner: Member) {
if (owner.constructor.name !== Member.name) {
throw new Error('Owner must be a Member type')
}
this._owner = owner
}
/**
* Circle members
*/
get members(): MemberList {
return this._members
}
/**
* Define members circle
*/
set members(members: MemberList) {
this._members = members
}
/**
* Add a member to this circle
*/
addMember(member: Member) {
if (member.constructor.name !== Member.name) {
throw new Error('Member must be a Member type')
}
const singleId = member.singleId
if (this._members[singleId]) {
console.warn('Ignoring duplicate member', member)
}
Vue.set(this._members, singleId, member)
}
/**
* Remove a member from this circle
*/
deleteMember(member: Member) {
if (member.constructor.name !== Member.name) {
throw new Error('Member must be a Member type')
}
const singleId = member.singleId
if (!this._members[singleId]) {
console.warn('The member was not in this circle. Nothing was done.', member)
}
// Delete and clear memory
Vue.delete(this._members, singleId)
}
// CONFIGS --------------------------------------------
get settings() {
return this._data.settings
}
/**
* Circle config
*/
get config() {
return this._data.config
}
/**
* Circle requires invite to be confirmed by moderator or above
*/
get requireJoinAccept() {
return (this._data.config & CircleConfigs.VISIBLE) !== 0
}
/**
* Circle can be requested to join
*/
get canJoin() {
return (this._data.config & CircleConfigs.OPEN) !== 0
}
/**
* Circle is visible to others
*/
get isVisible() {
return (this._data.config & CircleConfigs.VISIBLE) !== 0
}
/**
* Circle requires invite to be accepted by the member
*/
get requireInviteAccept() {
return (this._data.config & CircleConfigs.INVITE) !== 0
}
// PERMISSIONS SHORTCUTS ------------------------------
/**
* Can the initiator add members to this circle?
*/
get isOwner() {
return this.initiator?.level === MemberLevels.OWNER
}
/**
* Is the initiator a member of this circle?
*/
get isMember() {
return this.initiator?.level > MemberLevels.NONE
}
/**
* Can the initiator delete this circle?
*/
get canDelete() {
return this.isOwner
}
/**
* Can the initiator leave this circle?
*/
get canLeave() {
return this.isMember && !this.isOwner
}
/**
* Can the initiator add/remove members to this circle?
*/
get canManageMembers() {
return this.initiator?.level >= MemberLevels.MODERATOR
}
// PARAMS ---------------------------------------------
/**
* Vue router param
*/
get router() {
return {
name: 'circle',
params: { selectedCircle: this.id },
}
}
/**
* Default javascript fallback
* Used for sorting as well
*/
toString() {
return this.displayName
}
}