mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-06 14:46:04 +02:00
Add invite message editing to tools tab
This commit is contained in:
@@ -16,12 +16,10 @@
|
|||||||
<div style="flex: 1; display: flex; align-items: center; margin-left: 15px">
|
<div style="flex: 1; display: flex; align-items: center; margin-left: 15px">
|
||||||
<div style="flex: 1">
|
<div style="flex: 1">
|
||||||
<div>
|
<div>
|
||||||
<el-popover placement="top" trigger="click">
|
|
||||||
<template #reference>
|
|
||||||
<span
|
<span
|
||||||
class="dialog-title"
|
class="dialog-title"
|
||||||
style="margin-right: 5px; cursor: pointer"
|
style="margin-right: 5px; cursor: pointer"
|
||||||
@click="copyToClipboard(worldDialog.ref.name)">
|
@click="copyWorldName">
|
||||||
<el-icon
|
<el-icon
|
||||||
v-if="
|
v-if="
|
||||||
currentUser.$homeLocation &&
|
currentUser.$homeLocation &&
|
||||||
@@ -32,11 +30,6 @@
|
|||||||
/></el-icon>
|
/></el-icon>
|
||||||
{{ worldDialog.ref.name }}
|
{{ worldDialog.ref.name }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
|
||||||
<span style="display: block; text-align: center; font-family: monospace">{{
|
|
||||||
textToHex(worldDialog.ref.name)
|
|
||||||
}}</span>
|
|
||||||
</el-popover>
|
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 5px">
|
<div style="margin-top: 5px">
|
||||||
<span
|
<span
|
||||||
|
|||||||
+12
-12
@@ -376,6 +376,11 @@
|
|||||||
"screenshot_description": "Manage screenshots and view metadata",
|
"screenshot_description": "Manage screenshots and view metadata",
|
||||||
"inventory": "VRC+ Images & Inventory Management",
|
"inventory": "VRC+ Images & Inventory Management",
|
||||||
"inventory_description": "Manage VRC+ Images & Inventory"
|
"inventory_description": "Manage VRC+ Images & Inventory"
|
||||||
|
},
|
||||||
|
"other": {
|
||||||
|
"header": "Other",
|
||||||
|
"edit_invite_message": "Edit Invite Messages",
|
||||||
|
"edit_invite_message_description": "Edit invite and invite response messages"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
@@ -400,18 +405,6 @@
|
|||||||
"vrc_sdk_downloads": {
|
"vrc_sdk_downloads": {
|
||||||
"header": "VRC SDK Downloads"
|
"header": "VRC SDK Downloads"
|
||||||
},
|
},
|
||||||
"direct_access": {
|
|
||||||
"header": "Direct Access",
|
|
||||||
"username": "Username",
|
|
||||||
"user_id": "User ID",
|
|
||||||
"world_instance": "World/Instance",
|
|
||||||
"avatar": "Avatar"
|
|
||||||
},
|
|
||||||
"invite_messages": "Invite Messages",
|
|
||||||
"invite_response_messages": "Invite Response Messages",
|
|
||||||
"invite_request_messages": "Invite Request Messages",
|
|
||||||
"invite_request_response_messages": "Invite Request Response Messages",
|
|
||||||
"past_display_names": "Past Display Names",
|
|
||||||
"config_json": "Config JSON",
|
"config_json": "Config JSON",
|
||||||
"current_user_json": "Current User JSON",
|
"current_user_json": "Current User JSON",
|
||||||
"feedback": "Feedback",
|
"feedback": "Feedback",
|
||||||
@@ -1601,6 +1594,13 @@
|
|||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"save": "Save"
|
"save": "Save"
|
||||||
},
|
},
|
||||||
|
"edit_invite_messages": {
|
||||||
|
"header": "Edit Invite Messages",
|
||||||
|
"invite_message_tab": "Invite",
|
||||||
|
"invite_request_tab": "Invite Request",
|
||||||
|
"invite_request_response_tab": "Invite Request Response",
|
||||||
|
"invite_response_tab": "Invite Response"
|
||||||
|
},
|
||||||
"invite_message": {
|
"invite_message": {
|
||||||
"header": "Send Invite Message",
|
"header": "Send Invite Message",
|
||||||
"confirmation": "Are you sure you want to send?",
|
"confirmation": "Are you sure you want to send?",
|
||||||
|
|||||||
@@ -155,6 +155,30 @@
|
|||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tool-category">
|
||||||
|
<div class="category-header" @click="toggleCategory('other')">
|
||||||
|
<el-icon class="rotation-transition" :class="{ 'is-rotated': !categoryCollapsed['other'] }"
|
||||||
|
><ArrowRight
|
||||||
|
/></el-icon>
|
||||||
|
<span class="category-title">{{ t('view.tools.other.header') }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="tools-grid" v-show="!categoryCollapsed['other']">
|
||||||
|
<el-card :body-style="{ padding: '0px' }" class="tool-card">
|
||||||
|
<div class="tool-content" @click="showEditInviteMessageDialog">
|
||||||
|
<div class="tool-icon">
|
||||||
|
<i class="ri-edit-box-line"></i>
|
||||||
|
</div>
|
||||||
|
<div class="tool-info">
|
||||||
|
<div class="tool-name">{{ t('view.tools.other.edit_invite_message') }}</div>
|
||||||
|
<div class="tool-description">
|
||||||
|
{{ t('view.tools.other.edit_invite_message_description') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="isToolsTabVisible">
|
<template v-if="isToolsTabVisible">
|
||||||
@@ -175,6 +199,9 @@
|
|||||||
v-model:isExportFriendsListDialogVisible="isExportFriendsListDialogVisible"
|
v-model:isExportFriendsListDialogVisible="isExportFriendsListDialogVisible"
|
||||||
:friends="friends" />
|
:friends="friends" />
|
||||||
<ExportAvatarsListDialog v-model:isExportAvatarsListDialogVisible="isExportAvatarsListDialogVisible" />
|
<ExportAvatarsListDialog v-model:isExportAvatarsListDialogVisible="isExportAvatarsListDialogVisible" />
|
||||||
|
<EditInviteMessageDialog
|
||||||
|
v-model:isEditInviteMessagesDialogVisible="isEditInviteMessagesDialogVisible"
|
||||||
|
@close="isEditInviteMessagesDialogVisible = false" />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -193,6 +220,7 @@
|
|||||||
const ScreenshotMetadataDialog = defineAsyncComponent(() => import('./dialogs/ScreenshotMetadataDialog.vue'));
|
const ScreenshotMetadataDialog = defineAsyncComponent(() => import('./dialogs/ScreenshotMetadataDialog.vue'));
|
||||||
const NoteExportDialog = defineAsyncComponent(() => import('./dialogs/NoteExportDialog.vue'));
|
const NoteExportDialog = defineAsyncComponent(() => import('./dialogs/NoteExportDialog.vue'));
|
||||||
const GalleryDialog = defineAsyncComponent(() => import('./dialogs/GalleryDialog.vue'));
|
const GalleryDialog = defineAsyncComponent(() => import('./dialogs/GalleryDialog.vue'));
|
||||||
|
const EditInviteMessageDialog = defineAsyncComponent(() => import('./dialogs/EditInviteMessagesDialog.vue'));
|
||||||
|
|
||||||
const ExportDiscordNamesDialog = defineAsyncComponent(() => import('./dialogs/ExportDiscordNamesDialog.vue'));
|
const ExportDiscordNamesDialog = defineAsyncComponent(() => import('./dialogs/ExportDiscordNamesDialog.vue'));
|
||||||
const ExportFriendsListDialog = defineAsyncComponent(() => import('./dialogs/ExportFriendsListDialog.vue'));
|
const ExportFriendsListDialog = defineAsyncComponent(() => import('./dialogs/ExportFriendsListDialog.vue'));
|
||||||
@@ -215,6 +243,7 @@
|
|||||||
const isExportDiscordNamesDialogVisible = ref(false);
|
const isExportDiscordNamesDialogVisible = ref(false);
|
||||||
const isExportFriendsListDialogVisible = ref(false);
|
const isExportFriendsListDialogVisible = ref(false);
|
||||||
const isExportAvatarsListDialogVisible = ref(false);
|
const isExportAvatarsListDialogVisible = ref(false);
|
||||||
|
const isEditInviteMessagesDialogVisible = ref(false);
|
||||||
const isToolsTabVisible = computed(() => {
|
const isToolsTabVisible = computed(() => {
|
||||||
return useRoute().name === 'tools';
|
return useRoute().name === 'tools';
|
||||||
});
|
});
|
||||||
@@ -235,6 +264,10 @@
|
|||||||
categoryCollapsed.value[category] = !categoryCollapsed.value[category];
|
categoryCollapsed.value[category] = !categoryCollapsed.value[category];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showEditInviteMessageDialog = () => {
|
||||||
|
isEditInviteMessagesDialogVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
function showExportDiscordNamesDialog() {
|
function showExportDiscordNamesDialog() {
|
||||||
isExportDiscordNamesDialogVisible.value = true;
|
isExportDiscordNamesDialogVisible.value = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
class="x-dialog"
|
||||||
|
:model-value="isEditInviteMessageDialogVisible"
|
||||||
|
:title="t('dialog.edit_invite_message.header')"
|
||||||
|
width="400px"
|
||||||
|
@close="closeDialog">
|
||||||
|
<div style="font-size: 12px">
|
||||||
|
<span>{{ t('dialog.edit_invite_message.description') }}</span>
|
||||||
|
<el-input
|
||||||
|
v-model="message"
|
||||||
|
type="textarea"
|
||||||
|
size="small"
|
||||||
|
maxlength="64"
|
||||||
|
show-word-limit
|
||||||
|
:autosize="{ minRows: 2, maxRows: 5 }"
|
||||||
|
placeholder=""
|
||||||
|
style="margin-top: 10px"></el-input>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="closeDialog">{{ t('dialog.edit_invite_message.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="saveEditInviteMessage">{{
|
||||||
|
t('dialog.edit_invite_message.save')
|
||||||
|
}}</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import { inviteMessagesRequest } from '../../../api';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
isEditInviteMessageDialogVisible: { type: Boolean, default: false },
|
||||||
|
inviteMessage: { type: Object, required: true }
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:isEditInviteMessageDialogVisible', 'updateInviteMessages']);
|
||||||
|
|
||||||
|
const message = ref('');
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.inviteMessage,
|
||||||
|
(inviteMessage) => {
|
||||||
|
if (inviteMessage) {
|
||||||
|
message.value = inviteMessage.message;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
function saveEditInviteMessage() {
|
||||||
|
closeDialog();
|
||||||
|
if (props.inviteMessage.message !== message.value) {
|
||||||
|
const slot = props.inviteMessage.slot;
|
||||||
|
const messageType = props.inviteMessage.messageType;
|
||||||
|
const params = {
|
||||||
|
message: message.value
|
||||||
|
};
|
||||||
|
inviteMessagesRequest
|
||||||
|
.editInviteMessage(params, messageType, slot)
|
||||||
|
.catch((err) => {
|
||||||
|
throw err;
|
||||||
|
})
|
||||||
|
.then((args) => {
|
||||||
|
if (args.json[slot].message === props.inviteMessage.message) {
|
||||||
|
ElMessage({
|
||||||
|
message: "VRChat API didn't update message, try again",
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
throw new Error("VRChat API didn't update message, try again");
|
||||||
|
} else {
|
||||||
|
ElMessage({ message: 'Invite message updated', type: 'success' });
|
||||||
|
emit('updateInviteMessages', messageType);
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeDialog() {
|
||||||
|
emit('update:isEditInviteMessageDialogVisible', false);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
class="x-dialog"
|
||||||
|
:model-value="isEditInviteMessagesDialogVisible"
|
||||||
|
:title="t('dialog.edit_invite_messages.header')"
|
||||||
|
width="1000px"
|
||||||
|
@close="closeDialog">
|
||||||
|
<el-tabs v-model="activeTab" style="margin-top: 10px">
|
||||||
|
<el-tab-pane :label="t('dialog.edit_invite_messages.invite_message_tab')" name="message">
|
||||||
|
<DataTable
|
||||||
|
v-bind="inviteMessageTable"
|
||||||
|
style="margin-top: 10px; cursor: pointer"
|
||||||
|
@row-click="showEditInviteMessageDialog">
|
||||||
|
<el-table-column
|
||||||
|
:label="t('table.profile.invite_messages.slot')"
|
||||||
|
prop="slot"
|
||||||
|
:sortable="true"
|
||||||
|
width="70"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="t('table.profile.invite_messages.message')"
|
||||||
|
prop="message"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="t('table.profile.invite_messages.cool_down')"
|
||||||
|
prop="updatedAt"
|
||||||
|
:sortable="true"
|
||||||
|
width="110"
|
||||||
|
align="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<countdown-timer :datetime="scope.row.updatedAt" :hours="1"></countdown-timer>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</DataTable>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="t('dialog.edit_invite_messages.invite_request_tab')" name="request">
|
||||||
|
<DataTable
|
||||||
|
v-bind="inviteRequestMessageTable"
|
||||||
|
style="margin-top: 10px; cursor: pointer"
|
||||||
|
@row-click="showEditInviteMessageDialog">
|
||||||
|
<el-table-column
|
||||||
|
:label="t('table.profile.invite_messages.slot')"
|
||||||
|
prop="slot"
|
||||||
|
:sortable="true"
|
||||||
|
width="70"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="t('table.profile.invite_messages.message')"
|
||||||
|
prop="message"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="t('table.profile.invite_messages.cool_down')"
|
||||||
|
prop="updatedAt"
|
||||||
|
:sortable="true"
|
||||||
|
width="110"
|
||||||
|
align="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<countdown-timer :datetime="scope.row.updatedAt" :hours="1"></countdown-timer>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</DataTable>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="t('dialog.edit_invite_messages.invite_request_response_tab')" name="requestResponse">
|
||||||
|
<DataTable
|
||||||
|
v-bind="inviteRequestResponseMessageTable"
|
||||||
|
style="margin-top: 10px; cursor: pointer"
|
||||||
|
@row-click="showEditInviteMessageDialog">
|
||||||
|
<el-table-column
|
||||||
|
:label="t('table.profile.invite_messages.slot')"
|
||||||
|
prop="slot"
|
||||||
|
:sortable="true"
|
||||||
|
width="70"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="t('table.profile.invite_messages.message')"
|
||||||
|
prop="message"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="t('table.profile.invite_messages.cool_down')"
|
||||||
|
prop="updatedAt"
|
||||||
|
:sortable="true"
|
||||||
|
width="110"
|
||||||
|
align="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<countdown-timer :datetime="scope.row.updatedAt" :hours="1"></countdown-timer>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</DataTable>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="t('dialog.edit_invite_messages.invite_response_tab')" name="response">
|
||||||
|
<DataTable
|
||||||
|
v-bind="inviteResponseMessageTable"
|
||||||
|
style="margin-top: 10px; cursor: pointer"
|
||||||
|
@row-click="showEditInviteMessageDialog">
|
||||||
|
<el-table-column
|
||||||
|
:label="t('table.profile.invite_messages.slot')"
|
||||||
|
prop="slot"
|
||||||
|
:sortable="true"
|
||||||
|
width="70"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="t('table.profile.invite_messages.message')"
|
||||||
|
prop="message"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="t('table.profile.invite_messages.cool_down')"
|
||||||
|
prop="updatedAt"
|
||||||
|
:sortable="true"
|
||||||
|
width="110"
|
||||||
|
align="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<countdown-timer :datetime="scope.row.updatedAt" :hours="1"></countdown-timer>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</DataTable>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</el-dialog>
|
||||||
|
<template v-if="isEditInviteMessagesDialogVisible">
|
||||||
|
<EditInviteMessageDialog
|
||||||
|
v-model:isEditInviteMessageDialogVisible="isEditInviteMessageDialogVisible"
|
||||||
|
:inviteMessage="inviteMessage"
|
||||||
|
@close="isEditInviteMessageDialogVisible = false"
|
||||||
|
@updateInviteMessages="refreshInviteMessageTableData" />
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import { useInviteStore } from '../../../stores';
|
||||||
|
|
||||||
|
import DataTable from '../../../components/DataTable.vue';
|
||||||
|
import EditInviteMessageDialog from './EditInviteMessageDialog.vue';
|
||||||
|
|
||||||
|
const {
|
||||||
|
inviteMessageTable,
|
||||||
|
inviteRequestMessageTable,
|
||||||
|
inviteRequestResponseMessageTable,
|
||||||
|
inviteResponseMessageTable
|
||||||
|
} = storeToRefs(useInviteStore());
|
||||||
|
const { refreshInviteMessageTableData } = useInviteStore();
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
isEditInviteMessagesDialogVisible: {
|
||||||
|
type: Boolean
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const activeTab = ref('message');
|
||||||
|
|
||||||
|
const isEditInviteMessageDialogVisible = ref(false);
|
||||||
|
const inviteMessage = ref({});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.isEditInviteMessagesDialogVisible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
refreshInviteMessageTableData('message');
|
||||||
|
refreshInviteMessageTableData('request');
|
||||||
|
refreshInviteMessageTableData('requestResponse');
|
||||||
|
refreshInviteMessageTableData('response');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits(['close']);
|
||||||
|
|
||||||
|
function closeDialog() {
|
||||||
|
emit('close');
|
||||||
|
}
|
||||||
|
|
||||||
|
function showEditInviteMessageDialog(row) {
|
||||||
|
if (row.updatedAt) {
|
||||||
|
const cooldownEnd = new Date(row.updatedAt);
|
||||||
|
cooldownEnd.setHours(cooldownEnd.getHours() + 1);
|
||||||
|
const now = new Date();
|
||||||
|
if (now < cooldownEnd) {
|
||||||
|
ElMessage({
|
||||||
|
message: 'This invite message is on cooldown and cannot be edited yet.',
|
||||||
|
type: 'warning'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inviteMessage.value = row;
|
||||||
|
isEditInviteMessageDialogVisible.value = true;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user