2020-09-29 09:53:48 +02:00
|
|
|
<template>
|
2022-04-03 22:13:06 +02:00
|
|
|
<div
|
|
|
|
class="bg-white border border-gray-300 rounded-lg cursor-pointer"
|
|
|
|
v-if="selectedActor"
|
|
|
|
>
|
2020-09-29 09:53:48 +02:00
|
|
|
<!-- If we have a current actor (inline) -->
|
2020-11-30 10:24:11 +01:00
|
|
|
<div
|
2021-03-29 10:33:19 +02:00
|
|
|
v-if="inline && selectedActor.id"
|
2020-11-30 10:24:11 +01:00
|
|
|
class="inline box"
|
2021-11-07 21:02:06 +01:00
|
|
|
dir="auto"
|
2020-11-30 10:24:11 +01:00
|
|
|
@click="isComponentModalActive = true"
|
|
|
|
>
|
2020-09-29 09:53:48 +02:00
|
|
|
<div class="media">
|
|
|
|
<div class="media-left">
|
2021-03-29 10:33:19 +02:00
|
|
|
<figure class="image is-48x48" v-if="selectedActor.avatar">
|
2020-09-29 09:53:48 +02:00
|
|
|
<img
|
|
|
|
class="image is-rounded"
|
2021-03-29 10:33:19 +02:00
|
|
|
:src="selectedActor.avatar.url"
|
2021-09-07 17:52:34 +02:00
|
|
|
:alt="selectedActor.avatar.alt || ''"
|
2020-09-29 09:53:48 +02:00
|
|
|
/>
|
|
|
|
</figure>
|
|
|
|
<b-icon v-else size="is-large" icon="account-circle" />
|
|
|
|
</div>
|
2021-03-29 10:33:19 +02:00
|
|
|
<div class="media-content" v-if="selectedActor.name">
|
|
|
|
<p class="is-4">{{ selectedActor.name }}</p>
|
2021-09-07 17:52:34 +02:00
|
|
|
<p class="is-6 has-text-grey-dark">
|
2021-03-29 10:33:19 +02:00
|
|
|
{{ `@${selectedActor.preferredUsername}` }}
|
2020-11-30 10:24:11 +01:00
|
|
|
</p>
|
2020-09-29 09:53:48 +02:00
|
|
|
</div>
|
|
|
|
<div class="media-content" v-else>
|
2021-03-29 10:33:19 +02:00
|
|
|
{{ `@${selectedActor.preferredUsername}` }}
|
2020-09-29 09:53:48 +02:00
|
|
|
</div>
|
|
|
|
<b-button type="is-text" @click="isComponentModalActive = true">
|
|
|
|
{{ $t("Change") }}
|
|
|
|
</b-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- If we have a current actor -->
|
2020-11-30 10:24:11 +01:00
|
|
|
<span
|
2021-03-29 10:33:19 +02:00
|
|
|
v-else-if="selectedActor.id"
|
2020-11-30 10:24:11 +01:00
|
|
|
class="block"
|
|
|
|
@click="isComponentModalActive = true"
|
|
|
|
>
|
2020-09-29 09:53:48 +02:00
|
|
|
<img
|
|
|
|
class="image is-48x48"
|
2021-03-29 10:33:19 +02:00
|
|
|
v-if="selectedActor.avatar"
|
|
|
|
:src="selectedActor.avatar.url"
|
|
|
|
:alt="selectedActor.avatar.alt"
|
2020-09-29 09:53:48 +02:00
|
|
|
/>
|
|
|
|
<b-icon v-else size="is-large" icon="account-circle" />
|
|
|
|
</span>
|
2021-11-13 12:33:14 +01:00
|
|
|
<b-modal
|
|
|
|
:active.sync="isComponentModalActive"
|
|
|
|
has-modal-card
|
|
|
|
:close-button-aria-label="$t('Close')"
|
|
|
|
>
|
2020-09-29 09:53:48 +02:00
|
|
|
<div class="modal-card">
|
|
|
|
<header class="modal-card-head">
|
|
|
|
<p class="modal-card-title">{{ $t("Pick a profile or a group") }}</p>
|
|
|
|
</header>
|
|
|
|
<section class="modal-card-body">
|
|
|
|
<div class="columns">
|
2021-08-11 12:43:54 +02:00
|
|
|
<div class="column actor-picker">
|
2020-09-29 09:53:48 +02:00
|
|
|
<organizer-picker
|
2021-03-29 10:33:19 +02:00
|
|
|
v-model="selectedActor"
|
2020-09-29 09:53:48 +02:00
|
|
|
@input="relay"
|
|
|
|
:restrict-moderator-level="true"
|
|
|
|
/>
|
|
|
|
</div>
|
2021-08-11 12:43:54 +02:00
|
|
|
<div class="column contact-picker">
|
2021-12-13 17:02:10 +01:00
|
|
|
<div v-if="isSelectedActorAGroup">
|
2020-09-29 09:53:48 +02:00
|
|
|
<p>{{ $t("Add a contact") }}</p>
|
2021-08-11 12:43:54 +02:00
|
|
|
<b-input
|
|
|
|
:placeholder="$t('Filter by name')"
|
2022-04-03 22:17:07 +02:00
|
|
|
:value="contactFilter"
|
|
|
|
@input="debounceSetFilterByName"
|
2021-11-07 21:02:06 +01:00
|
|
|
dir="auto"
|
2021-08-11 12:43:54 +02:00
|
|
|
/>
|
2021-12-13 17:02:10 +01:00
|
|
|
<div v-if="actorMembers.length > 0">
|
|
|
|
<p
|
|
|
|
class="field"
|
|
|
|
v-for="actor in filteredActorMembers"
|
|
|
|
:key="actor.id"
|
|
|
|
>
|
|
|
|
<b-checkbox
|
|
|
|
v-model="actualContacts"
|
|
|
|
:native-value="actor.id"
|
|
|
|
>
|
|
|
|
<div class="media">
|
|
|
|
<div class="media-left">
|
|
|
|
<figure class="image is-48x48" v-if="actor.avatar">
|
|
|
|
<img
|
|
|
|
class="image is-rounded"
|
|
|
|
:src="actor.avatar.url"
|
|
|
|
:alt="actor.avatar.alt"
|
|
|
|
/>
|
|
|
|
</figure>
|
|
|
|
<b-icon
|
|
|
|
v-else
|
|
|
|
size="is-large"
|
|
|
|
icon="account-circle"
|
2020-09-29 09:53:48 +02:00
|
|
|
/>
|
2021-12-13 17:02:10 +01:00
|
|
|
</div>
|
|
|
|
<div class="media-content" v-if="actor.name">
|
|
|
|
<p class="is-4">{{ actor.name }}</p>
|
|
|
|
<p class="is-6 has-text-grey-dark">
|
|
|
|
{{ `@${usernameWithDomain(actor)}` }}
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="media-content" v-else>
|
2021-08-01 11:03:48 +02:00
|
|
|
{{ `@${usernameWithDomain(actor)}` }}
|
2021-12-13 17:02:10 +01:00
|
|
|
</div>
|
2020-09-29 09:53:48 +02:00
|
|
|
</div>
|
2021-12-13 17:02:10 +01:00
|
|
|
</b-checkbox>
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
v-else-if="
|
|
|
|
actorMembers.length === 0 && contactFilter.length > 0
|
|
|
|
"
|
|
|
|
>
|
|
|
|
<empty-content icon="account-multiple" :inline="true">
|
|
|
|
{{ $t("No group member found") }}
|
|
|
|
</empty-content>
|
|
|
|
</div>
|
2020-09-29 09:53:48 +02:00
|
|
|
</div>
|
2021-08-11 12:43:54 +02:00
|
|
|
<div v-else class="content has-text-grey-dark has-text-centered">
|
2020-09-29 09:53:48 +02:00
|
|
|
<p>{{ $t("Your profile will be shown as contact.") }}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
<footer class="modal-card-foot">
|
|
|
|
<button class="button is-primary" type="button" @click="pickActor">
|
|
|
|
{{ $t("Pick") }}
|
|
|
|
</button>
|
|
|
|
</footer>
|
|
|
|
</div>
|
|
|
|
</b-modal>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
|
|
import { Component, Prop, Vue, Watch } from "vue-property-decorator";
|
2020-11-27 19:27:44 +01:00
|
|
|
import { IMember } from "@/types/actor/member.model";
|
2021-03-29 10:33:19 +02:00
|
|
|
import { IActor, IGroup, IPerson, usernameWithDomain } from "../../types/actor";
|
2020-09-29 09:53:48 +02:00
|
|
|
import OrganizerPicker from "./OrganizerPicker.vue";
|
2021-12-13 17:02:10 +01:00
|
|
|
import EmptyContent from "../Utils/EmptyContent.vue";
|
2021-03-29 10:33:19 +02:00
|
|
|
import {
|
|
|
|
CURRENT_ACTOR_CLIENT,
|
2021-06-10 10:33:16 +02:00
|
|
|
IDENTITIES,
|
2022-04-03 22:18:33 +02:00
|
|
|
PERSON_GROUP_MEMBERSHIPS,
|
2021-03-29 10:33:19 +02:00
|
|
|
} from "../../graphql/actor";
|
2020-09-29 09:53:48 +02:00
|
|
|
import { Paginate } from "../../types/paginate";
|
2021-03-29 10:33:19 +02:00
|
|
|
import { GROUP_MEMBERS } from "@/graphql/member";
|
|
|
|
import { ActorType, MemberRole } from "@/types/enums";
|
2022-04-03 22:17:07 +02:00
|
|
|
import debounce from "lodash/debounce";
|
2021-03-29 10:33:19 +02:00
|
|
|
|
|
|
|
const MEMBER_ROLES = [
|
|
|
|
MemberRole.CREATOR,
|
|
|
|
MemberRole.ADMINISTRATOR,
|
|
|
|
MemberRole.MODERATOR,
|
|
|
|
MemberRole.MEMBER,
|
|
|
|
];
|
2020-09-29 09:53:48 +02:00
|
|
|
|
|
|
|
@Component({
|
2021-12-13 17:02:10 +01:00
|
|
|
components: { OrganizerPicker, EmptyContent },
|
2020-09-29 09:53:48 +02:00
|
|
|
apollo: {
|
2021-03-29 10:33:19 +02:00
|
|
|
members: {
|
|
|
|
query: GROUP_MEMBERS,
|
2020-09-29 09:53:48 +02:00
|
|
|
variables() {
|
|
|
|
return {
|
2021-12-13 17:02:10 +01:00
|
|
|
groupName: usernameWithDomain(this.selectedActor),
|
2021-03-29 10:33:19 +02:00
|
|
|
page: this.membersPage,
|
|
|
|
limit: 10,
|
|
|
|
roles: MEMBER_ROLES.join(","),
|
2021-12-13 17:02:10 +01:00
|
|
|
name: this.contactFilter,
|
2020-09-29 09:53:48 +02:00
|
|
|
};
|
|
|
|
},
|
2021-03-29 10:33:19 +02:00
|
|
|
update: (data) => data.group.members,
|
2020-09-29 09:53:48 +02:00
|
|
|
skip() {
|
2021-03-29 10:33:19 +02:00
|
|
|
return (
|
|
|
|
!this.selectedActor || this.selectedActor.type !== ActorType.GROUP
|
|
|
|
);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
currentActor: CURRENT_ACTOR_CLIENT,
|
2022-04-03 22:18:33 +02:00
|
|
|
personMemberships: {
|
|
|
|
query: PERSON_GROUP_MEMBERSHIPS,
|
2021-12-13 17:02:10 +01:00
|
|
|
variables() {
|
|
|
|
return {
|
2022-04-03 22:18:33 +02:00
|
|
|
id: this.currentActor?.id,
|
2021-12-13 17:02:10 +01:00
|
|
|
page: 1,
|
|
|
|
limit: 10,
|
2022-04-03 22:18:33 +02:00
|
|
|
groupId: this.$route.query?.actorId,
|
2021-12-13 17:02:10 +01:00
|
|
|
};
|
2020-09-29 09:53:48 +02:00
|
|
|
},
|
2022-04-03 22:18:33 +02:00
|
|
|
update: (data) => data.person.memberships,
|
2020-09-29 09:53:48 +02:00
|
|
|
},
|
2021-06-10 10:33:16 +02:00
|
|
|
identities: IDENTITIES,
|
2020-09-29 09:53:48 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
export default class OrganizerPickerWrapper extends Vue {
|
2021-03-29 10:33:19 +02:00
|
|
|
@Prop({ type: Object, required: false }) value!: IActor;
|
2020-09-29 09:53:48 +02:00
|
|
|
|
|
|
|
@Prop({ default: true, type: Boolean }) inline!: boolean;
|
|
|
|
|
2022-04-03 22:18:33 +02:00
|
|
|
@Prop({ type: Array, required: false, default: () => [] })
|
|
|
|
contacts!: IActor[];
|
|
|
|
|
2021-03-29 10:33:19 +02:00
|
|
|
currentActor!: IPerson;
|
2020-09-29 09:53:48 +02:00
|
|
|
|
2021-06-10 10:33:16 +02:00
|
|
|
identities!: IPerson[];
|
|
|
|
|
2020-09-29 09:53:48 +02:00
|
|
|
isComponentModalActive = false;
|
|
|
|
|
2021-08-11 12:43:54 +02:00
|
|
|
contactFilter = "";
|
|
|
|
|
2021-08-01 11:03:48 +02:00
|
|
|
usernameWithDomain = usernameWithDomain;
|
|
|
|
|
2021-03-29 10:33:19 +02:00
|
|
|
members: Paginate<IMember> = { elements: [], total: 0 };
|
|
|
|
|
|
|
|
membersPage = 1;
|
|
|
|
|
2022-04-03 22:18:33 +02:00
|
|
|
personMemberships: Paginate<IMember> = { elements: [], total: 0 };
|
2021-03-29 10:33:19 +02:00
|
|
|
|
2022-04-03 22:17:07 +02:00
|
|
|
data(): Record<string, unknown> {
|
|
|
|
return {
|
|
|
|
debounceSetFilterByName: debounce(this.setContactFilter, 1000),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-03-29 10:33:19 +02:00
|
|
|
get actualContacts(): (string | undefined)[] {
|
|
|
|
return this.contacts.map(({ id }) => id);
|
|
|
|
}
|
|
|
|
|
|
|
|
set actualContacts(contactsIds: (string | undefined)[]) {
|
|
|
|
this.$emit(
|
|
|
|
"update:contacts",
|
|
|
|
this.actorMembers.filter(({ id }) => contactsIds.includes(id))
|
|
|
|
);
|
|
|
|
}
|
2020-09-29 09:53:48 +02:00
|
|
|
|
2022-04-03 22:17:07 +02:00
|
|
|
setContactFilter(contactFilter: string) {
|
|
|
|
this.contactFilter = contactFilter;
|
|
|
|
}
|
|
|
|
|
2022-04-03 22:18:33 +02:00
|
|
|
@Watch("personMemberships")
|
2021-03-29 10:33:19 +02:00
|
|
|
setInitialActor(): void {
|
2022-04-03 22:18:33 +02:00
|
|
|
if (
|
|
|
|
this.personMemberships?.elements[0]?.parent?.id ===
|
|
|
|
this.$route.query?.actorId
|
|
|
|
) {
|
|
|
|
this.selectedActor = this.personMemberships?.elements[0]?.parent;
|
2021-03-29 10:33:19 +02:00
|
|
|
}
|
|
|
|
}
|
2020-09-29 09:53:48 +02:00
|
|
|
|
2021-03-29 10:33:19 +02:00
|
|
|
get selectedActor(): IActor | undefined {
|
|
|
|
if (this.value?.id) {
|
|
|
|
return this.value;
|
|
|
|
}
|
|
|
|
if (this.currentActor) {
|
2021-06-10 10:33:16 +02:00
|
|
|
return this.identities.find(
|
|
|
|
(identity) => identity.id === this.currentActor.id
|
|
|
|
);
|
2021-03-29 10:33:19 +02:00
|
|
|
}
|
|
|
|
return undefined;
|
2020-09-29 09:53:48 +02:00
|
|
|
}
|
|
|
|
|
2021-03-29 10:33:19 +02:00
|
|
|
set selectedActor(selectedActor: IActor | undefined) {
|
|
|
|
this.$emit("input", selectedActor);
|
2020-09-29 09:53:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async relay(group: IGroup): Promise<void> {
|
2021-03-29 10:33:19 +02:00
|
|
|
this.actualContacts = [];
|
|
|
|
this.selectedActor = group;
|
2020-09-29 09:53:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pickActor(): void {
|
|
|
|
this.isComponentModalActive = false;
|
|
|
|
}
|
|
|
|
|
2021-03-29 10:33:19 +02:00
|
|
|
get actorMembers(): IActor[] {
|
2021-08-11 12:43:54 +02:00
|
|
|
if (this.isSelectedActorAGroup) {
|
2021-03-29 10:33:19 +02:00
|
|
|
return this.members.elements.map(({ actor }: { actor: IActor }) => actor);
|
2020-09-29 09:53:48 +02:00
|
|
|
}
|
|
|
|
return [];
|
|
|
|
}
|
2021-08-11 12:43:54 +02:00
|
|
|
|
|
|
|
get filteredActorMembers(): IActor[] {
|
|
|
|
return this.actorMembers.filter((actor) => {
|
|
|
|
return [
|
|
|
|
actor.preferredUsername.toLowerCase(),
|
|
|
|
actor.name?.toLowerCase(),
|
|
|
|
actor.domain?.toLowerCase(),
|
2022-04-03 22:17:07 +02:00
|
|
|
];
|
2021-08-11 12:43:54 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
get isSelectedActorAGroup(): boolean {
|
|
|
|
return this.selectedActor?.type === ActorType.GROUP;
|
|
|
|
}
|
2020-09-29 09:53:48 +02:00
|
|
|
}
|
|
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
2021-08-11 12:43:54 +02:00
|
|
|
.modal-card-body .columns .column {
|
|
|
|
&.actor-picker,
|
|
|
|
&.contact-picker {
|
|
|
|
overflow-y: auto;
|
|
|
|
max-height: 400px;
|
2020-09-29 09:53:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|