2020-09-29 09:53:48 +02:00
|
|
|
<template>
|
2022-08-12 16:46:04 +02:00
|
|
|
<div class="max-w-md mx-auto">
|
2022-07-12 10:55:28 +02:00
|
|
|
<o-input
|
2021-11-07 21:02:06 +01:00
|
|
|
dir="auto"
|
2022-08-12 16:46:04 +02:00
|
|
|
:placeholder="t('Filter by profile or group name')"
|
|
|
|
v-model="actorFilterProxy"
|
|
|
|
class=""
|
2021-08-11 12:43:54 +02:00
|
|
|
/>
|
2022-04-03 22:13:06 +02:00
|
|
|
<transition-group
|
|
|
|
tag="ul"
|
|
|
|
class="grid grid-cols-1 gap-y-3 m-5 max-w-md mx-auto"
|
2022-08-12 16:46:04 +02:00
|
|
|
:class="{ hidden: actualFilteredAvailableActors.length === 0 }"
|
2022-04-03 22:13:06 +02:00
|
|
|
enter-active-class="duration-300 ease-out"
|
|
|
|
enter-from-class="transform opacity-0"
|
|
|
|
enter-to-class="opacity-100"
|
|
|
|
leave-active-class="duration-200 ease-in"
|
|
|
|
leave-from-class="opacity-100"
|
|
|
|
leave-to-class="transform opacity-0"
|
2020-09-29 09:53:48 +02:00
|
|
|
>
|
2022-04-03 22:13:06 +02:00
|
|
|
<li
|
|
|
|
class="relative focus-within:shadow-lg"
|
|
|
|
v-for="availableActor in actualFilteredAvailableActors"
|
2022-07-12 10:55:28 +02:00
|
|
|
:key="availableActor?.id"
|
2022-04-03 22:13:06 +02:00
|
|
|
>
|
|
|
|
<input
|
|
|
|
class="sr-only peer"
|
|
|
|
type="radio"
|
|
|
|
:value="availableActor"
|
|
|
|
name="availableActors"
|
|
|
|
v-model="selectedActor"
|
2022-07-12 10:55:28 +02:00
|
|
|
:id="`availableActor-${availableActor?.id}`"
|
2020-11-30 10:24:11 +01:00
|
|
|
/>
|
2022-04-03 22:13:06 +02:00
|
|
|
<label
|
2022-10-31 11:43:18 +01:00
|
|
|
class="flex flex-wrap gap-2 p-3 bg-white hover:bg-gray-50 dark:bg-violet-3 dark:hover:bg-violet-3/60 border border-gray-300 rounded-lg cursor-pointer peer-checked:ring-primary peer-checked:ring-2 peer-checked:border-transparent"
|
2022-07-12 10:55:28 +02:00
|
|
|
:for="`availableActor-${availableActor?.id}`"
|
2022-04-03 22:13:06 +02:00
|
|
|
>
|
2022-08-26 16:08:58 +02:00
|
|
|
<figure class="h-12 w-12" v-if="availableActor?.avatar">
|
2022-04-03 22:13:06 +02:00
|
|
|
<img
|
2022-08-26 16:08:58 +02:00
|
|
|
class="rounded-full h-full w-full object-cover"
|
2022-04-03 22:13:06 +02:00
|
|
|
:src="availableActor.avatar.url"
|
|
|
|
alt=""
|
2022-07-12 10:55:28 +02:00
|
|
|
width="48"
|
|
|
|
height="48"
|
2022-04-03 22:13:06 +02:00
|
|
|
/>
|
|
|
|
</figure>
|
2022-07-12 10:55:28 +02:00
|
|
|
<AccountCircle v-else :size="48" />
|
|
|
|
<div class="flex-1">
|
|
|
|
<h3>{{ availableActor?.name }}</h3>
|
|
|
|
<small>{{ `@${availableActor?.preferredUsername}` }}</small>
|
2022-04-03 22:13:06 +02:00
|
|
|
</div>
|
|
|
|
</label>
|
|
|
|
</li>
|
|
|
|
</transition-group>
|
2020-09-29 09:53:48 +02:00
|
|
|
</div>
|
|
|
|
</template>
|
2022-07-12 10:55:28 +02:00
|
|
|
<script lang="ts" setup>
|
2022-08-12 16:46:04 +02:00
|
|
|
import { IActor, IPerson } from "@/types/actor";
|
2020-11-27 19:27:44 +01:00
|
|
|
import { IMember } from "@/types/actor/member.model";
|
|
|
|
import { MemberRole } from "@/types/enums";
|
2022-08-12 16:46:04 +02:00
|
|
|
import { computed } from "vue";
|
|
|
|
import { useI18n } from "vue-i18n";
|
2022-07-12 10:55:28 +02:00
|
|
|
import AccountCircle from "vue-material-design-icons/AccountCircle.vue";
|
|
|
|
|
|
|
|
const props = withDefaults(
|
2022-08-12 16:46:04 +02:00
|
|
|
defineProps<{
|
|
|
|
currentActor: IPerson;
|
|
|
|
modelValue: IActor;
|
|
|
|
restrictModeratorLevel?: boolean;
|
|
|
|
identities: IActor[];
|
|
|
|
actorFilter: string;
|
|
|
|
groupMemberships: IMember[];
|
|
|
|
}>(),
|
2022-07-12 10:55:28 +02:00
|
|
|
{ restrictModeratorLevel: false }
|
|
|
|
);
|
|
|
|
|
2022-08-12 16:46:04 +02:00
|
|
|
const emit = defineEmits(["update:modelValue", "update:actorFilter"]);
|
2022-07-12 10:55:28 +02:00
|
|
|
|
2022-08-12 16:46:04 +02:00
|
|
|
const { t } = useI18n({ useScope: "global" });
|
2020-09-29 09:53:48 +02:00
|
|
|
|
2022-07-12 10:55:28 +02:00
|
|
|
const selectedActor = computed({
|
|
|
|
get(): IActor | undefined {
|
|
|
|
if (props.modelValue?.id) {
|
|
|
|
return props.modelValue;
|
2021-03-29 10:33:19 +02:00
|
|
|
}
|
2022-08-12 16:46:04 +02:00
|
|
|
if (props.currentActor) {
|
|
|
|
return props.identities.find(
|
|
|
|
(identity) => identity.id === props.currentActor?.id
|
2021-06-10 10:33:16 +02:00
|
|
|
);
|
2021-03-29 10:33:19 +02:00
|
|
|
}
|
|
|
|
return undefined;
|
2022-07-12 10:55:28 +02:00
|
|
|
},
|
2020-09-29 09:53:48 +02:00
|
|
|
|
2022-07-12 10:55:28 +02:00
|
|
|
set(actor: IActor | undefined) {
|
|
|
|
emit("update:modelValue", actor);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const actualMemberships = computed((): IMember[] => {
|
|
|
|
if (props.restrictModeratorLevel) {
|
2022-08-12 16:46:04 +02:00
|
|
|
return props.groupMemberships.filter((membership: IMember) =>
|
2022-07-12 10:55:28 +02:00
|
|
|
[
|
|
|
|
MemberRole.ADMINISTRATOR,
|
|
|
|
MemberRole.MODERATOR,
|
|
|
|
MemberRole.CREATOR,
|
|
|
|
].includes(membership.role)
|
|
|
|
);
|
2020-09-29 09:53:48 +02:00
|
|
|
}
|
2022-08-12 16:46:04 +02:00
|
|
|
return props.groupMemberships;
|
2022-07-12 10:55:28 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
const actualAvailableActors = computed((): (IActor | undefined)[] => {
|
|
|
|
return [
|
2022-08-12 16:46:04 +02:00
|
|
|
props.currentActor,
|
|
|
|
...props.identities.filter(
|
|
|
|
(identity: IActor) => identity.id !== props.currentActor?.id
|
2022-07-12 10:55:28 +02:00
|
|
|
),
|
|
|
|
...actualMemberships.value.map((member) => member.parent),
|
|
|
|
].filter((elem) => elem);
|
|
|
|
});
|
|
|
|
|
|
|
|
const actualFilteredAvailableActors = computed((): (IActor | undefined)[] => {
|
|
|
|
return (actualAvailableActors.value ?? []).filter((actor) => {
|
|
|
|
if (actor === undefined) return false;
|
2020-11-30 10:24:11 +01:00
|
|
|
return [
|
2022-08-12 16:46:04 +02:00
|
|
|
actor.preferredUsername?.toLowerCase(),
|
2022-07-12 10:55:28 +02:00
|
|
|
actor.name?.toLowerCase(),
|
|
|
|
actor.domain?.toLowerCase(),
|
2022-08-12 16:46:04 +02:00
|
|
|
].some((match) => match?.includes(actorFilterProxy.value.toLowerCase()));
|
2022-07-12 10:55:28 +02:00
|
|
|
});
|
|
|
|
});
|
2022-08-12 16:46:04 +02:00
|
|
|
|
|
|
|
const actorFilterProxy = computed({
|
|
|
|
get() {
|
|
|
|
return props.actorFilter;
|
|
|
|
},
|
|
|
|
set(newActorFilter: string) {
|
|
|
|
emit("update:actorFilter", newActorFilter);
|
|
|
|
},
|
|
|
|
});
|
2020-09-29 09:53:48 +02:00
|
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
2021-11-04 18:14:36 +01:00
|
|
|
@use "@/styles/_mixins" as *;
|
2022-07-12 10:55:28 +02:00
|
|
|
:deep(.list-item) {
|
2020-09-29 09:53:48 +02:00
|
|
|
box-sizing: content-box;
|
|
|
|
|
|
|
|
label.b-radio {
|
|
|
|
padding: 0.85rem 0;
|
|
|
|
|
|
|
|
.media {
|
|
|
|
padding: 0.25rem 0;
|
|
|
|
align-items: center;
|
|
|
|
|
2022-07-12 10:55:28 +02:00
|
|
|
// figure.image,
|
|
|
|
// span.icon.media-left {
|
|
|
|
// @include margin-right(0.5rem);
|
|
|
|
// }
|
2020-09-29 09:53:48 +02:00
|
|
|
|
2022-07-12 10:55:28 +02:00
|
|
|
// span.icon.media-left {
|
|
|
|
// @include margin-left(-0.25rem);
|
|
|
|
// }
|
2020-09-29 09:53:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|