gradido/admin/src/components/Federation/CommunityVisualizeItem.vue

202 lines
6.9 KiB
Vue

<template>
<div class="community-visualize-item">
<BRow v-on="{ click: toggleDetails }">
<BCol cols="1">
<variant-icon :icon="icon" :variant="variant" />
</BCol>
<BCol>
<div>
<a :href="item.url" target="_blank">{{ item.url }}</a>
</div>
<small>{{ `${item.publicKey.substring(0, 26)}` }}</small>
</BCol>
<BCol>
<span v-b-tooltip="`${item.description}`">{{ item.name }}</span>
</BCol>
<BCol cols="2">{{ lastAnnouncedAt }}</BCol>
<BCol cols="2">{{ createdAt }}</BCol>
</BRow>
<BRow v-if="details" class="details">
<BCol colspan="5">
<BListGroup>
<BListGroupItem v-if="item.uuid">
{{ $t('federation.communityUuid') }}&nbsp;{{ item.uuid }}
</BListGroupItem>
<BListGroupItem v-if="item.authenticatedAt">
{{ $t('federation.authenticatedAt') }}&nbsp;{{ item.authenticatedAt }}
</BListGroupItem>
<BListGroupItem>
{{ $t('federation.publicKey') }}&nbsp;{{ item.publicKey }}
</BListGroupItem>
<BListGroupItem v-if="!item.foreign">
<editable-group
:allow-edit="$store.state.moderator.roles.includes('ADMIN')"
@save="handleUpdateHomeCommunity"
@reset="resetHomeCommunityEditable"
>
<template #view>
<div class="d-flex">
<p style="text-wrap: nowrap">{{ $t('federation.gmsApiKey') }}&nbsp;</p>
<span class="d-block" style="overflow-x: auto">{{ gmsApiKey }}</span>
</div>
<BFormGroup>
{{ $t('federation.coordinates') }}
<span v-if="isValidLocation">
{{
$t('geo-coordinates.format', {
latitude: location.latitude,
longitude: location.longitude,
})
}}
</span>
</BFormGroup>
</template>
<template #edit>
<editable-groupable-label
v-model="gmsApiKey"
:label="$t('federation.gmsApiKey')"
id-name="home-community-api-key"
/>
<coordinates v-model="location" />
</template>
</editable-group>
</BListGroupItem>
<BListGroup-item>
<BListGroup>
<BRow>
<BCol class="ms-1">{{ $t('federation.verified') }}</BCol>
<BCol>{{ $t('federation.apiVersion') }}</BCol>
<BCol>{{ $t('federation.createdAt') }}</BCol>
<BCol>{{ $t('federation.lastAnnouncedAt') }}</BCol>
<BCol>{{ $t('federation.verifiedAt') }}</BCol>
<BCol>{{ $t('federation.lastErrorAt') }}</BCol>
</BRow>
<BListGroup-item
v-for="federation in item.federatedCommunities"
:key="federation.id"
:variant="!item.foreign ? 'primary' : 'warning'"
>
<federation-visualize-item :item="federation" />
</BListGroup-item>
</BListGroup>
</BListGroup-item>
</BListGroup>
</BCol>
</BRow>
</div>
</template>
<script setup>
import { ref, computed, toRefs } from 'vue'
import { useI18n } from 'vue-i18n'
import { useDateLocale } from '@/composables/useDateLocale'
import { useMutation } from '@vue/apollo-composable'
import { formatDistanceToNow } from 'date-fns'
import EditableGroup from '@/components/input/EditableGroup.vue'
import FederationVisualizeItem from './FederationVisualizeItem.vue'
import { updateHomeCommunity } from '@/graphql/updateHomeCommunity'
import Coordinates from '../input/Coordinates.vue'
import EditableGroupableLabel from '../input/EditableGroupableLabel.vue'
import { useAppToast } from '@/composables/useToast'
const props = defineProps({
item: { type: Object, required: true },
})
const { item } = toRefs(props)
const { t } = useI18n()
const { toastSuccess, toastError } = useAppToast()
const details = ref(false)
const gmsApiKey = ref(item.value.gmsApiKey)
const location = ref(item.value.location)
const originalGmsApiKey = ref(item.value.gmsApiKey)
const originalLocation = ref(item.value.location)
const { mutate: updateHomeCommunityMutation } = useMutation(updateHomeCommunity)
const verified = computed(() => {
if (!item.value.federatedCommunities || item.value.federatedCommunities.length === 0) {
return false
}
return item.value.federatedCommunities.some(
(federatedCommunity) =>
new Date(federatedCommunity.verifiedAt) >= new Date(federatedCommunity.lastAnnouncedAt),
)
})
const icon = computed(() => (verified.value ? 'check' : 'x-circle'))
const variant = computed(() => (verified.value ? 'success' : 'danger'))
const lastAnnouncedAt = computed(() => {
if (!item.value.federatedCommunities || item.value.federatedCommunities.length === 0) return ''
const minDate = new Date(0)
const lastAnnouncedAt = item.value.federatedCommunities.reduce(
(lastAnnouncedAt, federateCommunity) => {
if (!federateCommunity.lastAnnouncedAt) return lastAnnouncedAt
const date = new Date(federateCommunity.lastAnnouncedAt)
return date > lastAnnouncedAt ? date : lastAnnouncedAt
},
minDate,
)
if (lastAnnouncedAt !== minDate) {
return formatDistanceToNow(lastAnnouncedAt, {
includeSecond: true,
addSuffix: true,
locale: useDateLocale(),
})
}
return ''
})
const createdAt = computed(() => {
if (item.value.createdAt) {
return formatDistanceToNow(new Date(item.value.createdAt), {
includeSecond: true,
addSuffix: true,
locale: useDateLocale(),
})
}
return ''
})
const isLocationChanged = computed(() => originalLocation.value !== location.value)
const isGMSApiKeyChanged = computed(() => originalGmsApiKey.value !== gmsApiKey.value)
const isValidLocation = computed(
() => location.value && location.value.latitude && location.value.longitude,
)
const toggleDetails = () => {
details.value = !details.value
}
const handleUpdateHomeCommunity = async () => {
try {
await updateHomeCommunityMutation({
uuid: item.value.uuid,
gmsApiKey: gmsApiKey.value,
location: location.value,
})
if (isLocationChanged.value && isGMSApiKeyChanged.value) {
toastSuccess(t('federation.toast_gmsApiKeyAndLocationUpdated'))
} else if (isGMSApiKeyChanged.value) {
toastSuccess(t('federation.toast_gmsApiKeyUpdated'))
} else if (isLocationChanged.value) {
toastSuccess(t('federation.toast_gmsLocationUpdated'))
}
originalLocation.value = location.value
originalGmsApiKey.value = gmsApiKey.value
} catch (error) {
toastError(error.message)
}
}
const resetHomeCommunityEditable = () => {
location.value = originalLocation.value
gmsApiKey.value = originalGmsApiKey.value
}
</script>