Move toju-app into own its folder
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
@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>
|
||||
}
|
||||
Reference in New Issue
Block a user