mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-19 14:53:50 +02:00
Refactor moderation tab using Vue SFC (#1084)
* Refactor moderation tab * fix
This commit is contained in:
100
src/app.js
100
src/app.js
@@ -31,6 +31,9 @@ import _apiInit from './classes/apiInit.js';
|
|||||||
import _apiRequestHandler from './classes/apiRequestHandler.js';
|
import _apiRequestHandler from './classes/apiRequestHandler.js';
|
||||||
import _vrcxJsonStorage from './classes/vrcxJsonStorage.js';
|
import _vrcxJsonStorage from './classes/vrcxJsonStorage.js';
|
||||||
|
|
||||||
|
// tabs
|
||||||
|
import ModerationTab from './views/tabs/Moderation.vue';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import SimpleSwitch from './components/settings/SimpleSwitch.vue';
|
import SimpleSwitch from './components/settings/SimpleSwitch.vue';
|
||||||
|
|
||||||
@@ -96,7 +99,8 @@ console.log(`isLinux: ${LINUX}`);
|
|||||||
const i18n = new VueI18n({
|
const i18n = new VueI18n({
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
fallbackLocale: 'en',
|
fallbackLocale: 'en',
|
||||||
messages: localizedStrings
|
messages: localizedStrings,
|
||||||
|
silentTranslationWarn: true
|
||||||
});
|
});
|
||||||
const $t = i18n.t.bind(i18n);
|
const $t = i18n.t.bind(i18n);
|
||||||
Vue.use(ElementUI, {
|
Vue.use(ElementUI, {
|
||||||
@@ -157,6 +161,11 @@ console.log(`isLinux: ${LINUX}`);
|
|||||||
},
|
},
|
||||||
watch: {},
|
watch: {},
|
||||||
components: {
|
components: {
|
||||||
|
// tabs
|
||||||
|
ModerationTab,
|
||||||
|
|
||||||
|
// components
|
||||||
|
// - settings
|
||||||
SimpleSwitch
|
SimpleSwitch
|
||||||
},
|
},
|
||||||
el: '#x-app',
|
el: '#x-app',
|
||||||
@@ -3838,12 +3847,15 @@ console.log(`isLinux: ${LINUX}`);
|
|||||||
|
|
||||||
workerTimers.setTimeout(() => {
|
workerTimers.setTimeout(() => {
|
||||||
// fix some weird sorting bug when disabling data tables
|
// fix some weird sorting bug when disabling data tables
|
||||||
if (
|
|
||||||
typeof this.$refs.playerModerationTableRef?.sortData !==
|
// looks like it's not needed anymore
|
||||||
'undefined'
|
// if (
|
||||||
) {
|
// typeof this.$refs.playerModerationTableRef?.sortData !==
|
||||||
this.$refs.playerModerationTableRef.sortData.prop = 'created';
|
// 'undefined'
|
||||||
}
|
// ) {
|
||||||
|
// this.$refs.playerModerationTableRef.sortData.prop = 'created';
|
||||||
|
// }
|
||||||
|
|
||||||
if (
|
if (
|
||||||
typeof this.$refs.notificationTableRef?.sortData !== 'undefined'
|
typeof this.$refs.notificationTableRef?.sortData !== 'undefined'
|
||||||
) {
|
) {
|
||||||
@@ -7511,33 +7523,7 @@ console.log(`isLinux: ${LINUX}`);
|
|||||||
|
|
||||||
$app.data.playerModerationTable = {
|
$app.data.playerModerationTable = {
|
||||||
data: [],
|
data: [],
|
||||||
lastRunLength: 0,
|
pageSize: $app.data.tablePageSize
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
prop: 'type',
|
|
||||||
value: [],
|
|
||||||
filterFn: (row, filter) =>
|
|
||||||
filter.value.some((v) => v === row.type)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: ['sourceDisplayName', 'targetDisplayName'],
|
|
||||||
value: ''
|
|
||||||
}
|
|
||||||
],
|
|
||||||
tableProps: {
|
|
||||||
stripe: true,
|
|
||||||
size: 'mini',
|
|
||||||
defaultSort: {
|
|
||||||
prop: 'created',
|
|
||||||
order: 'descending'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
pageSize: $app.data.tablePageSize,
|
|
||||||
paginationProps: {
|
|
||||||
small: true,
|
|
||||||
layout: 'sizes,prev,pager,next,total',
|
|
||||||
pageSizes: [10, 15, 25, 50, 100]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
API.$on('LOGIN', function () {
|
API.$on('LOGIN', function () {
|
||||||
@@ -7545,10 +7531,10 @@ console.log(`isLinux: ${LINUX}`);
|
|||||||
});
|
});
|
||||||
|
|
||||||
API.$on('PLAYER-MODERATION', function (args) {
|
API.$on('PLAYER-MODERATION', function (args) {
|
||||||
var { ref } = args;
|
let { ref } = args;
|
||||||
var array = $app.playerModerationTable.data;
|
let array = $app.playerModerationTable.data;
|
||||||
var { length } = array;
|
let { length } = array;
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
if (array[i].id === ref.id) {
|
if (array[i].id === ref.id) {
|
||||||
Vue.set(array, i, ref);
|
Vue.set(array, i, ref);
|
||||||
return;
|
return;
|
||||||
@@ -7558,10 +7544,10 @@ console.log(`isLinux: ${LINUX}`);
|
|||||||
});
|
});
|
||||||
|
|
||||||
API.$on('PLAYER-MODERATION:@DELETE', function (args) {
|
API.$on('PLAYER-MODERATION:@DELETE', function (args) {
|
||||||
var { ref } = args;
|
let { ref } = args;
|
||||||
var array = $app.playerModerationTable.data;
|
let array = $app.playerModerationTable.data;
|
||||||
var { length } = array;
|
let { length } = array;
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
if (array[i].id === ref.id) {
|
if (array[i].id === ref.id) {
|
||||||
array.splice(i, 1);
|
array.splice(i, 1);
|
||||||
return;
|
return;
|
||||||
@@ -7569,26 +7555,6 @@ console.log(`isLinux: ${LINUX}`);
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$app.methods.deletePlayerModeration = function (row) {
|
|
||||||
API.deletePlayerModeration({
|
|
||||||
moderated: row.targetUserId,
|
|
||||||
type: row.type
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$app.methods.deletePlayerModerationPrompt = function (row) {
|
|
||||||
this.$confirm(`Continue? Delete Moderation ${row.type}`, 'Confirm', {
|
|
||||||
confirmButtonText: 'Confirm',
|
|
||||||
cancelButtonText: 'Cancel',
|
|
||||||
type: 'info',
|
|
||||||
callback: (action) => {
|
|
||||||
if (action === 'confirm') {
|
|
||||||
this.deletePlayerModeration(row);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
// #region | App: Notification
|
// #region | App: Notification
|
||||||
|
|
||||||
@@ -7844,10 +7810,6 @@ console.log(`isLinux: ${LINUX}`);
|
|||||||
'VRCX_friendLogTableFilters',
|
'VRCX_friendLogTableFilters',
|
||||||
JSON.stringify(this.friendLogTable.filters[0].value)
|
JSON.stringify(this.friendLogTable.filters[0].value)
|
||||||
);
|
);
|
||||||
await configRepository.setString(
|
|
||||||
'VRCX_playerModerationTableFilters',
|
|
||||||
JSON.stringify(this.playerModerationTable.filters[0].value)
|
|
||||||
);
|
|
||||||
await configRepository.setString(
|
await configRepository.setString(
|
||||||
'VRCX_notificationTableFilters',
|
'VRCX_notificationTableFilters',
|
||||||
JSON.stringify(this.notificationTable.filters[0].value)
|
JSON.stringify(this.notificationTable.filters[0].value)
|
||||||
@@ -7871,12 +7833,6 @@ console.log(`isLinux: ${LINUX}`);
|
|||||||
$app.data.friendLogTable.filters[0].value = JSON.parse(
|
$app.data.friendLogTable.filters[0].value = JSON.parse(
|
||||||
await configRepository.getString('VRCX_friendLogTableFilters', '[]')
|
await configRepository.getString('VRCX_friendLogTableFilters', '[]')
|
||||||
);
|
);
|
||||||
$app.data.playerModerationTable.filters[0].value = JSON.parse(
|
|
||||||
await configRepository.getString(
|
|
||||||
'VRCX_playerModerationTableFilters',
|
|
||||||
'[]'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$app.data.notificationTable.filters[0].value = JSON.parse(
|
$app.data.notificationTable.filters[0].value = JSON.parse(
|
||||||
await configRepository.getString('VRCX_notificationTableFilters', '[]')
|
await configRepository.getString('VRCX_notificationTableFilters', '[]')
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -71,8 +71,12 @@ html
|
|||||||
+friendLogTab()
|
+friendLogTab()
|
||||||
|
|
||||||
//- moderation
|
//- moderation
|
||||||
include ./mixins/tabs/moderation.pug
|
moderation-tab(
|
||||||
+moderationTab()
|
v-if="$refs.menu?.activeIndex === 'moderation'"
|
||||||
|
:Api='API'
|
||||||
|
:table-data='playerModerationTable'
|
||||||
|
:show-user-dialog='showUserDialog'
|
||||||
|
:shift-held='shiftHeld')
|
||||||
|
|
||||||
//- notification
|
//- notification
|
||||||
include ./mixins/tabs/notifications.pug
|
include ./mixins/tabs/notifications.pug
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
mixin moderationTab()
|
|
||||||
.x-container(v-if="$refs.menu && $refs.menu.activeIndex === 'moderation'")
|
|
||||||
data-tables(v-bind="playerModerationTable" ref="playerModerationTableRef" v-loading="API.isPlayerModerationsLoading")
|
|
||||||
template(#tool)
|
|
||||||
div(style="margin:0 0 10px;display:flex;align-items:center")
|
|
||||||
el-select(v-model="playerModerationTable.filters[0].value" @change="saveTableFilters" multiple clearable style="flex:1" :placeholder="$t('view.moderation.filter_placeholder')")
|
|
||||||
el-option(v-for="type in ['block', 'unblock', 'mute', 'unmute', 'interactOn', 'interactOff', 'muteChat']" :key="type" :label="$t('view.moderation.filters.' + type)" :value="type")
|
|
||||||
el-input(v-model="playerModerationTable.filters[1].value" :placeholder="$t('view.moderation.search_placeholder')" style="flex:none;width:150px;margin:0 10px")
|
|
||||||
el-tooltip(placement="bottom" :content="$t('view.moderation.refresh_tooltip')" :disabled="hideTooltips")
|
|
||||||
el-button(type="default" :loading="API.isPlayerModerationsLoading" @click="API.refreshPlayerModerations()" icon="el-icon-refresh" circle style="flex:none")
|
|
||||||
el-table-column(:label="$t('table.moderation.date')" prop="created" sortable="custom" width="120")
|
|
||||||
template(#default="scope")
|
|
||||||
el-tooltip(placement="right")
|
|
||||||
template(#content)
|
|
||||||
span {{ scope.row.created | formatDate('long') }}
|
|
||||||
span {{ scope.row.created | formatDate('short') }}
|
|
||||||
el-table-column(:label="$t('table.moderation.type')" prop="type" width="100")
|
|
||||||
template(#default="scope")
|
|
||||||
span(v-text="$t('view.moderation.filters.' + scope.row.type)")
|
|
||||||
el-table-column(:label="$t('table.moderation.source')" prop="sourceDisplayName")
|
|
||||||
template(#default="scope")
|
|
||||||
span.x-link(v-text="scope.row.sourceDisplayName" @click="showUserDialog(scope.row.sourceUserId)")
|
|
||||||
el-table-column(:label="$t('table.moderation.target')" prop="targetDisplayName")
|
|
||||||
template(#default="scope")
|
|
||||||
span.x-link(v-text="scope.row.targetDisplayName" @click="showUserDialog(scope.row.targetUserId)")
|
|
||||||
el-table-column(:label="$t('table.moderation.action')" width="80" align="right")
|
|
||||||
template(#default="scope")
|
|
||||||
template(v-if="scope.row.sourceUserId === API.currentUser.id")
|
|
||||||
el-button(v-if="shiftHeld" style="color:#f56c6c" type="text" icon="el-icon-close" size="mini" @click="deletePlayerModeration(scope.row)")
|
|
||||||
el-button(v-else type="text" icon="el-icon-close" size="mini" @click="deletePlayerModerationPrompt(scope.row)")
|
|
||||||
234
src/views/tabs/Moderation.vue
Normal file
234
src/views/tabs/Moderation.vue
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
<template>
|
||||||
|
<div class="x-container">
|
||||||
|
<data-tables
|
||||||
|
:data="tableData.data"
|
||||||
|
:pageSize="tableData.pageSize"
|
||||||
|
:filters="filters"
|
||||||
|
:tableProps="tableProps"
|
||||||
|
:paginationProps="paginationProps"
|
||||||
|
v-loading="Api.isPlayerModerationsLoading"
|
||||||
|
>
|
||||||
|
<template slot="tool">
|
||||||
|
<div class="tool-slot">
|
||||||
|
<el-select
|
||||||
|
v-model="filters[0].value"
|
||||||
|
@change="saveTableFilters()"
|
||||||
|
multiple
|
||||||
|
clearable
|
||||||
|
style="flex: 1"
|
||||||
|
:placeholder="$t('view.moderation.filter_placeholder')"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in moderationTypes"
|
||||||
|
:key="item"
|
||||||
|
:label="$t('view.moderation.filters.' + item)"
|
||||||
|
:value="item"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-input
|
||||||
|
v-model="filters[1].value"
|
||||||
|
:placeholder="$t('view.moderation.search_placeholder')"
|
||||||
|
class="filter-input"
|
||||||
|
/>
|
||||||
|
<el-tooltip
|
||||||
|
placement="bottom"
|
||||||
|
:content="$t('view.moderation.refresh_tooltip')"
|
||||||
|
:disabled="hideTooltips"
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
type="default"
|
||||||
|
:loading="Api.isPlayerModerationsLoading"
|
||||||
|
@click="Api.refreshPlayerModerations()"
|
||||||
|
icon="el-icon-refresh"
|
||||||
|
circle
|
||||||
|
/>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-table-column
|
||||||
|
:label="$t('table.moderation.date')"
|
||||||
|
prop="created"
|
||||||
|
sortable="custom"
|
||||||
|
width="120"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tooltip placement="right">
|
||||||
|
<template slot="content">
|
||||||
|
<span>{{
|
||||||
|
scope.row.created | formatDate('long')
|
||||||
|
}}</span>
|
||||||
|
</template>
|
||||||
|
<span>{{
|
||||||
|
scope.row.created | formatDate('short')
|
||||||
|
}}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="$t('table.moderation.type')"
|
||||||
|
prop="type"
|
||||||
|
width="100"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span
|
||||||
|
v-text="$t('view.moderation.filters.' + scope.row.type)"
|
||||||
|
></span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="$t('table.moderation.source')"
|
||||||
|
prop="sourceDisplayName"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span
|
||||||
|
class="x-link"
|
||||||
|
v-text="scope.row.sourceDisplayName"
|
||||||
|
@click="showUserDialog(scope.row.sourceUserId)"
|
||||||
|
></span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="$t('table.moderation.target')"
|
||||||
|
prop="targetDisplayName"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span
|
||||||
|
class="x-link"
|
||||||
|
v-text="scope.row.targetDisplayName"
|
||||||
|
@click="showUserDialog(scope.row.targetUserId)"
|
||||||
|
></span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="$t('table.moderation.action')"
|
||||||
|
width="80"
|
||||||
|
align="right"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<template
|
||||||
|
v-if="scope.row.sourceUserId === Api.currentUser.id"
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
v-if="shiftHeld"
|
||||||
|
style="color: #f56c6c"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-close"
|
||||||
|
size="mini"
|
||||||
|
@click="deletePlayerModeration(scope.row)"
|
||||||
|
></el-button>
|
||||||
|
<el-button
|
||||||
|
v-else
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-close"
|
||||||
|
size="mini"
|
||||||
|
@click="deletePlayerModerationPrompt(scope.row)"
|
||||||
|
></el-button>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</data-tables>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import configRepository from '../../repository/config.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ModerationTab',
|
||||||
|
props: {
|
||||||
|
Api: Object,
|
||||||
|
tableData: Object,
|
||||||
|
showUserDialog: Function,
|
||||||
|
shiftHeld: Boolean
|
||||||
|
},
|
||||||
|
created: async function () {
|
||||||
|
this.filters[0].value = JSON.parse(
|
||||||
|
await configRepository.getString(
|
||||||
|
'VRCX_playerModerationTableFilters',
|
||||||
|
'[]'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
prop: 'type',
|
||||||
|
value: [],
|
||||||
|
filterFn: (row, filter) =>
|
||||||
|
filter.value.some((v) => v === row.type)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: ['sourceDisplayName', 'targetDisplayName'],
|
||||||
|
value: ''
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// CONSTANTS
|
||||||
|
moderationTypes: [
|
||||||
|
'block',
|
||||||
|
'unblock',
|
||||||
|
'mute',
|
||||||
|
'unmute',
|
||||||
|
'interactOn',
|
||||||
|
'interactOff',
|
||||||
|
'muteChat'
|
||||||
|
],
|
||||||
|
tableProps: {
|
||||||
|
stripe: true,
|
||||||
|
size: 'mini',
|
||||||
|
defaultSort: {
|
||||||
|
prop: 'created',
|
||||||
|
order: 'descending'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
paginationProps: {
|
||||||
|
small: true,
|
||||||
|
layout: 'sizes,prev,pager,next,total',
|
||||||
|
pageSizes: [10, 15, 25, 50, 100]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
saveTableFilters() {
|
||||||
|
configRepository.setString(
|
||||||
|
'VRCX_playerModerationTableFilters',
|
||||||
|
JSON.stringify(this.filters[0].value)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
deletePlayerModeration(row) {
|
||||||
|
this.Api.deletePlayerModeration({
|
||||||
|
moderated: row.targetUserId,
|
||||||
|
type: row.type
|
||||||
|
});
|
||||||
|
},
|
||||||
|
deletePlayerModerationPrompt(row) {
|
||||||
|
this.$confirm(
|
||||||
|
`Continue? Delete Moderation ${row.type}`,
|
||||||
|
'Confirm',
|
||||||
|
{
|
||||||
|
confirmButtonText: 'Confirm',
|
||||||
|
cancelButtonText: 'Cancel',
|
||||||
|
type: 'info',
|
||||||
|
callback: (action) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
this.deletePlayerModeration(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.tool-slot {
|
||||||
|
margin: 0 0 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.filter-input {
|
||||||
|
width: 150px;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user