228 lines
8.8 KiB
HTML
228 lines
8.8 KiB
HTML
@if (serverData()) {
|
|
<div class="space-y-5 max-w-xl">
|
|
<section>
|
|
<h4 class="text-sm font-semibold text-foreground mb-3">Room Settings</h4>
|
|
@if (!isAdmin()) {
|
|
<p class="text-xs text-muted-foreground mb-3">
|
|
You are viewing this server's settings as a non-admin. Only the server owner can make changes.
|
|
</p>
|
|
}
|
|
<div class="space-y-4">
|
|
<div>
|
|
<label
|
|
for="room-name"
|
|
class="block text-xs font-medium text-muted-foreground mb-1"
|
|
>Room Name</label
|
|
>
|
|
<input
|
|
type="text"
|
|
[(ngModel)]="roomName"
|
|
[readOnly]="!isAdmin()"
|
|
id="room-name"
|
|
class="w-full px-3 py-2 bg-secondary rounded-lg border border-border text-foreground text-sm focus:outline-none focus:ring-2 focus:ring-primary"
|
|
[class.opacity-60]="!isAdmin()"
|
|
[class.cursor-not-allowed]="!isAdmin()"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label
|
|
for="room-description"
|
|
class="block text-xs font-medium text-muted-foreground mb-1"
|
|
>Description</label
|
|
>
|
|
<textarea
|
|
[(ngModel)]="roomDescription"
|
|
[readOnly]="!isAdmin()"
|
|
rows="3"
|
|
id="room-description"
|
|
class="w-full px-3 py-2 bg-secondary rounded-lg border border-border text-foreground text-sm focus:outline-none focus:ring-2 focus:ring-primary resize-none"
|
|
[class.opacity-60]="!isAdmin()"
|
|
[class.cursor-not-allowed]="!isAdmin()"
|
|
></textarea>
|
|
</div>
|
|
@if (isAdmin()) {
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<p class="text-sm font-medium text-foreground">Private Room</p>
|
|
<p class="text-xs text-muted-foreground">Require approval to join</p>
|
|
</div>
|
|
<button
|
|
(click)="togglePrivate()"
|
|
type="button"
|
|
class="p-2 rounded-lg transition-colors"
|
|
[class.bg-primary]="isPrivate()"
|
|
[class.text-primary-foreground]="isPrivate()"
|
|
[class.bg-secondary]="!isPrivate()"
|
|
[class.text-muted-foreground]="!isPrivate()"
|
|
>
|
|
@if (isPrivate()) {
|
|
<ng-icon
|
|
name="lucideLock"
|
|
class="w-4 h-4"
|
|
/>
|
|
} @else {
|
|
<ng-icon
|
|
name="lucideUnlock"
|
|
class="w-4 h-4"
|
|
/>
|
|
}
|
|
</button>
|
|
</div>
|
|
} @else {
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<p class="text-sm font-medium text-foreground">Private Room</p>
|
|
<p class="text-xs text-muted-foreground">Require approval to join</p>
|
|
</div>
|
|
<span class="text-sm text-muted-foreground">{{ isPrivate() ? 'Yes' : 'No' }}</span>
|
|
</div>
|
|
}
|
|
<div>
|
|
<label
|
|
for="room-max-users"
|
|
class="block text-xs font-medium text-muted-foreground mb-1"
|
|
>
|
|
Max Users (0 = unlimited)
|
|
</label>
|
|
<input
|
|
type="number"
|
|
[(ngModel)]="maxUsers"
|
|
[readOnly]="!isAdmin()"
|
|
min="0"
|
|
id="room-max-users"
|
|
class="w-full px-3 py-2 bg-secondary rounded-lg border border-border text-foreground text-sm focus:outline-none focus:ring-2 focus:ring-primary"
|
|
[class.opacity-60]="!isAdmin()"
|
|
[class.cursor-not-allowed]="!isAdmin()"
|
|
/>
|
|
</div>
|
|
|
|
@if (isAdmin()) {
|
|
<div class="rounded-lg border border-border bg-secondary/40 p-4 space-y-3">
|
|
<div class="flex items-start justify-between gap-4">
|
|
<div>
|
|
<p class="text-sm font-medium text-foreground">Server Password</p>
|
|
<p class="text-xs text-muted-foreground">
|
|
@if (hasPassword() && passwordAction() !== 'remove') {
|
|
Joined members stay whitelisted until they are kicked or banned.
|
|
} @else {
|
|
Add an optional password so new members need it to join.
|
|
}
|
|
</p>
|
|
</div>
|
|
|
|
@if (hasPassword() && passwordAction() !== 'remove') {
|
|
<button
|
|
type="button"
|
|
(click)="markPasswordForRemoval()"
|
|
class="rounded-lg border border-border px-3 py-2 text-xs font-medium text-muted-foreground transition-colors hover:bg-secondary"
|
|
>
|
|
Remove Password
|
|
</button>
|
|
} @else if (hasPassword() && passwordAction() === 'remove') {
|
|
<button
|
|
type="button"
|
|
(click)="keepCurrentPassword()"
|
|
class="rounded-lg border border-border px-3 py-2 text-xs font-medium text-muted-foreground transition-colors hover:bg-secondary"
|
|
>
|
|
Keep Password
|
|
</button>
|
|
}
|
|
</div>
|
|
|
|
<div class="text-xs text-muted-foreground">
|
|
@if (hasPassword() && passwordAction() !== 'remove') {
|
|
Password protection is currently enabled.
|
|
} @else if (hasPassword() && passwordAction() === 'remove') {
|
|
Password protection will be removed when you save.
|
|
} @else {
|
|
Password protection is currently disabled.
|
|
}
|
|
</div>
|
|
|
|
<div>
|
|
<label
|
|
for="room-password"
|
|
class="block text-xs font-medium text-muted-foreground mb-1"
|
|
>
|
|
{{ hasPassword() ? 'Set New Password' : 'Set Password' }}
|
|
</label>
|
|
<input
|
|
type="password"
|
|
id="room-password"
|
|
[ngModel]="roomPassword"
|
|
(ngModelChange)="onPasswordInput($event)"
|
|
class="w-full px-3 py-2 bg-secondary rounded-lg border border-border text-foreground text-sm focus:outline-none focus:ring-2 focus:ring-primary"
|
|
[placeholder]="hasPassword() ? 'Leave blank to keep the current password' : 'Optional password required for new joins'"
|
|
/>
|
|
|
|
@if (passwordAction() === 'update') {
|
|
<p class="mt-2 text-xs text-muted-foreground">The new password will replace the current one when you save.</p>
|
|
}
|
|
|
|
@if (passwordError()) {
|
|
<p class="mt-2 text-xs text-destructive">{{ passwordError() }}</p>
|
|
}
|
|
</div>
|
|
</div>
|
|
} @else {
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<p class="text-sm font-medium text-foreground">Server Password</p>
|
|
<p class="text-xs text-muted-foreground">Invite links bypass the password, but bans still apply.</p>
|
|
</div>
|
|
<span class="text-sm text-muted-foreground">{{ hasPassword() ? 'Enabled' : 'Disabled' }}</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
</section>
|
|
|
|
@if (isAdmin()) {
|
|
<button
|
|
(click)="saveServerSettings()"
|
|
type="button"
|
|
class="w-full px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 transition-colors flex items-center justify-center gap-2 text-sm"
|
|
[class.bg-green-600]="saveSuccess() === 'server'"
|
|
[class.hover:bg-green-600]="saveSuccess() === 'server'"
|
|
>
|
|
<ng-icon
|
|
name="lucideCheck"
|
|
class="w-4 h-4"
|
|
/>
|
|
{{ saveSuccess() === 'server' ? 'Saved!' : 'Save Settings' }}
|
|
</button>
|
|
|
|
<!-- Danger Zone -->
|
|
<div class="pt-4 border-t border-border">
|
|
<h4 class="text-sm font-medium text-destructive mb-3">Danger Zone</h4>
|
|
<button
|
|
(click)="confirmDeleteRoom()"
|
|
type="button"
|
|
class="w-full px-4 py-2 bg-destructive/10 text-destructive border border-destructive/20 rounded-lg hover:bg-destructive/20 transition-colors flex items-center justify-center gap-2 text-sm"
|
|
>
|
|
<ng-icon
|
|
name="lucideTrash2"
|
|
class="w-4 h-4"
|
|
/>
|
|
Delete Room
|
|
</button>
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<!-- Delete Confirmation (sub-modal) -->
|
|
@if (showDeleteConfirm()) {
|
|
<app-confirm-dialog
|
|
title="Delete Room"
|
|
confirmLabel="Delete Room"
|
|
variant="danger"
|
|
[widthClass]="'w-96 max-w-[90vw]'"
|
|
(confirmed)="deleteRoom()"
|
|
(cancelled)="showDeleteConfirm.set(false)"
|
|
>
|
|
<p>Are you sure you want to delete this room? This action cannot be undone.</p>
|
|
</app-confirm-dialog>
|
|
}
|
|
} @else {
|
|
<div class="flex items-center justify-center h-40 text-muted-foreground text-sm">Select a server from the sidebar to manage</div>
|
|
}
|