Add functionality for managing user-owned chat rooms: Implement getOwnRooms and deleteOwnRoom methods in ChatController and ChatService, add corresponding API routes in chatRouter, and enhance MultiChatDialog for displaying and deleting owned rooms with localized messages. Update i18n files for new features.
This commit is contained in:
@@ -71,17 +71,17 @@
|
||||
{{ $t('chat.multichat.createRoom.labels.visibility') }}
|
||||
<select v-model="roomCreateForm.visibility">
|
||||
<option value="">{{ $t('chat.multichat.createRoom.options.none') }}</option>
|
||||
<option value="public">public</option>
|
||||
<option value="private">private</option>
|
||||
<option value="public">{{ $t('chat.multichat.createRoom.options.visibilityPublic') }}</option>
|
||||
<option value="private">{{ $t('chat.multichat.createRoom.options.visibilityPrivate') }}</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
{{ $t('chat.multichat.createRoom.labels.gender') }}
|
||||
<select v-model="roomCreateForm.gender">
|
||||
<option value="">{{ $t('chat.multichat.createRoom.options.none') }}</option>
|
||||
<option value="m">m</option>
|
||||
<option value="f">f</option>
|
||||
<option value="any">any</option>
|
||||
<option value="m">{{ $t('chat.multichat.createRoom.options.genderMale') }}</option>
|
||||
<option value="f">{{ $t('chat.multichat.createRoom.options.genderFemale') }}</option>
|
||||
<option value="any">{{ $t('chat.multichat.createRoom.options.genderAny') }}</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
@@ -135,6 +135,26 @@
|
||||
<div class="room-create-preview">
|
||||
{{ $t('chat.multichat.createRoom.commandPrefix') }}: <code>{{ buildRoomCreateCommandPreview() || '/cr <raumname>' }}</code>
|
||||
</div>
|
||||
<div class="owned-rooms-section">
|
||||
<div class="owned-rooms-title">{{ $t('chat.multichat.createRoom.ownedRooms.title') }}</div>
|
||||
<div class="owned-rooms-hint">{{ $t('chat.multichat.createRoom.ownedRooms.hint') }}</div>
|
||||
<div v-if="!ownRooms.length" class="owned-rooms-empty">
|
||||
{{ $t('chat.multichat.createRoom.ownedRooms.empty') }}
|
||||
</div>
|
||||
<div v-else class="owned-rooms-list">
|
||||
<div v-for="room in ownRooms" :key="`own-room-${room.id}`" class="owned-room-item">
|
||||
<div class="owned-room-main">
|
||||
<span class="owned-room-name">{{ room.title }}</span>
|
||||
<span class="owned-room-badge" :class="room.isPublic ? 'public' : 'private'">
|
||||
{{ room.isPublic ? $t('chat.multichat.createRoom.ownedRooms.public') : $t('chat.multichat.createRoom.ownedRooms.private') }}
|
||||
</span>
|
||||
</div>
|
||||
<button type="button" class="owned-room-delete-btn" @click="deleteOwnedRoom(room)">
|
||||
{{ $t('common.delete') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-list">
|
||||
<div class="user-list-header">Teilnehmer ({{ usersInRoom.length }})</div>
|
||||
@@ -199,7 +219,7 @@
|
||||
|
||||
<script>
|
||||
import DialogWidget from '@/components/DialogWidget.vue';
|
||||
import { fetchPublicRooms, fetchRoomCreateOptions } from '@/api/chatApi.js';
|
||||
import { fetchPublicRooms, fetchRoomCreateOptions, fetchOwnRooms } from '@/api/chatApi.js';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { getChatWsUrl, getChatWsCandidates, getChatWsProtocols } from '@/services/chatWs.js';
|
||||
|
||||
@@ -293,6 +313,7 @@ export default {
|
||||
},
|
||||
roomCreateRights: [],
|
||||
roomCreateTypes: [],
|
||||
ownRooms: [],
|
||||
// Palette state
|
||||
paletteWidth: 420,
|
||||
paletteHeight: 220,
|
||||
@@ -375,12 +396,16 @@ export default {
|
||||
const candidates = [
|
||||
`chat.multichat.createRoom.rights.${raw}`,
|
||||
`navigation.${raw}`,
|
||||
`navigation.m-admin.${raw}`
|
||||
`navigation.m-administration.${raw}`
|
||||
];
|
||||
for (const key of candidates) {
|
||||
if (this.$te(key)) return this.$t(key);
|
||||
}
|
||||
return raw;
|
||||
return raw
|
||||
.replace(/_/g, ' ')
|
||||
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
},
|
||||
getRoomTypeLabel(roomType) {
|
||||
const raw = (roomType?.name || '').trim();
|
||||
@@ -399,6 +424,48 @@ export default {
|
||||
this.roomCreateTypes = [];
|
||||
}
|
||||
},
|
||||
async loadOwnRooms() {
|
||||
try {
|
||||
const rooms = await fetchOwnRooms();
|
||||
this.ownRooms = Array.isArray(rooms) ? rooms : [];
|
||||
} catch (e) {
|
||||
console.error('Failed loading own rooms', e);
|
||||
this.ownRooms = [];
|
||||
}
|
||||
},
|
||||
async deleteOwnedRoom(room) {
|
||||
const title = room?.title || '';
|
||||
const confirmed = window.confirm(this.$t('chat.multichat.createRoom.ownedRooms.confirmDelete', { room: title }));
|
||||
if (!confirmed) return;
|
||||
if (!this.transportConnected) {
|
||||
this.messages.push({
|
||||
id: Date.now(),
|
||||
user: 'System',
|
||||
text: this.$t('chat.multichat.createRoom.messages.noConnection')
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const payload = { type: 'message', message: `/dr ${title}` };
|
||||
if (this.debug) console.log('[Chat WS >>]', payload);
|
||||
this.sendWithToken(payload);
|
||||
this.messages.push({
|
||||
id: Date.now(),
|
||||
user: 'System',
|
||||
text: this.$t('chat.multichat.createRoom.ownedRooms.deleteSent', { room: title })
|
||||
});
|
||||
this.requestRoomRefreshAfterCreate();
|
||||
setTimeout(() => this.loadOwnRooms(), 700);
|
||||
setTimeout(() => this.loadOwnRooms(), 2000);
|
||||
} catch (e) {
|
||||
console.error('Failed deleting own room', e);
|
||||
this.messages.push({
|
||||
id: Date.now(),
|
||||
user: 'System',
|
||||
text: this.$t('chat.multichat.createRoom.ownedRooms.deleteError')
|
||||
});
|
||||
}
|
||||
},
|
||||
parseOptionalInteger(value) {
|
||||
if (value === null || value === undefined || value === '') return null;
|
||||
const num = Number(value);
|
||||
@@ -561,6 +628,7 @@ export default {
|
||||
this.showOptions = false;
|
||||
this.showRoomCreatePanel = false;
|
||||
this.loadRoomCreateOptions();
|
||||
this.loadOwnRooms();
|
||||
this.announcedRoomEnter = false;
|
||||
this.$refs.dialog.open();
|
||||
// Stelle die WS-Verbindung her, wenn der Dialog geöffnet wird
|
||||
@@ -1905,6 +1973,82 @@ export default {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.owned-rooms-section {
|
||||
margin-top: 0.9em;
|
||||
border-top: 1px solid #eee;
|
||||
padding-top: 0.7em;
|
||||
}
|
||||
|
||||
.owned-rooms-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
|
||||
.owned-rooms-hint {
|
||||
font-size: 0.85em;
|
||||
color: #666;
|
||||
margin-bottom: 0.45em;
|
||||
}
|
||||
|
||||
.owned-rooms-empty {
|
||||
font-size: 0.9em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.owned-rooms-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.35em;
|
||||
}
|
||||
|
||||
.owned-room-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.6em;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
padding: 0.35em 0.5em;
|
||||
}
|
||||
|
||||
.owned-room-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.owned-room-name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.owned-room-badge {
|
||||
font-size: 0.75em;
|
||||
border-radius: 999px;
|
||||
padding: 0.1em 0.5em;
|
||||
border: 1px solid #bbb;
|
||||
}
|
||||
|
||||
.owned-room-badge.public {
|
||||
background: #e8f5e9;
|
||||
border-color: #81c784;
|
||||
}
|
||||
|
||||
.owned-room-badge.private {
|
||||
background: #fff3e0;
|
||||
border-color: #ffb74d;
|
||||
}
|
||||
|
||||
.owned-room-delete-btn {
|
||||
border: 1px solid #bbb;
|
||||
border-radius: 3px;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
padding: 0.2em 0.55em;
|
||||
}
|
||||
|
||||
.room-create-error {
|
||||
color: #b00020;
|
||||
font-size: 0.85em;
|
||||
|
||||
Reference in New Issue
Block a user