nodebb-theme-harmony 1.0.0-beta.99 → 1.0.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/languages/en-GB/harmony.json +1 -0
- package/library.js +32 -1
- package/package.json +1 -1
- package/public/harmony.js +18 -13
- package/scss/chats.scss +22 -0
- package/scss/modals.scss +3 -6
- package/scss/modules/tags.scss +2 -2
- package/scss/modules/topic-navigator.scss +3 -1
- package/scss/topic.scss +6 -0
- package/templates/account/profile.tpl +17 -0
- package/templates/account/theme.tpl +5 -0
- package/templates/admin/plugins/harmony.tpl +4 -0
- package/templates/chats.tpl +1 -1
- package/templates/flags/list.tpl +0 -1
- package/templates/partials/categories/item.tpl +3 -3
- package/templates/partials/categories/lastpost.tpl +1 -1
- package/templates/partials/chats/message-window.tpl +4 -2
- package/templates/partials/chats/message.tpl +4 -4
- package/templates/partials/chats/recent_room.tpl +3 -3
- package/templates/partials/flags/bulk-actions.tpl +2 -2
- package/templates/partials/flags/filters.tpl +2 -0
- package/templates/partials/groups/invited.tpl +1 -1
- package/templates/partials/groups/memberlist.tpl +1 -1
- package/templates/partials/notifications_list.tpl +4 -4
- package/templates/partials/sidebar/notifications.tpl +1 -1
- package/templates/partials/sidebar/user-menu.tpl +5 -5
- package/templates/partials/topic/navigator.tpl +16 -14
- package/templates/partials/topic/post-menu-list.tpl +2 -2
- package/templates/partials/topic/post.tpl +2 -2
- package/templates/partials/topic/quickreply.tpl +1 -1
- package/templates/partials/topic/reply-button.tpl +4 -4
- package/templates/partials/topic-list-bar.tpl +1 -1
- package/templates/partials/topics_list.tpl +11 -8
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
"settings.title": "Theme settings",
|
|
7
7
|
"settings.enableQuickReply": "Enable quick reply",
|
|
8
8
|
"settings.centerHeaderElements": "Center header elements",
|
|
9
|
+
"settings.mobileTopicTeasers": "Show topic teasers on mobile",
|
|
9
10
|
"settings.stickyToolbar": "Sticky toolbar",
|
|
10
11
|
"settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page",
|
|
11
12
|
"settings.autohideBottombar": "Auto hide bottom bar",
|
package/library.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const nconf = require.main.require('nconf');
|
|
3
4
|
const meta = require.main.require('./src/meta');
|
|
4
5
|
const _ = require.main.require('lodash');
|
|
5
6
|
const user = require.main.require('./src/user');
|
|
@@ -11,6 +12,7 @@ const library = module.exports;
|
|
|
11
12
|
const defaults = {
|
|
12
13
|
enableQuickReply: 'on',
|
|
13
14
|
centerHeaderElements: 'off',
|
|
15
|
+
mobileTopicTeasers: 'off',
|
|
14
16
|
stickyToolbar: 'on',
|
|
15
17
|
autohideBottombar: 'off',
|
|
16
18
|
openSidebars: 'off',
|
|
@@ -28,8 +30,26 @@ library.init = async function (params) {
|
|
|
28
30
|
middleware.canViewUsers,
|
|
29
31
|
middleware.checkAccountPermissions,
|
|
30
32
|
], controllers.renderThemeSettings);
|
|
33
|
+
|
|
34
|
+
if (nconf.get('isPrimary') && process.env.NODE_ENV === 'production') {
|
|
35
|
+
setTimeout(buildSkins, 0);
|
|
36
|
+
}
|
|
31
37
|
};
|
|
32
38
|
|
|
39
|
+
async function buildSkins() {
|
|
40
|
+
try {
|
|
41
|
+
const plugins = require.main.require('./src/plugins');
|
|
42
|
+
await plugins.prepareForBuild(['client side styles']);
|
|
43
|
+
for (const skin of meta.css.supportedSkins) {
|
|
44
|
+
// eslint-disable-next-line no-await-in-loop
|
|
45
|
+
await meta.css.buildBundle(`client-${skin}`, true);
|
|
46
|
+
}
|
|
47
|
+
require.main.require('./src/meta/minifier').killAll();
|
|
48
|
+
} catch (err) {
|
|
49
|
+
console.error(err.stack);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
33
53
|
library.addAdminNavigation = async function (header) {
|
|
34
54
|
header.plugins.push({
|
|
35
55
|
route: '/plugins/harmony',
|
|
@@ -98,6 +118,16 @@ library.defineWidgetAreas = async function (areas) {
|
|
|
98
118
|
template: 'global',
|
|
99
119
|
location: 'brand-header',
|
|
100
120
|
},
|
|
121
|
+
{
|
|
122
|
+
name: 'About me (before)',
|
|
123
|
+
template: 'account/profile.tpl',
|
|
124
|
+
location: 'profile-aboutme-before',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: 'About me (after)',
|
|
128
|
+
template: 'account/profile.tpl',
|
|
129
|
+
location: 'profile-aboutme-after',
|
|
130
|
+
},
|
|
101
131
|
]);
|
|
102
132
|
|
|
103
133
|
return areas;
|
|
@@ -112,6 +142,7 @@ async function loadThemeConfig(uid) {
|
|
|
112
142
|
const config = { ...defaults, ...themeConfig, ...(_.pick(userConfig, Object.keys(defaults))) };
|
|
113
143
|
config.enableQuickReply = config.enableQuickReply === 'on';
|
|
114
144
|
config.centerHeaderElements = config.centerHeaderElements === 'on';
|
|
145
|
+
config.mobileTopicTeasers = config.mobileTopicTeasers === 'on';
|
|
115
146
|
config.stickyToolbar = config.stickyToolbar === 'on';
|
|
116
147
|
config.autohideBottombar = config.autohideBottombar === 'on';
|
|
117
148
|
config.openSidebars = config.openSidebars === 'on';
|
|
@@ -119,7 +150,7 @@ async function loadThemeConfig(uid) {
|
|
|
119
150
|
}
|
|
120
151
|
|
|
121
152
|
library.getThemeConfig = async function (config) {
|
|
122
|
-
config.theme = await loadThemeConfig(config.uid)
|
|
153
|
+
config.theme = await loadThemeConfig(config.uid);
|
|
123
154
|
config.openDraftsOnPageLoad = false;
|
|
124
155
|
return config;
|
|
125
156
|
};
|
package/package.json
CHANGED
package/public/harmony.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
$(document).ready(function () {
|
|
4
|
+
setupSkinSwitcher();
|
|
4
5
|
setupNProgress();
|
|
5
6
|
setupMobileMenu();
|
|
6
7
|
setupSearch();
|
|
@@ -9,21 +10,22 @@ $(document).ready(function () {
|
|
|
9
10
|
setupNavTooltips();
|
|
10
11
|
fixPlaceholders();
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
function setupSkinSwitcher() {
|
|
14
|
+
$('[component="skinSwitcher"]').on('click', '.dropdown-item', function () {
|
|
15
|
+
const skin = $(this).attr('data-value');
|
|
16
|
+
$('[component="skinSwitcher"] .dropdown-item .fa-check').addClass('invisible');
|
|
17
|
+
$(this).find('.fa-check').removeClass('invisible');
|
|
18
|
+
require(['forum/account/settings', 'hooks'], function (accountSettings, hooks) {
|
|
19
|
+
hooks.one('action:skin.change', function () {
|
|
20
|
+
$('[component="skinSwitcher"] [component="skinSwitcher/icon"]').removeClass('fa-fade');
|
|
21
|
+
});
|
|
22
|
+
$('[component="skinSwitcher"] [component="skinSwitcher/icon"]').addClass('fa-fade');
|
|
23
|
+
accountSettings.changeSkin(skin);
|
|
24
|
+
});
|
|
19
25
|
});
|
|
20
|
-
}
|
|
26
|
+
}
|
|
21
27
|
|
|
22
28
|
require(['hooks'], function (hooks) {
|
|
23
|
-
hooks.on('action:skin.change', function () {
|
|
24
|
-
$('[component="skinSwitcher"] [component="skinSwitcher/icon"]').removeClass('fa-fade');
|
|
25
|
-
});
|
|
26
|
-
|
|
27
29
|
$(window).on('action:composer.resize action:sidebar.toggle', function () {
|
|
28
30
|
$('[component="composer"]').css({
|
|
29
31
|
left: $('.sidebar-left').outerWidth(true),
|
|
@@ -65,6 +67,9 @@ $(document).ready(function () {
|
|
|
65
67
|
$body.on('hidden.bs.dropdown', '.sticky-tools', function () {
|
|
66
68
|
bottomBar.removeClass('hidden');
|
|
67
69
|
});
|
|
70
|
+
function isSearchVisible() {
|
|
71
|
+
return !!$('[component="bottombar"] [component="sidebar/search"] .search-dropdown.show').length;
|
|
72
|
+
}
|
|
68
73
|
|
|
69
74
|
let lastScrollTop = 0;
|
|
70
75
|
let newPostsLoaded = false;
|
|
@@ -76,7 +81,7 @@ $(document).ready(function () {
|
|
|
76
81
|
lastScrollTop = st;
|
|
77
82
|
return;
|
|
78
83
|
}
|
|
79
|
-
if (st !== lastScrollTop && !navigator.scrollActive) {
|
|
84
|
+
if (st !== lastScrollTop && !navigator.scrollActive && !isSearchVisible()) {
|
|
80
85
|
const diff = Math.abs(st - lastScrollTop);
|
|
81
86
|
const scrolledDown = st > lastScrollTop;
|
|
82
87
|
const scrolledUp = st < lastScrollTop;
|
package/scss/chats.scss
CHANGED
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
max-width: 100%;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
.stacked-avatars {
|
|
8
|
+
width: 32px;
|
|
9
|
+
height: 32px;
|
|
10
|
+
span:first-child {
|
|
11
|
+
top: 0;
|
|
12
|
+
left: 8px;
|
|
13
|
+
}
|
|
14
|
+
span:last-child {
|
|
15
|
+
left: 0;
|
|
16
|
+
top: 8px;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
7
20
|
body.page-user-chats {
|
|
8
21
|
overflow: hidden;
|
|
9
22
|
[data-widget-area="footer"] {
|
|
@@ -66,7 +79,16 @@ body.page-user-chats {
|
|
|
66
79
|
}
|
|
67
80
|
|
|
68
81
|
/* Mobile handling of chat page */
|
|
82
|
+
@include media-breakpoint-down(lg) {
|
|
83
|
+
.page-user-chats.chat-loaded {
|
|
84
|
+
padding-bottom: 4.75rem;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
69
88
|
@include media-breakpoint-down(md) {
|
|
89
|
+
.page-user-chats.chat-loaded {
|
|
90
|
+
padding-bottom: initial;
|
|
91
|
+
}
|
|
70
92
|
[component="chat/nav-wrapper"] {
|
|
71
93
|
width: 100%;
|
|
72
94
|
}
|
package/scss/modals.scss
CHANGED
package/scss/modules/tags.scss
CHANGED
package/scss/topic.scss
CHANGED
|
@@ -40,6 +40,9 @@
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
[component="post"] {
|
|
43
|
+
&.selected .post-container {
|
|
44
|
+
background-color: mix($body-bg, $body-color, 90%);
|
|
45
|
+
}
|
|
43
46
|
&.deleted .post-container {
|
|
44
47
|
opacity: .5;
|
|
45
48
|
}
|
|
@@ -50,6 +53,9 @@
|
|
|
50
53
|
pre {
|
|
51
54
|
max-height: calc($font-size-base * 24);
|
|
52
55
|
}
|
|
56
|
+
table { // text-break breaks table formatting
|
|
57
|
+
word-break:initial!important;
|
|
58
|
+
}
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
> [component="post/footer"] {
|
|
@@ -1,10 +1,27 @@
|
|
|
1
1
|
<!-- IMPORT partials/account/header.tpl -->
|
|
2
|
+
|
|
3
|
+
{{{ if widgets.profile-aboutme-before.length }}}
|
|
4
|
+
<div data-widget-area="profile-aboutme-before">
|
|
5
|
+
{{{each widgets.profile-aboutme-before}}}
|
|
6
|
+
{./html}
|
|
7
|
+
{{{end}}}
|
|
8
|
+
</div>
|
|
9
|
+
{{{ end }}}
|
|
10
|
+
|
|
2
11
|
{{{ if aboutme }}}
|
|
3
12
|
<div component="aboutme" class="text-sm text-break">
|
|
4
13
|
{aboutmeParsed}
|
|
5
14
|
</div>
|
|
6
15
|
{{{ end }}}
|
|
7
16
|
|
|
17
|
+
{{{ if widgets.profile-aboutme-after.length }}}
|
|
18
|
+
<div data-widget-area="profile-aboutme-after">
|
|
19
|
+
{{{each widgets.profile-aboutme-after}}}
|
|
20
|
+
{./html}
|
|
21
|
+
{{{end}}}
|
|
22
|
+
</div>
|
|
23
|
+
{{{ end }}}
|
|
24
|
+
|
|
8
25
|
<div class="account-stats container">
|
|
9
26
|
<div class="row row-cols-2 row-cols-xl-3 row-cols-xxl-4 g-2">
|
|
10
27
|
{{{ if !reputation:disabled }}}
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
<label class="form-check-label" for="centerHeaderElements">[[harmony:settings.centerHeaderElements]]</label>
|
|
18
18
|
</div>
|
|
19
19
|
|
|
20
|
+
<div class="form-check mb-3">
|
|
21
|
+
<input class="form-check-input" type="checkbox" id="mobileTopicTeasers" name="mobileTopicTeasers" {{{ if config.theme.mobileTopicTeasers }}}checked{{{ end }}}>
|
|
22
|
+
<label class="form-check-label" for="mobileTopicTeasers">[[harmony:settings.mobileTopicTeasers]]</label>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
20
25
|
<div class="form-check mb-3">
|
|
21
26
|
<input class="form-check-input" type="checkbox" id="stickyToolbar" name="stickyToolbar" {{{ if config.theme.stickyToolbar }}}checked{{{ end }}}>
|
|
22
27
|
<label class="form-check-label" for="stickyToolbar">
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
<input type="checkbox" class="form-check-input" id="centerHeaderElements" name="centerHeaderElements" />
|
|
11
11
|
<label for="centerHeaderElements" class="form-check-label">[[harmony:settings.centerHeaderElements]]</label>
|
|
12
12
|
</div>
|
|
13
|
+
<div class="form-check form-switch">
|
|
14
|
+
<input type="checkbox" class="form-check-input" id="mobileTopicTeasers" name="mobileTopicTeasers" />
|
|
15
|
+
<label for="mobileTopicTeasers" class="form-check-label">[[harmony:settings.mobileTopicTeasers]]</label>
|
|
16
|
+
</div>
|
|
13
17
|
<div class="form-check form-switch">
|
|
14
18
|
<input type="checkbox" class="form-check-input" id="stickyToolbar" name="stickyToolbar" />
|
|
15
19
|
<div for="stickyToolbar" class="form-check-label">
|
package/templates/chats.tpl
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
{{{end}}}
|
|
21
21
|
</div>
|
|
22
22
|
</div>
|
|
23
|
-
<div class="flex-grow-1 ms-md-2 ps-md-2 border-1 border-start-md h-100" component="chat/main-wrapper">
|
|
23
|
+
<div class="flex-grow-1 ms-md-2 ps-md-2 border-1 border-start-md h-100" component="chat/main-wrapper" style="min-width: 0;">
|
|
24
24
|
<!-- IMPORT partials/chats/message-window.tpl -->
|
|
25
25
|
</div>
|
|
26
26
|
<div class="imagedrop"><div>[[topic:composer.drag_and_drop_images]]</div></div>
|
package/templates/flags/list.tpl
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<li component="categories/category" data-cid="{./cid}" class="w-100 border-bottom py-3 py-lg-4 gap-1 d-flex flex-column flex-lg-row align-items-start category-{./cid}">
|
|
2
2
|
<meta itemprop="name" content="{./name}">
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
<div class="d-flex col-lg-7 gap-2 gap-lg-3">
|
|
5
5
|
<div class="flex-shrink-0">
|
|
6
6
|
{buildCategoryIcon(@value, "40px", "rounded-1")}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<!-- IMPORT partials/categories/link.tpl -->
|
|
11
11
|
</h2>
|
|
12
12
|
{{{ if ./descriptionParsed }}}
|
|
13
|
-
<div class="description text-muted text-
|
|
13
|
+
<div class="description text-muted text-sm w-100">
|
|
14
14
|
{./descriptionParsed}
|
|
15
15
|
</div>
|
|
16
16
|
{{{ end }}}
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
</div>
|
|
55
55
|
</div>
|
|
56
56
|
{{{ if !config.hideCategoryLastPost }}}
|
|
57
|
-
<div component="topic/teaser" class="teaser col-lg-6">
|
|
57
|
+
<div component="topic/teaser" class="teaser col-lg-6 {{{ if !config.theme.mobileTopicTeasers }}}d-none d-lg-block{{{ end }}}">
|
|
58
58
|
<!-- IMPORT partials/categories/lastpost.tpl -->
|
|
59
59
|
</div>
|
|
60
60
|
{{{ end }}}
|
|
@@ -24,8 +24,10 @@
|
|
|
24
24
|
<div component="chat/composer" class="d-flex flex-column flex-md-row gap-2 border-top pt-2 align-items-start align-items-md-end">
|
|
25
25
|
<div class="w-100 flex-grow-1 position-relative input-group">
|
|
26
26
|
<button component="chat/upload/button" class="btn btn-outline-primary btn-sm align-self-stretch px-3 px-md-2" type="button"><i class="fa fa-fw fa-upload"></i></button>
|
|
27
|
-
<
|
|
28
|
-
|
|
27
|
+
<div class="flex-grow-1 position-relative">
|
|
28
|
+
<textarea component="chat/input" placeholder="[[modules:chat.placeholder.mobile]]" class="form-control chat-input mousetrap rounded-0" style="height:0;max-height:30vh;resize:none;"></textarea>
|
|
29
|
+
<span component="chat/message/remaining" class="text-xs text-muted position-absolute me-1 mb-1 end-0 bottom-0">{maximumChatMessageLength}</span>
|
|
30
|
+
</div>
|
|
29
31
|
<button class="btn btn-primary btn-sm align-self-stretch px-3 px-md-2" type="button" data-action="send"><i class="fa fa-fw fa-paper-plane"></i></button>
|
|
30
32
|
</div>
|
|
31
33
|
<form class="hidden" component="chat/upload" method="post" enctype="multipart/form-data">
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
<li component="chat/message" class="chat-message mx-2 pe-2 clear{{{ if
|
|
1
|
+
<li component="chat/message" class="chat-message mx-2 pe-2 clear{{{ if messages.deleted }}} deleted{{{ end }}} {{{ if messages.newSet }}}border-top pt-3{{{ end }}}" data-index="{messages.index}" data-mid="{messages.messageId}" data-uid="{messages.fromuid}" data-self="{messages.self}" data-break="{messages.newSet}" data-timestamp="{messages.timestamp}">
|
|
2
2
|
<div class="message-header lh-1 d-flex align-items-center gap-2 text-sm {{{ if !messages.newSet }}}hidden{{{ end }}} pb-2">
|
|
3
3
|
<a href="{config.relative_path}/user/{messages.fromUser.userslug}" class="text-decoration-none">{buildAvatar(messages.fromUser, "18px", true, "not-responsive")}</a>
|
|
4
4
|
<span class="chat-user fw-semibold"><a href="{config.relative_path}/user/{messages.fromUser.userslug}">{messages.fromUser.displayname}</a></span>
|
|
5
|
-
{{{ if
|
|
5
|
+
{{{ if messages.fromUser.banned }}}
|
|
6
6
|
<span class="badge bg-danger">[[user:banned]]</span>
|
|
7
7
|
{{{ end }}}
|
|
8
|
-
{{{ if
|
|
8
|
+
{{{ if messages.fromUser.deleted }}}
|
|
9
9
|
<span class="badge bg-danger">[[user:deleted]]</span>
|
|
10
10
|
{{{ end }}}
|
|
11
11
|
<span class="chat-timestamp text-muted ms-2 timeago" title="{messages.timestampISO}"></span>
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
{messages.content}
|
|
19
19
|
</div>
|
|
20
20
|
|
|
21
|
-
{{{ if (!config.disableChatMessageEditing &&
|
|
21
|
+
{{{ if (!config.disableChatMessageEditing && messages.self ) }}}
|
|
22
22
|
<div class="position-relative">
|
|
23
23
|
<div class="btn-group border shadow-sm controls position-absolute small hover-d-block" style="bottom:5px; right:30px; display:none;">
|
|
24
24
|
<button class="btn btn-sm btn-link" data-action="edit"><i class="fa fa-pencil"></i></button>
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
<a class="stretched-link" href="{config.relative_path}/me/chats/{./roomId}"></a>
|
|
6
6
|
{{{ if ./users.length }}}
|
|
7
7
|
{{{ if ./groupChat}}}
|
|
8
|
-
<div class="position-relative
|
|
9
|
-
<span class="text-decoration-none position-absolute
|
|
10
|
-
<span class="text-decoration-none position-absolute
|
|
8
|
+
<div class="position-relative stacked-avatars">
|
|
9
|
+
<span class="text-decoration-none position-absolute" href="{config.relative_path}/user/{./users.1.userslug}">{buildAvatar(./users.1, "24px", true)}</span>
|
|
10
|
+
<span class="text-decoration-none position-absolute" href="{config.relative_path}/user/{./users.0.userslug}" >{buildAvatar(./users.0, "24px", true)}</span>
|
|
11
11
|
</div>
|
|
12
12
|
{{{ else }}}
|
|
13
13
|
<span href="{config.relative_path}/user/{./users.0.userslug}" class="text-decoration-none">{buildAvatar(./users.0, "32px", true)}</span>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<div class="
|
|
1
|
+
<div class="dropdown" component="flags/bulk-actions">
|
|
2
2
|
<button class="filter-btn btn btn-light btn-sm border" data-bs-toggle="dropdown" autocomplete="off" aria-haspopup="true" aria-expanded="false" disabled="disabled">
|
|
3
3
|
<span class="filter-label">[[flags:bulk-actions]]</span>
|
|
4
4
|
</button>
|
|
5
|
-
<ul class="dropdown-menu p-1 text-sm">
|
|
5
|
+
<ul class="dropdown-menu dropdown-menu-end p-1 text-sm">
|
|
6
6
|
<li><a href="#" class="dropdown-item rounded-1" data-action="bulk-assign">[[flags:assign-to-me]]</a></li>
|
|
7
7
|
<li><a href="#" class="dropdown-item rounded-1" data-action="bulk-mark-resolved">[[flags:bulk-resolve]]</a></li>
|
|
8
8
|
</ul>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
</div>
|
|
11
11
|
|
|
12
12
|
<div class="mb-2 clearfix">
|
|
13
|
-
<button class="btn btn-primary btn-sm float-end" component="groups/members/bulk-invite-button">[[groups:bulk-invite]]</button>
|
|
13
|
+
<button type="button" class="btn btn-primary btn-sm float-end" component="groups/members/bulk-invite-button">[[groups:bulk-invite]]</button>
|
|
14
14
|
</div>
|
|
15
15
|
|
|
16
16
|
<table component="groups/invited" class="table table-hover">
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div class="d-flex {{{ if group.isOwner }}}justify-content-between{{{ else }}}justify-content-end{{{ end }}} mb-3">
|
|
2
|
-
{{{ if
|
|
2
|
+
{{{ if isAdmin }}}
|
|
3
3
|
<div class="flex-shrink-0">
|
|
4
4
|
<button component="groups/members/add" type="button" class="btn btn-primary btn-sm me-3" title="[[groups:details.add-member]]"><i class="fa fa-user-plus"></i> [[groups:details.add-member]]</button>
|
|
5
5
|
</div>
|
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
{{{ each notifications }}}
|
|
9
9
|
<li class="{./readClass} mb-2 p-1" data-nid="{./nid}" data-path="{./path}" {{{ if ./pid }}}data-pid="{./pid}"{{{ end }}}{{{ if ./tid }}}data-tid="{./tid}"{{{ end }}}>
|
|
10
10
|
<div class="d-flex gap-1 justify-content-between">
|
|
11
|
-
<div class="d-flex gap-
|
|
11
|
+
<div class="btn-ghost-sm d-flex gap-2 flex-grow-1 align-items-start">
|
|
12
12
|
{{{ if ./image }}}
|
|
13
13
|
{{{ if ./from }}}
|
|
14
|
-
<a class="
|
|
14
|
+
<a class="flex-grow-0 flex-shrink-0" href="{config.relative_path}/user/{./user.userslug}"><img class="avatar avatar-rounded" style="--avatar-size: 32px;" src="{./image}" /></a>
|
|
15
15
|
{{{ end }}}
|
|
16
16
|
{{{ else }}}
|
|
17
|
-
<a class="
|
|
17
|
+
<a class="flex-grow-0 flex-shrink-0" href="{config.relative_path}/user/{./user.userslug}"><div class="avatar avatar-rounded" style="--avatar-size: 32px; background-color: {./user.icon:bgColor};">{./user.icon:text}</div></a>
|
|
18
18
|
{{{ end }}}
|
|
19
19
|
<div class="d-flex flex-grow-1 flex-column align-items-start position-relative">
|
|
20
|
-
<a href="{./path}" class="
|
|
20
|
+
<a href="{./path}" class="text-decoration-none d-inline-block text-reset text-break text-sm ff-sans stretched-link">
|
|
21
21
|
{./bodyShort}
|
|
22
22
|
</a>
|
|
23
23
|
<div class="text-xs text-muted">{{{ if ./timeagoLong }}}{./timeagoLong}{{{ else }}}<span class="timeago" title="{./datetimeISO}"></span>{{{ end }}}</div>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
</a>
|
|
11
11
|
<ul class="notifications-dropdown dropdown-menu p-1 shadow">
|
|
12
12
|
<li>
|
|
13
|
-
<ul component="notifications/list" class="list-container notification-list list-unstyled overscroll-behavior-contain ff-base">
|
|
13
|
+
<ul component="notifications/list" class="list-container notification-list list-unstyled overscroll-behavior-contain pe-1 ff-base">
|
|
14
14
|
<li class="mb-2 p-1">
|
|
15
15
|
<div class="d-flex gap-1 justify-content-between">
|
|
16
16
|
<div class="d-flex gap-2 flex-grow-1 placeholder-wave">
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<ul id="user-control-list" component="header/usercontrol" class="overscroll-behavior-contain user-dropdown dropdown-menu shadow p-1 text-sm ff-base" aria-labelledby="user_dropdown">
|
|
6
6
|
<li>
|
|
7
7
|
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" component="header/profilelink" href="{relative_path}/user/{user.userslug}">
|
|
8
|
-
<span component="user/status" class="flex-shrink-0
|
|
8
|
+
<span component="user/status" class="flex-shrink-0 border border-white border-2 rounded-circle status {user.status}"><span class="visually-hidden">[[global:{user.status}]]</span></span>
|
|
9
9
|
<span class="fw-semibold" component="header/username">{user.username}</span>
|
|
10
10
|
</a>
|
|
11
11
|
</li>
|
|
@@ -13,28 +13,28 @@
|
|
|
13
13
|
<li><h6 class="dropdown-header text-xs">[[global:status]]</h6></li>
|
|
14
14
|
<li>
|
|
15
15
|
<a href="#" class="dropdown-item rounded-1 user-status d-flex align-items-center gap-2 {{{ if user.online }}}selected{{{ end }}}" data-status="online">
|
|
16
|
-
<span component="user/status" class="flex-shrink-0
|
|
16
|
+
<span component="user/status" class="flex-shrink-0 border border-white border-2 rounded-circle status online"><span class="visually-hidden">[[global:online]]</span></span>
|
|
17
17
|
<span class="flex-grow-1">[[global:online]]</span>
|
|
18
18
|
<i class="fa-solid fa-check text-muted flex-shrink-0"></i>
|
|
19
19
|
</a>
|
|
20
20
|
</li>
|
|
21
21
|
<li>
|
|
22
22
|
<a href="#" class="dropdown-item rounded-1 user-status d-flex align-items-center gap-2 {{{ if user.away }}}selected{{{ end }}}" data-status="away">
|
|
23
|
-
<span component="user/status" class="flex-shrink-0
|
|
23
|
+
<span component="user/status" class="flex-shrink-0 border border-white border-2 rounded-circle status away"><span class="visually-hidden">[[global:away]]</span></span>
|
|
24
24
|
<span class="flex-grow-1">[[global:away]]</span>
|
|
25
25
|
<i class="fa-solid fa-check text-muted flex-shrink-0"></i>
|
|
26
26
|
</a>
|
|
27
27
|
</li>
|
|
28
28
|
<li>
|
|
29
29
|
<a href="#" class="dropdown-item rounded-1 user-status d-flex align-items-center gap-2 {{{ if user.dnd }}}selected{{{ end }}}" data-status="dnd">
|
|
30
|
-
<span component="user/status" class="flex-shrink-0
|
|
30
|
+
<span component="user/status" class="flex-shrink-0 border border-white border-2 rounded-circle status dnd"><span class="visually-hidden">[[global:dnd]]</span></span>
|
|
31
31
|
<span class="flex-grow-1">[[global:dnd]]</span>
|
|
32
32
|
<i class="fa-solid fa-check text-muted flex-shrink-0"></i>
|
|
33
33
|
</a>
|
|
34
34
|
</li>
|
|
35
35
|
<li>
|
|
36
36
|
<a href="#" class="dropdown-item rounded-1 user-status d-flex align-items-center gap-2 {{{ if user.offline }}}selected{{{ end }}}" data-status="offline">
|
|
37
|
-
<span component="user/status" class="flex-shrink-0
|
|
37
|
+
<span component="user/status" class="flex-shrink-0 border border-white border-2 rounded-circle status offline"><span class="visually-hidden">[[global:invisible]]</span></span>
|
|
38
38
|
<span class="flex-grow-1">[[global:invisible]]</span>
|
|
39
39
|
<i class="fa-solid fa-check text-muted flex-shrink-0"></i>
|
|
40
40
|
</a>
|
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
<div class="pagination-block d-none d-lg-block flex-grow-1 mb-2">
|
|
2
|
-
<div class="
|
|
3
|
-
<div class="
|
|
4
|
-
<div class="
|
|
5
|
-
|
|
6
|
-
<div class="scroller-
|
|
7
|
-
<div class="scroller-thumb-
|
|
8
|
-
|
|
9
|
-
<
|
|
10
|
-
|
|
2
|
+
<div class="d-flex justify-content-end sticky-top mt-4" style="top:6rem;z-index:1;">
|
|
3
|
+
<div class="ps-1 ps-md-0 d-inline-block">
|
|
4
|
+
<div class="scroller-content d-flex gap-2 flex-column align-items-start">
|
|
5
|
+
<div class="pointer pagetop btn-ghost-sm d-inline-flex" style="padding: 4px;"><i class="fa fa-chevron-up"></i> <span class="timeago text-xs text-muted text-nowrap" title="{./timestampISO}"></span></div>
|
|
6
|
+
<div class="scroller-container position-relative">
|
|
7
|
+
<div class="scroller-thumb d-flex gap-2 text-nowrap position-relative" style="height: 40px;">
|
|
8
|
+
<div class="scroller-thumb-icon bg-primary rounded d-inline-block" style="width:9px; height: 40px;"></div>
|
|
9
|
+
<div>
|
|
10
|
+
<p class="small thumb-text d-none d-md-inline-block ff-secondary fw-semibold user-select-none mb-0"></p>
|
|
11
|
+
<p class="meta thumb-timestamp timeago text-xs text-muted ff-secondary fw-semibold mb-0 user-select-none"></p>
|
|
12
|
+
</div>
|
|
11
13
|
</div>
|
|
12
|
-
</div>
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
<div class="unread d-inline-block position-absolute bottom-0">
|
|
16
|
+
<div class="meta small position-absolute top-50 translate-middle-y text-nowrap fw-semibold ms-2">
|
|
17
|
+
<a class="text-decoration-none" href="{url}"></a>
|
|
18
|
+
</div>
|
|
17
19
|
</div>
|
|
18
20
|
</div>
|
|
21
|
+
<div class="pointer pagebottom btn-ghost-sm d-inline-flex" style="padding: 4px;"><i class="fa fa-chevron-down"></i> <span class="timeago text-xs text-muted text-nowrap" title="{./lastposttimeISO}"></span></div>
|
|
19
22
|
</div>
|
|
20
|
-
<div class="pointer pagebottom btn-ghost-sm d-inline-flex" style="padding: 4px;"><i class="fa fa-chevron-down"></i> <span class="timeago text-xs text-muted" title="{./lastposttimeISO}"></span></div>
|
|
21
23
|
</div>
|
|
22
24
|
</div>
|
|
23
25
|
</div>
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
</li>
|
|
7
7
|
<li {{{ if posts.deleted }}}hidden{{{ end }}}>
|
|
8
8
|
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" component="post/delete" role="menuitem" tabindex="-1" href="#" class="{{{ if posts.deleted }}}hidden{{{ end }}}">
|
|
9
|
-
<span class="menu-icon"><i class="fa fa-fw text-muted fa-trash-o"></i
|
|
9
|
+
<span class="menu-icon"><i class="fa fa-fw text-muted fa-trash-o"></i></span> [[topic:delete]]
|
|
10
10
|
</a>
|
|
11
11
|
</li>
|
|
12
12
|
<li {{{ if !posts.deleted }}}hidden{{{ end }}}>
|
|
13
13
|
<a class="dropdown-item rounded-1 d-flex align-items-center gap-2" component="post/restore" role="menuitem" tabindex="-1" href="#" class="{{{ if !posts.deleted }}}hidden{{{ end }}}">
|
|
14
|
-
<span class="menu-icon"><i class="fa fa-fw text-muted fa-history"></i
|
|
14
|
+
<span class="menu-icon"><i class="fa fa-fw text-muted fa-history"></i></span> [[topic:restore]]
|
|
15
15
|
</a>
|
|
16
16
|
</li>
|
|
17
17
|
{{{ if posts.display_purge_tools }}}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<div class="icon py-1 bg-body d-none d-sm-block">
|
|
11
11
|
<a class="d-inline-block position-relative text-decoration-none" href="{{{ if ./user.userslug }}}{config.relative_path}/user/{./user.userslug}{{{ else }}}#{{{ end }}}">
|
|
12
12
|
{buildAvatar(posts.user, "48px", true, "", "user/picture")}
|
|
13
|
-
<span component="user/status" class="position-absolute translate-middle-y
|
|
13
|
+
<span component="user/status" class="position-absolute translate-middle-y border border-white border-2 rounded-circle status {posts.user.status}"><span class="visually-hidden">[[global:{posts.user.status}]]</span></span>
|
|
14
14
|
</a>
|
|
15
15
|
</div>
|
|
16
16
|
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
<div class="icon bg-body d-sm-none">
|
|
20
20
|
<a class="d-inline-block position-relative text-decoration-none" href="{{{ if ./user.userslug }}}{config.relative_path}/user/{./user.userslug}{{{ else }}}#{{{ end }}}">
|
|
21
21
|
{buildAvatar(posts.user, "20px", true, "", "user/picture")}
|
|
22
|
-
<span component="user/status" class="position-absolute translate-middle-y
|
|
22
|
+
<span component="user/status" class="position-absolute translate-middle-y border border-white border-2 rounded-circle status {posts.user.status}"><span class="visually-hidden">[[global:{posts.user.status}]]</span></span>
|
|
23
23
|
</a>
|
|
24
24
|
</div>
|
|
25
25
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<div class="icon hidden-xs">
|
|
4
4
|
<a class="d-inline-block position-relative" href="{{{ if loggedInUser.userslug }}}{config.relative_path}/user/{loggedInUser.userslug}{{{ else }}}#{{{ end }}}">
|
|
5
5
|
{buildAvatar(loggedInUser, "48px", true, "", "user/picture")}
|
|
6
|
-
{{{ if loggedInUser.status }}}<span component="user/status" class="position-absolute translate-middle-y
|
|
6
|
+
{{{ if loggedInUser.status }}}<span component="user/status" class="position-absolute translate-middle-y border border-white border-2 rounded-circle status {loggedInUser.status}"><span class="visually-hidden">[[global:{loggedInUser.status}]]</span></span>{{{ end }}}
|
|
7
7
|
</a>
|
|
8
8
|
</div>
|
|
9
9
|
<form class="flex-grow-1 d-flex flex-column gap-2" method="post" action="{config.relative_path}/compose">
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div component="topic/reply/container" class="btn-group action-bar {{{ if !privileges.topics:reply }}}hidden{{{ end }}}">
|
|
2
|
-
<a href="{config.relative_path}/compose?tid={tid}
|
|
2
|
+
<a href="{config.relative_path}/compose?tid={tid}" class="d-flex align-items-center btn btn-sm btn-primary px-3 fw-semibold " component="topic/reply" data-ajaxify="false" role="button"><i class="fa fa-reply d-sm-block d-md-none"></i><span class="d-none d-md-block"> [[topic:reply]]</span></a>
|
|
3
3
|
<button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-bs-toggle="dropdown">
|
|
4
4
|
<span class="caret"></span>
|
|
5
5
|
</button>
|
|
@@ -11,15 +11,15 @@
|
|
|
11
11
|
{{{ if loggedIn }}}
|
|
12
12
|
{{{ if !privileges.topics:reply }}}
|
|
13
13
|
{{{ if locked }}}
|
|
14
|
-
<a component="topic/reply/locked" class="d-flex gap-2 align-items-center fw-semibold btn btn-primary disabled" disabled><i class="fa fa-lock"></i> [[topic:locked]]</a>
|
|
14
|
+
<a component="topic/reply/locked" class="d-flex gap-2 align-items-center fw-semibold btn btn-sm btn-primary disabled" disabled><i class="fa fa-lock"></i> [[topic:locked]]</a>
|
|
15
15
|
{{{ end }}}
|
|
16
16
|
{{{ end }}}
|
|
17
17
|
|
|
18
18
|
{{{ if !locked }}}
|
|
19
|
-
<a component="topic/reply/locked" class="d-flex gap-2 align-items-center fw-semibold btn btn-primary disabled hidden" disabled><i class="fa fa-lock"></i> [[topic:locked]]</a>
|
|
19
|
+
<a component="topic/reply/locked" class="d-flex gap-2 align-items-center fw-semibold btn btn-sm btn-primary disabled hidden" disabled><i class="fa fa-lock"></i> [[topic:locked]]</a>
|
|
20
20
|
{{{ end }}}
|
|
21
21
|
{{{ else }}}
|
|
22
22
|
{{{ if !privileges.topics:reply }}}
|
|
23
|
-
<a component="topic/reply/guest" href="{config.relative_path}/login" class="d-flex align-items-center fw-semibold btn btn-primary">[[topic:guest-login-reply]]</a>
|
|
23
|
+
<a component="topic/reply/guest" href="{config.relative_path}/login" class="d-flex align-items-center fw-semibold btn btn-sm btn-primary">[[topic:guest-login-reply]]</a>
|
|
24
24
|
{{{ end }}}
|
|
25
25
|
{{{ end }}}
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
{{{ end }}}
|
|
47
47
|
<!-- only show login button if not logged in and doesn't have any posting privilege -->
|
|
48
48
|
{{{ if (!loggedIn && (!privileges.topics:create && !canPost))}}}
|
|
49
|
-
<a component="category/post/guest" href="{config.relative_path}/login" class="btn btn-primary">[[category:guest-login-post]]</a>
|
|
49
|
+
<a component="category/post/guest" href="{config.relative_path}/login" class="btn btn-sm btn-primary">[[category:guest-login-post]]</a>
|
|
50
50
|
{{{ end }}}
|
|
51
51
|
</div>
|
|
52
52
|
</div>
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
{buildAvatar(./user, "40px", true, "avatar avatar-tooltip")}
|
|
16
16
|
</a>
|
|
17
17
|
{{{ if showSelect }}}
|
|
18
|
-
<div class="checkbox position-absolute top-100 start-50 translate-middle-x
|
|
19
|
-
<i component="topic/select" class="fa text-muted pointer fa-square-o"></i>
|
|
18
|
+
<div class="checkbox position-absolute top-100 start-50 translate-middle-x pt-2 m-0 d-none d-lg-flex" style="max-width:max-content">
|
|
19
|
+
<i component="topic/select" class="fa text-muted pointer fa-square-o p-1"></i>
|
|
20
20
|
</div>
|
|
21
21
|
{{{ end }}}
|
|
22
22
|
</div>
|
|
@@ -52,11 +52,14 @@
|
|
|
52
52
|
{{{ if ./tags.length }}}
|
|
53
53
|
<span class="lh-1 tag-list hidden-xs d-flex flex-wrap gap-1">
|
|
54
54
|
{{{ each ./tags }}}
|
|
55
|
-
<a href="{config.relative_path}/tags/{./valueEncoded}"><span class="badge border border-gray-300
|
|
55
|
+
<a href="{config.relative_path}/tags/{./valueEncoded}"><span class="badge border border-gray-300 fw-normal tag tag-class-{./class}" data-tag="{./value}">{./valueEscaped}</span></a>
|
|
56
56
|
{{{ end }}}
|
|
57
57
|
</span>
|
|
58
58
|
{{{ end }}}
|
|
59
|
-
<
|
|
59
|
+
<a href="{config.relative_path}/topic/{./slug}" class="hidden-xs badge bg-transparent text-muted fw-normal timeago" title="{./timestampISO}"></a>
|
|
60
|
+
{{{ if !config.theme.mobileTopicTeasers}}}
|
|
61
|
+
<span class="visible-xs-inline badge bg-transparent text-muted fw-normal timeago" title="{{{ if ./teaser.timestampISO }}}{./teaser.timestampISO}{{{ else }}}{./timestampISO}{{{ end }}}"></span>
|
|
62
|
+
{{{ end }}}
|
|
60
63
|
</span>
|
|
61
64
|
</div>
|
|
62
65
|
{{{ if ./thumbs.length }}}
|
|
@@ -87,7 +90,7 @@
|
|
|
87
90
|
<i class="d-xl-none fa fa-fw text-xs text-muted opacity-75 fa-eye"></i>
|
|
88
91
|
</div>
|
|
89
92
|
</div>
|
|
90
|
-
<div component="topic/teaser" class="meta teaser col-lg-6">
|
|
93
|
+
<div component="topic/teaser" class="meta teaser col-lg-6 {{{ if !config.theme.mobileTopicTeasers }}}d-none d-lg-block{{{ end }}}">
|
|
91
94
|
<div class="lastpost background-link-container border-start border-2 lh-sm h-100" style="border-color: {./category.bgColor}!important;">
|
|
92
95
|
<a class="background-link" href="{config.relative_path}/topic/{./slug}/{./teaser.index}"></a>
|
|
93
96
|
{{{ if ./unreplied }}}
|
|
@@ -101,7 +104,7 @@
|
|
|
101
104
|
<a class="permalink text-muted timeago text-xs" href="{config.relative_path}/topic/{./slug}/{./teaser.index}" title="{./teaser.timestampISO}">
|
|
102
105
|
</a>
|
|
103
106
|
</div>
|
|
104
|
-
<div class="post-content text-xs ps-2 line-clamp-2 lh-sm text-break">
|
|
107
|
+
<div class="post-content text-xs ps-2 line-clamp-sm-2 lh-sm text-break">
|
|
105
108
|
{./teaser.content}
|
|
106
109
|
</div>
|
|
107
110
|
{{{ end }}}
|
|
@@ -110,8 +113,8 @@
|
|
|
110
113
|
</div>
|
|
111
114
|
</div>
|
|
112
115
|
{{{ if showSelect }}}
|
|
113
|
-
<div class="checkbox position-absolute top-0 end-0
|
|
114
|
-
<i component="topic/select" class="fa fa-square-o text-muted pointer"></i>
|
|
116
|
+
<div class="checkbox position-absolute top-0 end-0 mt-3 m-0 d-flex d-lg-none" style="max-width:max-content">
|
|
117
|
+
<i component="topic/select" class="fa fa-square-o text-muted pointer p-1"></i>
|
|
115
118
|
</div>
|
|
116
119
|
{{{ end }}}
|
|
117
120
|
</li>
|