nodebb-theme-harmony 3.0.0-beta.1 → 3.0.0-beta.2
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/package.json +2 -2
- package/public/harmony.js +9 -11
- package/scss/harmony.scss +0 -2
- package/templates/account/categories.tpl +1 -1
- package/templates/account/consent.tpl +3 -1
- package/templates/account/profile.tpl +2 -2
- package/templates/account/settings.tpl +3 -3
- package/templates/account/tags.tpl +1 -1
- package/templates/account/uploads.tpl +1 -1
- package/templates/category.tpl +1 -1
- package/templates/notifications.tpl +1 -1
- package/templates/partials/account/header.tpl +1 -1
- package/templates/partials/account/sidebar-left.tpl +1 -1
- package/templates/partials/cookie-consent.tpl +2 -2
- package/templates/partials/mobile-nav.tpl +2 -2
- package/templates/partials/notifications_list.tpl +2 -2
- package/templates/partials/search-results.tpl +2 -3
- package/templates/partials/sidebar/drafts.tpl +8 -3
- package/templates/partials/tags_list.tpl +3 -3
- package/templates/partials/topic/post.tpl +7 -10
- package/templates/partials/topic-list-bar.tpl +1 -1
- package/templates/partials/topics_list.tpl +2 -2
- package/templates/world.tpl +1 -1
- package/scss/groups.scss +0 -20
- package/scss/modules/cover.scss +0 -104
- package/templates/groups/details.tpl +0 -92
- package/templates/groups/list.tpl +0 -58
- package/templates/groups/members.tpl +0 -10
- package/templates/partials/groups/admin.tpl +0 -90
- package/templates/partials/groups/badge.tpl +0 -1
- package/templates/partials/groups/invited.tpl +0 -33
- package/templates/partials/groups/list.tpl +0 -17
- package/templates/partials/groups/memberlist.tpl +0 -47
- package/templates/partials/groups/pending.tpl +0 -29
- package/templates/partials/groups/sidebar-left.tpl +0 -27
- package/templates/partials/toast.tpl +0 -19
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodebb-theme-harmony",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.2",
|
|
4
4
|
"nbbpm": {
|
|
5
5
|
"compatibility": "^4.14.0"
|
|
6
6
|
},
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@fontsource/poppins": "5.2.7"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"eslint": "10.
|
|
48
|
+
"eslint": "10.5.0",
|
|
49
49
|
"eslint-config-nodebb": "^2.0.2"
|
|
50
50
|
}
|
|
51
51
|
}
|
package/public/harmony.js
CHANGED
|
@@ -141,7 +141,7 @@ $(document).ready(function () {
|
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
function setupDrafts() {
|
|
144
|
-
require(['composer/drafts', 'bootbox'], function (drafts, bootbox) {
|
|
144
|
+
require(['composer/drafts', 'bootbox', 'api'], function (drafts, bootbox, api) {
|
|
145
145
|
const draftsEl = $('[component="sidebar/drafts"]');
|
|
146
146
|
const bottomBarDraftsEl = $('[component="bottombar"] [component="sidebar/drafts"]');
|
|
147
147
|
function updateBadgeCount() {
|
|
@@ -159,17 +159,15 @@ $(document).ready(function () {
|
|
|
159
159
|
draftListEl.find('.draft-item-container').html('');
|
|
160
160
|
return;
|
|
161
161
|
}
|
|
162
|
-
draftItems.reverse()
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
).replace(/(?:\r\n|\r|\n)/g, '<br>');
|
|
162
|
+
draftItems.reverse();
|
|
163
|
+
await Promise.all(draftItems.map(async (item) => {
|
|
164
|
+
const cid = String(item.cid);
|
|
165
|
+
if (item && item.action === 'topics.post' && cid !== '0') {
|
|
166
|
+
const categoryUrl = cid !== '-1' ?
|
|
167
|
+
`/api/category/${encodeURIComponent(cid)}` : `/api/world`;
|
|
168
|
+
item.category = await api.get(categoryUrl, {});
|
|
170
169
|
}
|
|
171
|
-
});
|
|
172
|
-
|
|
170
|
+
}));
|
|
173
171
|
const html = await app.parseAndTranslate('partials/sidebar/drafts', 'drafts', { drafts: draftItems });
|
|
174
172
|
draftListEl.find('.no-drafts').addClass('hidden');
|
|
175
173
|
draftListEl.find('.placeholder-wave').addClass('hidden');
|
package/scss/harmony.scss
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
@import "mobilebar";
|
|
11
11
|
@import "status";
|
|
12
12
|
@import "account";
|
|
13
|
-
@import "groups";
|
|
14
13
|
@import "world";
|
|
15
14
|
@import "modals";
|
|
16
15
|
|
|
@@ -19,7 +18,6 @@
|
|
|
19
18
|
@import "modules/user-menu";
|
|
20
19
|
@import "modules/topic-navigator";
|
|
21
20
|
@import "modules/topics-list";
|
|
22
|
-
@import "modules/cover";
|
|
23
21
|
@import "modules/nprogress";
|
|
24
22
|
@import "modules/paginator";
|
|
25
23
|
@import "modules/filters";
|
|
@@ -54,7 +54,8 @@
|
|
|
54
54
|
|
|
55
55
|
<hr />
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
{{{ if canExport }}}
|
|
58
|
+
<div class="d-grid gap-2">
|
|
58
59
|
<a data-action="export-profile" class="btn btn-outline-secondary">
|
|
59
60
|
<i class="fa fa-download"></i> [[user:consent.export-profile]]
|
|
60
61
|
</a>
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
<i class="fa fa-download"></i> [[user:consent.export-uploads]]
|
|
66
67
|
</a>
|
|
67
68
|
</div>
|
|
69
|
+
{{{ end }}}
|
|
68
70
|
</div>
|
|
69
71
|
</div>
|
|
70
72
|
</div>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
{{{ if aboutme }}}
|
|
12
12
|
<div component="aboutme" class="text-sm text-break">
|
|
13
|
-
{{aboutmeParsed}}
|
|
13
|
+
{{txEscape(aboutmeParsed)}}
|
|
14
14
|
</div>
|
|
15
15
|
{{{ end }}}
|
|
16
16
|
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
{{{ if ./value }}}
|
|
77
77
|
<div class="stat">
|
|
78
78
|
<div class="align-items-center justify-content-center card card-header p-3 border-0 rounded-1 h-100 gap-2">
|
|
79
|
-
<span class="stat-label text-xs fw-semibold"><span><i class="text-muted {./icon}"></i> {./name}</span></span>
|
|
79
|
+
<span class="stat-label text-xs fw-semibold"><span><i class="text-muted {./icon}"></i> {tx(./name)}</span></span>
|
|
80
80
|
{{{ if (./type == "input-link") }}}
|
|
81
81
|
<a class="text-center text-break w-100 px-2 ff-secondary text-underline text-reset" href="{./value}" rel="nofollow noreferrer">{./linkValue}</a>
|
|
82
82
|
{{{ else }}}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<label for="bootswatchSkin" class="form-label fw-bold">[[user:select-skin]]</label>
|
|
11
11
|
<select class="form-select form-select-sm" id="bootswatchSkin" data-property="bootswatchSkin">
|
|
12
12
|
{{{each bootswatchSkinOptions}}}
|
|
13
|
-
<option value="{bootswatchSkinOptions.value}" {{{ if bootswatchSkinOptions.selected }}}selected{{{ end }}}>{bootswatchSkinOptions.name}</option>
|
|
13
|
+
<option value="{bootswatchSkinOptions.value}" {{{ if bootswatchSkinOptions.selected }}}selected{{{ end }}}>{tx(bootswatchSkinOptions.name)}</option>
|
|
14
14
|
{{{end}}}
|
|
15
15
|
</select>
|
|
16
16
|
|
|
@@ -177,7 +177,7 @@
|
|
|
177
177
|
<label class="form-label text-sm" for="dailyDigestFreq">[[user:digest-label]]</label>
|
|
178
178
|
<select class="form-select form-select-sm" id="dailyDigestFreq" data-property="dailyDigestFreq" autocomplete="off">
|
|
179
179
|
{{{each dailyDigestFreqOptions}}}
|
|
180
|
-
<option value="{./value}" {{{ if ./selected }}}selected="1"{{{ end }}}>{./name}</option>
|
|
180
|
+
<option value="{./value}" {{{ if ./selected }}}selected="1"{{{ end }}}>{tx(./name)}</option>
|
|
181
181
|
{{{end}}}
|
|
182
182
|
</select>
|
|
183
183
|
<p class="form-text text-xs">[[user:digest-description]]</p>
|
|
@@ -271,7 +271,7 @@
|
|
|
271
271
|
<tr component="notification/setting" class="align-middle">
|
|
272
272
|
<td style="width:100%;">
|
|
273
273
|
<div class="align-items-center">
|
|
274
|
-
<label class="text-sm tracking-tight" for="{./name}">{./label}</label>
|
|
274
|
+
<label class="text-sm tracking-tight" for="{./name}">{tx(./label)}</label>
|
|
275
275
|
<input type="hidden" data-property="{./name}" value="{./value}">
|
|
276
276
|
</div>
|
|
277
277
|
</td>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- IMPORT partials/account/header.tpl -->
|
|
2
2
|
|
|
3
|
-
<h3 class="fw-semibold fs-5">{title}</h3>
|
|
3
|
+
<h3 class="fw-semibold fs-5">{tx(title)}</h3>
|
|
4
4
|
|
|
5
5
|
<div class="alert alert-info text-center">
|
|
6
6
|
{{{ if privateUploads }}}[[uploads:private-uploads-info]]{{{ else }}}[[uploads:public-uploads-info]]{{{ end }}}
|
package/templates/category.tpl
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<span class="text-lowercase fw-normal">[[global:posts]]</span>
|
|
19
19
|
</span>
|
|
20
20
|
{{{ if !isNumber(cid) }}}
|
|
21
|
-
<a href="{
|
|
21
|
+
<a href="{./url}" class="badge text-body border border-gray-300 text-xs" data-ajaxify="false">
|
|
22
22
|
<span class="fw-normal">View Original</span>
|
|
23
23
|
<i class="fa fa-external-link"></i>
|
|
24
24
|
</a>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<hr/>
|
|
11
11
|
{{{ else }}}
|
|
12
12
|
<a class="btn btn-ghost d-flex gap-2 text-start align-items-baseline text-sm ff-secondary fw-semibold {{{ if ./selected }}}active{{{ end }}}" href="{config.relative_path}/notifications?filter={./filter}">
|
|
13
|
-
<div class="flex-grow-1">{filters.name}</div>
|
|
13
|
+
<div class="flex-grow-1">{tx(filters.name)}</div>
|
|
14
14
|
{{{ if ./filter }}}
|
|
15
15
|
<span class="flex-shrink-0 text-xs" title="{./count}">{humanReadableNumber(./count)}</span>
|
|
16
16
|
{{{ end }}}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div class="account w-100 mx-auto">
|
|
2
|
-
<div class="cover position-absolute start-0 top-0 w-100" component="account/cover" style="background-image: url({
|
|
2
|
+
<div class="cover position-absolute start-0 top-0 w-100" component="account/cover" style="background-image: url({cover:url}); background-position: {cover:position};">
|
|
3
3
|
<div class="container">
|
|
4
4
|
{{{ if (allowCoverPicture && canEdit) }}}
|
|
5
5
|
<div class="controls text-center">
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
|
|
120
120
|
{{{ each profile_links }}}
|
|
121
121
|
<a href="{config.relative_path}/user/{userslug}/{./route}" class="btn btn-ghost btn-sm ff-secondary text-xs text-start plugin-link {{{ if ./public }}}public{{{ else }}}private{{{ end }}} {{{ if (url == ./url) }}}active{{{ end }}}" id="{./id}">
|
|
122
|
-
<div class="flex-grow-1">{./name}</div>
|
|
122
|
+
<div class="flex-grow-1">{tx(./name)}</div>
|
|
123
123
|
</a>
|
|
124
124
|
{{{end}}}
|
|
125
125
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div class="position-fixed bottom-0 w-100 px-3 px-md-0 pb-5 mb-5 pb-lg-0 mb-lg-0" style="z-index: 2;">
|
|
2
2
|
<div class="cookie-consent d-flex flex-column flex-lg-row gap-2 text-bg-info col-12 col-sm-8 col-lg-6 p-3 mx-auto rounded mb-5 mb-md-3 justify-content-between align-items-center">
|
|
3
|
-
<span>{message} <a class="fw-bold" target="_blank" rel="noopener" href="{link_url}">{link}</a></span>
|
|
4
|
-
<button class="btn btn-primary text-nowrap">{dismiss}</button>
|
|
3
|
+
<span>{tx(message)} <a class="fw-bold" target="_blank" rel="noopener" href="{link_url}">{tx(link)}</a></span>
|
|
4
|
+
<button class="btn btn-primary text-nowrap">{tx(dismiss)}</button>
|
|
5
5
|
</div>
|
|
6
6
|
</div>
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
<ul class="navigation-dropdown dropdown-menu" role="menu">
|
|
11
11
|
{{{ each navigation }}}
|
|
12
12
|
{{{ if displayMenuItem(@root, @index) }}}
|
|
13
|
-
<li class="nav-item {./class}{{{ if ./dropdown }}} dropend{{{ end }}}" title="{./title}">
|
|
13
|
+
<li class="nav-item {./class}{{{ if ./dropdown }}} dropend{{{ end }}}" title="{tx(./title)}">
|
|
14
14
|
<a class="nav-link navigation-link px-3 py-2 {{{ if ./dropdown }}}dropdown-toggle{{{ end }}}" {{{ if ./dropdown }}} href="#" role="button" data-bs-toggle="collapse" data-bs-target="#collapse-target-{@index}" onclick="event.stopPropagation();" {{{ else }}} href="{./route}"{{{ end }}} {{{ if ./id }}}id="{./id}"{{{ end }}}{{{ if ./targetBlank }}} target="_blank"{{{ end }}}>
|
|
15
15
|
<span class="d-inline-flex justify-content-between align-items-center w-100">
|
|
16
16
|
<span class="text-nowrap">
|
|
17
17
|
{{{ if ./iconClass }}}
|
|
18
18
|
<i class="fa fa-fw {./iconClass}" data-content="{./content}"></i>
|
|
19
19
|
{{{ end }}}
|
|
20
|
-
{{{ if ./text }}}<span class="nav-text px-2 fw-semibold">{./text}</span>{{{ end }}}
|
|
20
|
+
{{{ if ./text }}}<span class="nav-text px-2 fw-semibold">{tx(./text)}</span>{{{ end }}}
|
|
21
21
|
</span>
|
|
22
22
|
<span component="navigation/count" class="badge rounded-1 bg-primary {{{ if !./content }}}hidden{{{ end }}}">{./content}</span>
|
|
23
23
|
</span>
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
|
|
24
24
|
<div class="d-flex flex-grow-1 flex-column gap-1 align-items-start position-relative">
|
|
25
25
|
<a href="{./path}" class="text-decoration-none d-inline-block text-reset text-break text-sm ff-sans stretched-link" component="notifications/item/link">
|
|
26
|
-
{./bodyShort}
|
|
26
|
+
{{./bodyShort}}
|
|
27
27
|
</a>
|
|
28
28
|
{{{ if ./bodyLong}}}
|
|
29
29
|
<div class="text-secondary text-sm line-clamp-2 text-contain hidden-blockquote hidden-pre hidden-first-child-br">
|
|
30
|
-
{./bodyLong}
|
|
30
|
+
{{./bodyLong}}
|
|
31
31
|
</div>
|
|
32
32
|
{{{ end }}}
|
|
33
33
|
<div class="text-xs text-muted">{{{ if ./timeagoLong }}}{./timeagoLong}{{{ else }}}<span class="timeago" title="{./datetimeISO}"></span>{{{ end }}}</div>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
{{{ if matchCount }}}
|
|
2
|
-
<div class="card card-header text-xs px-2 py-1 fw-semibold border-0 align-self-start">
|
|
3
|
-
</div>
|
|
2
|
+
<div class="card card-header text-xs px-2 py-1 fw-semibold border-0 align-self-start">{{tx("search:results-matching", matchCount, txEscape(search_query), time)}}</div>
|
|
4
3
|
{{{ else }}}
|
|
5
4
|
{{{ if search_query }}}
|
|
6
5
|
<div class="badge text-bg-warning align-self-start">[[search:no-matches]]</div>
|
|
@@ -25,7 +24,7 @@
|
|
|
25
24
|
<div class="d-flex gap-3 post-info">
|
|
26
25
|
<div class="post-author d-flex gap-1">
|
|
27
26
|
<a class="lh-1 text-decoration-none" href="{config.relative_path}/user/{./user.userslug}">{{buildAvatar(./user, "16px", true, "not-responsive")}}</a>
|
|
28
|
-
<a class="fw-semibold text-sm" href="{config.relative_path}/user/{./user.userslug}">{
|
|
27
|
+
<a class="fw-semibold text-sm" href="{config.relative_path}/user/{./user.userslug}">{./user.displayname}</a>
|
|
29
28
|
</div>
|
|
30
29
|
<span class="timeago text-sm text-muted" title="{./timestampISO}"></span>
|
|
31
30
|
</div>
|
|
@@ -35,17 +35,22 @@
|
|
|
35
35
|
{{{ end }}}
|
|
36
36
|
|
|
37
37
|
{{{ if (./action == "posts.reply") }}}
|
|
38
|
-
<div class="text text-xs fw-semibold line-clamp-2 text-break">
|
|
38
|
+
<div class="text text-xs fw-semibold line-clamp-2 text-break">{{tx("topic:composer.replying-to", txEscape(quote(./title)))}}</div>
|
|
39
39
|
{{{ end }}}
|
|
40
40
|
|
|
41
41
|
{{{ if (./action == "posts.edit") }}}
|
|
42
|
-
<div class="text text-xs fw-semibold line-clamp-2">
|
|
42
|
+
<div class="text text-xs fw-semibold line-clamp-2">{{tx("topic:composer.editing-in", txEscape(quote(./title)))}}</div>
|
|
43
43
|
{{{ end }}}
|
|
44
44
|
|
|
45
45
|
{{{ if ./text }}}
|
|
46
46
|
<div class="text text-sm line-clamp-3 text-break">{./text}</div>
|
|
47
47
|
{{{ end }}}
|
|
48
|
-
<div class="
|
|
48
|
+
<div class="d-flex align-items-baseline gap-2">
|
|
49
|
+
{{{ if (./action == "topics.post") }}}
|
|
50
|
+
{{buildCategoryLabel(./category, "span", "border")}}
|
|
51
|
+
{{{ end }}}
|
|
52
|
+
<div class="timeago text-xs text-muted" title="{./timestampISO}"></div>
|
|
53
|
+
</div>
|
|
49
54
|
</a>
|
|
50
55
|
<div>
|
|
51
56
|
<button component="drafts/delete" data-save-id="{./save_id}" class="btn btn-light btn-sm">
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{{{each tags}}}
|
|
2
2
|
<div>
|
|
3
|
-
<a href="{config.relative_path}/tags/{./valueEncoded}" data-tag="{./
|
|
4
|
-
<div class="fw-semibold text-nowrap tag-item w-100 text-start text-truncate">{./
|
|
5
|
-
<div class="text-xs text-muted text-nowrap tag-topic-count">
|
|
3
|
+
<a href="{config.relative_path}/tags/{./valueEncoded}" data-tag="{./value}" class="btn btn-ghost ff-base d-flex flex-column gap-1 align-items-start justify-content-start text-truncate p-2">
|
|
4
|
+
<div class="fw-semibold text-nowrap tag-item w-100 text-start text-truncate">{./value}</div>
|
|
5
|
+
<div class="text-xs text-muted text-nowrap tag-topic-count">{tx("global:x-topics", formattedNumber(./score))}</div>
|
|
6
6
|
</a>
|
|
7
7
|
</div>
|
|
8
8
|
{{{end}}}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
{{{ else }}}
|
|
18
18
|
<span component="user/locality" class="position-absolute top-100 start-100 lh-1 border border-white border-2 rounded-circle small" title="[[global:remote-user]]">
|
|
19
19
|
<span class="visually-hidden">[[global:remote-user]]</span>
|
|
20
|
-
<i class="fa fa-globe"></i>
|
|
20
|
+
<i class="fa fa-globe fa-width-auto"></i>
|
|
21
21
|
</span>
|
|
22
22
|
{{{ end }}}
|
|
23
23
|
</a>
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
{{{ else }}}
|
|
38
38
|
<span component="user/locality" class="position-absolute top-100 start-100 lh-1 border border-white border-2 rounded-circle small" title="[[global:remote-user]]">
|
|
39
39
|
<span class="visually-hidden">[[global:remote-user]]</span>
|
|
40
|
-
<i class="fa fa-globe"></i>
|
|
40
|
+
<i class="fa fa-globe fa-width-auto"></i>
|
|
41
41
|
</span>
|
|
42
42
|
{{{ end }}}
|
|
43
43
|
</a>
|
|
@@ -64,13 +64,10 @@
|
|
|
64
64
|
</div>
|
|
65
65
|
|
|
66
66
|
{{{ if posts.user.custom_profile_info.length }}}
|
|
67
|
-
<div>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
{{posts.user.custom_profile_info.content}}
|
|
72
|
-
{{{ end }}}
|
|
73
|
-
</span>
|
|
67
|
+
<div class="d-flex gap-1 align-items-center">
|
|
68
|
+
{{{ each posts.user.custom_profile_info }}}
|
|
69
|
+
{{posts.user.custom_profile_info.content}}
|
|
70
|
+
{{{ end }}}
|
|
74
71
|
</div>
|
|
75
72
|
{{{ end }}}
|
|
76
73
|
</div>
|
|
@@ -86,7 +83,7 @@
|
|
|
86
83
|
|
|
87
84
|
<div component="post/footer" class="post-footer border-bottom pb-2">
|
|
88
85
|
{{{ if posts.user.signature }}}
|
|
89
|
-
<div component="post/signature" data-uid="{posts.user.uid}" class="text-xs text-muted mt-2">{{posts.user.signature}}</div>
|
|
86
|
+
<div component="post/signature" data-uid="{posts.user.uid}" class="text-xs text-muted mt-2">{{txEscape(posts.user.signature)}}</div>
|
|
90
87
|
{{{ end }}}
|
|
91
88
|
|
|
92
89
|
<div class="d-flex flex-wrap-reverse gap-2 {{{ if (hideReplies || !posts.replies.count) }}}justify-content-end{{{ else }}}justify-content-between{{{ end }}}">
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
|
|
55
55
|
<!-- IMPORT partials/category/tools-dropdown-left.tpl -->
|
|
56
56
|
|
|
57
|
-
<a href="{{{ if (template.category || template.world) }}}{
|
|
57
|
+
<a href="{{{ if (template.category || template.world) }}}{url}{{{ else }}}{config.relative_path}/{selectedFilter.url}{querystring}{{{ end }}}" class="btn btn-secondary fw-semibold position-absolute top-100 translate-middle-x start-50 mt-1 hide" style="--bs-btn-padding-y: .25rem; --bs-btn-padding-x: .5rem; --bs-btn-font-size: .75rem;" id="new-topics-alert">
|
|
58
58
|
<i class="fa fa-fw fa-arrow-up"></i> [[recent:load-new-posts]]
|
|
59
59
|
</a>
|
|
60
60
|
</div>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
{{{ each topics }}}
|
|
4
4
|
<li component="category/topic" class="category-item hover-parent border-bottom py-3 py-lg-4 d-flex flex-column flex-lg-row align-items-start {generateTopicClass(@value)}" <!-- IMPORT partials/data/category.tpl -->>
|
|
5
5
|
<link itemprop="url" content="{config.relative_path}/topic/{./slug}" />
|
|
6
|
-
<meta itemprop="name" content="{
|
|
6
|
+
<meta itemprop="name" content="{./title}" />
|
|
7
7
|
<meta itemprop="itemListOrder" content="descending" />
|
|
8
8
|
<meta itemprop="position" content="{increment(./index, "1")}" />
|
|
9
9
|
<a id="{./index}" data-index="{./index}" component="topic/anchor"></a>
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
</div>
|
|
22
22
|
<div class="flex-grow-1 d-flex flex-wrap gap-1 position-relative">
|
|
23
23
|
<h3 component="topic/header" class="title text-break text-wrap-pretty fs-5 fw-semibold m-0 tracking-tight w-100 {{{ if showSelect }}}me-4 me-lg-0{{{ end }}}">
|
|
24
|
-
<a class="text-reset" href="{{{ if topics.noAnchor }}}#{{{ else }}}{config.relative_path}/topic/{./slug}{{{ if ./bookmark }}}/{./bookmark}{{{ end }}}{{{ end }}}">{
|
|
24
|
+
<a class="text-reset" href="{{{ if topics.noAnchor }}}#{{{ else }}}{config.relative_path}/topic/{./slug}{{{ if ./bookmark }}}/{./bookmark}{{{ end }}}{{{ end }}}">{./title}</a>
|
|
25
25
|
</h3>
|
|
26
26
|
<span component="topic/labels" class="d-flex flex-wrap gap-1 w-100">
|
|
27
27
|
<span component="topic/watched" class="badge border border-gray-300 text-body {{{ if !./followed }}}hidden{{{ end }}}">
|
package/templates/world.tpl
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
</div>
|
|
44
44
|
<div class="d-grid gap-0">
|
|
45
45
|
<div class="title fw-semibold">
|
|
46
|
-
<a class="text-reset stretched-link" href="{{{ if ./link }}}{./link}{{{ else }}}{config.relative_path}/category/{./slug}{{{ end }}}" itemprop="url">{
|
|
46
|
+
<a class="text-reset stretched-link" href="{{{ if ./link }}}{./link}{{{ else }}}{config.relative_path}/category/{./slug}{{{ end }}}" itemprop="url">{./name}</a>
|
|
47
47
|
</div>
|
|
48
48
|
{{{ if ./descriptionParsed }}}
|
|
49
49
|
<div class="description text-muted text-xs w-100 line-clamp-sm-5">{{./descriptionParsed}}</div>
|
package/scss/groups.scss
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
.template-groups-details #panel {
|
|
2
|
-
margin-top: 0px!important;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
.group-hover-bg {
|
|
6
|
-
$hover-color: mix($body-bg, $body-color, 90%);
|
|
7
|
-
$border-color: mix($body-bg, $body-color, 90%);
|
|
8
|
-
border-color: $border-color!important;
|
|
9
|
-
&:hover {
|
|
10
|
-
background-color: $hover-color;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.groups.details {
|
|
15
|
-
margin-top: 200px;
|
|
16
|
-
|
|
17
|
-
@include media-breakpoint-up(md) {
|
|
18
|
-
margin-top: 300px;
|
|
19
|
-
}
|
|
20
|
-
}
|
package/scss/modules/cover.scss
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
// used in group and account pages
|
|
2
|
-
.cover {
|
|
3
|
-
background-size: cover;
|
|
4
|
-
background-repeat: no-repeat;
|
|
5
|
-
height: 200px;
|
|
6
|
-
position: absolute;
|
|
7
|
-
background-origin: content-box;
|
|
8
|
-
width: 100%;
|
|
9
|
-
top: var(--panel-offset)!important;
|
|
10
|
-
left: auto;
|
|
11
|
-
right: 0px;
|
|
12
|
-
|
|
13
|
-
&:hover .controls, .controls:focus-within {
|
|
14
|
-
opacity: 1;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.controls {
|
|
18
|
-
height: 200px;
|
|
19
|
-
line-height: 200px;
|
|
20
|
-
opacity: 0;
|
|
21
|
-
@include transition(opacity .15s linear);
|
|
22
|
-
cursor: pointer;
|
|
23
|
-
pointer-events: none;
|
|
24
|
-
|
|
25
|
-
> * {
|
|
26
|
-
pointer-events: all;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
&.active {
|
|
31
|
-
&:hover {
|
|
32
|
-
cursor: move;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
.controls {
|
|
36
|
-
> * {
|
|
37
|
-
display: none;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.save {
|
|
42
|
-
display: inline-block;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
&.saving {
|
|
47
|
-
.save {
|
|
48
|
-
display: none;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.indicator {
|
|
52
|
-
display: inline-block;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.save, .indicator {
|
|
57
|
-
display: inline-block;
|
|
58
|
-
position: absolute;
|
|
59
|
-
bottom: 1em;
|
|
60
|
-
left: 50%;
|
|
61
|
-
transform: translateX(-50%);
|
|
62
|
-
opacity: 1;
|
|
63
|
-
padding: 0.5em;
|
|
64
|
-
font-weight: bold;
|
|
65
|
-
|
|
66
|
-
&:hover {
|
|
67
|
-
cursor: pointer;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.save {
|
|
72
|
-
display: none;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.indicator {
|
|
76
|
-
display: none;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.cover > .container {
|
|
81
|
-
height: 200px;
|
|
82
|
-
position: relative;
|
|
83
|
-
pointer-events: none;
|
|
84
|
-
.save {
|
|
85
|
-
pointer-events: all;
|
|
86
|
-
}
|
|
87
|
-
.controls {
|
|
88
|
-
pointer-events: none;
|
|
89
|
-
> * {
|
|
90
|
-
pointer-events: all;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
@include media-breakpoint-up(md) {
|
|
96
|
-
.cover, .cover > .container {
|
|
97
|
-
height: 300px;
|
|
98
|
-
|
|
99
|
-
.controls {
|
|
100
|
-
height: 300px;
|
|
101
|
-
line-height: 300px;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
<div component="groups/container" class="groups details flex-fill">
|
|
2
|
-
<div class="cover position-absolute start-0 top-0" component="groups/cover" style="background-image: url({escape(group.cover:url)}?{config.cache-buster}); background-position: {group.cover:position};">
|
|
3
|
-
<div class="container">
|
|
4
|
-
{{{ if group.isOwner }}}
|
|
5
|
-
<div class="controls text-center">
|
|
6
|
-
<span class="upload p-2 m-2 rounded-1 text-bg-light opacity-75"><i class="fa fa-fw fa-upload"></i></span>
|
|
7
|
-
<span class="resize p-2 m-2 rounded-1 text-bg-light opacity-75"><i class="fa fa-fw fa-arrows"></i></span>
|
|
8
|
-
<span class="remove p-2 m-2 rounded-1 text-bg-light opacity-75"><i class="fa fa-fw fa-times"></i></span>
|
|
9
|
-
</div>
|
|
10
|
-
<a href="#" class="save btn btn-primary">[[groups:cover-save]] <i class="fa fa-fw fa-floppy-o"></i></a>
|
|
11
|
-
<div class="indicator text-bg-primary">[[groups:cover-saving]] <i class="fa fa-fw fa-refresh fa-spin"></i></div>
|
|
12
|
-
{{{ end }}}
|
|
13
|
-
</div>
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
<div class="d-flex flex-column flex-md-row justify-content-md-between pb-4 mb-4 mt-2 border-bottom gap-3">
|
|
17
|
-
<div class="d-flex flex-column mt-1 gap-2">
|
|
18
|
-
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2">
|
|
19
|
-
<h3 class="mb-0 text-capitalize">{generateGroupDisplayName(group)}</h3>
|
|
20
|
-
<div>
|
|
21
|
-
{{{ if group.private }}}<span class="badge text-bg-light border border-1">[[groups:details.private]]</span>{{{ end }}}
|
|
22
|
-
{{{ if group.hidden }}}<span class="badge text-bg-light border border-1">[[groups:details.hidden]]</span>{{{ end }}}
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
25
|
-
<div>
|
|
26
|
-
{{group.descriptionParsed}}
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
<div class="d-flex gap-2 align-items-start">
|
|
30
|
-
{{{ if loggedIn }}}
|
|
31
|
-
{{membershipBtn(group)}}
|
|
32
|
-
{{{ end }}}
|
|
33
|
-
{{{ if isAdmin }}}
|
|
34
|
-
<a href="{config.relative_path}/admin/manage/groups/{group.slug}" target="_blank" class="btn btn-light text-nowrap"><i class="fa fa-gear"></i> [[user:edit]]</a>
|
|
35
|
-
{{{ end }}}
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
38
|
-
|
|
39
|
-
<div class="d-flex flex-column flex-md-row">
|
|
40
|
-
<div data-widget-area="left">
|
|
41
|
-
{{{each widgets.left}}}
|
|
42
|
-
{{widgets.left.html}}
|
|
43
|
-
{{{end}}}
|
|
44
|
-
</div>
|
|
45
|
-
<!-- IMPORT partials/groups/sidebar-left.tpl -->
|
|
46
|
-
|
|
47
|
-
<div class="flex-grow-1 ps-md-2 ps-lg-5" style="min-width:0;">
|
|
48
|
-
<div class="tab-content">
|
|
49
|
-
<div class="tab-pane fade show active" id="groups-posts" role="tabpanel">
|
|
50
|
-
<h3 class="fw-semibold fs-5 mb-0">[[global:posts]]</h3>
|
|
51
|
-
{{{ if !posts.length }}}
|
|
52
|
-
<div class="alert alert-info my-2">[[groups:details.has-no-posts]]</div>
|
|
53
|
-
{{{ end }}}
|
|
54
|
-
<!-- IMPORT partials/posts_list.tpl -->
|
|
55
|
-
</div>
|
|
56
|
-
<div class="tab-pane fade" id="groups-members" role="tabpanel">
|
|
57
|
-
<h3 class="fw-semibold fs-5 mb-3">[[groups:details.members]]</h3>
|
|
58
|
-
|
|
59
|
-
<!-- IMPORT partials/groups/memberlist.tpl -->
|
|
60
|
-
</div>
|
|
61
|
-
{{{ if group.isOwner }}}
|
|
62
|
-
<div class="tab-pane fade" id="groups-pending" role="tabpanel">
|
|
63
|
-
<h3 class="fw-semibold fs-5 mb-3">[[groups:details.pending]]</h3>
|
|
64
|
-
<!-- IMPORT partials/groups/pending.tpl -->
|
|
65
|
-
</div>
|
|
66
|
-
|
|
67
|
-
<div class="tab-pane fade" id="groups-invited" role="tabpanel">
|
|
68
|
-
<h3 class="fw-semibold fs-5 mb-3">[[groups:details.invited]]</h3>
|
|
69
|
-
<!-- IMPORT partials/groups/invited.tpl -->
|
|
70
|
-
</div>
|
|
71
|
-
|
|
72
|
-
<div class="tab-pane fade" id="groups-admin" role="tabpanel">
|
|
73
|
-
<div class="d-flex align-items-center gap-1 justify-content-between mb-3 flex-wrap">
|
|
74
|
-
<h3 class="fw-semibold fs-5">[[groups:details.owner-options]]</h3>
|
|
75
|
-
<div class="d-flex justify-content-end gap-2">
|
|
76
|
-
<button class="btn btn-link btn-sm text-danger border-danger" type="button" data-action="delete">[[groups:details.delete-group]]</button>
|
|
77
|
-
<button class="btn btn-primary btn-sm" type="button" data-action="update">[[global:save-changes]]</button>
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
<!-- IMPORT partials/groups/admin.tpl -->
|
|
81
|
-
</div>
|
|
82
|
-
{{{ end }}}
|
|
83
|
-
</div>
|
|
84
|
-
</div>
|
|
85
|
-
|
|
86
|
-
<div data-widget-area="right">
|
|
87
|
-
{{{each widgets.right}}}
|
|
88
|
-
{{widgets.right.html}}
|
|
89
|
-
{{{end}}}
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
<div data-widget-area="header">
|
|
2
|
-
{{{each widgets.header}}}
|
|
3
|
-
{{widgets.header.html}}
|
|
4
|
-
{{{end}}}
|
|
5
|
-
</div>
|
|
6
|
-
<div class="groups list flex-fill">
|
|
7
|
-
<h3 class="fw-semibold">[[pages:groups]]</h3>
|
|
8
|
-
<div class="d-flex flex-wrap justify-content-between">
|
|
9
|
-
<div class="mb-2 mb-md-0">
|
|
10
|
-
<div class="text-sm d-flex flex-wrap align-items-center gap-2">
|
|
11
|
-
[[topic:sort-by]]
|
|
12
|
-
<div class="d-flex flex-wrap gap-2">
|
|
13
|
-
<a href="?sort=alpha" class="btn btn-ghost btn-sm ff-secondary fw-semibold text-nowrap {{{ if (sort == "alpha") }}}active{{{ end }}}">[[groups:details.group-name]]</a>
|
|
14
|
-
<a href="?sort=count" class="btn btn-ghost btn-sm ff-secondary fw-semibold text-nowrap {{{ if (sort == "count") }}}active{{{ end }}}">[[groups:details.member-count]]</a>
|
|
15
|
-
<a href="?sort=date" class="btn btn-ghost btn-sm ff-secondary fw-semibold text-nowrap {{{ if (sort == "date") }}}active{{{ end }}}">[[groups:details.creation-date]]</a>
|
|
16
|
-
</div>
|
|
17
|
-
</div>
|
|
18
|
-
</div>
|
|
19
|
-
<div>
|
|
20
|
-
<div class="d-flex justify-content-end gap-2">
|
|
21
|
-
<div>
|
|
22
|
-
{{{ if allowGroupCreation }}}
|
|
23
|
-
<button class="btn btn-primary btn-sm text-nowrap" data-action="new"><i class="fa fa-users"></i> [[groups:new-group]]</button>
|
|
24
|
-
{{{ end }}}
|
|
25
|
-
<select class="form-select hidden" id="search-sort">
|
|
26
|
-
<option value="alpha">[[groups:details.group-name]]</option>
|
|
27
|
-
<option value="count">[[groups:details.member-count]]</option>
|
|
28
|
-
<option value="date">[[groups:details.creation-date]]</option>
|
|
29
|
-
</select>
|
|
30
|
-
</div>
|
|
31
|
-
<div>
|
|
32
|
-
<div class="input-group">
|
|
33
|
-
<input type="text" class="form-control form-control-sm" placeholder="[[global:search]]" name="query" id="search-text">
|
|
34
|
-
<button id="search-button" class="btn btn-primary btn-sm" aria-label="[[global:search]]">
|
|
35
|
-
<i class="fa fa-search"></i>
|
|
36
|
-
</button>
|
|
37
|
-
</div>
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
|
|
43
|
-
<hr />
|
|
44
|
-
|
|
45
|
-
<div component="groups/container" class="row" id="groups-list">
|
|
46
|
-
{{{ if groups.length }}}
|
|
47
|
-
<!-- IMPORT partials/groups/list.tpl -->
|
|
48
|
-
{{{ else }}}
|
|
49
|
-
<div class="col-12">
|
|
50
|
-
<div class="alert alert-warning">
|
|
51
|
-
[[groups:no-groups-found]]
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
{{{ end }}}
|
|
55
|
-
</div>
|
|
56
|
-
|
|
57
|
-
<!-- IMPORT partials/paginator.tpl -->
|
|
58
|
-
</div>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<!-- IMPORT partials/breadcrumbs.tpl -->
|
|
2
|
-
<div class="users flex-fill">
|
|
3
|
-
<div id="users-container" class="users-container row row-cols-2 row-cols-md-3 row-cols-lg-4 row-cols-xl-5 g-4">
|
|
4
|
-
{{{ each users }}}
|
|
5
|
-
<!-- IMPORT partials/users/item.tpl -->
|
|
6
|
-
{{{ end }}}
|
|
7
|
-
</div>
|
|
8
|
-
|
|
9
|
-
<!-- IMPORT partials/paginator.tpl -->
|
|
10
|
-
</div>
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
<div class="options mb-5">
|
|
2
|
-
<form component="groups/settings" role="form">
|
|
3
|
-
<div class="row">
|
|
4
|
-
<div class="col-12 col-lg-6">
|
|
5
|
-
<div class="mb-3">
|
|
6
|
-
<label class="form-label" for="name">[[groups:details.group-name]]</label>
|
|
7
|
-
<input {{{ if group.system }}}readonly{{{ end }}} class="form-control" name="name" id="name" type="text" value="{group.displayName}" />
|
|
8
|
-
</div>
|
|
9
|
-
<div class="mb-3">
|
|
10
|
-
<label class="form-label" for="description">[[groups:details.description]]</label>
|
|
11
|
-
<textarea class="form-control" name="description" id="description" type="text" maxlength="255" rows="5">{group.description}</textarea>
|
|
12
|
-
</div>
|
|
13
|
-
|
|
14
|
-
<div class="form-check mb-3">
|
|
15
|
-
<label class="form-check-label" for="private">[[groups:details.private]]</label>
|
|
16
|
-
<input class="form-check-input" name="private" id="private" type="checkbox"{{{ if group.private }}} checked{{{ end }}}>
|
|
17
|
-
{{{ if !allowPrivateGroups }}}
|
|
18
|
-
<p class="form-text">
|
|
19
|
-
[[groups:details.private-system-help]]
|
|
20
|
-
</p>
|
|
21
|
-
{{{ end }}}
|
|
22
|
-
<p class="form-text text-xs m-0">
|
|
23
|
-
[[groups:details.private-help]]
|
|
24
|
-
</p>
|
|
25
|
-
</div>
|
|
26
|
-
<div class="form-check mb-3">
|
|
27
|
-
<label class="form-check-label" for="hidden">[[groups:details.hidden]]</label>
|
|
28
|
-
<input class="form-check-input" name="hidden" id="hidden" type="checkbox"{{{ if group.hidden }}} checked{{{ end }}}>
|
|
29
|
-
<p class="form-text text-xs m-0">
|
|
30
|
-
[[groups:details.hidden-help]]
|
|
31
|
-
</p>
|
|
32
|
-
</div>
|
|
33
|
-
|
|
34
|
-
<div class="form-check mb-3">
|
|
35
|
-
<label class="form-check-label" for="disableJoinRequests">[[groups:details.disableJoinRequests]]</label>
|
|
36
|
-
<input class="form-check-input" name="disableJoinRequests" id="disableJoinRequests" type="checkbox"{{{ if group.disableJoinRequests }}} checked{{{ end }}}>
|
|
37
|
-
</div>
|
|
38
|
-
<div class="form-check mb-3">
|
|
39
|
-
<label class="form-check-label" for="disableLeave">[[groups:details.disableLeave]]</label>
|
|
40
|
-
<input class="form-check-input" name="disableLeave" id="disableLeave" type="checkbox"{{{if group.disableLeave}}} checked{{{end}}}>
|
|
41
|
-
</div>
|
|
42
|
-
|
|
43
|
-
<div class="mb-3">
|
|
44
|
-
<label class="form-label" for="memberPostCids">[[groups:details.member-post-cids]]</label>
|
|
45
|
-
<div class="d-flex gap-1">
|
|
46
|
-
<div class="member-post-cids-selector">
|
|
47
|
-
<!-- IMPORT partials/category/selector-dropdown-left.tpl -->
|
|
48
|
-
</div>
|
|
49
|
-
<input id="memberPostCids" type="text" class="form-control form-control-sm" value="{group.memberPostCids}">
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
<div class="col-12 col-lg-6">
|
|
54
|
-
<div class="d-flex gap-2 align-items-center mb-3">
|
|
55
|
-
<div class="form-check">
|
|
56
|
-
<label class="form-check-label" for="userTitleEnabled">[[groups:details.userTitleEnabled]]</label>
|
|
57
|
-
<input class="form-check-input" name="userTitleEnabled" id="userTitleEnabled" type="checkbox"{{{ if group.userTitleEnabled }}} checked{{{ end }}}>
|
|
58
|
-
</div>
|
|
59
|
-
<span class="badge rounded-1 text-uppercase text-truncate rounded-1 d-flex align-items-center gap-1 {{{ if !group.userTitleEnabled }}} hide{{{ end }}}" style="max-width:150px; color: {group.textColor}; background-color: {group.labelColor}"><i class="fa {{{ if (group.icon && (group.icon != "fa-nbb-none")) }}}{group.icon}{{{ else }}}hidden{{{ end }}}"></i><span class="badge-text">{{{ if group.userTitle }}}{group.userTitle}{{{ end }}}</span></span>
|
|
60
|
-
</div>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
<div class="mb-3">
|
|
64
|
-
<label class="form-label" for="userTitle">[[groups:details.badge-text]]</label>
|
|
65
|
-
<div class="d-flex gap-1">
|
|
66
|
-
<input component="groups/userTitleOption" class="form-control" name="userTitle" id="userTitle" type="text" maxlength="40" value="{group.userTitleEscaped}"{{{ if !group.userTitleEnabled }}} disabled{{{ end }}} />
|
|
67
|
-
<button component="groups/userTitleOption" type="button" class="btn btn-outline-secondary text-nowrap" data-action="icon-select"{{{ if !group.userTitleEnabled }}} disabled{{{ end }}}>[[groups:details.change-icon]]</button>
|
|
68
|
-
<input type="hidden" name="icon" value="{{{ if group.icon }}}{group.icon}{{{ end }}}" />
|
|
69
|
-
<div id="icons" class="hidden">
|
|
70
|
-
<div class="icon-container">
|
|
71
|
-
<div class="row nbb-fa-icons">
|
|
72
|
-
<!-- IMPORT partials/fontawesome.tpl -->
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
</div>
|
|
76
|
-
</div>
|
|
77
|
-
</div>
|
|
78
|
-
<div class="mb-3 d-flex align-items-center justify-content-between gap-5">
|
|
79
|
-
<label class="form-label mb-0 text-nowrap" for="labelColor" class="badge-color-label">[[groups:details.change-label-colour]]</label>
|
|
80
|
-
<input class="form-control p-1" component="groups/userTitleOption" type="color" name="labelColor" id="labelColor" value="{{{ if group.labelColor }}}{group.labelColor}{{{ end }}}" style="width: 128px;" />
|
|
81
|
-
</div>
|
|
82
|
-
<div class="d-flex align-items-center justify-content-between gap-5">
|
|
83
|
-
<label class="form-label mb-0 text-nowrap" for="textColor" class="badge-color-label">[[groups:details.change-text-colour]]</label>
|
|
84
|
-
<input class="form-control p-1" component="groups/userTitleOption" type="color" name="textColor" id="textColor" value="{{{ if group.textColor }}}{group.textColor}{{{ end }}}" style="width: 128px;"/>
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
88
|
-
|
|
89
|
-
</form>
|
|
90
|
-
</div>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<a href="{config.relative_path}/groups/{./slug}" class="badge rounded-1 text-uppercase text-truncate text-decoration-none d-flex align-items-center gap-1" style="max-width: 150px; line-height: normal; color:{./textColor};background-color: {./labelColor};"><i class="fa {{{ if (./icon && (./icon != "fa-nbb-none")) }}}{./icon}{{{else}}}hidden{{{ end }}}"></i><span class="badge-text">{{{ if ./userTitle }}}{./userTitle}{{{ end }}}</span></a>
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
<label class="text-xs text-muted">[[groups:invited.search]]</label>
|
|
2
|
-
<div class="input-group mb-2">
|
|
3
|
-
<input class="form-control" type="text" component="groups/members/invite"/>
|
|
4
|
-
<span class="input-group-text search-button"><i class="fa fa-search"></i></span>
|
|
5
|
-
</div>
|
|
6
|
-
|
|
7
|
-
<div class="mb-2">
|
|
8
|
-
<label class="text-xs text-muted">[[groups:bulk-invite-instructions]]</label>
|
|
9
|
-
<textarea class="form-control" component="groups/members/bulk-invite"></textarea>
|
|
10
|
-
</div>
|
|
11
|
-
|
|
12
|
-
<div class="mb-2 clearfix">
|
|
13
|
-
<button type="button" class="btn btn-primary btn-sm float-end" component="groups/members/bulk-invite-button">[[groups:bulk-invite]]</button>
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
<div style="max-height: 500px; overflow: auto;">
|
|
17
|
-
<div component="groups/invited/alert" class="alert alert-info {{{ if group.invited.length }}}hidden{{{ end }}}">[[groups:invited.none]]</div>
|
|
18
|
-
<table component="groups/invited" class="table table-hover">
|
|
19
|
-
<tbody>
|
|
20
|
-
{{{ each group.invited }}}
|
|
21
|
-
<tr data-uid="{group.invited.uid}" class="align-middle">
|
|
22
|
-
<td class="member-name p-2 d-flex align-items-center justify-content-between">
|
|
23
|
-
<div class="d-flex align-items-center gap-2">
|
|
24
|
-
<a class="text-decoration-none" href="{config.relative_path}/user/{group.invited.userslug}">{{buildAvatar(group.invited, "24px", true)}}</a>
|
|
25
|
-
<a href="{config.relative_path}/user/{group.invited.userslug}">{group.invited.username}</a>
|
|
26
|
-
</div>
|
|
27
|
-
<button class="btn btn-outline-secondary btn-sm text-nowrap" data-action="rescindInvite">[[groups:invited.uninvite]]</button>
|
|
28
|
-
</td>
|
|
29
|
-
</tr>
|
|
30
|
-
{{{ end }}}
|
|
31
|
-
</tbody>
|
|
32
|
-
</table>
|
|
33
|
-
</div>
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{{{ each groups }}}
|
|
2
|
-
<div class="col-xl-4 col-lg-6 col-sm-12 mb-3" component="groups/summary" data-slug="{./slug}">
|
|
3
|
-
<div class="card h-100 group-hover-bg border p-1">
|
|
4
|
-
<a href="{config.relative_path}/groups/{./slug}" class="card-header border-0 rounded-1 pointer d-block list-cover" style="{{{ if ./cover:thumb:url }}}background-image: url({./cover:thumb:url});background-size: cover; min-height: 125px; background-position: {./cover:position}{{{ end }}}" aria-label="[[aria:group-page-link-for, {txEscape(./displayName)}]]"></a>
|
|
5
|
-
<a href="{config.relative_path}/groups/{./slug}" class="d-block h-100 text-reset text-decoration-none">
|
|
6
|
-
<div class="card-body d-flex flex-column gap-2 h-100 pb-2">
|
|
7
|
-
<div class="d-flex">
|
|
8
|
-
<div class="flex-grow-1 fs-6 fw-semibold text-capitalize">{generateGroupDisplayName(@value)}</div>
|
|
9
|
-
<div class="align-self-start flex-shrink-0 badge border border-gray-300 fw-normal text-body"><i class="text-secondary fa-solid fa-users"></i> {formattedNumber(./memberCount)}</div>
|
|
10
|
-
</div>
|
|
11
|
-
<div class="text-sm line-clamp-3">{./description}</div>
|
|
12
|
-
<span class="timeago text-xs text-secondary mt-auto" title="{./createtimeISO}"></span>
|
|
13
|
-
</div>
|
|
14
|
-
</a>
|
|
15
|
-
</div>
|
|
16
|
-
</div>
|
|
17
|
-
{{{ end }}}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
<div class="d-flex {{{ if group.isOwner }}}justify-content-between{{{ else }}}justify-content-end{{{ end }}} mb-3">
|
|
2
|
-
{{{ if isAdmin }}}
|
|
3
|
-
<div class="flex-shrink-0">
|
|
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
|
-
</div>
|
|
6
|
-
{{{ end }}}
|
|
7
|
-
<div>
|
|
8
|
-
<div class="input-group">
|
|
9
|
-
<input class="form-control form-control-sm" type="text" component="groups/members/search" placeholder="[[global:search]]"/>
|
|
10
|
-
<button class="btn btn-primary btn-sm search-button" type="button">
|
|
11
|
-
<i class="fa fa-search"></i>
|
|
12
|
-
</button>
|
|
13
|
-
</div>
|
|
14
|
-
</div>
|
|
15
|
-
</div>
|
|
16
|
-
|
|
17
|
-
<div component="groups/members" data-nextstart="{group.membersNextStart}" class="mb-5" style="max-height: 500px; overflow: auto;">
|
|
18
|
-
<table class="table table-hover">
|
|
19
|
-
<tbody>
|
|
20
|
-
{{{each group.members}}}
|
|
21
|
-
<tr class="w-100" data-uid="{group.members.uid}" data-isowner="{{{ if group.members.isOwner }}}1{{{ else }}}0{{{ end }}}">
|
|
22
|
-
<td class="member-name p-2 w-100 ">
|
|
23
|
-
<div class="d-flex align-items-center justify-content-between">
|
|
24
|
-
<div class="d-flex align-items-center gap-2">
|
|
25
|
-
<a class="text-decoration-none" href="{config.relative_path}/user/{group.members.userslug}">{{buildAvatar(group.members, "24px", true)}}</a>
|
|
26
|
-
<a class="align-text-top" href="{config.relative_path}/user/{group.members.userslug}">{group.members.username}</a>
|
|
27
|
-
<i component="groups/owner/icon" title="[[groups:owner]]" class="user-owner-icon fa fa-star align-text-top text-warning {{{ if !group.members.isOwner }}}invisible{{{ end }}}"></i>
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
{{{ if group.isOwner }}}
|
|
31
|
-
<div class="owner-controls d-flex gap-1">
|
|
32
|
-
<a class="btn btn-light btn-sm" href="#" data-action="toggleOwnership" title="[[groups:details.grant]]">
|
|
33
|
-
<i class="fa fa-star text-warning"></i>
|
|
34
|
-
</a>
|
|
35
|
-
|
|
36
|
-
<a class="btn btn-light btn-sm" href="#" data-action="kick" title="[[groups:details.kick]]">
|
|
37
|
-
<i class="fa fa-ban text-danger"></i>
|
|
38
|
-
</a>
|
|
39
|
-
</div>
|
|
40
|
-
{{{ end }}}
|
|
41
|
-
</div>
|
|
42
|
-
</td>
|
|
43
|
-
</tr>
|
|
44
|
-
{{{end}}}
|
|
45
|
-
</tbody>
|
|
46
|
-
</table>
|
|
47
|
-
</div>
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{{{ if group.pending.length }}}
|
|
2
|
-
<div class="d-flex justify-content-end gap-2 mb-3">
|
|
3
|
-
<button class="btn btn-danger btn-sm" data-action="rejectAll">[[groups:pending.reject-all]]</button>
|
|
4
|
-
<button class="btn btn-success btn-sm" data-action="acceptAll">[[groups:pending.accept-all]]</button>
|
|
5
|
-
|
|
6
|
-
</div>
|
|
7
|
-
{{{ end }}}
|
|
8
|
-
|
|
9
|
-
<div style="max-height: 500px;overflow: auto;">
|
|
10
|
-
<div component="groups/pending/alert" class="alert alert-info {{{ if group.pending.length }}}hidden{{{ end }}}">[[groups:pending.none]]</div>
|
|
11
|
-
<table component="groups/pending" class="table table-hover">
|
|
12
|
-
<tbody>
|
|
13
|
-
{{{ each group.pending }}}
|
|
14
|
-
<tr data-uid="{group.pending.uid}" class="align-middle">
|
|
15
|
-
<td class="member-name p-2 d-flex align-items-center justify-content-between">
|
|
16
|
-
<div class="d-flex gap-2">
|
|
17
|
-
<a class="text-decoration-none" href="{config.relative_path}/user/{group.pending.userslug}">{{buildAvatar(group.pending, "24px", true)}}</a>
|
|
18
|
-
<a href="{config.relative_path}/user/{group.pending.userslug}">{group.pending.username}</a>
|
|
19
|
-
</div>
|
|
20
|
-
<div class="d-flex gap-2">
|
|
21
|
-
<button class="btn btn-danger btn-sm" data-action="reject">[[groups:pending.reject]]</a></li>
|
|
22
|
-
<button class="btn btn-success btn-sm" data-action="accept">[[groups:pending.accept]]</a></li>
|
|
23
|
-
</div>
|
|
24
|
-
</td>
|
|
25
|
-
</tr>
|
|
26
|
-
{{{ end }}}
|
|
27
|
-
</tbody>
|
|
28
|
-
</table>
|
|
29
|
-
</div>
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
<div class="flex-shrink-0 pe-2 border-end-md text-sm mb-3 flex-basis-md-200">
|
|
2
|
-
<div class="nav sticky-md-top d-flex flex-row flex-md-column flex-wrap gap-1" style="top: 1rem; z-index: 1;">
|
|
3
|
-
<button data-bs-toggle="tab" data-bs-target="#groups-posts" class="btn btn-ghost btn-sm text-start d-flex align-items-baseline ff-secondary fw-semibold {{{ if template.groups/details }}}active{{{ end }}}">
|
|
4
|
-
<div class="flex-grow-1">[[global:posts]]</div>
|
|
5
|
-
</button>
|
|
6
|
-
<button data-bs-toggle="tab" data-bs-target="#groups-members" class="btn btn-ghost btn-sm text-start d-flex align-items-baseline ff-secondary fw-semibold gap-2">
|
|
7
|
-
<div class="flex-grow-1">[[groups:members]]</div>
|
|
8
|
-
<span component="group/member/count" class="flex-shrink-0 text-xs lh-1" title="{formattedNumber(group.memberCount)}">{humanReadableNumber(group.memberCount)}</span>
|
|
9
|
-
</button>
|
|
10
|
-
|
|
11
|
-
{{{ if group.isOwner }}}
|
|
12
|
-
<button data-bs-toggle="tab" data-bs-target="#groups-pending" class="btn btn-ghost btn-sm text-start d-flex align-items-baseline ff-secondary fw-semibold gap-2">
|
|
13
|
-
<div class="flex-grow-1">[[groups:details.pending]]</div>
|
|
14
|
-
<span component="group/pending/count" class="flex-shrink-0 text-xs lh-1" title="{formattedNumber(group.pending.length)}">{humanReadableNumber(group.pending.length)}</span>
|
|
15
|
-
</button>
|
|
16
|
-
|
|
17
|
-
<button data-bs-toggle="tab" data-bs-target="#groups-invited" class="btn btn-ghost btn-sm text-start d-flex align-items-baseline ff-secondary fw-semibold gap-2">
|
|
18
|
-
<div class="flex-grow-1">[[groups:details.invited]]</div>
|
|
19
|
-
<span component="group/invited/count" class="flex-shrink-0 text-xs lh-1" title="{formattedNumber(group.invited.length)}">{humanReadableNumber(group.invited.length)}</span>
|
|
20
|
-
</button>
|
|
21
|
-
|
|
22
|
-
<button data-bs-toggle="tab" data-bs-target="#groups-admin" class="btn btn-ghost btn-sm text-start d-flex align-items-baseline ff-secondary fw-semibold">
|
|
23
|
-
<div class="flex-grow-1">[[global:header.admin]]</div>
|
|
24
|
-
</button>
|
|
25
|
-
{{{ end }}}
|
|
26
|
-
</div>
|
|
27
|
-
</div>
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<div id="{alert_id}" role="alert" class="alert alert-dismissible alert-{type} fade show" component="toaster/toast">
|
|
2
|
-
<div class="alert-progress position-absolute top-0 start-0 bottom-0 h-100 z-0" style=" opacity:0.1;"></div>
|
|
3
|
-
<div class="d-flex flex-wrap gap-2 position-relative">
|
|
4
|
-
{{{ if image }}}
|
|
5
|
-
<img src="{image}" height="80" style="width: auto;" />
|
|
6
|
-
{{{ end }}}
|
|
7
|
-
<div class="d-flex flex-column gap-2">
|
|
8
|
-
{{{ if title }}}
|
|
9
|
-
<strong>{tx(title)}</strong>
|
|
10
|
-
{{{ end }}}
|
|
11
|
-
|
|
12
|
-
{{{ if message }}}
|
|
13
|
-
<p class="m-0">{tx(message)}</p>
|
|
14
|
-
{{{ end }}}
|
|
15
|
-
</div>
|
|
16
|
-
</div>
|
|
17
|
-
|
|
18
|
-
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="close"></button>
|
|
19
|
-
</div>
|