mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-20 15:23:50 +02:00
replace el-dialog
This commit is contained in:
@@ -1,56 +1,58 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="x-dialog"
|
||||
v-model="bioDialog.visible"
|
||||
:title="t('dialog.bio.header')"
|
||||
width="600px"
|
||||
append-to-body>
|
||||
<div v-loading="bioDialog.loading">
|
||||
<InputGroupTextareaField
|
||||
v-model="bioDialog.bio"
|
||||
:maxlength="512"
|
||||
:rows="5"
|
||||
:placeholder="t('dialog.bio.bio_placeholder')"
|
||||
class="mb-2.5"
|
||||
show-count />
|
||||
<Dialog v-model:open="bioDialog.visible">
|
||||
<DialogContent class="x-dialog sm:max-w-150">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{{ t('dialog.bio.header') }}</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<InputGroupAction
|
||||
v-for="(link, index) in bioDialog.bioLinks"
|
||||
:key="index"
|
||||
v-model="bioDialog.bioLinks[index]"
|
||||
:maxlength="64"
|
||||
show-count
|
||||
size="sm"
|
||||
style="margin-top: 5px">
|
||||
<template #leading>
|
||||
<img :src="getFaviconUrl(link)" style="width: 16px; height: 16px; vertical-align: middle" />
|
||||
</template>
|
||||
<template #actions>
|
||||
<Button variant="ghost" size="icon-sm" @click="bioDialog.bioLinks.splice(index, 1)"
|
||||
><Trash2 class="size-4"
|
||||
/></Button>
|
||||
</template>
|
||||
</InputGroupAction>
|
||||
<div v-loading="bioDialog.loading">
|
||||
<InputGroupTextareaField
|
||||
v-model="bioDialog.bio"
|
||||
:maxlength="512"
|
||||
:rows="5"
|
||||
:placeholder="t('dialog.bio.bio_placeholder')"
|
||||
class="mb-2.5"
|
||||
show-count />
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
:disabled="bioDialog.bioLinks.length >= 3"
|
||||
size="sm"
|
||||
class="mt-2"
|
||||
@click="bioDialog.bioLinks.push('')">
|
||||
{{ t('dialog.bio.add_link') }}
|
||||
</Button>
|
||||
</div>
|
||||
<InputGroupAction
|
||||
v-for="(link, index) in bioDialog.bioLinks"
|
||||
:key="index"
|
||||
v-model="bioDialog.bioLinks[index]"
|
||||
:maxlength="64"
|
||||
show-count
|
||||
size="sm"
|
||||
style="margin-top: 5px">
|
||||
<template #leading>
|
||||
<img :src="getFaviconUrl(link)" style="width: 16px; height: 16px; vertical-align: middle" />
|
||||
</template>
|
||||
<template #actions>
|
||||
<Button variant="ghost" size="icon-sm" @click="bioDialog.bioLinks.splice(index, 1)"
|
||||
><Trash2 class="size-4"
|
||||
/></Button>
|
||||
</template>
|
||||
</InputGroupAction>
|
||||
|
||||
<template #footer>
|
||||
<Button :disabled="bioDialog.loading" @click="saveBio">
|
||||
{{ t('dialog.bio.update') }}
|
||||
</Button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<Button
|
||||
variant="outline"
|
||||
:disabled="bioDialog.bioLinks.length >= 3"
|
||||
size="sm"
|
||||
class="mt-2"
|
||||
@click="bioDialog.bioLinks.push('')">
|
||||
{{ t('dialog.bio.add_link') }}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<Button :disabled="bioDialog.loading" @click="saveBio">
|
||||
{{ t('dialog.bio.update') }}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import { InputGroupAction, InputGroupTextareaField } from '@/components/ui/input-group';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Trash2 } from 'lucide-vue-next';
|
||||
|
||||
@@ -1,45 +1,49 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="x-dialog"
|
||||
:model-value="props.visible"
|
||||
title="Edit Note And Memo"
|
||||
:show-close="false"
|
||||
top="30vh"
|
||||
width="500px"
|
||||
append-to-body
|
||||
@close="cancel">
|
||||
<template v-if="!hideUserNotes || (hideUserNotes && hideUserMemos)">
|
||||
<span class="name my-2">{{ t('dialog.user.info.note') }}</span>
|
||||
<br />
|
||||
<InputGroupTextareaField
|
||||
v-model="note"
|
||||
:autosize="{ minRows: 6, maxRows: 20 }"
|
||||
:maxlength="256"
|
||||
:rows="6"
|
||||
:placeholder="t('dialog.user.info.note_placeholder')"
|
||||
input-class="extra resize-none"
|
||||
class="my-2"
|
||||
show-count />
|
||||
</template>
|
||||
<template v-if="!hideUserMemos || (hideUserNotes && hideUserMemos)">
|
||||
<span class="name">{{ t('dialog.user.info.memo') }}</span>
|
||||
<InputGroupTextareaField
|
||||
v-model="memo"
|
||||
class="extra mt-2"
|
||||
:rows="6"
|
||||
:placeholder="t('dialog.user.info.memo_placeholder')"
|
||||
input-class="resize-none min-h-0" />
|
||||
</template>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<Dialog
|
||||
:open="props.visible"
|
||||
@update:open="
|
||||
(open) => {
|
||||
if (!open) cancel();
|
||||
}
|
||||
">
|
||||
<DialogContent class="x-dialog sm:max-w-125 translate-y-0" style="top: 30vh" :show-close-button="false">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Edit Note And Memo</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<template v-if="!hideUserNotes || (hideUserNotes && hideUserMemos)">
|
||||
<span class="name my-2">{{ t('dialog.user.info.note') }}</span>
|
||||
<br />
|
||||
<InputGroupTextareaField
|
||||
v-model="note"
|
||||
:autosize="{ minRows: 6, maxRows: 20 }"
|
||||
:maxlength="256"
|
||||
:rows="6"
|
||||
:placeholder="t('dialog.user.info.note_placeholder')"
|
||||
input-class="extra resize-none"
|
||||
class="my-2"
|
||||
show-count />
|
||||
</template>
|
||||
<template v-if="!hideUserMemos || (hideUserNotes && hideUserMemos)">
|
||||
<span class="name">{{ t('dialog.user.info.memo') }}</span>
|
||||
<InputGroupTextareaField
|
||||
v-model="memo"
|
||||
class="extra mt-2"
|
||||
:rows="6"
|
||||
:placeholder="t('dialog.user.info.memo_placeholder')"
|
||||
input-class="resize-none min-h-0" />
|
||||
</template>
|
||||
|
||||
<DialogFooter>
|
||||
<Button variant="secondary" @click="cancel" class="mr-2">Cancel</Button>
|
||||
<Button @click="saveChanges">Confirm</Button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import { ref, watch } from 'vue';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { InputGroupTextareaField } from '@/components/ui/input-group';
|
||||
|
||||
@@ -1,63 +1,67 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="x-dialog"
|
||||
v-model="languageDialog.visible"
|
||||
:title="t('dialog.language.header')"
|
||||
width="400px"
|
||||
append-to-body>
|
||||
<div v-loading="languageDialog.loading">
|
||||
<div v-for="item in currentUser.$languages" :key="item.key" style="margin: 6px 0">
|
||||
<Badge variant="outline" style="margin-right: 5px">
|
||||
<span
|
||||
class="flags"
|
||||
:class="languageClass(item.key)"
|
||||
style="display: inline-block; margin-right: 5px"></span>
|
||||
{{ item.value }} ({{ item.key.toUpperCase() }})
|
||||
<button
|
||||
type="button"
|
||||
style="
|
||||
margin-left: 6px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
"
|
||||
@click="removeUserLanguage(item.key)">
|
||||
<X class="h-3 w-3" />
|
||||
</button>
|
||||
</Badge>
|
||||
<Dialog v-model:open="languageDialog.visible">
|
||||
<DialogContent class="x-dialog sm:max-w-100">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{{ t('dialog.language.header') }}</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<div v-loading="languageDialog.loading">
|
||||
<div v-for="item in currentUser.$languages" :key="item.key" style="margin: 6px 0">
|
||||
<Badge variant="outline" style="margin-right: 5px">
|
||||
<span
|
||||
class="flags"
|
||||
:class="languageClass(item.key)"
|
||||
style="display: inline-block; margin-right: 5px"></span>
|
||||
{{ item.value }} ({{ item.key.toUpperCase() }})
|
||||
<button
|
||||
type="button"
|
||||
style="
|
||||
margin-left: 6px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
"
|
||||
@click="removeUserLanguage(item.key)">
|
||||
<X class="h-3 w-3" />
|
||||
</button>
|
||||
</Badge>
|
||||
</div>
|
||||
<Select
|
||||
:model-value="selectedLanguageToAdd"
|
||||
:disabled="
|
||||
languageDialog.loading || (currentUser.$languages && currentUser.$languages.length === 3)
|
||||
"
|
||||
@update:modelValue="handleAddUserLanguage">
|
||||
<SelectTrigger size="sm" style="margin-top: 14px">
|
||||
<SelectValue :placeholder="t('dialog.language.select_language')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem
|
||||
v-for="item in languageDialog.languages"
|
||||
:key="item.key"
|
||||
:value="item.key"
|
||||
:text-value="item.value">
|
||||
<span
|
||||
class="flags"
|
||||
:class="languageClass(item.key)"
|
||||
style="display: inline-block; margin-right: 5px"></span>
|
||||
{{ item.value }} ({{ item.key.toUpperCase() }})
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<Select
|
||||
:model-value="selectedLanguageToAdd"
|
||||
:disabled="languageDialog.loading || (currentUser.$languages && currentUser.$languages.length === 3)"
|
||||
@update:modelValue="handleAddUserLanguage">
|
||||
<SelectTrigger size="sm" style="margin-top: 14px">
|
||||
<SelectValue :placeholder="t('dialog.language.select_language')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem
|
||||
v-for="item in languageDialog.languages"
|
||||
:key="item.key"
|
||||
:value="item.key"
|
||||
:text-value="item.value">
|
||||
<span
|
||||
class="flags"
|
||||
:class="languageClass(item.key)"
|
||||
style="display: inline-block; margin-right: 5px"></span>
|
||||
{{ item.value }} ({{ item.key.toUpperCase() }})
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import { X } from 'lucide-vue-next';
|
||||
import { ref } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
@@ -1,35 +1,37 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:z-index="previousInstancesUserDialogIndex"
|
||||
v-model="isVisible"
|
||||
:title="t('dialog.previous_instances.header')"
|
||||
width="1000px"
|
||||
append-to-body>
|
||||
<DataTableLayout
|
||||
class="min-w-0 w-full"
|
||||
:table="table"
|
||||
:loading="loading"
|
||||
:table-style="tableStyle"
|
||||
:page-sizes="pageSizes"
|
||||
:total-items="totalItems"
|
||||
:on-page-size-change="handlePageSizeChange">
|
||||
<template #toolbar>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between">
|
||||
<span style="font-size: 14px" v-text="previousInstancesUserDialog.userRef.displayName"></span>
|
||||
<InputGroupField
|
||||
v-model="search"
|
||||
:placeholder="t('dialog.previous_instances.search_placeholder')"
|
||||
clearable
|
||||
class="w-1/3"
|
||||
style="display: block" />
|
||||
</div>
|
||||
</template>
|
||||
</DataTableLayout>
|
||||
</el-dialog>
|
||||
<Dialog v-model:open="isVisible">
|
||||
<DialogContent class="sm:max-w-250">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{{ t('dialog.previous_instances.header') }}</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<DataTableLayout
|
||||
class="min-w-0 w-full"
|
||||
:table="table"
|
||||
:loading="loading"
|
||||
:table-style="tableStyle"
|
||||
:page-sizes="pageSizes"
|
||||
:total-items="totalItems"
|
||||
:on-page-size-change="handlePageSizeChange">
|
||||
<template #toolbar>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between">
|
||||
<span style="font-size: 14px" v-text="previousInstancesUserDialog.userRef.displayName"></span>
|
||||
<InputGroupField
|
||||
v-model="search"
|
||||
:placeholder="t('dialog.previous_instances.search_placeholder')"
|
||||
clearable
|
||||
class="w-1/3"
|
||||
style="display: block" />
|
||||
</div>
|
||||
</template>
|
||||
</DataTableLayout>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, nextTick, ref, watch } from 'vue';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { InputGroupField } from '@/components/ui/input-group';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
@@ -52,7 +54,6 @@
|
||||
import { DataTableLayout } from '../../ui/data-table';
|
||||
import { createColumns } from './previousInstancesUserColumns.jsx';
|
||||
import { database } from '../../../service/database';
|
||||
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
|
||||
import { useVrcxVueTable } from '../../../lib/table/useVrcxVueTable';
|
||||
|
||||
const props = defineProps({
|
||||
@@ -90,8 +91,6 @@
|
||||
const vrcxStore = useVrcxStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
const previousInstancesUserDialogIndex = ref(2000);
|
||||
|
||||
const isVisible = computed({
|
||||
get: () => props.previousInstancesUserDialog.visible,
|
||||
set: (value) => {
|
||||
@@ -178,9 +177,6 @@
|
||||
() => props.previousInstancesUserDialog.openFlg,
|
||||
() => {
|
||||
if (props.previousInstancesUserDialog.visible) {
|
||||
nextTick(() => {
|
||||
previousInstancesUserDialogIndex.value = getNextDialogIndex();
|
||||
});
|
||||
refreshPreviousInstancesUserTable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,30 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="x-dialog"
|
||||
v-model="pronounsDialog.visible"
|
||||
:title="t('dialog.pronouns.header')"
|
||||
width="600px"
|
||||
append-to-body>
|
||||
<div v-loading="pronounsDialog.loading">
|
||||
<InputGroupTextareaField
|
||||
v-model="pronounsDialog.pronouns"
|
||||
:maxlength="32"
|
||||
:rows="2"
|
||||
:placeholder="t('dialog.pronouns.pronouns_placeholder')"
|
||||
show-count />
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button :disabled="pronounsDialog.loading" @click="savePronouns">
|
||||
{{ t('dialog.pronouns.update') }}
|
||||
</Button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<Dialog v-model:open="pronounsDialog.visible">
|
||||
<DialogContent class="x-dialog sm:max-w-150">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{{ t('dialog.pronouns.header') }}</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<div v-loading="pronounsDialog.loading">
|
||||
<InputGroupTextareaField
|
||||
v-model="pronounsDialog.pronouns"
|
||||
:maxlength="32"
|
||||
:rows="2"
|
||||
:placeholder="t('dialog.pronouns.pronouns_placeholder')"
|
||||
show-count />
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<Button :disabled="pronounsDialog.loading" @click="savePronouns">
|
||||
{{ t('dialog.pronouns.update') }}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { InputGroupTextareaField } from '@/components/ui/input-group';
|
||||
import { toast } from 'vue-sonner';
|
||||
|
||||
@@ -1,30 +1,37 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="x-dialog"
|
||||
:model-value="sendInviteRequestDialogVisible"
|
||||
:title="t('dialog.invite_request_message.header')"
|
||||
width="800px"
|
||||
append-to-body
|
||||
@close="cancelSendInviteRequest">
|
||||
<template v-if="isLocalUserVrcPlusSupporter">
|
||||
<input class="inviteImageUploadButton" type="file" accept="image/*" @change="inviteImageUpload" />
|
||||
</template>
|
||||
<Dialog
|
||||
:open="sendInviteRequestDialogVisible"
|
||||
@update:open="
|
||||
(open) => {
|
||||
if (!open) cancelSendInviteRequest();
|
||||
}
|
||||
">
|
||||
<DialogContent class="x-dialog sm:max-w-200">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{{ t('dialog.invite_request_message.header') }}</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<DataTableLayout
|
||||
style="margin-top: 10px"
|
||||
:table="inviteRequestMessageTanstackTable"
|
||||
:loading="false"
|
||||
:show-pagination="false"
|
||||
:on-row-click="handleInviteRequestMessageRowClick" />
|
||||
<template v-if="isLocalUserVrcPlusSupporter">
|
||||
<input class="inviteImageUploadButton" type="file" accept="image/*" @change="inviteImageUpload" />
|
||||
</template>
|
||||
|
||||
<DataTableLayout
|
||||
style="margin-top: 10px"
|
||||
:table="inviteRequestMessageTanstackTable"
|
||||
:loading="false"
|
||||
:show-pagination="false"
|
||||
:on-row-click="handleInviteRequestMessageRowClick" />
|
||||
|
||||
<DialogFooter>
|
||||
<Button variant="secondary" class="mr-2" @click="cancelSendInviteRequest">{{
|
||||
t('dialog.invite_request_message.cancel')
|
||||
}}</Button>
|
||||
<Button @click="refreshInviteMessageTableData('request')">{{
|
||||
t('dialog.invite_request_message.refresh')
|
||||
}}</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
|
||||
<template #footer>
|
||||
<Button variant="secondary" class="mr-2" @click="cancelSendInviteRequest">{{
|
||||
t('dialog.invite_request_message.cancel')
|
||||
}}</Button>
|
||||
<Button @click="refreshInviteMessageTableData('request')">{{
|
||||
t('dialog.invite_request_message.refresh')
|
||||
}}</Button>
|
||||
</template>
|
||||
<SendInviteConfirmDialog
|
||||
v-model:isSendInviteConfirmDialogVisible="isSendInviteConfirmDialogVisible"
|
||||
:sendInviteDialog="sendInviteDialog"
|
||||
@@ -37,10 +44,11 @@
|
||||
@update:sendInviteDialog="emit('update:sendInviteDialog', $event)"
|
||||
:invite-dialog="inviteDialog"
|
||||
@closeInviteDialog="closeInviteDialog" />
|
||||
</el-dialog>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import { computed, ref } from 'vue';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { DataTableLayout } from '@/components/ui/data-table';
|
||||
|
||||
@@ -1,96 +1,98 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="x-dialog"
|
||||
v-model="socialStatusDialog.visible"
|
||||
:title="t('dialog.social_status.header')"
|
||||
append-to-body
|
||||
width="400px">
|
||||
<div v-loading="socialStatusDialog.loading">
|
||||
<Select :model-value="socialStatusDialog.status" @update:modelValue="handleSocialStatusChange">
|
||||
<SelectTrigger size="sm" style="margin-top: 10px; width: 100%">
|
||||
<span class="flex items-center gap-2">
|
||||
<i v-if="socialStatusDialog.status === 'join me'" class="x-user-status joinme"></i>
|
||||
<i v-else-if="socialStatusDialog.status === 'active'" class="x-user-status online"></i>
|
||||
<i v-else-if="socialStatusDialog.status === 'ask me'" class="x-user-status askme"></i>
|
||||
<i v-else-if="socialStatusDialog.status === 'busy'" class="x-user-status busy"></i>
|
||||
<i v-else-if="socialStatusDialog.status === 'offline'" class="x-user-status offline"></i>
|
||||
<SelectValue :placeholder="t('dialog.social_status.status_placeholder')" />
|
||||
</span>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="join me" :text-value="t('dialog.user.status.join_me')">
|
||||
<i class="x-user-status joinme"></i> {{ t('dialog.user.status.join_me') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="active" :text-value="t('dialog.user.status.online')">
|
||||
<i class="x-user-status online"></i> {{ t('dialog.user.status.online') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="ask me" :text-value="t('dialog.user.status.ask_me')">
|
||||
<i class="x-user-status askme"></i> {{ t('dialog.user.status.ask_me') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="busy" :text-value="t('dialog.user.status.busy')">
|
||||
<i class="x-user-status busy"></i> {{ t('dialog.user.status.busy') }}
|
||||
</SelectItem>
|
||||
<SelectItem
|
||||
v-if="currentUser.$isModerator"
|
||||
value="offline"
|
||||
:text-value="t('dialog.user.status.offline')">
|
||||
<i class="x-user-status offline"></i> {{ t('dialog.user.status.offline') }}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Dialog v-model:open="socialStatusDialog.visible">
|
||||
<DialogContent class="x-dialog sm:max-w-100">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{{ t('dialog.social_status.header') }}</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<InputGroupField
|
||||
v-model="socialStatusDialog.statusDescription"
|
||||
:placeholder="t('dialog.social_status.status_placeholder')"
|
||||
:maxlength="32"
|
||||
clearable
|
||||
show-count
|
||||
class="mt-2.5" />
|
||||
<Collapsible v-model:open="isOpen" class="mt-3 flex w-full flex-col gap-2">
|
||||
<div class="flex items-center justify-between gap-4 px-4">
|
||||
<h4 class="text-sm font-semibold">{{ t('dialog.social_status.history') }}</h4>
|
||||
<CollapsibleTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="size-8">
|
||||
<ChevronsUpDown />
|
||||
<span class="sr-only">Toggle</span>
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
</div>
|
||||
<div
|
||||
v-if="!isOpen && latestHistoryItem"
|
||||
class="cursor-pointer rounded-md border w-full px-4 py-2 font-mono text-sm"
|
||||
@click="setSocialStatusFromHistory(latestHistoryItem)">
|
||||
{{ latestHistoryItem.status }}
|
||||
</div>
|
||||
<CollapsibleContent class="flex flex-col gap-2">
|
||||
<div
|
||||
v-for="item in historyItems"
|
||||
:key="item.no ?? item.status"
|
||||
class="cursor-pointer rounded-md border w-full px-4 py-2 font-mono text-sm"
|
||||
@click="setSocialStatusFromHistory(item)">
|
||||
{{ item.status }}
|
||||
<div v-loading="socialStatusDialog.loading">
|
||||
<Select :model-value="socialStatusDialog.status" @update:modelValue="handleSocialStatusChange">
|
||||
<SelectTrigger size="sm" style="margin-top: 10px; width: 100%">
|
||||
<span class="flex items-center gap-2">
|
||||
<i v-if="socialStatusDialog.status === 'join me'" class="x-user-status joinme"></i>
|
||||
<i v-else-if="socialStatusDialog.status === 'active'" class="x-user-status online"></i>
|
||||
<i v-else-if="socialStatusDialog.status === 'ask me'" class="x-user-status askme"></i>
|
||||
<i v-else-if="socialStatusDialog.status === 'busy'" class="x-user-status busy"></i>
|
||||
<i v-else-if="socialStatusDialog.status === 'offline'" class="x-user-status offline"></i>
|
||||
<SelectValue :placeholder="t('dialog.social_status.status_placeholder')" />
|
||||
</span>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="join me" :text-value="t('dialog.user.status.join_me')">
|
||||
<i class="x-user-status joinme"></i> {{ t('dialog.user.status.join_me') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="active" :text-value="t('dialog.user.status.online')">
|
||||
<i class="x-user-status online"></i> {{ t('dialog.user.status.online') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="ask me" :text-value="t('dialog.user.status.ask_me')">
|
||||
<i class="x-user-status askme"></i> {{ t('dialog.user.status.ask_me') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="busy" :text-value="t('dialog.user.status.busy')">
|
||||
<i class="x-user-status busy"></i> {{ t('dialog.user.status.busy') }}
|
||||
</SelectItem>
|
||||
<SelectItem
|
||||
v-if="currentUser.$isModerator"
|
||||
value="offline"
|
||||
:text-value="t('dialog.user.status.offline')">
|
||||
<i class="x-user-status offline"></i> {{ t('dialog.user.status.offline') }}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<InputGroupField
|
||||
v-model="socialStatusDialog.statusDescription"
|
||||
:placeholder="t('dialog.social_status.status_placeholder')"
|
||||
:maxlength="32"
|
||||
clearable
|
||||
show-count
|
||||
class="mt-2.5" />
|
||||
<Collapsible v-model:open="isOpen" class="mt-3 flex w-full flex-col gap-2">
|
||||
<div class="flex items-center justify-between gap-4 px-4">
|
||||
<h4 class="text-sm font-semibold">{{ t('dialog.social_status.history') }}</h4>
|
||||
<CollapsibleTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="size-8">
|
||||
<ChevronsUpDown />
|
||||
<span class="sr-only">Toggle</span>
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
</div>
|
||||
<div
|
||||
v-if="!isOpen && latestHistoryItem"
|
||||
class="cursor-pointer rounded-md border w-full px-4 py-2 font-mono text-sm"
|
||||
@click="setSocialStatusFromHistory(latestHistoryItem)">
|
||||
{{ latestHistoryItem.status }}
|
||||
</div>
|
||||
<CollapsibleContent class="flex flex-col gap-2">
|
||||
<div
|
||||
v-for="item in historyItems"
|
||||
:key="item.no ?? item.status"
|
||||
class="cursor-pointer rounded-md border w-full px-4 py-2 font-mono text-sm"
|
||||
@click="setSocialStatusFromHistory(item)">
|
||||
{{ item.status }}
|
||||
</div>
|
||||
</CollapsibleContent></Collapsible
|
||||
>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<Button :disabled="socialStatusDialog.loading" @click="saveSocialStatus">
|
||||
{{ t('dialog.social_status.update') }}
|
||||
</Button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<DialogFooter>
|
||||
<Button :disabled="socialStatusDialog.loading" @click="saveSocialStatus">
|
||||
{{ t('dialog.social_status.update') }}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
|
||||
import { computed, ref } from 'vue';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { InputGroupField } from '@/components/ui/input-group';
|
||||
import { ChevronsUpDown } from 'lucide-vue-next';
|
||||
import { InputGroupField } from '@/components/ui/input-group';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { toast } from 'vue-sonner';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user