Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Members module with member list page #3106

Merged
merged 44 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
862a5db
initial work
tadhgboyle Sep 24, 2022
ae8b186
migration
tadhgboyle Sep 24, 2022
60827ad
Merge branch 'develop' into feat/member-list
tadhgboyle Jan 23, 2023
3322c9e
Merge branch 'develop' into feat/member-list
tadhgboyle Jan 28, 2023
c1829aa
wip
tadhgboyle Jan 28, 2023
c8b3acf
Prevent long usernames going to new line
tadhgboyle Feb 17, 2023
14df436
wip
tadhgboyle Feb 17, 2023
d327189
Merge branch 'develop' into feat/member-list
tadhgboyle Feb 17, 2023
1fd9a5e
wip
tadhgboyle Feb 17, 2023
00cda1d
wip
tadhgboyle Feb 17, 2023
f1e6817
add search and new members widget
tadhgboyle Feb 17, 2023
898b805
make sidebar a little wider
tadhgboyle Feb 17, 2023
82e3317
move to built in Members module
tadhgboyle Feb 18, 2023
7716221
wip
tadhgboyle Feb 18, 2023
3cee66b
wip - add "by group" widget
tadhgboyle Feb 18, 2023
63d4451
wip
tadhgboyle Feb 18, 2023
aeaa697
display group html on list-specific pages
tadhgboyle Feb 19, 2023
6e1e28c
PR amendments (use fetch, improve speed, translate) wip
tadhgboyle Feb 23, 2023
105594c
Change min username length to 2
tadhgboyle Feb 23, 2023
35b4c08
Rate limit search
tadhgboyle Feb 23, 2023
e0c219d
Cache `member_list` query
tadhgboyle Feb 23, 2023
20beeff
Allow selecting specific groups to view
tadhgboyle Feb 24, 2023
2446387
wip pagination
tadhgboyle Feb 24, 2023
f27d343
fix pagination, rename to MemberListManager
tadhgboyle Feb 25, 2023
2f5f0c0
improve search
tadhgboyle Feb 25, 2023
03f163d
add "registered members" list
tadhgboyle Feb 25, 2023
bcdc89f
wip (make seeder counts more customizable)
tadhgboyle Feb 27, 2023
05c8777
add check for no overview lists enabled and for disabled lists
tadhgboyle Feb 28, 2023
ee9337e
document code
tadhgboyle Feb 28, 2023
88ec28d
undo changes
tadhgboyle Feb 28, 2023
10c0f32
Merge branch 'develop' into feat/member-list
tadhgboyle Feb 28, 2023
9e4f302
add back paginator
tadhgboyle Feb 28, 2023
3fe3e2c
remove unused term + move back text
tadhgboyle Feb 28, 2023
f9c297e
undo changes to Text class
tadhgboyle Mar 2, 2023
36901c2
undo changes to custom css
tadhgboyle Mar 2, 2023
3d2cdda
undo changes to forum module
tadhgboyle Mar 2, 2023
fb3b670
Merge branch 'develop' into feat/member-list
tadhgboyle Mar 2, 2023
21b4106
add back forum module changes
tadhgboyle Mar 2, 2023
b203713
pr amendments
tadhgboyle Mar 2, 2023
903f2ac
Add limit 5 to users query, add rate limiting (60 rq/m)
tadhgboyle Mar 2, 2023
9344bee
PR amendments (+ update dicebear api url)
tadhgboyle Mar 3, 2023
af9cf38
Fix
tadhgboyle Mar 3, 2023
8f8b63c
Fix avatar svg -> png url
tadhgboyle Mar 3, 2023
00a3127
Merge branch 'develop' into feat/member-list
tadhgboyle Mar 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
PR amendments (+ update dicebear api url)
  • Loading branch information
tadhgboyle committed Mar 3, 2023
commit 9344bee7fc4a83aeef58c5a3540ef89e7cba4c04
3 changes: 2 additions & 1 deletion Dockerfile.phpdoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ RUN mkdir /target && \
-d /source/modules/Core/classes \
-d "/source/modules/Discord Integration/classes" \
-d "/source/modules/Cookie Consent/classes" \
-d /source/modules/Forum/classes -t /target -i /vendor
-d /source/modules/Forum/classes
-d /source/modules/Members/classes -t /target -i /vendor

