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:
Torsten Schulz (local)
2026-03-04 23:22:16 +01:00
parent 2bc34acacf
commit 190cf626f9
8 changed files with 334 additions and 26 deletions

View File

@@ -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;