For PR 1247 roles

This commit is contained in:
ScrawnyRonnie 2024-12-20 19:15:48 -05:00
parent daac0eede9
commit a64195bbed
12 changed files with 302 additions and 11 deletions

View file

@ -19,6 +19,6 @@
{/if}
{#if account.admin}
<span class="badge badge-success">GM</span>
<span class="badge badge-success">Admin</span>
{/if}
</span>

View file

@ -25,7 +25,7 @@
data-account-id={account.id}
data-account-name={account.name}
data-toggle="modal"
data-target="#actionModal">Remove GM</button>
data-target="#actionModal">Remove Admin</button>
{:else}
<button type="button"
class="btn btn-success btn-sm"
@ -33,6 +33,6 @@
data-account-id={account.id}
data-account-name={account.name}
data-toggle="modal"
data-target="#actionModal">Make GM</button>
data-target="#actionModal">Make Admin</button>
{/if}
{/if}

View file

@ -11,6 +11,12 @@
<a class="character-link" href="/user/{character.account_id}">
<FactionIcon {character} />
<span>{character.name}</span>
{#if character.can_gm}
<span class="badge badge-success">GM</span>
{/if}
{#if character.can_spectate}
<span class="badge badge-success">Spec</span>
{/if}
</a>
{:else}
<span class="character-link">

View file

@ -0,0 +1,38 @@
<script>
export let avatar;
</script>
{#if avatar.can_spectate}
<button type="button"
class="btn btn-warning btn-sm"
data-action="remove_spectate"
data-avatar-id={avatar.id}
data-account-name={avatar.name}
data-toggle="modal"
data-target="#roleModal">- Spec</button>
{:else}
<button type="button"
class="btn btn-success btn-sm"
data-action="add_spectate"
data-avatar-id={avatar.id}
data-account-name={avatar.name}
data-toggle="modal"
data-target="#roleModal">+ Spec</button>
{/if}
{#if avatar.can_gm}
<button type="button"
class="btn btn-warning btn-sm"
data-action="remove_gm"
data-avatar-id={avatar.id}
data-account-name={avatar.name}
data-toggle="modal"
data-target="#roleModal">- GM</button>
{:else}
<button type="button"
class="btn btn-success btn-sm"
data-action="add_gm"
data-avatar-id={avatar.id}
data-account-name={avatar.name}
data-toggle="modal"
data-target="#roleModal">+ GM</button>
{/if}

View file

@ -0,0 +1,74 @@
<script>
import { onMount } from 'svelte';
import axios from 'axios'
import Alert from './Alert'
import jq from 'jquery'
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
let modalAlert;
onMount(() => setup_actions());
function setup_actions() {
const modal = jq('#roleModal');
modal.on('hide.bs.modal', () => modalAlert.message(""));
modal.on('show.bs.modal', (event) => {
const button = jq(event.relatedTarget) // Button that triggered the modal
const username = button.data('account-name')
const avatar_id = button.data('avatar-id')
const action_type = button.data('action')
const action_name = button.text();
modal.find('.modal-title').text("Confirm " + action_name)
modal.find('.modal-body p').text("Are you sure you want to perform this action on \'" + username + "\'?")
const submit = modal.find('.modal-footer .btn-primary')
submit.text(action_name)
// remove ALL previous click handlers
submit.off()
submit.click(async (event) => {
submit.addClass("disabled")
try {
await axios.post("/api/roles/"+ avatar_id + "/" + action_type)
dispatch('action', {
target: avatar_id,
action: action_type,
});
modal.modal('hide')
} catch (e) {
modalAlert.message(e.message)
} finally {
submit.removeClass("disabled")
}
});
})
}
</script>
<div class="modal fade" id="roleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Perform Action</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<Alert bind:this={modalAlert} />
<p>Are you sure?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
<button type="button" class="btn btn-primary">Yes</button>
</div>
</div>
</div>
</div>

View file

@ -2,6 +2,7 @@
import { onMount } from 'svelte'
import UserList from '../views/UserList'
import CharacterList from '../views/CharacterList'
import RoleList from '../views/RoleList'
import CharacterLink from '../components/CharacterLink'
import AccountLink from '../components/AccountLink'
import { monitor_tabs } from '../util/navigation'
@ -41,6 +42,9 @@
<li class="nav-item">
<a class="nav-link" id="characters-tab" data-toggle="tab" href="#characters" role="tab" aria-controls="profile" aria-selected="false">Characters</a>
</li>
<li class="nav-item">
<a class="nav-link" id="roles-tab" data-toggle="tab" href="#roles" role="tab" aria-controls="profile" aria-selected="false">Roles</a>
</li>
</ul>
<div class="tab-content" id="tabs-tabContent">
@ -74,4 +78,7 @@
<div class="tab-pane" id="characters" role="tabpanel" aria-labelledby="characters-tab">
<CharacterList setURLParam={true} {appAlert} />
</div>
<div class="tab-pane" id="roles" role="tabpanel" aria-labelledby="roles-tab">
<RoleList setURLParam={true} {appAlert} />
</div>
</div>

View file

@ -6,7 +6,8 @@
import moment from 'moment'
export let setURLParam = true;
export let appAlert
export let appAlert;
let characterList;
async function fetch(page) {
try {
@ -20,7 +21,7 @@
}
</script>
<PaginatedList {setURLParam} URLSearchName='page_char' bind:fetch={fetch} let:data={characters} let:pagination={pagination}>
<PaginatedList {setURLParam} URLSearchName='page_char' bind:this={characterList} bind:fetch={fetch} let:data={characters} let:pagination={pagination}>
<div slot="header">
<p>{pagination.item_count.toLocaleString()} characters in the database</p>
</div>

View file

@ -10,7 +10,9 @@
import LoginList from '../components/LoginList'
import AccountLink from '../components/AccountLink'
import ActionButtons from '../components/ActionButtons'
import PermissionButtons from '../components/PermissionButtons'
import ActionModal from '../components/ActionModal.svelte'
import RoleModal from '../components/RoleModal.svelte'
export let pageCtx;
export let appAlert;
@ -86,7 +88,7 @@
{#if characters.length >= 1}
<div class="row">
{#each characters as char, i}
<div class="col-md-4 col-12"><CharacterLink character={char} /></div>
<div class="col-md-4 col-12">{char.name} <PermissionButtons avatar={char} /></div>
{/each}
</div>
{:else}
@ -101,3 +103,4 @@
{/if}
<ActionModal on:action={() => refresh()} />
<RoleModal on:action={() => refresh()} />

52
app/views/RoleList.svelte Normal file
View file

@ -0,0 +1,52 @@
<script>
import { onMount } from 'svelte'
import axios from 'axios'
import CharacterLink from '../components/CharacterLink'
import PermissionButtons from '../components/PermissionButtons'
import PaginatedList from '../components/PaginatedList'
import RoleModal from '../components/RoleModal.svelte'
import moment from 'moment'
export let setURLParam = true;
export let appAlert;
let roleList;
async function fetch(page) {
try {
const resp = await axios.get("/api/roles?page="+page)
appAlert.message("")
return [resp.data.characters, resp.data.page];
} catch (e) {
appAlert.message(e.message)
return undefined;
}
}
</script>
<PaginatedList {setURLParam} URLSearchName='page_role' bind:this={roleList} bind:fetch={fetch} let:data={roles} let:pagination={pagination}>
<div slot="header">
<p>{pagination.item_count.toLocaleString()} characters in the database have a role assigned</p>
</div>
<table slot="body" class="table table-sm table-dark table-responsive-md table-striped table-hover">
<thead class="thead-light">
<th>ID</th>
<th>Name</th>
<th>Last Played</th>
<th>Actions</th>
</thead>
<tbody>
{#each roles as char, i}
<tr>
<td>#{char.id}</td>
<td><CharacterLink character={char} /></td>
<td>{moment(char.last_login).fromNow()}</td>
<td><PermissionButtons avatar={char} /></td>
</tr>
{/each}
</tbody>
</table>
</PaginatedList>
<RoleModal on:action={() => roleList.refresh()} />

View file

@ -110,7 +110,7 @@
<div class="form-check">
<input type="checkbox" class="form-check-input" name="gm" id="userFilterGM">
<label class="form-check-label" for="userFilterGM">
GM
Admin
</label>
</div>
<div class="form-check">