FROM nginxinc/nginx-unprivileged:stable

Expand Down
2 changes: 1 addition & 1 deletion core/classes/Avatars/AvatarSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public static function getAvatarFromUserData(object $data, bool $allow_gifs = fa
}
}

return "https://avatars.dicebear.com/api/initials/{$data->username}.png?size={$size}";
return "https://api.dicebear.com/5.x/initials/svg?seed={$data->username}&size={$size}";
}

/**
Expand Down
55 changes: 0 additions & 55 deletions custom/panel_templates/Default/members/member_lists.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -37,31 +37,6 @@
<!-- Success and Error Alerts -->
{include file='includes/alerts.tpl'}

<form id="toggleHideBannedUsers" action="" method="post">
<input type="hidden" name="token" value="{$TOKEN}">
<div class="form-group custom-control custom-switch">
<input type="hidden" name="action" value="toggle_hide_banned_users">
<input id="inputToggleHideBannedUsers" name="hide_banned_users" type="checkbox" class="custom-control-input js-check-change" value="1" {if $HIDE_BANNED_USERS_VALUE eq 1} checked{/if} />
<label for="inputToggleHideBannedUsers" class="custom-control-label">
{$HIDE_BANNED_USERS}
</label>
</div>
</form>

<form action="" method="post">
<input type="hidden" name="token" value="{$TOKEN}">
<div class="form-group">
<label for="groups">{$GROUPS}</label>
<select name="groups[]" id="groups" class="form-control" multiple>
{foreach from=$GROUPS_ARRAY item=group}
<option value="{$group.id}" {if in_array($group.id, $GROUPS_VALUE)} selected{/if}>{$group.name}</option>
{/foreach}
</select>
</div>
</form>

<hr>

<div class="table-responsive">
<table class="table table-borderless table-striped">
<thead>
Expand Down Expand Up @@ -122,36 +97,6 @@
</div>

{include file='scripts.tpl'}
<script>
const groupSelector = $('#groups');
groupSelector.select2({
placeholder: "{$NO_ITEM_SELECTED}"
});
groupSelector.on('change', (e) => {
const selectedGroups = [];
const selectedOptions = e.delegateTarget.selectedOptions;
for (const group of selectedOptions) {
selectedGroups.push(group.value);
}

$.ajax({
url: "{$SELECT_CHANGE_URL}",
type: "POST",
data: {
token: "{$TOKEN}",
action: "update_groups",
groups: selectedGroups,
},
success: function (response) {
// Success
},
error: function (xhr) {
// Error
console.log(xhr);
}
});
});
</script>

</body>

Expand Down
112 changes: 112 additions & 0 deletions custom/panel_templates/Default/members/members_settings.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{include file='header.tpl'}

<body id="page-top">

<!-- Wrapper -->
<div id="wrapper">

<!-- Sidebar -->
{include file='sidebar.tpl'}

<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">

<!-- Main content -->
<div id="content">

<!-- Topbar -->
{include file='navbar.tpl'}

<!-- Begin Page Content -->
<div class="container-fluid">

<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">{$SETTINGS}</h1>
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{$PANEL_INDEX}">{$DASHBOARD}</a></li>
<li class="breadcrumb-item active">{$MEMBERS}</li>
<li class="breadcrumb-item active">{$SETTINGS}</li>
</ol>
</div>

<!-- Update Notification -->
{include file='includes/update.tpl'}

<div class="card shadow mb-4">
<div class="card-body">

<!-- Success and Error Alerts -->
{include file='includes/alerts.tpl'}

<form action="" method="post">
<div class="form-group">
<label for="link_location">{$LINK_LOCATION}</label>
<select class="form-control" id="link_location" name="link_location">
<option value="1" {if $LINK_LOCATION_VALUE eq 1} selected{/if}>
{$LINK_NAVBAR}
</option>
<option value="2" {if $LINK_LOCATION_VALUE eq 2} selected{/if}>
{$LINK_MORE}
</option>
<option value="3" {if $LINK_LOCATION_VALUE eq 3} selected{/if}>
{$LINK_FOOTER}
</option>
<option value="4" {if $LINK_LOCATION_VALUE eq 4} selected{/if}>
{$LINK_NONE}
</option>
</select>
</div>

<div class="form-group custom-control custom-switch">
<input type="hidden" name="action" value="toggle_hide_banned_users">
<input id="inputToggleHideBannedUsers" name="hide_banned_users" type="checkbox" class="custom-control-input js-check-change" value="1" {if $HIDE_BANNED_USERS_VALUE eq 1} checked{/if} />
<label for="inputToggleHideBannedUsers" class="custom-control-label">
{$HIDE_BANNED_USERS}
</label>
</div>

<div class="form-group">
<label for="groups">{$GROUPS}</label>
<select name="groups[]" id="groups" class="form-control" multiple>
{foreach from=$GROUPS_ARRAY item=group}
<option value="{$group.id}" {if in_array($group.id, $GROUPS_VALUE)} selected{/if}>{$group.name}</option>
{/foreach}
</select>
</div>

<div class="form-group">
<input type="hidden" name="token" value="{$TOKEN}">
<input type="submit" class="btn btn-primary" value="{$SUBMIT}" />
</div>
</form>
</div>
</div>

<!-- Spacing -->
<div style="height:1rem;"></div>

<!-- End Page Content -->
</div>

<!-- End Main Content -->
</div>

{include file='footer.tpl'}

<!-- End Content Wrapper -->
</div>

<!-- End Wrapper -->
</div>

{include file='scripts.tpl'}
<script>
$('#groups').select2({
placeholder: "{$NO_ITEM_SELECTED}"
});
</script>

</body>

</html>
2 changes: 1 addition & 1 deletion custom/templates/DefaultRevamp/members/members.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@
url: 'profile_url',
},
apiSettings: {
url: '{$SEARCH_URL}&search={literal}{query}{/literal}'
url: '{$SEARCH_URL}&search={literal}{query}{/literal}&limit=5'
},
error: {
noResultsHeader: "{$NO_RESULTS_HEADER}",
Expand Down
3 changes: 2 additions & 1 deletion modules/Core/queries/users.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

$query = '%' . $_GET['search'] . '%';

$users = DB::getInstance()->query('SELECT id, username, nickname, gravatar, email, has_avatar, avatar_updated FROM nl2_users WHERE username LIKE ? OR nickname LIKE ? LIMIT 5', [
$limit = isset($_GET['limit']) ? 'LIMIT ' . (int) $_GET['limit'] : '';
$users = DB::getInstance()->query("SELECT id, username, nickname, gravatar, email, has_avatar, avatar_updated FROM nl2_users WHERE username LIKE ? OR nickname LIKE ? $limit", [
$query, $query
])->results();

Expand Down
4 changes: 4 additions & 0 deletions modules/Members/classes/MemberListProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ public function getMemberCount(): int {
*/
private function filterBanned(array $rows, string $id_column): array {
$ids = implode(',', array_map(static fn ($row) => $row->{$id_column}, $rows));
if (empty($ids)) {
return [];
}

$bans = DB::getInstance()->query("SELECT id, isbanned FROM nl2_users WHERE id IN ($ids)")->results();

return array_filter($rows, static function ($row) use ($bans, $id_column) {
Expand Down
4 changes: 2 additions & 2 deletions modules/Members/init.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

require_once ROOT_PATH . '/modules/Members/module.php';

$member_language = new Language(ROOT_PATH . '/modules/Members/language');
$members_language = new Language(ROOT_PATH . '/modules/Members/language');

$module = new Members_Module($language, $member_language, $pages);
$module = new Members_Module($language, $members_language, $pages);
3 changes: 2 additions & 1 deletion modules/Members/language/en_UK.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
"members/viewable_groups": "Viewable groups",
"members/no_results_header": "No results found",
"members/no_results_text": "Your search returned no results",
"members/no_overview_lists_enabled": "No overview lists are enabled."
"members/no_overview_lists_enabled": "No overview lists are enabled.",
"members/settings_updated_successfully": "Settings updated successfully."
}
55 changes: 43 additions & 12 deletions modules/Members/module.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
class Members_Module extends Module {

private Language $_language;
private Language $_member_language;
private Language $_members_language;

public function __construct(Language $language, Language $member_language, Pages $pages) {
public function __construct(Language $language, Language $members_language, Pages $pages) {
$this->_language = $language;
$this->_member_language = $member_language;
$this->_members_language = $members_language;

$name = 'Members';
$author = '<a href="https://tadhg.sh" target="_blank" rel="nofollow noopener">Aberdeener</a>';
Expand All @@ -28,7 +28,8 @@ public function __construct(Language $language, Language $member_language, Pages
// Define URLs which belong to this module
$pages->add('Members', '/members', 'pages/members.php');
$pages->add('Members', '/queries/member_list', 'queries/member_list.php');
$pages->add('Members', '/panel/core/member_lists', 'pages/panel/member_lists.php');
$pages->add('Members', '/panel/members/member_lists', 'pages/panel/member_lists.php');
$pages->add('Members', '/panel/members/settings', 'pages/panel/settings.php');
}

public function onInstall() {
Expand All @@ -52,7 +53,7 @@ public function onPageLoad(User $user, Pages $pages, Cache $cache, Smarty $smart

// AdminCP
PermissionHandler::registerPermissions($language->get('moderator', 'staff_cp'), [
'admincp.members' => $this->_member_language->get('members', 'member_lists')
'admincp.members' => $this->_members_language->get('members', 'member_lists')
]);

if (defined('FRONT_END')) {
Expand All @@ -70,7 +71,29 @@ public function onPageLoad(User $user, Pages $pages, Cache $cache, Smarty $smart
} else {
$members_icon = $cache->retrieve('members_icon');
}
$navs[0]->add('members', $this->_member_language->get('members', 'members'), URL::build('/members'), 'top', null, $members_order, $members_icon);

$cache->setCache('nav_location');
if (!$cache->isCached('members_location')) {
$link_location = 1;
$cache->store('members_location', 1);
} else {
$link_location = $cache->retrieve('members_location');
}

switch ($link_location) {
case 1:
// Navbar
$navs[0]->add('members', $this->_members_language->get('members', 'members'), URL::build('/members'), 'top', null, $members_order, $members_icon);
break;
case 2:
// "More" dropdown
$navs[0]->addItemToDropdown('more_dropdown', 'members', $this->_members_language->get('members', 'members'), URL::build('/members'), 'top', null, $members_icon, $members_order);
break;
case 3:
// Footer
$navs[0]->add('members', $this->_members_language->get('members', 'members'), URL::build('/members'), 'footer', null, $members_order, $members_icon);
break;
}
}

if (defined('BACK_END')) {
Expand All @@ -85,15 +108,23 @@ public function onPageLoad(User $user, Pages $pages, Cache $cache, Smarty $smart
$order = $cache->retrieve('members_order');
}

if (!$cache->isCached('members_icon')) {
$icon = '<i class="nav-icon fas fa-list"></i>';
$cache->store('members_icon', $icon);
if (!$cache->isCached('members_settings_icon')) {
$members_settings_icon = '<i class="nav-icon fas fa-cogs"></i>';
$cache->store('members_settings_icon', $members_settings_icon);
} else {
$members_settings_icon = $cache->retrieve('members_settings_icon');
}

if (!$cache->isCached('member_lists_icon')) {
$member_lists_icon = '<i class="nav-icon fas fa-list"></i>';
$cache->store('member_lists_icon', $member_lists_icon);
} else {
$icon = $cache->retrieve('members_icon');
$member_lists_icon = $cache->retrieve('member_lists_icon');
}

$navs[2]->add('members_divider', mb_strtoupper($this->_member_language->get('members', 'members'), 'UTF-8'), 'divider', 'top', null, $order);
$navs[2]->add('member_lists_settings', $this->_member_language->get('members', 'member_lists'), URL::build('/panel/core/member_lists'), 'top', null, $order + 0.1, $icon);
$navs[2]->add('members_divider', mb_strtoupper($this->_members_language->get('members', 'members'), 'UTF-8'), 'divider', 'top', null, $order);
$navs[2]->add('members_settings', $this->_language->get('admin', 'settings'), URL::build('/panel/members/settings'), 'top', null, $order + 0.1, $members_settings_icon);
$navs[2]->add('member_lists_settings', $this->_members_language->get('members', 'member_lists'), URL::build('/panel/members/member_lists'), 'top', null, $order + 0.2, $member_lists_icon);
}
}
}
Expand Down
Loading