diff --git a/html/src/app.js b/html/src/app.js
index 4fd63ee7..29a7c190 100644
--- a/html/src/app.js
+++ b/html/src/app.js
@@ -5726,7 +5726,7 @@ speechSynthesis.getVoices();
if (this.branch === 'Stable') {
this.nextAppUpdateCheck = 14400; // 2hours
} else {
- this.nextAppUpdateCheck = 1800; // 15mins
+ this.nextAppUpdateCheck = 7200; // 1hour
}
if (this.autoUpdateVRCX !== 'Off') {
this.checkForVRCXUpdate();
@@ -6685,6 +6685,9 @@ speechSynthesis.getVoices();
return '';
})
.then((args) => {
+ if (!args.json) {
+ return '';
+ }
if (
this.displayVRCPlusIconsAsAvatar &&
args.json.userIcon
@@ -29433,6 +29436,10 @@ speechSynthesis.getVoices();
n: 100,
offset: 0
};
+ if (this.groupMemberModeration.selectedAuditLogTypes.length) {
+ params.eventTypes =
+ this.groupMemberModeration.selectedAuditLogTypes;
+ }
var count = 50; // 5000 max
this.isGroupMembersLoading = true;
try {
@@ -29460,9 +29467,44 @@ speechSynthesis.getVoices();
* @param {{ groupId: string }} params
* @return { Promise<{json: any, params}> }
*/
+ API.getGroupAuditLogTypes = function (params) {
+ return this.call(`groups/${params.groupId}/auditLogTypes`, {
+ method: 'GET'
+ }).then((json) => {
+ var args = {
+ json,
+ params
+ };
+ this.$emit('GROUP:AUDITLOGTYPES', args);
+ return args;
+ });
+ };
+ API.$on('GROUP:AUDITLOGTYPES', function (args) {
+ if ($app.groupMemberModeration.id !== args.params.groupId) {
+ return;
+ }
+
+ $app.groupMemberModeration.auditLogTypes = args.json;
+ });
+
+ $app.methods.getAuditLogTypeName = function (auditLogType) {
+ if (!auditLogType) {
+ return '';
+ }
+ return auditLogType
+ .replace('group.', '')
+ .replace(/\./g, ' ')
+ .replace(/\b\w/g, (l) => l.toUpperCase());
+ };
+
+ /**
+ * @param {{ groupId: string, eventTypes: array }} params
+ * @return { Promise<{json: any, params}> }
+ */
API.getGroupLogs = function (params) {
return this.call(`groups/${params.groupId}/auditLogs`, {
- method: 'GET'
+ method: 'GET',
+ params
}).then((json) => {
var args = {
json,
@@ -29479,7 +29521,12 @@ speechSynthesis.getVoices();
}
for (var json of args.json.results) {
- $app.groupLogsModerationTable.data.push(json);
+ const existsInData = $app.groupLogsModerationTable.data.some(
+ (dataItem) => dataItem.id === json.id
+ );
+ if (!existsInData) {
+ $app.groupLogsModerationTable.data.push(json);
+ }
}
});
@@ -31698,6 +31745,8 @@ speechSynthesis.getVoices();
loading: false,
id: '',
groupRef: {},
+ auditLogTypes: [],
+ selectedAuditLogTypes: [],
note: '',
selectedUsers: new Map(),
selectedUsersArray: [],
@@ -31743,6 +31792,12 @@ speechSynthesis.getVoices();
$app.data.groupLogsModerationTable = {
data: [],
+ filters: [
+ {
+ prop: ['description'],
+ value: ''
+ }
+ ],
tableProps: {
stripe: true,
size: 'mini'
@@ -31827,9 +31882,12 @@ speechSynthesis.getVoices();
D.selectedUsersArray = [];
D.selectedRoles = [];
D.groupRef = {};
+ D.auditLogTypes = [];
+ D.selectedAuditLogTypes = [];
API.getCachedGroup({ groupId }).then((args) => {
D.groupRef = args.ref;
});
+ API.getGroupAuditLogTypes({ groupId });
this.groupMemberModerationTableForceUpdate = 0;
D.visible = true;
this.setGroupMemberModerationTable(this.groupDialog.members);
diff --git a/html/src/index.pug b/html/src/index.pug
index 931106bd..ae38d12e 100644
--- a/html/src/index.pug
+++ b/html/src/index.pug
@@ -3195,6 +3195,13 @@ html
el-button(type="default" @click="getAllGroupLogs(groupMemberModeration.id)" size="mini" icon="el-icon-refresh" :loading="isGroupMembersLoading" circle)
span(style="font-size:14px;margin-left:5px;margin-right:5px") {{ groupLogsModerationTable.data.length }}
br
+ el-select(v-model="groupMemberModeration.selectedAuditLogTypes" multiple collapse-tags :placeholder="$t('dialog.group_member_moderation.filter_type')")
+ el-option-group(:label="$t('dialog.group_member_moderation.select_type')")
+ el-option.x-friend-item(v-for="type in groupMemberModeration.auditLogTypes" :key="type" :label="getAuditLogTypeName(type)" :value="type")
+ .detail
+ span.name(v-text="getAuditLogTypeName(type)")
+ el-input(v-model="groupLogsModerationTable.filters[0].value" :placeholder="$t('dialog.group_member_moderation.search_placeholder')" style="display:inline-block;width:150px;margin:10px")
+ br
data-tables(v-bind="groupLogsModerationTable" style="margin-top:10px")
el-table-column(:label="$t('dialog.group_member_moderation.created_at')" width="170" prop="created_at" sortable)
template(v-once #default="scope")
@@ -3213,11 +3220,13 @@ html
template(v-once #default="scope")
span(v-if="Object.keys(scope.row.data).length" v-text="JSON.stringify(scope.row.data)")
br
+ br
span.name {{ $t('dialog.group_member_moderation.user_id') }}
br
el-input(v-model="groupMemberModeration.selectUserId" size="mini" style="margin-top:5px;width:340px" :placeholder="$t('dialog.group_member_moderation.user_id_placeholder')" clearable)
el-button(size="small" @click="selectGroupMemberUserId" :disabled="!groupMemberModeration.selectUserId") {{ $t('dialog.group_member_moderation.select_user') }}
br
+ br
span.name {{ $t('dialog.group_member_moderation.selected_users') }}
el-button(type="default" @click="clearSelectedGroupMembers" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
br
@@ -3226,7 +3235,8 @@ html
br
br
span.name {{ $t('dialog.group_member_moderation.notes') }}
- el-input.extra(v-model="groupMemberModeration.note" type="textarea" :rows="2" :autosize="{ minRows: 1, maxRows: 20 }" :placeholder="$t('dialog.group_member_moderation.note_placeholder')" size="mini" resize="none")
+ el-input.extra(v-model="groupMemberModeration.note" type="textarea" :rows="2" :autosize="{ minRows: 1, maxRows: 20 }" :placeholder="$t('dialog.group_member_moderation.note_placeholder')" size="mini" resize="none" style="margin-top:5px")
+ br
br
span.name {{ $t('dialog.group_member_moderation.selected_roles') }}
br
@@ -3236,6 +3246,7 @@ html
.detail
span.name(v-text="role.name")
br
+ br
span.name {{ $t('dialog.group_member_moderation.actions') }}
br
el-button(@click="groupMembersAddRoles" :disabled="!groupMemberModeration.selectedRoles.length || groupMemberModeration.progressCurrent || !hasGroupPermission(groupDialog.ref, 'group-roles-assign')") {{ $t('dialog.group_member_moderation.add_roles') }}
diff --git a/html/src/localization/en/en.json b/html/src/localization/en/en.json
index c747e1c3..235f1da9 100644
--- a/html/src/localization/en/en.json
+++ b/html/src/localization/en/en.json
@@ -1312,6 +1312,9 @@
},
"group_member_moderation": {
"header": "Group Member Moderation",
+ "filter_type": "Filter Type",
+ "select_type": "Select Type",
+ "search_placeholder": "Search",
"members": "Members",
"bans": "Bans",
"invites": "Invites",
diff --git a/html/src/vr.pug b/html/src/vr.pug
index f57b11ee..bfc9967c 100644
--- a/html/src/vr.pug
+++ b/html/src/vr.pug
@@ -123,12 +123,12 @@ html
.detail
span.extra
span.time {{ feed.created_at | formatDate }}
- | 👉 #[span.name(v-text="feed.message")]
+ | 👉 #[span.name(v-text="feed.senderUsername")] #[span(v-text="feed.message")]
div(v-else-if="feed.type === 'groupChange'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
.detail
span.extra
span.time {{ feed.created_at | formatDate }}
- | 🏷️ #[span.name(v-text="feed.senderUsername")] #[span.name(v-text="feed.message")]
+ | 🏷️ #[span.name(v-text="feed.senderUsername")] #[span(v-text="feed.message")]
div(v-else-if="feed.type === 'group.announcement'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
.detail
span.extra
@@ -353,12 +353,12 @@ html
.detail
span.extra
span.time {{ feed.created_at | formatDate }}
- | #[span.name(v-text="feed.message")]
+ | #[span.name(v-text="feed.senderUsername")] #[span(v-text="feed.message")]
div(v-else-if="feed.type === 'groupChange'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
.detail
span.extra
span.time {{ feed.created_at | formatDate }}
- | #[span.name(v-text="feed.senderUsername")] #[span.name(v-text="feed.message")]
+ | #[span.name(v-text="feed.senderUsername")] #[span(v-text="feed.message")]
div(v-else-if="feed.type === 'group.announcement'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
.detail
span.extra