nodebb-plugin-admin-chats 3.5.0 → 3.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -7
- package/lib/access.js +89 -0
- package/lib/history.js +144 -0
- package/lib/hooks.js +310 -0
- package/lib/lock.js +145 -0
- package/lib/overrides.js +186 -0
- package/lib/routes.js +432 -0
- package/library.js +5 -1501
- package/package.json +1 -1
- package/plugin.json +6 -6
- package/static/lib/live-updates.js +42 -0
- package/static/lib/lock-toggle.js +57 -0
- package/static/lib/profile-link.js +98 -0
- package/static/lib/switch-chat.js +234 -0
- package/templates/partials/chats/message-window.tpl +60 -0
- package/templates/partials/chats/message.tpl +78 -0
- package/templates/partials/chats/options.tpl +111 -0
- package/templates/partials/chats/recent_room.tpl +60 -0
- package/.github/workflows/npm-publish.yml +0 -62
- package/.vscode/settings.json +0 -3
- package/client.js +0 -917
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<div class="d-flex gap-1 align-items-stretch">
|
|
2
|
+
<!-- search -->
|
|
3
|
+
<button class="btn btn-ghost btn-sm" component="chat/room/search/toggle" data-manual-tooltip="1" title="{{tx("global:header.search")}}">
|
|
4
|
+
<i class="fa fa-search text-muted"></i>
|
|
5
|
+
</button>
|
|
6
|
+
<div component="chat/room/search/container" class="position-relative hidden align-self-center">
|
|
7
|
+
<input component="chat/room/search" class="form-control form-control-sm" placeholder="{{tx("search:type-to-search")}}" style="width: 150px;">
|
|
8
|
+
<a component="chat/room/search/clear" href="#" class="hidden px-2 py-1 position-absolute top-50 end-0 translate-middle-y">
|
|
9
|
+
<i class="fa fa-times text-muted opacity-75"></i>
|
|
10
|
+
</a>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
<!-- notification dropdown -->
|
|
15
|
+
<div class="dropdown d-flex" data-manual-tooltip="1" title="{{tx("modules:chat.notification-settings")}}" component="chat/notification/setting">
|
|
16
|
+
<button class="btn btn-ghost btn-sm position-relative" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
17
|
+
<i class="fa fa-bell text-muted"></i>
|
|
18
|
+
<span class="position-absolute top-0 end-0 text-xs text-muted opacity-50" style="font-size: 10px!important; padding: 1px; line-height: 10px;">
|
|
19
|
+
<i component="chat/notification/setting/icon" class="fa {notificationOptionsIcon}"></i>
|
|
20
|
+
</span>
|
|
21
|
+
</button>
|
|
22
|
+
<ul class="dropdown-menu dropdown-menu-end p-1 text-sm" role="menu">
|
|
23
|
+
{{{ each notificationOptions }}}
|
|
24
|
+
<li>
|
|
25
|
+
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-value="{./value}" data-icon="{./icon}" role="menuitem">
|
|
26
|
+
<div class="d-flex flex-column gap-1">
|
|
27
|
+
<div class="d-flex align-items-center gap-2">
|
|
28
|
+
<div class="flex-grow-1">{{tx(./label)}}</div>
|
|
29
|
+
<i class="flex-shrink-0 fa fa-fw fa-check {{{ if !./selected }}}hidden{{{ end }}}"></i>
|
|
30
|
+
</div>
|
|
31
|
+
{{{ if @first}}}
|
|
32
|
+
<div component="chat/notification/setting/sub-label" class="text-sm text-muted">{{tx(./subLabel)}}</div>
|
|
33
|
+
{{{ end }}}
|
|
34
|
+
</div>
|
|
35
|
+
</a>
|
|
36
|
+
</li>
|
|
37
|
+
|
|
38
|
+
{{{ if @first }}}
|
|
39
|
+
<li><hr class="dropdown-divider"></li>
|
|
40
|
+
{{{ end }}}
|
|
41
|
+
{{{ end }}}
|
|
42
|
+
</ul>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<!-- pinned messages -->
|
|
46
|
+
<button component="chat/pinned/messages/btn" class="btn btn-ghost btn-sm d-none d-lg-block flex-nowrap" title="{{tx("modules:chat.pinned-messages")}}" data-bs-toggle="tooltip" data-bs-placement="bottom">
|
|
47
|
+
<i class="fa fa-thumb-tack text-muted"></i>
|
|
48
|
+
</button>
|
|
49
|
+
|
|
50
|
+
<!-- manage/options dropdown -->
|
|
51
|
+
<div class="dropdown d-flex" data-manual-tooltip="1" title="{{tx("modules:chat.options")}}">
|
|
52
|
+
<button component="chat/controlsToggle" class="btn btn-ghost btn-sm" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
53
|
+
<i class="fa fa-gear text-muted"></i>
|
|
54
|
+
</button>
|
|
55
|
+
<ul class="dropdown-menu dropdown-menu-end p-1 text-sm" component="chat/controls" role="menu">
|
|
56
|
+
{{{ if isAdminOrGlobalMod }}}
|
|
57
|
+
<li role="presentation">
|
|
58
|
+
<a href="#" role="menuitem" class="dropdown-item rounded-1 d-flex align-items-center gap-2 admin-chat-lock-toggle-item" data-room-id="{roomId}" data-locked="{{{ if adminChatLock.isLocked }}}true{{{ else }}}false{{{ end }}}">
|
|
59
|
+
<i class="fa fa-fw {{{ if adminChatLock.isLocked }}}fa-lock-open{{{ else }}}fa-lock{{{ end }}}"></i>
|
|
60
|
+
<span>{{{ if adminChatLock.isLocked }}}{{tx("admin-chats:menu.release")}}{{{ else }}}{{tx("admin-chats:menu.lock")}}{{{ end }}}</span>
|
|
61
|
+
</a>
|
|
62
|
+
</li>
|
|
63
|
+
<li role="presentation"><hr class="dropdown-divider"></li>
|
|
64
|
+
{{{ end }}}
|
|
65
|
+
<li>
|
|
66
|
+
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-action="manage" role="menuitem">
|
|
67
|
+
<i class="fa fa-fw text-muted fa-cog"></i> {{tx("modules:chat.manage-room")}}
|
|
68
|
+
</a>
|
|
69
|
+
</li>
|
|
70
|
+
{{{ if isOwner }}}
|
|
71
|
+
<li>
|
|
72
|
+
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-action="rename" role="menuitem">
|
|
73
|
+
<i class="fa fa-fw text-muted fa-edit"></i> {{tx("modules:chat.rename-room")}}
|
|
74
|
+
</a>
|
|
75
|
+
</li>
|
|
76
|
+
{{{ end }}}
|
|
77
|
+
{{{ if !adminAllChats }}}
|
|
78
|
+
<li>
|
|
79
|
+
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-action="leave" role="menuitem">
|
|
80
|
+
<i class="fa fa-fw text-muted fa-sign-out"></i> {{tx("modules:chat.leave-room")}}
|
|
81
|
+
</a>
|
|
82
|
+
</li>
|
|
83
|
+
{{{ end }}}
|
|
84
|
+
{{{ if (public && isAdmin) }}}
|
|
85
|
+
<li>
|
|
86
|
+
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-action="delete" role="menuitem">
|
|
87
|
+
<i class="fa fa-fw text-danger fa-trash"></i> {{tx("modules:chat.delete-room")}}
|
|
88
|
+
</a>
|
|
89
|
+
</li>
|
|
90
|
+
{{{ end }}}
|
|
91
|
+
</ul>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<!-- users toggle -->
|
|
95
|
+
{{{ if users.length }}}
|
|
96
|
+
<div component="chat/user/list/btn" class="btn btn-ghost btn-sm d-none d-lg-flex flex-nowrap align-items-center gap-2" title="{{tx("modules:chat.view-users-list")}}" data-bs-toggle="tooltip" data-bs-placement="bottom">
|
|
97
|
+
<div class="d-flex text-nowrap">
|
|
98
|
+
{{{ if ./users.0 }}}
|
|
99
|
+
<span style="width: 18px; z-index: 3;" class="text-decoration-none" href="{config.relative_path}/user/{./users.0.userslug}">{{buildAvatar(./users.0, "24px", true)}}</span>
|
|
100
|
+
{{{ end }}}
|
|
101
|
+
{{{ if ./users.1 }}}
|
|
102
|
+
<span style="width: 18px; z-index: 2;" class="text-decoration-none" href="{config.relative_path}/user/{./users.1.userslug}">{{buildAvatar(./users.1, "24px", true)}}</span>
|
|
103
|
+
{{{ end }}}
|
|
104
|
+
{{{ if ./users.2 }}}
|
|
105
|
+
<span style="width: 24px; z-index: 1;" class="text-decoration-none" href="{config.relative_path}/user/{./users.2.userslug}">{{buildAvatar(./users.2, "24px", true)}}</span>
|
|
106
|
+
{{{ end }}}
|
|
107
|
+
</div>
|
|
108
|
+
{formattedNumber(./userCount)}
|
|
109
|
+
</div>
|
|
110
|
+
{{{ end }}}
|
|
111
|
+
</div>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{{{ if (loadingMore && @first)}}}
|
|
2
|
+
<hr class="my-1" />
|
|
3
|
+
{{{ end }}}
|
|
4
|
+
<div component="chat/recent/room" data-roomid="{./roomId}" data-full="1" class="rounded-1 {{{ if ./unread }}}unread{{{ end }}}">
|
|
5
|
+
<div class="d-flex gap-1 justify-content-between">
|
|
6
|
+
<a href="#" class="chat-room-btn position-relative d-flex flex-grow-1 gap-2 justify-content-start align-items-start btn btn-ghost btn-sm ff-sans text-start">
|
|
7
|
+
<div class="main-avatar">
|
|
8
|
+
{{{ if ./users.length }}}
|
|
9
|
+
{{{ if ./groupChat}}}
|
|
10
|
+
<div class="position-relative stacked-avatars">
|
|
11
|
+
<span class="text-decoration-none position-absolute" href="{config.relative_path}/user/{./users.1.userslug}">{{buildAvatar(./users.1, "24px", true)}}</span>
|
|
12
|
+
<span class="text-decoration-none position-absolute" href="{config.relative_path}/user/{./users.0.userslug}" >{{buildAvatar(./users.0, "24px", true)}}</span>
|
|
13
|
+
</div>
|
|
14
|
+
{{{ else }}}
|
|
15
|
+
<span href="{config.relative_path}/user/{./users.0.userslug}" class="text-decoration-none">{{buildAvatar(./users.0, "32px", true)}}</span>
|
|
16
|
+
{{{ end }}}
|
|
17
|
+
{{{ else }}}
|
|
18
|
+
<span class="avatar avatar-rounded text-bg-warning" component="avatar/icon" style="--avatar-size: 32px;">?</span>
|
|
19
|
+
{{{ end }}}
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<div class="d-flex flex-grow-1 flex-column w-100">
|
|
23
|
+
<div component="chat/room/title" class="room-name fw-semibold text-xs text-break">
|
|
24
|
+
{{{ if ./roomName}}}
|
|
25
|
+
{./roomName}
|
|
26
|
+
{{{ else }}}
|
|
27
|
+
{{{ if !./lastUser.uid }}}
|
|
28
|
+
{{tx("modules:chat.no-users-in-room")}}
|
|
29
|
+
{{{ else }}}
|
|
30
|
+
{{{ if greaterthan(./users.length, "3") }}}
|
|
31
|
+
{{tx(./usernames)}}
|
|
32
|
+
{{{ else }}}
|
|
33
|
+
{./usernames}
|
|
34
|
+
{{{ end }}}
|
|
35
|
+
{{{ end }}}
|
|
36
|
+
{{{ end }}}
|
|
37
|
+
</div>
|
|
38
|
+
<!-- IMPORT partials/chats/room-teaser.tpl -->
|
|
39
|
+
{{{ if ./participantsLabel }}}
|
|
40
|
+
<div class="admin-chat-participants text-muted text-xs text-break line-clamp-2"><span class="fw-semibold">{{tx("admin-chats:participants")}}:</span> {./participantsLabel}</div>
|
|
41
|
+
{{{ end }}}
|
|
42
|
+
</div>
|
|
43
|
+
</a>
|
|
44
|
+
{{{ if !adminAllChats }}}
|
|
45
|
+
<div>
|
|
46
|
+
<button class="mark-read btn btn-ghost btn-sm d-flex align-items-center justify-content-center flex-grow-0 flex-shrink-0 p-1" style="width: 1.5rem; height: 1.5rem;">
|
|
47
|
+
<i class="unread fa fa-2xs fa-circle text-primary {{{ if !./unread }}}hidden{{{ end }}}" aria-label="{{tx("unread:mark-as-read")}}"></i>
|
|
48
|
+
<i class="read fa fa-2xs fa-circle-o text-secondary {{{ if ./unread }}}hidden{{{ end }}}" aria-label="{{tx("unread:mark-as-unread")}}"></i>
|
|
49
|
+
</button>
|
|
50
|
+
</div>
|
|
51
|
+
{{{ end }}}
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
{{{ if !@last }}}
|
|
55
|
+
<hr class="my-1" />
|
|
56
|
+
{{{ else }}}
|
|
57
|
+
{{{ if showBottomHr }}}
|
|
58
|
+
<hr class="my-1" />
|
|
59
|
+
{{{ end }}}
|
|
60
|
+
{{{ end }}}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
name: Publish to npm on version bump
|
|
2
|
-
|
|
3
|
-
# Runs on every push to the default branch. If the version in package.json is
|
|
4
|
-
# not yet on the npm registry, it publishes the package. Bump the version in a
|
|
5
|
-
# commit and this workflow does the rest. Requires an NPM_TOKEN repository (or
|
|
6
|
-
# organization) secret; without it the publish step is skipped, not failed.
|
|
7
|
-
|
|
8
|
-
on:
|
|
9
|
-
push:
|
|
10
|
-
branches: [main, master]
|
|
11
|
-
|
|
12
|
-
permissions:
|
|
13
|
-
contents: read
|
|
14
|
-
|
|
15
|
-
concurrency:
|
|
16
|
-
group: npm-publish-${{ github.ref }}
|
|
17
|
-
cancel-in-progress: false
|
|
18
|
-
|
|
19
|
-
jobs:
|
|
20
|
-
publish:
|
|
21
|
-
runs-on: ubuntu-latest
|
|
22
|
-
steps:
|
|
23
|
-
- name: Checkout
|
|
24
|
-
uses: actions/checkout@v4
|
|
25
|
-
|
|
26
|
-
- name: Setup Node.js
|
|
27
|
-
uses: actions/setup-node@v4
|
|
28
|
-
with:
|
|
29
|
-
node-version: 20
|
|
30
|
-
registry-url: https://registry.npmjs.org
|
|
31
|
-
|
|
32
|
-
- name: Determine if this version needs publishing
|
|
33
|
-
id: check
|
|
34
|
-
run: |
|
|
35
|
-
NAME=$(node -p "require('./package.json').name")
|
|
36
|
-
VERSION=$(node -p "require('./package.json').version")
|
|
37
|
-
echo "Package: $NAME@$VERSION"
|
|
38
|
-
if npm view "$NAME@$VERSION" version >/dev/null 2>&1; then
|
|
39
|
-
echo "Version already on npm - nothing to do."
|
|
40
|
-
echo "publish=false" >> "$GITHUB_OUTPUT"
|
|
41
|
-
else
|
|
42
|
-
echo "Version not on npm - will publish."
|
|
43
|
-
echo "publish=true" >> "$GITHUB_OUTPUT"
|
|
44
|
-
fi
|
|
45
|
-
|
|
46
|
-
- name: Verify NPM_TOKEN is configured
|
|
47
|
-
id: token
|
|
48
|
-
env:
|
|
49
|
-
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
50
|
-
run: |
|
|
51
|
-
if [ -n "$NPM_TOKEN" ]; then
|
|
52
|
-
echo "set=true" >> "$GITHUB_OUTPUT"
|
|
53
|
-
else
|
|
54
|
-
echo "::warning::NPM_TOKEN secret is not set - skipping publish."
|
|
55
|
-
echo "set=false" >> "$GITHUB_OUTPUT"
|
|
56
|
-
fi
|
|
57
|
-
|
|
58
|
-
- name: Publish to npm
|
|
59
|
-
if: steps.check.outputs.publish == 'true' && steps.token.outputs.set == 'true'
|
|
60
|
-
run: npm publish --access public
|
|
61
|
-
env:
|
|
62
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/.vscode/settings.json
DELETED