mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-27 02:40:39 +01:00
Compare commits
37 Commits
v1.14.3-be
...
v1.14.x
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
668ad8abf7 | ||
|
|
f5ba852e78 | ||
|
|
8479809a73 | ||
|
|
311675916a | ||
|
|
c98f55b454 | ||
|
|
c2477d9d5f | ||
|
|
28970b030d | ||
|
|
b54c54f62b | ||
|
|
ddf5c3bf7f | ||
|
|
afe1073e03 | ||
|
|
1c0eb70046 | ||
|
|
28302c55dc | ||
|
|
e0d285032d | ||
|
|
6bb0241daf | ||
|
|
a2c62f2e11 | ||
|
|
f01ac65c5a | ||
|
|
c07cca574f | ||
|
|
226620140c | ||
|
|
2ee196b4da | ||
|
|
b3c4db621a | ||
|
|
592b880b1c | ||
|
|
553dbd73ba | ||
|
|
6721d4151e | ||
|
|
64c0e1433b | ||
|
|
d142e7c86a | ||
|
|
5acf5acb3a | ||
|
|
830c59eb4f | ||
|
|
60ba66c0a3 | ||
|
|
470835e6f7 | ||
|
|
7b4d726c5d | ||
|
|
a49b774800 | ||
|
|
0569c27c88 | ||
|
|
4e1c26becb | ||
|
|
5aea87ade2 | ||
|
|
d93eba9f3b | ||
|
|
626def8b31 | ||
|
|
a10b5eade8 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -67,5 +67,4 @@ test/files/normalise.jpg.png
|
||||
test/files/normalise-resized.jpg
|
||||
package-lock.json
|
||||
/package.json
|
||||
*.mongodb
|
||||
link-plugins.sh
|
||||
*.mongodb
|
||||
48
CHANGELOG.md
48
CHANGELOG.md
@@ -1,51 +1,3 @@
|
||||
#### 1.14.2 (2020-07-15)
|
||||
|
||||
##### Chores
|
||||
|
||||
* incrementing version number - v1.14.2 (1e4d683f)
|
||||
* update changelog for v1.14.2 (488e69fd)
|
||||
* up theme (63fb2ad7)
|
||||
* incrementing version number - v1.14.2-beta.1 (9d1465d0)
|
||||
* up theme (15aabfd3)
|
||||
* up theme (599c5015)
|
||||
* incrementing version number - v1.14.2-beta.0 (fca4ee31)
|
||||
* incrementing version number - v1.14.1 (31203b16)
|
||||
* update changelog for v1.14.1 (d4c16086)
|
||||
* **deps:** update commitlint monorepo to v9.1.1 (0ca7e28a)
|
||||
|
||||
##### New Features
|
||||
|
||||
* logic for flag note editing, #8499 (14417209)
|
||||
* logic for flag note deletion, #8499 (f85a45c7)
|
||||
* #8460, export groups members as csv (00d39fb3)
|
||||
* pass connection options to socket.io-adapter-mongo (393f19b4)
|
||||
* #8023, allow wildcard search for uid/email (3dcf5387)
|
||||
* up composer (6235b31c)
|
||||
* #8427, daily downvote limits (c513b88d)
|
||||
* warn user if whitelisted tags are less than minTags (4adbf87c)
|
||||
|
||||
##### Bug Fixes
|
||||
|
||||
* **deps:**
|
||||
* update dependency nodebb-plugin-mentions to v2.9.1 (c54287fe)
|
||||
* update dependency nodebb-plugin-mentions to v2.9.0 (7730e7da)
|
||||
* update dependency nodebb-theme-persona to v10.1.62 (#8485) (4e9743ab)
|
||||
* update dependency nodebb-plugin-composer-default to v6.3.49 (#8479) (ab244ca6)
|
||||
* #8499 (65240a17)
|
||||
* #8500 (5e984d10)
|
||||
* invalid session error modal during logout (2286ee2a)
|
||||
* #8488 (b3a88331)
|
||||
* category search in selector (46a66863)
|
||||
* groups.updateCover (73ddf1cb)
|
||||
* **docs:** bad changelog (60bf488f)
|
||||
|
||||
##### Other Changes
|
||||
|
||||
* update changelog for v1.14.2" (e085c846)
|
||||
* flag.showModal on flag modal appearance (3379d65f)
|
||||
* NodeBB/NodeBB (2fba0a14)
|
||||
* update changelog for v1.14.1" (26c74409)
|
||||
|
||||
#### 1.14.1 (2020-07-08)
|
||||
|
||||
##### Chores
|
||||
|
||||
@@ -48,7 +48,7 @@ Our minimalist "Persona" theme gets you going right away, no coding experience r
|
||||
|
||||
NodeBB requires the following software to be installed:
|
||||
|
||||
* A version of Node.js at least 10 or greater ([installation/upgrade instructions](https://github.com/nodesource/distributions))
|
||||
* A version of Node.js at least 8 or greater ([installation/upgrade instructions](https://github.com/nodesource/distributions))
|
||||
* Redis, version 2.8.9 or greater **or** MongoDB, version 2.6 or greater
|
||||
* nginx, version 1.3.13 or greater (**only if** intending to use nginx to proxy requests to a NodeBB)
|
||||
|
||||
|
||||
@@ -79,7 +79,6 @@
|
||||
"min:rep:website": 0,
|
||||
"min:rep:aboutme": 0,
|
||||
"min:rep:signature": 0,
|
||||
"flags:limitPerTarget": 0,
|
||||
"notificationType_upvote": "notification",
|
||||
"notificationType_new-topic": "notification",
|
||||
"notificationType_new-reply": "notification",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "nodebb",
|
||||
"license": "GPL-3.0",
|
||||
"description": "NodeBB Forum",
|
||||
"version": "1.14.3-beta.5",
|
||||
"version": "1.14.3",
|
||||
"homepage": "http://www.nodebb.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -18,8 +18,8 @@
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "npx lint-staged",
|
||||
"commit-msg": "npx commitlint -E HUSKY_GIT_PARAMS"
|
||||
"pre-commit": "lint-staged",
|
||||
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
@@ -30,26 +30,26 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"ace-builds": "^1.4.9",
|
||||
"archiver": "^5.0.0",
|
||||
"archiver": "^4.0.0",
|
||||
"async": "^3.2.0",
|
||||
"autoprefixer": "^9.7.6",
|
||||
"bcryptjs": "2.4.3",
|
||||
"benchpressjs": "^2.0.2",
|
||||
"body-parser": "^1.19.0",
|
||||
"bootstrap": "^3.4.1",
|
||||
"bootswatch": "thomaspark/bootswatch#v3.4.1+1",
|
||||
"bootswatch": "git://github.com/thomaspark/bootswatch.git#c41a8f066feb8950c6f9c6bcf5a3c37d1085404e",
|
||||
"chart.js": "^2.9.3",
|
||||
"cli-graph": "^3.2.2",
|
||||
"clipboard": "^2.0.6",
|
||||
"colors": "^1.4.0",
|
||||
"commander": "^6.0.0",
|
||||
"commander": "^5.0.0",
|
||||
"compression": "^1.7.4",
|
||||
"connect-ensure-login": "^0.1.1",
|
||||
"connect-flash": "^0.1.1",
|
||||
"connect-mongo": "3.2.0",
|
||||
"connect-multiparty": "^2.2.0",
|
||||
"connect-pg-simple": "^6.1.0",
|
||||
"connect-redis": "5.0.0",
|
||||
"connect-redis": "4.0.4",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"cron": "^1.8.2",
|
||||
"cropperjs": "^1.5.6",
|
||||
@@ -70,7 +70,7 @@
|
||||
"less": "^3.11.1",
|
||||
"lodash": "^4.17.15",
|
||||
"logrotate-stream": "^0.2.6",
|
||||
"lru-cache": "6.0.0",
|
||||
"lru-cache": "5.1.1",
|
||||
"material-design-lite": "^1.3.0",
|
||||
"mime": "^2.4.4",
|
||||
"mkdirp": "^1.0.4",
|
||||
@@ -80,19 +80,19 @@
|
||||
"@nodebb/mubsub": "^1.6.0",
|
||||
"@nodebb/socket.io-adapter-mongo": "3.0.1",
|
||||
"nconf": "^0.10.0",
|
||||
"nodebb-plugin-composer-default": "6.3.53",
|
||||
"nodebb-plugin-dbsearch": "4.1.2",
|
||||
"nodebb-plugin-composer-default": "6.3.50",
|
||||
"nodebb-plugin-dbsearch": "4.1.1",
|
||||
"nodebb-plugin-emoji": "^3.3.0",
|
||||
"nodebb-plugin-emoji-android": "2.0.0",
|
||||
"nodebb-plugin-markdown": "8.11.2",
|
||||
"nodebb-plugin-mentions": "2.9.3",
|
||||
"nodebb-plugin-mentions": "2.9.1",
|
||||
"nodebb-plugin-soundpack-default": "1.0.0",
|
||||
"nodebb-plugin-spam-be-gone": "0.7.2",
|
||||
"nodebb-rewards-essentials": "0.1.3",
|
||||
"nodebb-theme-lavender": "5.0.11",
|
||||
"nodebb-theme-persona": "10.2.0",
|
||||
"nodebb-theme-lavender": "5.1.0",
|
||||
"nodebb-theme-persona": "10.1.65",
|
||||
"nodebb-theme-slick": "1.2.29",
|
||||
"nodebb-theme-vanilla": "11.2.0",
|
||||
"nodebb-theme-vanilla": "11.1.33",
|
||||
"nodebb-widget-essentials": "4.1.1",
|
||||
"nodemailer": "^6.4.6",
|
||||
"passport": "^0.4.1",
|
||||
@@ -132,28 +132,28 @@
|
||||
"zxcvbn": "^4.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@apidevtools/swagger-parser": "10.0.1",
|
||||
"@apidevtools/swagger-parser": "9.0.1",
|
||||
"@commitlint/cli": "9.1.1",
|
||||
"@commitlint/config-angular": "9.1.1",
|
||||
"coveralls": "3.1.0",
|
||||
"eslint": "7.5.0",
|
||||
"eslint": "7.3.1",
|
||||
"eslint-config-airbnb-base": "14.1.0",
|
||||
"eslint-plugin-import": "2.21.1",
|
||||
"grunt": "1.2.1",
|
||||
"grunt": "1.1.0",
|
||||
"grunt-contrib-watch": "1.1.0",
|
||||
"husky": "4.2.5",
|
||||
"jsdom": "16.3.0",
|
||||
"jsdom": "16.2.2",
|
||||
"lint-staged": "10.2.11",
|
||||
"mocha": "8.0.1",
|
||||
"mocha-lcov-reporter": "1.3.0",
|
||||
"nyc": "15.1.0",
|
||||
"nyc": "15.0.1",
|
||||
"smtp-server": "3.7.0"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/NodeBB/NodeBB/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">=8"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
@@ -172,4 +172,4 @@
|
||||
"url": "https://github.com/barisusakli"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
3
public/js-enabled.css
Normal file
3
public/js-enabled.css
Normal file
@@ -0,0 +1,3 @@
|
||||
/*
|
||||
The following stylesheet is only included on pages that can execute javascript
|
||||
*/
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "إلغاء",
|
||||
"bootbox.confirm": "تأكيد",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Качване на файл",
|
||||
"composer.zen_mode": "Режим Дзен",
|
||||
"composer.select_category": "Изберете категория",
|
||||
"composer.textarea.placeholder": "Въведете съдържанието на публикацията си тук. Можете също да влачите и пускате снимки.",
|
||||
"bootbox.ok": "Добре",
|
||||
"bootbox.cancel": "Отказ",
|
||||
"bootbox.confirm": "Потвърждаване",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Cancel",
|
||||
"bootbox.confirm": "Confirm",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Nahrát soubor",
|
||||
"composer.zen_mode": "Režim Zem",
|
||||
"composer.select_category": "Vyberte kategorii",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Zrušit",
|
||||
"bootbox.confirm": "Potvrdit",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Annuller",
|
||||
"bootbox.confirm": "Bekræft",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Datei hochladen",
|
||||
"composer.zen_mode": "Zen Modus",
|
||||
"composer.select_category": "Wähle eine Kategorie",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Abbrechen",
|
||||
"bootbox.confirm": "Bestätigen",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Cancel",
|
||||
"bootbox.confirm": "Confirm",
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"ip": "IP <strong>%1</strong>",
|
||||
"nodes-responded": "%1 nodes responded within %2ms!",
|
||||
"host": "host",
|
||||
"primary": "primary / run jobs",
|
||||
"pid": "pid",
|
||||
"nodejs": "nodejs",
|
||||
"online": "online",
|
||||
|
||||
@@ -79,6 +79,5 @@
|
||||
"alert.not-enough-whitelisted-tags": "Whitelisted tags are less than minimum tags, you need to create more whitelisted tags!",
|
||||
"collapse-all": "Collapse All",
|
||||
"expand-all": "Expand All",
|
||||
"disable-on-create": "Disable on create",
|
||||
"no-matches": "No matches"
|
||||
"disable-on-create": "Disable on create"
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
"admin": "Admin",
|
||||
"group-privileges": "Group Privileges",
|
||||
"user-privileges": "User Privileges",
|
||||
"edit-privileges": "Edit Privileges",
|
||||
"chat": "Chat",
|
||||
"upload-images": "Upload Images",
|
||||
"upload-files": "Upload Files",
|
||||
@@ -34,6 +33,7 @@
|
||||
"delete-topics": "Delete Topics",
|
||||
"purge": "Purge",
|
||||
"moderate": "Moderate",
|
||||
|
||||
"admin-dashboard": "Dashboard",
|
||||
"admin-categories": "Categories",
|
||||
"admin-privileges": "Privileges",
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"settings/general": "General",
|
||||
"settings/homepage": "Home Page",
|
||||
"settings/navigation": "Navigation",
|
||||
"settings/reputation": "Reputation & Flags",
|
||||
"settings/reputation": "Reputation",
|
||||
"settings/email": "Email",
|
||||
"settings/user": "Users",
|
||||
"settings/group": "Groups",
|
||||
|
||||
@@ -12,9 +12,5 @@
|
||||
"min-rep-aboutme": "Minimum reputation to add \"About me\" to user profile",
|
||||
"min-rep-signature": "Minimum reputation to add \"Signature\" to user profile",
|
||||
"min-rep-profile-picture": "Minimum reputation to add \"Profile Picture\" to user profile",
|
||||
"min-rep-cover-picture": "Minimum reputation to add \"Cover Picture\" to user profile",
|
||||
|
||||
"flags": "Flag Settings",
|
||||
"flags.limit-per-target": "Maximum number of times something can be flagged",
|
||||
"flags.limit-per-target-placeholder": "Default: 0"
|
||||
"min-rep-cover-picture": "Minimum reputation to add \"Cover Picture\" to user profile"
|
||||
}
|
||||
@@ -163,10 +163,7 @@
|
||||
"not-enough-reputation-min-rep-signature": "You do not have enough reputation to add a signature",
|
||||
"not-enough-reputation-min-rep-profile-picture": "You do not have enough reputation to add a profile picture",
|
||||
"not-enough-reputation-min-rep-cover-picture": "You do not have enough reputation to add a cover picture",
|
||||
"post-already-flagged": "You have already flagged this post",
|
||||
"user-already-flagged": "You have already flagged this user",
|
||||
"post-flagged-too-many-times": "This post has been flagged by others already",
|
||||
"user-flagged-too-many-times": "This user has been flagged by others already",
|
||||
"already-flagged": "You have already flagged this post",
|
||||
"self-vote": "You cannot vote on your own post",
|
||||
"too-many-downvotes-today": "You can only downvote %1 times a day",
|
||||
"too-many-downvotes-today-user": "You can only downvote a user %1 times a day",
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"state": "State",
|
||||
"reports": "Reports",
|
||||
"first-reported": "First Reported",
|
||||
"reporter": "Reporter",
|
||||
"reported-at": "Reported At",
|
||||
"description": "Description",
|
||||
"no-flags": "Hooray! No flags found.",
|
||||
"assignee": "Assignee",
|
||||
"update": "Update",
|
||||
@@ -25,7 +26,6 @@
|
||||
"filter-quick-mine": "Assigned to me",
|
||||
"filter-cid-all": "All categories",
|
||||
"apply-filters": "Apply Filters",
|
||||
"more-filters": "More Filters",
|
||||
|
||||
"quick-actions": "Quick Actions",
|
||||
"flagged-user": "Flagged User",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"chat.chatting_with": "Chat with",
|
||||
"chat.placeholder": "Type chat message here, press enter to send",
|
||||
"chat.scroll-up-alert": "You are looking at older messages, click here to go to most recent message.",
|
||||
"chat.send": "Send",
|
||||
"chat.no_active": "You have no active chats.",
|
||||
"chat.user_typing": "%1 is typing ...",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Cancel",
|
||||
"bootbox.confirm": "Confirm",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Cancel",
|
||||
"bootbox.confirm": "Confirm",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Subir archivo",
|
||||
"composer.zen_mode": "Modo Zen",
|
||||
"composer.select_category": "Selecciona una categoría",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Cancelar",
|
||||
"bootbox.confirm": "Confirmar",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Lae fail üles",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "Olgu",
|
||||
"bootbox.cancel": "Katkesta",
|
||||
"bootbox.confirm": "Kinnita",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "بارگذاری فایل",
|
||||
"composer.zen_mode": "حالت ذن",
|
||||
"composer.select_category": "یک دستهبندی انتخاب کنید",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "باشه",
|
||||
"bootbox.cancel": "انصراف",
|
||||
"bootbox.confirm": "تایید",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Cancel",
|
||||
"bootbox.confirm": "Confirm",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Envoyer un fichier",
|
||||
"composer.zen_mode": "Mode Zen",
|
||||
"composer.select_category": "Sélectionnez une catégorie",
|
||||
"composer.textarea.placeholder": "Saisissez le contenu de votre message ici, faites glisser et déposez les images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Annuler",
|
||||
"bootbox.confirm": "Confirmer",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Subir arquivo",
|
||||
"composer.zen_mode": "Modo Zen",
|
||||
"composer.select_category": "Selecciona unha categoría",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "De acordo",
|
||||
"bootbox.cancel": "Cancelar",
|
||||
"bootbox.confirm": "Confirmar",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "העלה קובץ",
|
||||
"composer.zen_mode": "מצב זן",
|
||||
"composer.select_category": "בחר קטגוריה",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "אוקיי",
|
||||
"bootbox.cancel": "בטל",
|
||||
"bootbox.confirm": "אשר",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Učitaj datoteku",
|
||||
"composer.zen_mode": "Zen",
|
||||
"composer.select_category": "Odaberi kategoriju",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Odbaci",
|
||||
"bootbox.confirm": "Potvrdi",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Fájl feltöltése",
|
||||
"composer.zen_mode": "Zen mód",
|
||||
"composer.select_category": "Kategória választása",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Mégse",
|
||||
"bootbox.confirm": "Megerősítés",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Cancel",
|
||||
"bootbox.confirm": "Confirm",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Carica file",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Seleziona una categoria",
|
||||
"composer.textarea.placeholder": "Inserisci qui il contenuto del tuo post, trascina e rilascia le immagini",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Annulla",
|
||||
"bootbox.confirm": "Conferma",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "ファイルをアップロード",
|
||||
"composer.zen_mode": "Zen モード",
|
||||
"composer.select_category": "カテゴリを選択",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "キャンセル",
|
||||
"bootbox.confirm": "確認",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "파일 업로드",
|
||||
"composer.zen_mode": "전체화면",
|
||||
"composer.select_category": "카테고리 선택",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "확인",
|
||||
"bootbox.cancel": "취소",
|
||||
"bootbox.confirm": "확인",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Cancel",
|
||||
"bootbox.confirm": "Confirm",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Augšupielādēt failu",
|
||||
"composer.zen_mode": "Zen režīms",
|
||||
"composer.select_category": "Izvēlēties kategoriju",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "Labi",
|
||||
"bootbox.cancel": "Atcelt",
|
||||
"bootbox.confirm": "Apstiprināt",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "Ok",
|
||||
"bootbox.cancel": "Batal",
|
||||
"bootbox.confirm": "Pasti",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Avbryt",
|
||||
"bootbox.confirm": "Bekreft",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload bestand",
|
||||
"composer.zen_mode": "Zen-modus",
|
||||
"composer.select_category": "Selecteer een categorie",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Annuleren",
|
||||
"bootbox.confirm": "Bevestig",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Wyślij plik",
|
||||
"composer.zen_mode": "Tryb Zen",
|
||||
"composer.select_category": "Wybierz kategorię",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Anuluj",
|
||||
"bootbox.confirm": "Potwierdź",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Fazer upload de Arquivo",
|
||||
"composer.zen_mode": "Modo Zen",
|
||||
"composer.select_category": "Escolha uma categoria",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Cancelar",
|
||||
"bootbox.confirm": "Confirmar",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Enviar um ficheiro",
|
||||
"composer.zen_mode": "Modo Zen",
|
||||
"composer.select_category": "Selecionar uma categoria",
|
||||
"composer.textarea.placeholder": "Escreve aqui o conteúdo da tua publicação, arrasta e solta imagens",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Cancelar",
|
||||
"bootbox.confirm": "Confirmar",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Cancel",
|
||||
"bootbox.confirm": "Confirm",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Загрузить файл",
|
||||
"composer.zen_mode": "Полноэкранный режим",
|
||||
"composer.select_category": "Выберите категорию",
|
||||
"composer.textarea.placeholder": "Введите содержание вашего сообщения здесь, перетащите изображения",
|
||||
"bootbox.ok": "ОК",
|
||||
"bootbox.cancel": "Отмена",
|
||||
"bootbox.confirm": "Подтвердить",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "Sawa",
|
||||
"bootbox.cancel": "Isubire",
|
||||
"bootbox.confirm": "Emeza",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Cancel",
|
||||
"bootbox.confirm": "Confirm",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Nahrať súbor",
|
||||
"composer.zen_mode": "Režim Zen",
|
||||
"composer.select_category": "Vyberte kategóriu",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Zrušiť",
|
||||
"bootbox.confirm": "Potvrdiť",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Prenesi datoteko",
|
||||
"composer.zen_mode": "Zen način",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "V redu",
|
||||
"bootbox.cancel": "Prekliči",
|
||||
"bootbox.confirm": "Potrdi",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Отпреми датотеку",
|
||||
"composer.zen_mode": "Цео екран",
|
||||
"composer.select_category": "Изаберите категорију",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "ОК",
|
||||
"bootbox.cancel": "Откажи",
|
||||
"bootbox.confirm": "Потврди",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Ladda upp fil",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Välj en kategori",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Avbryt",
|
||||
"bootbox.confirm": "Bekräfta",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "อัพโหลดไฟล์",
|
||||
"composer.zen_mode": "เซ็นโหมด",
|
||||
"composer.select_category": "เลือกหมวดหมู่",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "ตกลง",
|
||||
"bootbox.cancel": "ยกเลิก",
|
||||
"bootbox.confirm": "ยืนยัน",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Dosya Yükle",
|
||||
"composer.zen_mode": "Tam ekran modu",
|
||||
"composer.select_category": "Bir kategori seç",
|
||||
"composer.textarea.placeholder": "İletinizi buraya giriniz, görselleri sürükleyip bırakabilirsiniz",
|
||||
"bootbox.ok": "Kabul",
|
||||
"bootbox.cancel": "İptal",
|
||||
"bootbox.confirm": "Onayla",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Завантажити файл",
|
||||
"composer.zen_mode": "Режим Дзен",
|
||||
"composer.select_category": "Обрати категорію",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "ОК",
|
||||
"bootbox.cancel": "Скасувати",
|
||||
"bootbox.confirm": "Підтвердити",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "Tải file lên",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Chọn một chuyên mục",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "Huỷ bỏ",
|
||||
"bootbox.confirm": "Xác nhận",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "上传文件",
|
||||
"composer.zen_mode": "无干扰模式",
|
||||
"composer.select_category": "选择一个版块",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "确认",
|
||||
"bootbox.cancel": "取消",
|
||||
"bootbox.confirm": "确认",
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
"composer.upload-file": "上傳檔案",
|
||||
"composer.zen_mode": "無干擾模式",
|
||||
"composer.select_category": "選擇一個版面",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"bootbox.ok": "確認",
|
||||
"bootbox.cancel": "取消",
|
||||
"bootbox.confirm": "確認",
|
||||
|
||||
@@ -27,9 +27,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-admin-groups {
|
||||
[component="category/list"] li {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,4 @@
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.page-admin-privileges {
|
||||
@keyframes fadeOut {
|
||||
0% {background-color: @brand-primary;}
|
||||
100% {background-color: white;}
|
||||
}
|
||||
|
||||
[data-group-name].selected {
|
||||
animation-name: fadeOut;
|
||||
animation-duration: 5s;
|
||||
animation-fill-mode: both;
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
}
|
||||
@@ -1317,36 +1317,6 @@ paths:
|
||||
type: string
|
||||
selected:
|
||||
type: boolean
|
||||
categories:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
cid:
|
||||
type: number
|
||||
description: A category identifier
|
||||
name:
|
||||
type: string
|
||||
icon:
|
||||
type: string
|
||||
selected:
|
||||
type: boolean
|
||||
level:
|
||||
type: string
|
||||
parentCid:
|
||||
type: number
|
||||
description: The category identifier for the category that is the immediate
|
||||
ancestor of the current category
|
||||
color:
|
||||
type: string
|
||||
bgColor:
|
||||
type: string
|
||||
imageClass:
|
||||
type: string
|
||||
required:
|
||||
- cid
|
||||
- name
|
||||
- icon
|
||||
allowPrivateGroups:
|
||||
type: number
|
||||
maximumGroupNameLength:
|
||||
@@ -2225,24 +2195,11 @@ paths:
|
||||
load:
|
||||
type: string
|
||||
description: CPU load
|
||||
nodebb:
|
||||
type: object
|
||||
properties:
|
||||
isPrimary:
|
||||
type: boolean
|
||||
isCluster:
|
||||
type: boolean
|
||||
runJobs:
|
||||
type: boolean
|
||||
jobsDisabled:
|
||||
type: boolean
|
||||
git:
|
||||
type: object
|
||||
properties:
|
||||
hash:
|
||||
type: string
|
||||
hashShort:
|
||||
type: string
|
||||
branch:
|
||||
type: string
|
||||
stats:
|
||||
@@ -3089,9 +3046,6 @@ paths:
|
||||
type: boolean
|
||||
downvoted:
|
||||
type: boolean
|
||||
flagId:
|
||||
type: number
|
||||
description: The flag identifier, if this particular post has been flagged before
|
||||
"/api/topic/tid/{id}":
|
||||
get:
|
||||
tags:
|
||||
@@ -3738,9 +3692,6 @@ paths:
|
||||
type: boolean
|
||||
display_post_menu:
|
||||
type: boolean
|
||||
flagId:
|
||||
type: number
|
||||
description: The flag identifier, if this particular post has been flagged before
|
||||
category:
|
||||
$ref: components/schemas/CategoryObject.yaml#/CategoryObject
|
||||
tagWhitelist:
|
||||
@@ -4794,9 +4745,6 @@ paths:
|
||||
properties:
|
||||
state:
|
||||
type: string
|
||||
heat:
|
||||
type: number
|
||||
description: The number of reports that make up this flag
|
||||
flagId:
|
||||
type: number
|
||||
type:
|
||||
@@ -4805,8 +4753,34 @@ paths:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
description:
|
||||
type: string
|
||||
uid:
|
||||
type: number
|
||||
description: A user identifier
|
||||
datetime:
|
||||
type: number
|
||||
reporter:
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
description: A friendly name for a given user account
|
||||
picture:
|
||||
nullable: true
|
||||
type: string
|
||||
icon:bgColor:
|
||||
type: string
|
||||
description: A six-character hexadecimal colour code assigned to the user. This
|
||||
value is used in conjunction with
|
||||
`icon:text` for the user's auto-generated
|
||||
icon
|
||||
example: "#f44336"
|
||||
icon:text:
|
||||
type: string
|
||||
description: A single-letter representation of a username. This is used in the
|
||||
auto-generated icon given to users without
|
||||
an avatar
|
||||
labelClass:
|
||||
type: string
|
||||
target_readable:
|
||||
@@ -4869,6 +4843,11 @@ paths:
|
||||
type: string
|
||||
targetId:
|
||||
type: number
|
||||
description:
|
||||
type: string
|
||||
uid:
|
||||
type: number
|
||||
description: A user identifier
|
||||
datetime:
|
||||
type: number
|
||||
datetimeISO:
|
||||
@@ -4984,45 +4963,34 @@ paths:
|
||||
`icon:text` for the user's auto-generated
|
||||
icon
|
||||
example: "#f44336"
|
||||
reports:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
value:
|
||||
type: string
|
||||
timestamp:
|
||||
type: number
|
||||
timestampISO:
|
||||
type: string
|
||||
reporter:
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
description: A friendly name for a given user account
|
||||
userslug:
|
||||
type: string
|
||||
description: An URL-safe variant of the username (i.e. lower-cased, spaces
|
||||
removed, etc.)
|
||||
picture:
|
||||
nullable: true
|
||||
reputation:
|
||||
type: number
|
||||
uid:
|
||||
type: number
|
||||
description: A user identifier
|
||||
icon:text:
|
||||
type: string
|
||||
description: A single-letter representation of a username. This is used in the
|
||||
auto-generated icon given to users without an
|
||||
avatar
|
||||
icon:bgColor:
|
||||
type: string
|
||||
description: A six-character hexadecimal colour code assigned to the user. This
|
||||
value is used in conjunction with `icon:text` for
|
||||
the user's auto-generated icon
|
||||
example: "#f44336"
|
||||
reporter:
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
description: A friendly name for a given user account
|
||||
userslug:
|
||||
type: string
|
||||
description: An URL-safe variant of the username (i.e. lower-cased, spaces
|
||||
removed, etc.)
|
||||
picture:
|
||||
nullable: true
|
||||
reputation:
|
||||
type: number
|
||||
uid:
|
||||
type: number
|
||||
description: A user identifier
|
||||
icon:text:
|
||||
type: string
|
||||
description: A single-letter representation of a username. This is used in the
|
||||
auto-generated icon given to users without an
|
||||
avatar
|
||||
icon:bgColor:
|
||||
type: string
|
||||
description: A six-character hexadecimal colour code assigned to the user. This
|
||||
value is used in conjunction with `icon:text` for
|
||||
the user's auto-generated icon
|
||||
example: "#f44336"
|
||||
type_path:
|
||||
type: string
|
||||
assignees:
|
||||
@@ -5075,35 +5043,6 @@ paths:
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
allCategories:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
bgColor:
|
||||
type: string
|
||||
cid:
|
||||
type: number
|
||||
color:
|
||||
type: string
|
||||
disabled:
|
||||
type: number
|
||||
disabledClass:
|
||||
type: boolean
|
||||
icon:
|
||||
type: string
|
||||
imageClass:
|
||||
type: string
|
||||
level:
|
||||
type: string
|
||||
link:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
parentCid:
|
||||
type: number
|
||||
slug:
|
||||
type: string
|
||||
posts:
|
||||
type: array
|
||||
items:
|
||||
|
||||
@@ -11,9 +11,9 @@ define('admin/manage/categories', [
|
||||
var sortables;
|
||||
|
||||
Categories.init = function () {
|
||||
socket.emit('admin.categories.getAll', function (err, payload) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
socket.emit('admin.categories.getAll', function (error, payload) {
|
||||
if (error) {
|
||||
return app.alertError(error.message);
|
||||
}
|
||||
|
||||
Categories.render(payload);
|
||||
@@ -63,55 +63,8 @@ define('admin/manage/categories', [
|
||||
el.find('i').toggleClass('fa-minus', expand).toggleClass('fa-plus', !expand);
|
||||
el.closest('[data-cid]').find('> ul[data-cid]').toggleClass('hidden', !expand);
|
||||
}
|
||||
|
||||
$('#category-search').on('keyup', function () {
|
||||
searchCategory();
|
||||
});
|
||||
};
|
||||
|
||||
function searchCategory() {
|
||||
var container = $('#content .categories');
|
||||
function revealParents(cid) {
|
||||
var parentCid = container.find('li[data-cid="' + cid + '"]').attr('data-parent-cid');
|
||||
if (parentCid) {
|
||||
container.find('li[data-cid="' + parentCid + '"]').removeClass('hidden');
|
||||
revealParents(parentCid);
|
||||
}
|
||||
}
|
||||
|
||||
function revealChildren(cid) {
|
||||
var els = container.find('li[data-parent-cid="' + cid + '"]');
|
||||
els.each(function (index, el) {
|
||||
var $el = $(el);
|
||||
$el.removeClass('hidden');
|
||||
revealChildren($el.attr('data-cid'));
|
||||
});
|
||||
}
|
||||
|
||||
var categoryEls = container.find('li[data-cid]');
|
||||
var val = $('#category-search').val().toLowerCase();
|
||||
var noMatch = true;
|
||||
var cids = [];
|
||||
categoryEls.each(function () {
|
||||
var liEl = $(this);
|
||||
var isMatch = liEl.attr('data-name').toLowerCase().indexOf(val) !== -1;
|
||||
if (noMatch && isMatch) {
|
||||
noMatch = false;
|
||||
}
|
||||
if (isMatch && val) {
|
||||
cids.push(liEl.attr('data-cid'));
|
||||
}
|
||||
liEl.toggleClass('hidden', !isMatch);
|
||||
});
|
||||
|
||||
cids.forEach(function (cid) {
|
||||
revealParents(cid);
|
||||
revealChildren(cid);
|
||||
});
|
||||
|
||||
$('[component="category/no-matches"]').toggleClass('hidden', !noMatch);
|
||||
}
|
||||
|
||||
Categories.throwCreateModal = function () {
|
||||
socket.emit('categories.getSelectCategories', {}, function (err, categories) {
|
||||
if (err) {
|
||||
|
||||
@@ -5,8 +5,7 @@ define('admin/manage/group', [
|
||||
'forum/groups/memberlist',
|
||||
'iconSelect',
|
||||
'admin/modules/colorpicker',
|
||||
'translator',
|
||||
], function (memberList, iconSelect, colorpicker, translator) {
|
||||
], function (memberList, iconSelect, colorpicker) {
|
||||
var Groups = {};
|
||||
|
||||
Groups.init = function () {
|
||||
@@ -37,68 +36,6 @@ define('admin/manage/group', [
|
||||
groupLabelPreview.css('color', changeGroupTextColor.val() || '#ffffff');
|
||||
});
|
||||
|
||||
setupGroupMembersMenu(groupName);
|
||||
|
||||
$('#group-icon, #group-icon-label').on('click', function () {
|
||||
iconSelect.init(groupIcon, function () {
|
||||
var newIcon = groupIcon.attr('value');
|
||||
if (newIcon === 'fa-nbb-none') {
|
||||
newIcon = 'hidden';
|
||||
}
|
||||
$('#group-icon-preview').attr('class', 'fa fa-fw ' + (newIcon || 'hidden'));
|
||||
});
|
||||
});
|
||||
|
||||
$('[component="category/list"] [data-cid]').on('click', navigateToCategory);
|
||||
|
||||
colorpicker.enable(changeGroupLabelColor, function (hsb, hex) {
|
||||
groupLabelPreview.css('background-color', '#' + hex);
|
||||
});
|
||||
|
||||
colorpicker.enable(changeGroupTextColor, function (hsb, hex) {
|
||||
groupLabelPreview.css('color', '#' + hex);
|
||||
});
|
||||
|
||||
$('form').on('change', 'input, select, textarea', function () {
|
||||
app.flags = app.flags || {};
|
||||
app.flags._unsaved = true;
|
||||
});
|
||||
|
||||
$('#save').on('click', function () {
|
||||
socket.emit('admin.groups.update', {
|
||||
groupName: groupName,
|
||||
values: {
|
||||
name: $('#change-group-name').val(),
|
||||
userTitle: changeGroupUserTitle.val(),
|
||||
description: $('#change-group-desc').val(),
|
||||
icon: groupIcon.attr('value'),
|
||||
labelColor: changeGroupLabelColor.val(),
|
||||
textColor: changeGroupTextColor.val(),
|
||||
userTitleEnabled: $('#group-userTitleEnabled').is(':checked'),
|
||||
private: $('#group-private').is(':checked'),
|
||||
hidden: $('#group-hidden').is(':checked'),
|
||||
disableJoinRequests: $('#group-disableJoinRequests').is(':checked'),
|
||||
disableLeave: $('#group-disableLeave').is(':checked'),
|
||||
},
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
|
||||
var newName = $('#change-group-name').val();
|
||||
|
||||
// If the group name changed, change url
|
||||
if (groupName !== newName) {
|
||||
ajaxify.go('admin/manage/groups/' + encodeURIComponent(newName), undefined, true);
|
||||
}
|
||||
|
||||
app.alertSuccess('[[admin/manage/groups:edit.save-success]]');
|
||||
});
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
function setupGroupMembersMenu(groupName) {
|
||||
$('[component="groups/members"]').on('click', '[data-action]', function () {
|
||||
var btnEl = $(this);
|
||||
var userRow = btnEl.parents('[data-uid]');
|
||||
@@ -140,27 +77,58 @@ define('admin/manage/group', [
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function navigateToCategory() {
|
||||
var cid = $(this).attr('data-cid');
|
||||
$('#group-icon, #group-icon-label').on('click', function () {
|
||||
iconSelect.init(groupIcon, function () {
|
||||
var newIcon = groupIcon.attr('value');
|
||||
if (newIcon === 'fa-nbb-none') {
|
||||
newIcon = 'hidden';
|
||||
}
|
||||
$('#group-icon-preview').attr('class', 'fa fa-fw ' + (newIcon || 'hidden'));
|
||||
});
|
||||
});
|
||||
|
||||
if (cid) {
|
||||
var url = 'admin/manage/privileges/' + cid + '?group=' + ajaxify.data.group.name;
|
||||
if (app.flags && app.flags._unsaved === true) {
|
||||
translator.translate('[[global:unsaved-changes]]', function (text) {
|
||||
bootbox.confirm(text, function (navigate) {
|
||||
if (navigate) {
|
||||
app.flags._unsaved = false;
|
||||
ajaxify.go(url);
|
||||
}
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
ajaxify.go(url);
|
||||
}
|
||||
}
|
||||
colorpicker.enable(changeGroupLabelColor, function (hsb, hex) {
|
||||
groupLabelPreview.css('background-color', '#' + hex);
|
||||
});
|
||||
|
||||
colorpicker.enable(changeGroupTextColor, function (hsb, hex) {
|
||||
groupLabelPreview.css('color', '#' + hex);
|
||||
});
|
||||
|
||||
$('#save').on('click', function () {
|
||||
socket.emit('admin.groups.update', {
|
||||
groupName: groupName,
|
||||
values: {
|
||||
name: $('#change-group-name').val(),
|
||||
userTitle: changeGroupUserTitle.val(),
|
||||
description: $('#change-group-desc').val(),
|
||||
icon: groupIcon.attr('value'),
|
||||
labelColor: changeGroupLabelColor.val(),
|
||||
textColor: changeGroupTextColor.val(),
|
||||
userTitleEnabled: $('#group-userTitleEnabled').is(':checked'),
|
||||
private: $('#group-private').is(':checked'),
|
||||
hidden: $('#group-hidden').is(':checked'),
|
||||
disableJoinRequests: $('#group-disableJoinRequests').is(':checked'),
|
||||
disableLeave: $('#group-disableLeave').is(':checked'),
|
||||
},
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
|
||||
var newName = $('#change-group-name').val();
|
||||
|
||||
// If the group name changed, change url
|
||||
if (groupName !== newName) {
|
||||
ajaxify.go('admin/manage/groups/' + encodeURIComponent(newName), undefined, true);
|
||||
}
|
||||
|
||||
app.alertSuccess('[[admin/manage/groups:edit.save-success]]');
|
||||
});
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
return Groups;
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
define('admin/manage/post-queue', ['categorySelector'], function (categorySelector) {
|
||||
define('admin/manage/post-queue', function () {
|
||||
var PostQueue = {};
|
||||
|
||||
PostQueue.init = function () {
|
||||
@@ -22,64 +22,31 @@ define('admin/manage/post-queue', ['categorySelector'], function (categorySelect
|
||||
return false;
|
||||
});
|
||||
|
||||
handleContentEdit('.post-content', '.post-content-editable', 'textarea');
|
||||
handleContentEdit('.topic-title', '.topic-title-editable', 'input');
|
||||
|
||||
$('.posts-list').on('click', '.topic-category[data-editable]', function () {
|
||||
var $this = $(this);
|
||||
var id = $this.parents('[data-id]').attr('data-id');
|
||||
categorySelector.modal(ajaxify.data.allCategories, function (cid) {
|
||||
var category = ajaxify.data.allCategories.find(function (c) {
|
||||
return parseInt(c.cid, 10) === parseInt(cid, 10);
|
||||
});
|
||||
socket.emit('posts.editQueuedContent', {
|
||||
id: id,
|
||||
cid: cid,
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
app.parseAndTranslate('admin/manage/post-queue', 'posts', {
|
||||
posts: [{
|
||||
category: category,
|
||||
}],
|
||||
}, function (html) {
|
||||
$this.replaceWith(html.find('.topic-category'));
|
||||
});
|
||||
});
|
||||
});
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
function handleContentEdit(displayClass, editableClass, inputSelector) {
|
||||
$('.posts-list').on('click', displayClass, function () {
|
||||
$('.posts-list').on('click', '.post-content', function () {
|
||||
var el = $(this);
|
||||
el.addClass('hidden');
|
||||
var inputEl = el.parent().find(editableClass);
|
||||
inputEl.removeClass('hidden').find(inputSelector).focus();
|
||||
var textareaParent = el.parent().find('.post-content-editable');
|
||||
textareaParent.removeClass('hidden').find('textarea').focus();
|
||||
});
|
||||
|
||||
$('.posts-list').on('blur', editableClass + ' ' + inputSelector, function () {
|
||||
$('.posts-list').on('blur', '.post-content-editable textarea', function () {
|
||||
var textarea = $(this);
|
||||
var preview = textarea.parent().parent().find(displayClass);
|
||||
var preview = textarea.parent().parent().find('.post-content');
|
||||
var id = textarea.parents('[data-id]').attr('data-id');
|
||||
var titleEdit = displayClass === '.topic-title';
|
||||
|
||||
socket.emit('posts.editQueuedContent', {
|
||||
id: id,
|
||||
title: titleEdit ? textarea.val() : undefined,
|
||||
content: titleEdit ? undefined : textarea.val(),
|
||||
content: textarea.val(),
|
||||
}, function (err, data) {
|
||||
if (err) {
|
||||
return app.alertError(err);
|
||||
}
|
||||
preview.html(titleEdit ? data.postData.title : data.postData.content);
|
||||
preview.html(data.postData.content);
|
||||
textarea.parent().addClass('hidden');
|
||||
preview.removeClass('hidden');
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return PostQueue;
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ define('admin/manage/privileges', [
|
||||
'benchpress',
|
||||
'categorySelector',
|
||||
], function (autocomplete, translator, Benchpress, categorySelector) {
|
||||
var Privileges = {};
|
||||
var Privileges = {};
|
||||
|
||||
var cid;
|
||||
|
||||
@@ -21,8 +21,6 @@ define('admin/manage/privileges', [
|
||||
});
|
||||
|
||||
Privileges.setupPrivilegeTable();
|
||||
|
||||
highlightRow();
|
||||
};
|
||||
|
||||
Privileges.setupPrivilegeTable = function () {
|
||||
@@ -81,7 +79,7 @@ define('admin/manage/privileges', [
|
||||
Privileges.exposeAssumedPrivileges();
|
||||
};
|
||||
|
||||
Privileges.refreshPrivilegeTable = function (groupToHighlight) {
|
||||
Privileges.refreshPrivilegeTable = function () {
|
||||
socket.emit('admin.categories.getPrivilegeSettings', cid, function (err, privileges) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
@@ -94,10 +92,6 @@ define('admin/manage/privileges', [
|
||||
translator.translate(html, function (html) {
|
||||
$('.privilege-table-container').html(html);
|
||||
Privileges.exposeAssumedPrivileges();
|
||||
|
||||
if (groupToHighlight) {
|
||||
$('[data-group-name="' + groupToHighlight + '"]').addClass('selected');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -188,7 +182,24 @@ define('admin/manage/privileges', [
|
||||
inputEl.focus();
|
||||
|
||||
autocomplete.group(inputEl, function (ev, ui) {
|
||||
addGroupToCategory(ui.item.group.name, function () {
|
||||
var defaultPrivileges;
|
||||
if (ajaxify.data.url === '/admin/manage/privileges/admin') {
|
||||
defaultPrivileges = ['groups:admin:dashboard'];
|
||||
} else {
|
||||
defaultPrivileges = cid ? ['groups:find', 'groups:read', 'groups:topics:read'] : ['groups:chat'];
|
||||
}
|
||||
|
||||
socket.emit('admin.categories.setPrivilege', {
|
||||
cid: isNaN(cid) ? 0 : cid,
|
||||
privilege: defaultPrivileges,
|
||||
set: true,
|
||||
member: ui.item.group.name,
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
|
||||
Privileges.refreshPrivilegeTable();
|
||||
modal.modal('hide');
|
||||
});
|
||||
});
|
||||
@@ -224,42 +235,5 @@ define('admin/manage/privileges', [
|
||||
});
|
||||
};
|
||||
|
||||
function highlightRow() {
|
||||
var params = utils.params();
|
||||
if (params.group) {
|
||||
var el = $('[data-group-name="' + params.group + '"]');
|
||||
if (el.length) {
|
||||
return el.addClass('selected');
|
||||
}
|
||||
|
||||
addGroupToCategory(params.group);
|
||||
}
|
||||
}
|
||||
|
||||
function addGroupToCategory(group, cb) {
|
||||
var defaultPrivileges;
|
||||
if (ajaxify.data.url === '/admin/manage/privileges/admin') {
|
||||
defaultPrivileges = ['groups:admin:dashboard'];
|
||||
} else {
|
||||
defaultPrivileges = cid ? ['groups:find', 'groups:read', 'groups:topics:read'] : ['groups:chat'];
|
||||
}
|
||||
|
||||
socket.emit('admin.categories.setPrivilege', {
|
||||
cid: isNaN(cid) ? 0 : cid,
|
||||
privilege: defaultPrivileges,
|
||||
set: true,
|
||||
member: group,
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
|
||||
Privileges.refreshPrivilegeTable(group);
|
||||
if (typeof cb === 'function') {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return Privileges;
|
||||
});
|
||||
|
||||
@@ -38,6 +38,8 @@ app.cacheBuster = null;
|
||||
});
|
||||
|
||||
app.load = function () {
|
||||
app.loadProgressiveStylesheet();
|
||||
|
||||
overrides.overrideTimeago();
|
||||
|
||||
var url = ajaxify.start(window.location.pathname.slice(1) + window.location.search + window.location.hash);
|
||||
@@ -749,6 +751,14 @@ app.cacheBuster = null;
|
||||
});
|
||||
};
|
||||
|
||||
app.loadProgressiveStylesheet = function () {
|
||||
var linkEl = document.createElement('link');
|
||||
linkEl.rel = 'stylesheet';
|
||||
linkEl.href = config.relative_path + '/assets/js-enabled.css?' + app.cacheBuster;
|
||||
|
||||
document.head.appendChild(linkEl);
|
||||
};
|
||||
|
||||
app.showCookieWarning = function () {
|
||||
require(['translator', 'storage'], function (translator, storage) {
|
||||
if (!config.cookies.enabled || !navigator.cookieEnabled) {
|
||||
|
||||
@@ -56,7 +56,6 @@ define('forum/chats', [
|
||||
Chats.addRenameHandler(ajaxify.data.roomId, components.get('chat/controls').find('[data-action="rename"]'));
|
||||
Chats.addLeaveHandler(ajaxify.data.roomId, components.get('chat/controls').find('[data-action="leave"]'));
|
||||
Chats.addScrollHandler(ajaxify.data.roomId, ajaxify.data.uid, $('.chat-content'));
|
||||
Chats.addScrollBottomHandler($('.chat-content'));
|
||||
Chats.addCharactersLeftHandler($('[component="chat/main-wrapper"]'));
|
||||
Chats.addIPHandler($('[component="chat/main-wrapper"]'));
|
||||
Chats.createAutoComplete($('[component="chat/input"]'));
|
||||
@@ -102,7 +101,6 @@ define('forum/chats', [
|
||||
Chats.addScrollHandler = function (roomId, uid, el) {
|
||||
var loading = false;
|
||||
el.off('scroll').on('scroll', function () {
|
||||
messages.toggleScrollUpAlert(el);
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
@@ -146,14 +144,6 @@ define('forum/chats', [
|
||||
});
|
||||
};
|
||||
|
||||
Chats.addScrollBottomHandler = function (chatContent) {
|
||||
chatContent.parent()
|
||||
.find('[component="chat/messages/scroll-up-alert"]')
|
||||
.off('click').on('click', function () {
|
||||
messages.scrollToBottom(chatContent);
|
||||
});
|
||||
};
|
||||
|
||||
Chats.addCharactersLeftHandler = function (parent) {
|
||||
var element = parent.find('[component="chat/input"]');
|
||||
element.on('change keyup paste', function () {
|
||||
|
||||
@@ -84,13 +84,11 @@ define('forum/chats/messages', ['components', 'sounds', 'translator', 'benchpres
|
||||
|
||||
function onMessagesParsed(chatContentEl, html) {
|
||||
var newMessage = $(html);
|
||||
var isAtBottom = messages.isAtBottom(chatContentEl);
|
||||
|
||||
newMessage.appendTo(chatContentEl);
|
||||
newMessage.find('.timeago').timeago();
|
||||
newMessage.find('img:not(.not-responsive)').addClass('img-responsive');
|
||||
if (isAtBottom) {
|
||||
messages.scrollToBottom(chatContentEl);
|
||||
}
|
||||
messages.scrollToBottom(chatContentEl);
|
||||
|
||||
$(window).trigger('action:chat.received', {
|
||||
messageEl: newMessage,
|
||||
@@ -114,31 +112,13 @@ define('forum/chats/messages', ['components', 'sounds', 'translator', 'benchpres
|
||||
}
|
||||
};
|
||||
|
||||
messages.isAtBottom = function (containerEl, threshold) {
|
||||
if (containerEl.length) {
|
||||
var distanceToBottom = containerEl[0].scrollHeight - (
|
||||
containerEl.outerHeight() + containerEl.scrollTop()
|
||||
);
|
||||
return distanceToBottom < (threshold || 100);
|
||||
}
|
||||
};
|
||||
|
||||
messages.scrollToBottom = function (containerEl) {
|
||||
if (containerEl && containerEl.length) {
|
||||
if (containerEl.length) {
|
||||
containerEl.scrollTop(containerEl[0].scrollHeight - containerEl.height());
|
||||
containerEl.parent()
|
||||
.find('[component="chat/messages/scroll-up-alert"]')
|
||||
.addClass('hidden');
|
||||
}
|
||||
};
|
||||
|
||||
messages.toggleScrollUpAlert = function (containerEl) {
|
||||
var isAtBottom = messages.isAtBottom(containerEl, 300);
|
||||
containerEl.parent()
|
||||
.find('[component="chat/messages/scroll-up-alert"]')
|
||||
.toggleClass('hidden', isAtBottom);
|
||||
};
|
||||
|
||||
messages.prepEdit = function (inputEl, messageId, roomId) {
|
||||
socket.emit('modules.chats.getRaw', { mid: messageId, roomId: roomId }, function (err, raw) {
|
||||
if (err) {
|
||||
|
||||
@@ -5,18 +5,7 @@ define('forum/flags/list', ['components', 'Chart'], function (components, Chart)
|
||||
|
||||
Flags.init = function () {
|
||||
Flags.enableFilterForm();
|
||||
|
||||
components.get('flags/list').on('click', '[data-flag-id]', function () {
|
||||
var flagId = this.getAttribute('data-flag-id');
|
||||
ajaxify.go('flags/' + flagId);
|
||||
});
|
||||
|
||||
var graphWrapper = $('#flags-daily-wrapper');
|
||||
var graphFooter = graphWrapper.siblings('.panel-footer');
|
||||
$('#flags-daily-wrapper').one('shown.bs.collapse', function () {
|
||||
Flags.handleGraphs();
|
||||
});
|
||||
graphFooter.on('click', graphWrapper.collapse.bind(graphWrapper, 'toggle'));
|
||||
Flags.handleGraphs();
|
||||
};
|
||||
|
||||
Flags.enableFilterForm = function () {
|
||||
@@ -29,7 +18,7 @@ define('forum/flags/list', ['components', 'Chart'], function (components, Chart)
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('apply-filters').addEventListener('click', function () {
|
||||
filtersEl.find('button').on('click', function () {
|
||||
var payload = filtersEl.serializeArray().filter(function (item) {
|
||||
return !!item.value;
|
||||
});
|
||||
|
||||
@@ -91,9 +91,7 @@ define('chat', [
|
||||
|
||||
if (modal.is(':visible')) {
|
||||
taskbar.updateActive(modal.attr('data-uuid'));
|
||||
if (ChatsMessages.isAtBottom(modal.find('.chat-content'))) {
|
||||
ChatsMessages.scrollToBottom(modal.find('.chat-content'));
|
||||
}
|
||||
ChatsMessages.scrollToBottom(modal.find('.chat-content'));
|
||||
} else if (!ajaxify.data.template.chats) {
|
||||
module.toggleNew(modal.attr('data-uuid'), true, true);
|
||||
}
|
||||
@@ -241,7 +239,6 @@ define('chat', [
|
||||
Chats.createAutoComplete(chatModal.find('[component="chat/input"]'));
|
||||
|
||||
Chats.addScrollHandler(chatModal.attr('data-roomid'), data.uid, chatModal.find('.chat-content'));
|
||||
Chats.addScrollBottomHandler(chatModal.find('.chat-content'));
|
||||
|
||||
Chats.addCharactersLeftHandler(chatModal);
|
||||
Chats.addIPHandler(chatModal);
|
||||
|
||||
@@ -278,7 +278,7 @@
|
||||
}
|
||||
|
||||
if (namespace && !key) {
|
||||
warn('Missing key in translation token "' + name + '" for language "' + self.lang + '"');
|
||||
warn('Missing key in translation token "' + name + '"');
|
||||
return Promise.resolve('[[' + namespace + ']]');
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@
|
||||
return translation.then(function (translated) {
|
||||
// check if the translation is missing first
|
||||
if (!translated) {
|
||||
warn('Missing translation "' + name + '" for language "' + self.lang + '"');
|
||||
warn('Missing translation "' + name + '"');
|
||||
return backup || key;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,12 @@
|
||||
var winston = require('winston');
|
||||
|
||||
module.exports = factory(require('xregexp'), winston);
|
||||
module.exports.walk = function (dir, done) {
|
||||
// DEPRECATED
|
||||
var file = require('../../src/file');
|
||||
winston.warn('[deprecated] `utils.walk` is deprecated. Use `file.walk` instead.');
|
||||
file.walk(dir, done);
|
||||
};
|
||||
|
||||
process.profile = function (operation, start) {
|
||||
console.log('%s took %d milliseconds', operation, process.elapsedTimeSince(start));
|
||||
|
||||
@@ -238,4 +238,4 @@ Analytics.getBlacklistAnalytics = async function () {
|
||||
});
|
||||
};
|
||||
|
||||
require('./promisify')(Analytics);
|
||||
Analytics.async = require('./promisify')(Analytics);
|
||||
|
||||
@@ -367,4 +367,4 @@ Categories.buildForSelectCategories = function (categories, fields) {
|
||||
return categoriesData.map(category => _.pick(category, pickFields));
|
||||
};
|
||||
|
||||
require('../promisify')(Categories);
|
||||
Categories.async = require('../promisify')(Categories);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
const user = require('../../user');
|
||||
const meta = require('../../meta');
|
||||
const plugins = require('../../plugins');
|
||||
const helpers = require('../helpers');
|
||||
const groups = require('../../groups');
|
||||
const accountHelpers = require('./helpers');
|
||||
@@ -66,7 +67,9 @@ editController.get = async function (req, res, next) {
|
||||
},
|
||||
]);
|
||||
userData.editButtons = [];
|
||||
res.render('account/edit', userData);
|
||||
|
||||
const result = await plugins.fireHook('filter:user.account.edit', userData);
|
||||
res.render('account/edit', result);
|
||||
};
|
||||
|
||||
editController.password = async function (req, res, next) {
|
||||
|
||||
@@ -56,9 +56,11 @@ notificationsController.get = async function (req, res, next) {
|
||||
nids = nids.slice(start, stop + 1);
|
||||
|
||||
const notifications = await user.notifications.getNotifications(nids, req.uid);
|
||||
|
||||
res.render('notifications', {
|
||||
const data = await plugins.fireHook('filter:notifications.get', {
|
||||
notifications: notifications,
|
||||
});
|
||||
res.render('notifications', {
|
||||
notifications: data.notifications,
|
||||
pagination: pagination.create(page, pageCount, req.query),
|
||||
filters: allFilters,
|
||||
regularFilters: regularFilters,
|
||||
|
||||
@@ -6,6 +6,7 @@ const db = require('../../database');
|
||||
const user = require('../../user');
|
||||
const posts = require('../../posts');
|
||||
const categories = require('../../categories');
|
||||
const plugins = require('../../plugins');
|
||||
const meta = require('../../meta');
|
||||
const accountHelpers = require('./helpers');
|
||||
const helpers = require('../helpers');
|
||||
@@ -57,7 +58,8 @@ profileController.get = async function (req, res, next) {
|
||||
userData.selectedGroup = userData.groups.filter(group => group && userData.groupTitleArray.includes(group.name))
|
||||
.sort((a, b) => userData.groupTitleArray.indexOf(a.name) - userData.groupTitleArray.indexOf(b.name));
|
||||
|
||||
res.render('account/profile', userData);
|
||||
const results = await plugins.fireHook('filter:user.account', { userData: userData, uid: req.uid });
|
||||
res.render('account/profile', results.userData);
|
||||
};
|
||||
|
||||
async function incrementProfileViews(req, userData) {
|
||||
|
||||
@@ -5,7 +5,6 @@ const validator = require('validator');
|
||||
|
||||
const db = require('../../database');
|
||||
const user = require('../../user');
|
||||
const categories = require('../../categories');
|
||||
const groups = require('../../groups');
|
||||
const meta = require('../../meta');
|
||||
const pagination = require('../../pagination');
|
||||
@@ -51,15 +50,12 @@ groupsController.get = async function (req, res, next) {
|
||||
};
|
||||
});
|
||||
|
||||
const allCategories = await categories.buildForSelectAll();
|
||||
|
||||
res.render('admin/manage/group', {
|
||||
group: group,
|
||||
groupNames: groupNameData,
|
||||
allowPrivateGroups: meta.config.allowPrivateGroups,
|
||||
maximumGroupNameLength: meta.config.maximumGroupNameLength,
|
||||
maximumGroupTitleLength: meta.config.maximumGroupTitleLength,
|
||||
categories: allCategories,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -79,12 +79,6 @@ async function getNodeInfo() {
|
||||
release: os.release(),
|
||||
load: os.loadavg().map(function (load) { return load.toFixed(2); }).join(', '),
|
||||
},
|
||||
nodebb: {
|
||||
isCluster: nconf.get('isCluster'),
|
||||
isPrimary: nconf.get('isPrimary'),
|
||||
runJobs: nconf.get('runJobs'),
|
||||
jobsDisabled: nconf.get('jobsDisabled'),
|
||||
},
|
||||
};
|
||||
data.process.cpuUsage.user /= 1000000;
|
||||
data.process.cpuUsage.user = data.process.cpuUsage.user.toFixed(2);
|
||||
@@ -115,5 +109,5 @@ async function getGitInfo() {
|
||||
getAsync('git rev-parse HEAD'),
|
||||
getAsync('git rev-parse --abbrev-ref HEAD'),
|
||||
]);
|
||||
return { hash: hash, hashShort: hash.substr(0, 6), branch: branch };
|
||||
return { hash: hash, branch: branch };
|
||||
}
|
||||
|
||||
@@ -264,7 +264,9 @@ function continueLogin(req, res, next) {
|
||||
await authenticationController.doLogin(req, userData.uid);
|
||||
var destination;
|
||||
if (req.session.returnTo) {
|
||||
destination = req.session.returnTo;
|
||||
destination = req.session.returnTo.startsWith('http') ?
|
||||
req.session.returnTo :
|
||||
nconf.get('relative_path') + req.session.returnTo;
|
||||
delete req.session.returnTo;
|
||||
} else {
|
||||
destination = nconf.get('relative_path') + '/';
|
||||
|
||||
@@ -181,17 +181,12 @@ modsController.postQueue = async function (req, res, next) {
|
||||
const page = parseInt(req.query.page, 10) || 1;
|
||||
const postsPerPage = 20;
|
||||
|
||||
const [ids, isAdminOrGlobalMod, moderatedCids, allCategories] = await Promise.all([
|
||||
const [ids, isAdminOrGlobalMod, moderatedCids] = await Promise.all([
|
||||
db.getSortedSetRange('post:queue', 0, -1),
|
||||
user.isAdminOrGlobalMod(req.uid),
|
||||
user.getModeratedCids(req.uid),
|
||||
categories.buildForSelect(req.uid, 'find', ['disabled', 'link', 'slug']),
|
||||
]);
|
||||
|
||||
allCategories.forEach((c) => {
|
||||
c.disabledClass = !isAdminOrGlobalMod && !moderatedCids.includes(String(c.cid));
|
||||
});
|
||||
|
||||
let postData = await getQueuedPosts(ids);
|
||||
postData = postData.filter(p => p && (isAdminOrGlobalMod || moderatedCids.includes(String(p.category.cid))));
|
||||
|
||||
@@ -203,7 +198,6 @@ modsController.postQueue = async function (req, res, next) {
|
||||
res.render('admin/manage/post-queue', {
|
||||
title: '[[pages:post-queue]]',
|
||||
posts: postData,
|
||||
allCategories: allCategories,
|
||||
pagination: pagination.create(page, pageCount),
|
||||
breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[pages:post-queue]]' }]),
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ const meta = require('../meta');
|
||||
const topics = require('../topics');
|
||||
const posts = require('../posts');
|
||||
const privileges = require('../privileges');
|
||||
const plugins = require('../plugins');
|
||||
const helpers = require('./helpers');
|
||||
const pagination = require('../pagination');
|
||||
const utils = require('../utils');
|
||||
@@ -68,6 +69,8 @@ topicsController.get = async function getTopic(req, res, callback) {
|
||||
|
||||
topics.modifyPostsByPrivilege(topicData, userPrivileges);
|
||||
|
||||
const hookData = await plugins.fireHook('filter:controllers.topic.get', { topicData: topicData, uid: req.uid });
|
||||
|
||||
topicData.privileges = userPrivileges;
|
||||
topicData.topicStaleDays = meta.config.topicStaleDays;
|
||||
topicData['reputation:disabled'] = meta.config['reputation:disabled'];
|
||||
@@ -88,7 +91,7 @@ topicsController.get = async function getTopic(req, res, callback) {
|
||||
topicData.postIndex = postIndex;
|
||||
|
||||
await Promise.all([
|
||||
buildBreadcrumbs(topicData),
|
||||
buildBreadcrumbs(hookData.topicData),
|
||||
addTags(topicData, req, res),
|
||||
]);
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ unreadController.get = async function (req, res, next) {
|
||||
req.query.page = Math.max(1, Math.min(data.pageCount, page));
|
||||
return helpers.redirect(res, '/unread?' + querystring.stringify(req.query));
|
||||
}
|
||||
data.showSelect = true;
|
||||
data.showSelect = isPrivileged;
|
||||
data.showTopicTools = isPrivileged;
|
||||
data.categories = watchedCategories.categories;
|
||||
data.allCategoriesUrl = 'unread' + helpers.buildQueryString('', filter, '');
|
||||
|
||||
@@ -178,4 +178,4 @@ require('./mongo/sorted')(mongoModule);
|
||||
require('./mongo/list')(mongoModule);
|
||||
require('./mongo/transaction')(mongoModule);
|
||||
|
||||
require('../promisify')(mongoModule, ['client', 'sessionStore']);
|
||||
mongoModule.async = require('../promisify')(mongoModule, ['client', 'sessionStore']);
|
||||
|
||||
@@ -420,4 +420,4 @@ require('./postgres/sorted')(postgresModule);
|
||||
require('./postgres/list')(postgresModule);
|
||||
require('./postgres/transaction')(postgresModule);
|
||||
|
||||
require('../promisify')(postgresModule, ['client', 'sessionStore', 'pool', 'transaction']);
|
||||
postgresModule.async = require('../promisify')(postgresModule, ['client', 'sessionStore', 'pool', 'transaction']);
|
||||
|
||||
@@ -155,4 +155,4 @@ require('./redis/sorted')(redisModule);
|
||||
require('./redis/list')(redisModule);
|
||||
require('./redis/transaction')(redisModule);
|
||||
|
||||
require('../promisify')(redisModule, ['client', 'sessionStore']);
|
||||
redisModule.async = require('../promisify')(redisModule, ['client', 'sessionStore']);
|
||||
|
||||
@@ -53,6 +53,11 @@ file.base64ToLocal = async function (imageData, uploadPath) {
|
||||
return uploadPath;
|
||||
};
|
||||
|
||||
file.isFileTypeAllowed = async function (path) {
|
||||
winston.warn('[deprecated] file.isFileTypeAllowed is deprecated, use image.isFileTypeAllowed');
|
||||
await require('./image').isFileTypeAllowed(path);
|
||||
};
|
||||
|
||||
// https://stackoverflow.com/a/31205878/583363
|
||||
file.appendToFileName = function (filename, string) {
|
||||
const dotIndex = filename.lastIndexOf('.');
|
||||
|
||||
176
src/flags.js
176
src/flags.js
@@ -84,28 +84,32 @@ Flags.init = async function () {
|
||||
};
|
||||
|
||||
Flags.get = async function (flagId) {
|
||||
const [base, history, notes, reports] = await Promise.all([
|
||||
const [base, history, notes] = await Promise.all([
|
||||
db.getObject('flag:' + flagId),
|
||||
Flags.getHistory(flagId),
|
||||
Flags.getNotes(flagId),
|
||||
Flags.getReports(flagId),
|
||||
]);
|
||||
if (!base) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [userObj, targetObj] = await Promise.all([
|
||||
user.getUserFields(base.uid, ['username', 'userslug', 'picture', 'reputation']),
|
||||
Flags.getTarget(base.type, base.targetId, 0),
|
||||
]);
|
||||
|
||||
const flagObj = {
|
||||
state: 'open',
|
||||
assignee: null,
|
||||
...base,
|
||||
description: validator.escape(base.description),
|
||||
datetimeISO: utils.toISOString(base.datetime),
|
||||
target_readable: base.type.charAt(0).toUpperCase() + base.type.slice(1) + ' ' + base.targetId,
|
||||
target: await Flags.getTarget(base.type, base.targetId, 0),
|
||||
target: targetObj,
|
||||
history: history,
|
||||
notes: notes,
|
||||
reports: reports,
|
||||
reporter: userObj,
|
||||
};
|
||||
|
||||
const data = await plugins.fireHook('filter:flags.get', {
|
||||
flag: flagObj,
|
||||
});
|
||||
@@ -156,19 +160,24 @@ Flags.list = async function (filters, uid) {
|
||||
const pageCount = Math.ceil(flagIds.length / flagsPerPage);
|
||||
flagIds = flagIds.slice((filters.page - 1) * flagsPerPage, filters.page * flagsPerPage);
|
||||
|
||||
const reportCounts = await db.sortedSetsCard(flagIds.map(flagId => `flag:${flagId}:reports`));
|
||||
|
||||
const flags = await Promise.all(flagIds.map(async (flagId, idx) => {
|
||||
const flags = await Promise.all(flagIds.map(async (flagId) => {
|
||||
let flagObj = await db.getObject('flag:' + flagId);
|
||||
const userObj = await user.getUserFields(flagObj.uid, ['username', 'picture']);
|
||||
flagObj = {
|
||||
state: 'open',
|
||||
assignee: null,
|
||||
heat: reportCounts[idx],
|
||||
...flagObj,
|
||||
reporter: {
|
||||
username: userObj.username,
|
||||
picture: userObj.picture,
|
||||
'icon:bgColor': userObj['icon:bgColor'],
|
||||
'icon:text': userObj['icon:text'],
|
||||
},
|
||||
};
|
||||
flagObj.labelClass = Flags._constants.state_class[flagObj.state];
|
||||
|
||||
return Object.assign(flagObj, {
|
||||
description: validator.escape(String(flagObj.description)),
|
||||
target_readable: flagObj.type.charAt(0).toUpperCase() + flagObj.type.slice(1) + ' ' + flagObj.targetId,
|
||||
datetimeISO: utils.toISOString(flagObj.datetime),
|
||||
});
|
||||
@@ -233,24 +242,6 @@ Flags.getNote = async function (flagId, datetime) {
|
||||
return notes[0];
|
||||
};
|
||||
|
||||
Flags.getFlagIdByTarget = async function (type, id) {
|
||||
let method;
|
||||
switch (type) {
|
||||
case 'post':
|
||||
method = posts.getPostField;
|
||||
break;
|
||||
|
||||
case 'user':
|
||||
method = user.getUserField;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
}
|
||||
|
||||
return await method(id, 'flagId');
|
||||
};
|
||||
|
||||
async function modifyNotes(notes) {
|
||||
const uids = [];
|
||||
notes = notes.map(function (note) {
|
||||
@@ -286,135 +277,72 @@ Flags.create = async function (type, id, uid, reason, timestamp) {
|
||||
timestamp = Date.now();
|
||||
doHistoryAppend = true;
|
||||
}
|
||||
const [flagExists, targetExists,, targetFlagged, targetUid, targetCid] = await Promise.all([
|
||||
const [flagExists, targetExists, canFlag, targetUid, targetCid] = await Promise.all([
|
||||
// Sanity checks
|
||||
Flags.exists(type, id, uid),
|
||||
Flags.targetExists(type, id),
|
||||
Flags.canFlag(type, id, uid),
|
||||
Flags.targetFlagged(type, id),
|
||||
|
||||
// Extra data for zset insertion
|
||||
Flags.getTargetUid(type, id),
|
||||
Flags.getTargetCid(type, id),
|
||||
]);
|
||||
if (flagExists) {
|
||||
throw new Error(`[[error:${type}-already-flagged]]`);
|
||||
throw new Error('[[error:already-flagged]]');
|
||||
} else if (!targetExists) {
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
} else if (!canFlag) {
|
||||
throw new Error('[[error:no-privileges]]');
|
||||
}
|
||||
|
||||
// If the flag already exists, just add the report
|
||||
if (targetFlagged) {
|
||||
const flagId = await Flags.getFlagIdByTarget(type, id);
|
||||
await Promise.all([
|
||||
Flags.addReport(flagId, uid, reason, timestamp),
|
||||
Flags.update(flagId, uid, { state: 'open' }),
|
||||
]);
|
||||
|
||||
return await Flags.get(flagId);
|
||||
}
|
||||
|
||||
const flagId = await db.incrObjectField('global', 'nextFlagId');
|
||||
const batched = [];
|
||||
|
||||
batched.push(
|
||||
db.setObject.bind(db, 'flag:' + flagId, {
|
||||
flagId: flagId,
|
||||
type: type,
|
||||
targetId: id,
|
||||
datetime: timestamp,
|
||||
}),
|
||||
Flags.addReport.bind(Flags, flagId, uid, reason, timestamp),
|
||||
db.sortedSetAdd.bind(db, 'flags:datetime', timestamp, flagId), // by time, the default
|
||||
db.sortedSetAdd.bind(db, 'flags:byType:' + type, timestamp, flagId), // by flag type
|
||||
db.sortedSetAdd.bind(db, 'flags:hash', flagId, [type, id, uid].join(':')), // save zset for duplicate checking
|
||||
db.sortedSetIncrBy.bind(db, 'flags:byTarget', 1, [type, id].join(':')), // by flag target (score is count)
|
||||
analytics.increment.bind(analytics, 'flags') // some fancy analytics
|
||||
);
|
||||
await db.setObject('flag:' + flagId, {
|
||||
flagId: flagId,
|
||||
type: type,
|
||||
targetId: id,
|
||||
description: reason,
|
||||
uid: uid,
|
||||
datetime: timestamp,
|
||||
});
|
||||
await db.sortedSetAdd('flags:datetime', timestamp, flagId); // by time, the default
|
||||
await db.sortedSetAdd('flags:byReporter:' + uid, timestamp, flagId); // by reporter
|
||||
await db.sortedSetAdd('flags:byType:' + type, timestamp, flagId); // by flag type
|
||||
await db.sortedSetAdd('flags:hash', flagId, [type, id, uid].join(':')); // save zset for duplicate checking
|
||||
await analytics.increment('flags'); // some fancy analytics
|
||||
|
||||
if (targetUid) {
|
||||
batched.push(db.sortedSetAdd.bind(db, 'flags:byTargetUid:' + targetUid, timestamp, flagId)); // by target uid
|
||||
await db.sortedSetAdd('flags:byTargetUid:' + targetUid, timestamp, flagId); // by target uid
|
||||
}
|
||||
|
||||
if (targetCid) {
|
||||
batched.push(db.sortedSetAdd.bind(db, 'flags:byCid:' + targetCid, timestamp, flagId)); // by target cid
|
||||
await db.sortedSetAdd('flags:byCid:' + targetCid, timestamp, flagId); // by target cid
|
||||
}
|
||||
|
||||
if (type === 'post') {
|
||||
batched.push(
|
||||
db.sortedSetAdd.bind(db, 'flags:byPid:' + id, timestamp, flagId), // by target pid
|
||||
posts.setPostField.bind(posts, id, 'flagId', flagId)
|
||||
);
|
||||
|
||||
await db.sortedSetAdd('flags:byPid:' + id, timestamp, flagId); // by target pid
|
||||
if (targetUid) {
|
||||
batched.push(user.incrementUserFlagsBy.bind(user, targetUid, 1));
|
||||
await user.incrementUserFlagsBy(targetUid, 1);
|
||||
}
|
||||
} else if (type === 'user') {
|
||||
batched.push(user.setUserField.bind(user, id, 'flagId', flagId));
|
||||
}
|
||||
|
||||
// Run all the database calls in one single batched call...
|
||||
await Promise.all(batched.map(async method => await method()));
|
||||
|
||||
if (doHistoryAppend) {
|
||||
Flags.update(flagId, uid, { state: 'open' });
|
||||
await Flags.update(flagId, uid, { state: 'open' });
|
||||
}
|
||||
|
||||
return await Flags.get(flagId);
|
||||
};
|
||||
|
||||
Flags.getReports = async function (flagId) {
|
||||
const [reports, reporterUids] = await Promise.all([
|
||||
db.getSortedSetRevRangeWithScores(`flag:${flagId}:reports`, 0, -1),
|
||||
db.getSortedSetRevRange(`flag:${flagId}:reporters`, 0, -1),
|
||||
]);
|
||||
|
||||
await Promise.all(reports.map(async (report, idx) => {
|
||||
report.timestamp = report.score;
|
||||
report.timestampISO = new Date(report.score).toISOString();
|
||||
delete report.score;
|
||||
report.reporter = await user.getUserFields(reporterUids[idx], ['username', 'userslug', 'picture', 'reputation']);
|
||||
}));
|
||||
|
||||
return reports;
|
||||
};
|
||||
|
||||
Flags.addReport = async function (flagId, uid, reason, timestamp) {
|
||||
// adds to reporters/report zsets
|
||||
await Promise.all([
|
||||
db.sortedSetAdd(`flags:byReporter:${uid}`, timestamp, flagId),
|
||||
db.sortedSetAdd(`flag:${flagId}:reports`, timestamp, reason),
|
||||
db.sortedSetAdd(`flag:${flagId}:reporters`, timestamp, uid),
|
||||
]);
|
||||
};
|
||||
|
||||
Flags.exists = async function (type, id, uid) {
|
||||
return await db.isSortedSetMember('flags:hash', [type, id, uid].join(':'));
|
||||
};
|
||||
|
||||
Flags.canFlag = async function (type, id, uid) {
|
||||
const limit = meta.config['flags:limitPerTarget'];
|
||||
if (limit > 0) {
|
||||
const score = await db.sortedSetScore('flags:byTarget', `${type}:${id}`);
|
||||
if (score >= limit) {
|
||||
throw new Error(`[[error:${type}-flagged-too-many-times]]`);
|
||||
}
|
||||
if (type === 'user') {
|
||||
return true;
|
||||
}
|
||||
|
||||
const canRead = await privileges.posts.can('topics:read', id, uid);
|
||||
switch (type) {
|
||||
case 'user':
|
||||
return true;
|
||||
|
||||
case 'post':
|
||||
if (!canRead) {
|
||||
throw new Error('[[error:no-privileges]]');
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
if (type === 'post') {
|
||||
return await privileges.posts.can('topics:read', id, uid);
|
||||
}
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
};
|
||||
|
||||
Flags.getTarget = async function (type, id, uid) {
|
||||
@@ -443,10 +371,6 @@ Flags.targetExists = async function (type, id) {
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
};
|
||||
|
||||
Flags.targetFlagged = async function (type, id) {
|
||||
return await db.sortedSetScore('flags:byTarget', [type, id].join(':')) >= 1;
|
||||
};
|
||||
|
||||
Flags.getTargetUid = async function (type, id) {
|
||||
if (type === 'post') {
|
||||
return await posts.getPostField(id, 'uid');
|
||||
@@ -504,7 +428,7 @@ Flags.update = async function (flagId, uid, changeset) {
|
||||
tasks.push(db.sortedSetAdd('flags:byState:' + changeset[prop], now, flagId));
|
||||
tasks.push(db.sortedSetRemove('flags:byState:' + current[prop], flagId));
|
||||
if (changeset[prop] === 'resolved' || changeset[prop] === 'rejected') {
|
||||
tasks.push(notifications.rescind('flag:' + current.type + ':' + current.targetId));
|
||||
tasks.push(notifications.rescind('flag:' + current.type + ':' + current.targetId + ':uid:' + current.uid));
|
||||
}
|
||||
}
|
||||
} else if (prop === 'assignee') {
|
||||
@@ -606,11 +530,11 @@ Flags.notify = async function (flagObj, uid) {
|
||||
|
||||
notifObj = await notifications.create({
|
||||
type: 'new-post-flag',
|
||||
bodyShort: '[[notifications:user_flagged_post_in, ' + flagObj.reports[flagObj.reports.length - 1].reporter.username + ', ' + titleEscaped + ']]',
|
||||
bodyShort: '[[notifications:user_flagged_post_in, ' + flagObj.reporter.username + ', ' + titleEscaped + ']]',
|
||||
bodyLong: flagObj.description,
|
||||
pid: flagObj.targetId,
|
||||
path: '/flags/' + flagObj.flagId,
|
||||
nid: 'flag:post:' + flagObj.targetId,
|
||||
nid: 'flag:post:' + flagObj.targetId + ':uid:' + uid,
|
||||
from: uid,
|
||||
mergeId: 'notifications:user_flagged_post_in|' + flagObj.targetId,
|
||||
topicTitle: title,
|
||||
@@ -619,10 +543,10 @@ Flags.notify = async function (flagObj, uid) {
|
||||
} else if (flagObj.type === 'user') {
|
||||
notifObj = await notifications.create({
|
||||
type: 'new-user-flag',
|
||||
bodyShort: '[[notifications:user_flagged_user, ' + flagObj.reports[flagObj.reports.length - 1].reporter.username + ', ' + flagObj.target.username + ']]',
|
||||
bodyShort: '[[notifications:user_flagged_user, ' + flagObj.reporter.username + ', ' + flagObj.target.username + ']]',
|
||||
bodyLong: flagObj.description,
|
||||
path: '/flags/' + flagObj.flagId,
|
||||
nid: 'flag:user:' + flagObj.targetId,
|
||||
nid: 'flag:user:' + flagObj.targetId + ':uid:' + uid,
|
||||
from: uid,
|
||||
mergeId: 'notifications:user_flagged_user|' + flagObj.targetId,
|
||||
});
|
||||
|
||||
@@ -228,4 +228,4 @@ Groups.existsBySlug = async function (slug) {
|
||||
return await db.isObjectField('groupslug:groupname', slug);
|
||||
};
|
||||
|
||||
require('../promisify')(Groups);
|
||||
Groups.async = require('../promisify')(Groups);
|
||||
|
||||
@@ -26,6 +26,10 @@ function requireSharp() {
|
||||
|
||||
image.isFileTypeAllowed = async function (path) {
|
||||
const plugins = require('./plugins');
|
||||
// deprecated: remove in 1.14.0
|
||||
if (plugins.hasListeners('filter:file.isFileTypeAllowed')) {
|
||||
return await plugins.fireHook('filter:file.isFileTypeAllowed', path);
|
||||
}
|
||||
if (plugins.hasListeners('filter:image.isFileTypeAllowed')) {
|
||||
return await plugins.fireHook('filter:image.isFileTypeAllowed', path);
|
||||
}
|
||||
|
||||
@@ -284,4 +284,4 @@ Messaging.hasPrivateChat = async (uid, withUid) => {
|
||||
return roomId;
|
||||
};
|
||||
|
||||
require('../promisify')(Messaging);
|
||||
Messaging.async = require('../promisify')(Messaging);
|
||||
|
||||
@@ -50,11 +50,10 @@ module.exports = function (Messaging) {
|
||||
db.sortedSetAdd('chat:room:' + roomId + ':uids', now, uid),
|
||||
]);
|
||||
await Promise.all([
|
||||
Messaging.addSystemMessage('user-join', uid, roomId), // chat owner should also get the user-join system message
|
||||
Messaging.addUsersToRoom(uid, toUids, roomId),
|
||||
Messaging.addRoomToUsers(roomId, [uid].concat(toUids), now),
|
||||
]);
|
||||
// chat owner should also get the user-join system message
|
||||
await Messaging.addSystemMessage('user-join', uid, roomId);
|
||||
|
||||
return roomId;
|
||||
};
|
||||
|
||||
@@ -218,7 +218,7 @@ exports.build = function (targets, options, callback) {
|
||||
},
|
||||
], function (err) {
|
||||
if (err) {
|
||||
winston.error('[build] Encountered error during build step\n' + (err.stack ? err.stack : err));
|
||||
winston.error('[build] Encountered error during build step\n' + err.stack ? err.stack : err);
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,4 +68,4 @@ Meta.getSessionTTLSeconds = function () {
|
||||
return ttl;
|
||||
};
|
||||
|
||||
require('../promisify')(Meta);
|
||||
Meta.async = require('../promisify')(Meta);
|
||||
|
||||
@@ -271,8 +271,7 @@ function buildCSS(data, callback) {
|
||||
javascriptEnabled: true,
|
||||
}, function (err, lessOutput) {
|
||||
if (err) {
|
||||
// display less parser errors properly
|
||||
return callback(new Error(String(err)));
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
postcss(data.minify ? [
|
||||
|
||||
@@ -56,6 +56,10 @@ Tags.parse = async (req, data, meta, link) => {
|
||||
}, {
|
||||
rel: 'manifest',
|
||||
href: nconf.get('relative_path') + '/manifest.json',
|
||||
}, {
|
||||
rel: 'preload',
|
||||
href: nconf.get('relative_path') + '/assets/js-enabled.css?' + (Meta.config['cache-buster'] ? '?' + Meta.config['cache-buster'] : ''),
|
||||
as: 'style',
|
||||
}];
|
||||
|
||||
if (plugins.hasListeners('filter:search.query')) {
|
||||
|
||||
@@ -20,6 +20,10 @@ var controllers = {
|
||||
|
||||
module.exports = function (middleware) {
|
||||
middleware.admin = {};
|
||||
middleware.admin.isAdmin = helpers.try(async function (req, res, next) {
|
||||
winston.warn('[middleware.admin.isAdmin] deprecation warning, no need to use this from plugins!');
|
||||
await middleware.isAdmin(req, res, next);
|
||||
});
|
||||
|
||||
middleware.admin.buildHeader = helpers.try(async function (req, res, next) {
|
||||
res.locals.renderAdminHeader = true;
|
||||
|
||||
@@ -65,18 +65,10 @@ module.exports = function (middleware) {
|
||||
});
|
||||
|
||||
middleware.autoLocale = helpers.try(async function autoLocale(req, res, next) {
|
||||
let langs;
|
||||
if (req.query.lang) {
|
||||
langs = await listCodes();
|
||||
if (!langs.includes(req.query.lang)) {
|
||||
req.query.lang = meta.config.defaultLang;
|
||||
}
|
||||
if (parseInt(req.uid, 10) > 0 || !meta.config.autoDetectLang || req.query.lang) {
|
||||
return next();
|
||||
}
|
||||
if (parseInt(req.uid, 10) > 0 || !meta.config.autoDetectLang) {
|
||||
return next();
|
||||
}
|
||||
langs = await listCodes();
|
||||
const langs = await listCodes();
|
||||
const lang = req.acceptsLanguages(langs);
|
||||
if (!lang) {
|
||||
return next();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const nconf = require('nconf');
|
||||
const winston = require('winston');
|
||||
|
||||
const meta = require('../meta');
|
||||
const user = require('../user');
|
||||
@@ -75,6 +76,11 @@ module.exports = function (middleware) {
|
||||
return next();
|
||||
}
|
||||
|
||||
middleware.checkGlobalPrivacySettings = helpers.try(async function checkGlobalPrivacySettings(req, res, next) {
|
||||
winston.warn('[middleware], checkGlobalPrivacySettings deprecated, use canViewUsers or canViewGroups');
|
||||
await middleware.canViewUsers(req, res, next);
|
||||
});
|
||||
|
||||
middleware.canViewUsers = helpers.try(async function canViewUsers(req, res, next) {
|
||||
if (parseInt(res.locals.uid, 10) === req.uid) {
|
||||
return next();
|
||||
|
||||
@@ -418,4 +418,4 @@ Notifications.merge = async function (notifications) {
|
||||
return data && data.notifications;
|
||||
};
|
||||
|
||||
require('./promisify')(Notifications);
|
||||
Notifications.async = require('./promisify')(Notifications);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user