mirror of
https://github.com/psforever/PSFPortal.git
synced 2026-07-14 16:04:38 +00:00
Make ActionModal to component
This commit is contained in:
parent
cb918033a6
commit
e048d28ad3
7 changed files with 137 additions and 112 deletions
14
api/db.js
14
api/db.js
|
|
@ -229,15 +229,11 @@ export async function get_characters(pagination, sort, order) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const char_count = await get_row_count(CHARACTER.THIS);
|
const char_count = await get_row_count(CHARACTER.THIS);
|
||||||
const chars = await pool.query(`SELECT id, name, faction_id, created, last_login FROM characters ORDER BY ${to_sql(sort)} ${to_sql(order)} OFFSET $1 LIMIT $2`, values);
|
const chars = await pool.query(`SELECT id, account_id, name, faction_id, created, last_login FROM characters ORDER BY ${to_sql(sort)} ${to_sql(order)} OFFSET $1 LIMIT $2`, values);
|
||||||
|
|
||||||
pagination.item_count = char_count;
|
pagination.item_count = char_count;
|
||||||
pagination.page_count = Math.ceil(pagination.item_count / pagination.items_per_page);
|
pagination.page_count = Math.ceil(pagination.item_count / pagination.items_per_page);
|
||||||
|
|
||||||
chars.rows.forEach((r) => {
|
|
||||||
delete r.account_id;
|
|
||||||
});
|
|
||||||
|
|
||||||
return chars.rows;
|
return chars.rows;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code)
|
if (e.code)
|
||||||
|
|
@ -302,8 +298,7 @@ export async function get_stats() {
|
||||||
try {
|
try {
|
||||||
const account_count = await get_row_count(ACCOUNT.THIS);
|
const account_count = await get_row_count(ACCOUNT.THIS);
|
||||||
const character_count = await get_row_count(CHARACTER.THIS);
|
const character_count = await get_row_count(CHARACTER.THIS);
|
||||||
const last_account = await pool.query('SELECT id, username, created FROM accounts ORDER BY id DESC LIMIT 1');
|
const last_character = await pool.query('SELECT id, account_id, name, faction_id, created FROM characters ORDER BY id DESC LIMIT 1');
|
||||||
const last_character = await pool.query('SELECT id, name, faction_id, created FROM characters ORDER BY id DESC LIMIT 1');
|
|
||||||
const empires = await pool.query('SELECT faction_id, COUNT(*) FROM characters GROUP BY faction_id');
|
const empires = await pool.query('SELECT faction_id, COUNT(*) FROM characters GROUP BY faction_id');
|
||||||
|
|
||||||
const stats = {}
|
const stats = {}
|
||||||
|
|
@ -311,9 +306,6 @@ export async function get_stats() {
|
||||||
stats.characters = character_count;
|
stats.characters = character_count;
|
||||||
stats.last = {};
|
stats.last = {};
|
||||||
stats.last.character = last_character.rows[0];
|
stats.last.character = last_character.rows[0];
|
||||||
stats.last.account = last_account.rows[0];
|
|
||||||
stats.last.account.name = stats.last.account.username
|
|
||||||
delete stats.last.account.username;
|
|
||||||
stats.empires = {};
|
stats.empires = {};
|
||||||
|
|
||||||
empires.rows.forEach((r) =>
|
empires.rows.forEach((r) =>
|
||||||
|
|
@ -354,7 +346,7 @@ export async function search(term, pagination) {
|
||||||
const accounts = await pool.query('SELECT id, username, gm FROM accounts ' +
|
const accounts = await pool.query('SELECT id, username, gm FROM accounts ' +
|
||||||
'WHERE upper(username) LIKE $1 '+
|
'WHERE upper(username) LIKE $1 '+
|
||||||
` ORDER BY username OFFSET $2 LIMIT $3`, values);
|
` ORDER BY username OFFSET $2 LIMIT $3`, values);
|
||||||
const characters = await pool.query('SELECT id, name, faction_id FROM characters ' +
|
const characters = await pool.query('SELECT id, name, account_id, faction_id FROM characters ' +
|
||||||
'WHERE name LIKE $1 '+
|
'WHERE name LIKE $1 '+
|
||||||
` ORDER BY upper(name) OFFSET $2 LIMIT $3`, values);
|
` ORDER BY upper(name) OFFSET $2 LIMIT $3`, values);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ api.get('/user/:user/profile', async (req, res, next) => {
|
||||||
email : "bademail@email.com",
|
email : "bademail@email.com",
|
||||||
account_created : account.created,
|
account_created : account.created,
|
||||||
admin : account.gm,
|
admin : account.gm,
|
||||||
|
inactive: account.inactive,
|
||||||
characters: characters,
|
characters: characters,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -124,4 +124,6 @@ All other trademarks or tradenames are properties of their respective owners.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
|
||||||
38
app/components/ActionButtons.svelte
Normal file
38
app/components/ActionButtons.svelte
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
<script>
|
||||||
|
export let account;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if account.inactive}
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-warning btn-sm"
|
||||||
|
data-action="unban"
|
||||||
|
data-account-id={account.id}
|
||||||
|
data-account-name={account.name}
|
||||||
|
data-toggle="modal"
|
||||||
|
data-target="#actionModal">Unban</button>
|
||||||
|
{:else}
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-danger btn-sm"
|
||||||
|
data-action="ban"
|
||||||
|
data-account-id={account.id}
|
||||||
|
data-account-name={account.name}
|
||||||
|
data-toggle="modal"
|
||||||
|
data-target="#actionModal">Ban</button>
|
||||||
|
{#if account.admin}
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-warning btn-sm"
|
||||||
|
data-action="remove_gm"
|
||||||
|
data-account-id={account.id}
|
||||||
|
data-account-name={account.name}
|
||||||
|
data-toggle="modal"
|
||||||
|
data-target="#actionModal">Remove GM</button>
|
||||||
|
{:else}
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-success btn-sm"
|
||||||
|
data-action="add_gm"
|
||||||
|
data-account-id={account.id}
|
||||||
|
data-account-name={account.name}
|
||||||
|
data-toggle="modal"
|
||||||
|
data-target="#actionModal">Make GM</button>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
74
app/components/ActionModal.svelte
Normal file
74
app/components/ActionModal.svelte
Normal 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('#actionModal');
|
||||||
|
|
||||||
|
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 account_id = button.data('account-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/user/"+ account_id + "/" + action_type)
|
||||||
|
dispatch('action', {
|
||||||
|
target: account_id,
|
||||||
|
action: action_type,
|
||||||
|
});
|
||||||
|
modal.modal('hide')
|
||||||
|
} catch (e) {
|
||||||
|
modalAlert.message(e.message)
|
||||||
|
} finally {
|
||||||
|
submit.removeClass("disabled")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="modal fade" id="actionModal" 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">×</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>
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import { userId } from '../UserState'
|
||||||
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import page from 'page'
|
import page from 'page'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
|
||||||
import CharacterLink from '../components/CharacterLink'
|
import CharacterLink from '../components/CharacterLink'
|
||||||
import { userId } from '../UserState'
|
|
||||||
import LoginList from '../components/LoginList'
|
import LoginList from '../components/LoginList'
|
||||||
import AccountLink from '../components/AccountLink'
|
import AccountLink from '../components/AccountLink'
|
||||||
|
import ActionButtons from '../components/ActionButtons'
|
||||||
|
import ActionModal from '../components/ActionModal.svelte'
|
||||||
|
|
||||||
export let pageCtx;
|
export let pageCtx;
|
||||||
export let appAlert;
|
export let appAlert;
|
||||||
|
|
@ -22,7 +26,7 @@
|
||||||
let email;
|
let email;
|
||||||
let account;
|
let account;
|
||||||
|
|
||||||
onMount(async () => {
|
async function refresh() {
|
||||||
let loadID = params.id || $userId;
|
let loadID = params.id || $userId;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -47,6 +51,10 @@
|
||||||
appAlert.message(e.message)
|
appAlert.message(e.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
await refresh();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -56,6 +64,8 @@
|
||||||
|
|
||||||
{#if account}
|
{#if account}
|
||||||
<h1>Account: <AccountLink account={account}/></h1>
|
<h1>Account: <AccountLink account={account}/></h1>
|
||||||
|
<ActionButtons {account} />
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="staticEmail" class="col-sm-2 col-form-label">Email</label>
|
<label for="staticEmail" class="col-sm-2 col-form-label">Email</label>
|
||||||
|
|
@ -73,7 +83,7 @@
|
||||||
|
|
||||||
<h2>Characters</h2>
|
<h2>Characters</h2>
|
||||||
<p>
|
<p>
|
||||||
{#if characters.length > 1}
|
{#if characters.length >= 1}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{#each characters as char, i}
|
{#each characters as char, i}
|
||||||
<div class="col-md-4 col-12"><CharacterLink character={char} /></div>
|
<div class="col-md-4 col-12"><CharacterLink character={char} /></div>
|
||||||
|
|
@ -90,3 +100,4 @@
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<ActionModal on:action={refresh} />
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,13 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte'
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import AccountLink from '../components/AccountLink'
|
import AccountLink from '../components/AccountLink'
|
||||||
import PaginatedList from '../components/PaginatedList'
|
import PaginatedList from '../components/PaginatedList'
|
||||||
import Alert from '../components/Alert'
|
import ActionButtons from '../components/ActionButtons'
|
||||||
|
import ActionModal from '../components/ActionModal.svelte'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import jq from 'jquery'
|
|
||||||
|
|
||||||
export let appAlert
|
export let appAlert
|
||||||
let modalAlert, userList;
|
let userList;
|
||||||
|
|
||||||
onMount(() => setup_actions());
|
|
||||||
|
|
||||||
async function fetch(page) {
|
async function fetch(page) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -22,42 +19,6 @@
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setup_actions() {
|
|
||||||
const modal = jq('#actionModal');
|
|
||||||
|
|
||||||
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 account_id = button.data('account-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/user/"+ account_id + "/" + action_type)
|
|
||||||
await userList.refresh()
|
|
||||||
modal.modal('hide')
|
|
||||||
} catch (e) {
|
|
||||||
modalAlert.message(e.message)
|
|
||||||
} finally {
|
|
||||||
submit.removeClass("disabled")
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<PaginatedList bind:this={userList} bind:fetch={fetch} let:data={users} let:pagination={pagination}>
|
<PaginatedList bind:this={userList} bind:fetch={fetch} let:data={users} let:pagination={pagination}>
|
||||||
|
|
@ -86,65 +47,11 @@
|
||||||
Never logged in
|
Never logged in
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td><ActionButtons account={user} /></td>
|
||||||
{#if user.inactive}
|
|
||||||
<button type="button"
|
|
||||||
class="btn btn-warning btn-sm"
|
|
||||||
data-action="unban"
|
|
||||||
data-account-id={user.id}
|
|
||||||
data-account-name={user.name}
|
|
||||||
data-toggle="modal"
|
|
||||||
data-target="#actionModal">Unban</button>
|
|
||||||
{:else}
|
|
||||||
<button type="button"
|
|
||||||
class="btn btn-danger btn-sm"
|
|
||||||
data-action="ban"
|
|
||||||
data-account-id={user.id}
|
|
||||||
data-account-name={user.name}
|
|
||||||
data-toggle="modal"
|
|
||||||
data-target="#actionModal">Ban</button>
|
|
||||||
{#if user.admin}
|
|
||||||
<button type="button"
|
|
||||||
class="btn btn-warning btn-sm"
|
|
||||||
data-action="remove_gm"
|
|
||||||
data-account-id={user.id}
|
|
||||||
data-account-name={user.name}
|
|
||||||
data-toggle="modal"
|
|
||||||
data-target="#actionModal">Remove GM</button>
|
|
||||||
{:else}
|
|
||||||
<button type="button"
|
|
||||||
class="btn btn-success btn-sm"
|
|
||||||
data-action="add_gm"
|
|
||||||
data-account-id={user.id}
|
|
||||||
data-account-name={user.name}
|
|
||||||
data-toggle="modal"
|
|
||||||
data-target="#actionModal">Make GM</button>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</PaginatedList>
|
</PaginatedList>
|
||||||
|
|
||||||
<div class="modal fade" id="actionModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
<ActionModal on:action={userList.refresh} />
|
||||||
<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">×</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>
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue