mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-24 09:20:32 +01:00
Compare commits
23 Commits
chat-pruni
...
v2.5.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd6d104820 | ||
|
|
af27606e20 | ||
|
|
dc4a850cac | ||
|
|
ba484d5478 | ||
|
|
dd4e9cce09 | ||
|
|
e92238d09a | ||
|
|
7dc45afa4c | ||
|
|
67efaeb4b8 | ||
|
|
b879b6a0c2 | ||
|
|
e35b0a869f | ||
|
|
e7d0040d17 | ||
|
|
58b2f10ee9 | ||
|
|
b91ef6dd76 | ||
|
|
aabf073c89 | ||
|
|
89eb0340d1 | ||
|
|
ebd5dcc6d6 | ||
|
|
fe0020fb31 | ||
|
|
177d904812 | ||
|
|
989b55d07e | ||
|
|
7240e8ce57 | ||
|
|
803398e915 | ||
|
|
aad0a618c8 | ||
|
|
14515f6004 |
3
.github/workflows/docker.yml
vendored
3
.github/workflows/docker.yml
vendored
@@ -11,6 +11,9 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
10
.github/workflows/test.yaml
vendored
10
.github/workflows/test.yaml
vendored
@@ -14,8 +14,14 @@ defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
permissions:
|
||||
checks: write # for coverallsapp/github-action to create new checks
|
||||
contents: read # for actions/checkout to fetch code
|
||||
name: Lint and test
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -42,7 +48,7 @@ jobs:
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: 'postgres:14-alpine'
|
||||
image: 'postgres:10-alpine'
|
||||
env:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
@@ -194,6 +200,8 @@ jobs:
|
||||
parallel: true
|
||||
|
||||
finish:
|
||||
permissions:
|
||||
checks: write # for coverallsapp/github-action to create new checks
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
75
CHANGELOG.md
75
CHANGELOG.md
@@ -1,11 +1,12 @@
|
||||
#### v2.5.3 (2022-09-19)
|
||||
#### v2.5.6 (2022-10-13)
|
||||
|
||||
##### Chores
|
||||
|
||||
* remove duplicate version increment lines in changelog (5dbcfef9)
|
||||
* bring back treding plugins (8aa1596d)
|
||||
* incrementing version number - v2.5.5 (3509ed94)
|
||||
* update changelog for v2.5.5 (e7d0040d)
|
||||
* incrementing version number - v2.5.4 (e83260ca)
|
||||
* incrementing version number - v2.5.3 (7e922936)
|
||||
* incrementing version number - v2.5.2 (babcd17e)
|
||||
* update changelog for v2.5.2 (84b6a7c7)
|
||||
* incrementing version number - v2.5.1 (ce3aa950)
|
||||
* incrementing version number - v2.5.0 (01d276cb)
|
||||
* incrementing version number - v2.4.5 (dd3e1a28)
|
||||
@@ -17,6 +18,72 @@
|
||||
* incrementing version number - v2.3.1 (d2425942)
|
||||
* incrementing version number - v2.3.0 (046ea120)
|
||||
|
||||
##### Bug Fixes
|
||||
|
||||
* use admin:groups priv for groups (#10960) (b879b6a0)
|
||||
* https://github.com/NodeBB/NodeBB/issues/10525 (e35b0a86)
|
||||
|
||||
#### v2.5.5 (2022-10-11)
|
||||
|
||||
##### Chores
|
||||
|
||||
* up plugins (b91ef6dd)
|
||||
* incrementing version number - v2.5.4 (e83260ca)
|
||||
* update changelog for v2.5.4 (aabf073c)
|
||||
* incrementing version number - v2.5.3 (7e922936)
|
||||
* incrementing version number - v2.5.2 (babcd17e)
|
||||
* incrementing version number - v2.5.1 (ce3aa950)
|
||||
* incrementing version number - v2.5.0 (01d276cb)
|
||||
* incrementing version number - v2.4.5 (dd3e1a28)
|
||||
* incrementing version number - v2.4.4 (d5525c87)
|
||||
* incrementing version number - v2.4.3 (9c647c6c)
|
||||
* incrementing version number - v2.4.2 (3aa7b855)
|
||||
* incrementing version number - v2.4.1 (60cbd148)
|
||||
* incrementing version number - v2.4.0 (4834cde3)
|
||||
* incrementing version number - v2.3.1 (d2425942)
|
||||
* incrementing version number - v2.3.0 (046ea120)
|
||||
|
||||
#### v2.5.4 (2022-10-11)
|
||||
|
||||
##### Chores
|
||||
|
||||
* 🤔 (7240e8ce)
|
||||
* incrementing version number - v2.5.3 (7e922936)
|
||||
* update changelog for v2.5.3 (fdf240f6)
|
||||
* incrementing version number - v2.5.2 (babcd17e)
|
||||
* incrementing version number - v2.5.1 (ce3aa950)
|
||||
* incrementing version number - v2.5.0 (01d276cb)
|
||||
* incrementing version number - v2.4.5 (dd3e1a28)
|
||||
* incrementing version number - v2.4.4 (d5525c87)
|
||||
* incrementing version number - v2.4.3 (9c647c6c)
|
||||
* incrementing version number - v2.4.2 (3aa7b855)
|
||||
* incrementing version number - v2.4.1 (60cbd148)
|
||||
* incrementing version number - v2.4.0 (4834cde3)
|
||||
* incrementing version number - v2.3.1 (d2425942)
|
||||
* incrementing version number - v2.3.0 (046ea120)
|
||||
|
||||
##### Continuous Integration
|
||||
|
||||
* add minimum GitHub token permissions for workflows Signed-off-by: Ashish Kurmi <akurmi@stepsecurity.io> (fe0020fb)
|
||||
|
||||
##### Bug Fixes
|
||||
|
||||
* EEXISTS error on linux if plugin/theme overrides core js file (ebd5dcc6)
|
||||
* category ordering add test (177d9048)
|
||||
* crash in category drag, closes #10932 (989b55d0)
|
||||
* broken flag history on flag update (803398e9)
|
||||
* scroll to post if theme doesn't have top navbar (aad0a618)
|
||||
* add lru-cache to checked packages, to fix upgrade issue with lru-cache (14515f60)
|
||||
|
||||
#### v2.5.3 (2022-09-19)
|
||||
|
||||
##### Chores
|
||||
|
||||
* remove duplicate version increment lines in changelog (5dbcfef9)
|
||||
* bring back treding plugins (8aa1596d)
|
||||
* incrementing version number - v2.5.2 (babcd17e)
|
||||
* update changelog for v2.5.2 (84b6a7c7)
|
||||
|
||||
##### New Features
|
||||
|
||||
* store topic title and tags in diffs (#10900) (b5dd89e1)
|
||||
|
||||
@@ -138,10 +138,9 @@ module.exports = function (grunt) {
|
||||
});
|
||||
const build = require('./src/meta/build');
|
||||
if (!grunt.option('skip')) {
|
||||
await build.build(true, { webpack: false });
|
||||
await build.build(true, { watch: true });
|
||||
}
|
||||
run();
|
||||
await build.webpack({ watch: true });
|
||||
done();
|
||||
});
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "nodebb",
|
||||
"license": "GPL-3.0",
|
||||
"description": "NodeBB Forum",
|
||||
"version": "2.5.3",
|
||||
"version": "2.5.7",
|
||||
"homepage": "http://www.nodebb.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -30,10 +30,10 @@
|
||||
"dependencies": {
|
||||
"@adactive/bootstrap-tagsinput": "0.8.2",
|
||||
"@isaacs/ttlcache": "1.2.0",
|
||||
"ace-builds": "1.11.1",
|
||||
"ace-builds": "1.9.5",
|
||||
"archiver": "5.3.1",
|
||||
"async": "3.2.4",
|
||||
"autoprefixer": "10.4.12",
|
||||
"autoprefixer": "10.4.8",
|
||||
"bcryptjs": "2.4.3",
|
||||
"benchpressjs": "2.4.3",
|
||||
"body-parser": "1.20.0",
|
||||
@@ -45,7 +45,7 @@
|
||||
"clipboard": "2.0.11",
|
||||
"colors": "1.4.0",
|
||||
"commander": "9.4.0",
|
||||
"compare-versions": "5.0.1",
|
||||
"compare-versions": "4.1.4",
|
||||
"compression": "1.7.4",
|
||||
"connect-flash": "0.1.1",
|
||||
"connect-mongo": "4.6.0",
|
||||
@@ -58,6 +58,7 @@
|
||||
"csurf": "1.11.0",
|
||||
"daemon": "1.1.0",
|
||||
"diff": "5.1.0",
|
||||
"esbuild": "0.15.10",
|
||||
"express": "4.18.1",
|
||||
"express-session": "1.17.3",
|
||||
"express-useragent": "1.0.15",
|
||||
@@ -67,7 +68,7 @@
|
||||
"helmet": "5.1.1",
|
||||
"html-to-text": "8.2.1",
|
||||
"ipaddr.js": "2.0.1",
|
||||
"jquery": "3.6.1",
|
||||
"jquery": "3.6.0",
|
||||
"jquery-deserialize": "2.0.0",
|
||||
"jquery-form": "4.3.0",
|
||||
"jquery-serializeobject": "1.0.0",
|
||||
@@ -82,23 +83,23 @@
|
||||
"material-design-lite": "1.3.0",
|
||||
"mime": "3.0.0",
|
||||
"mkdirp": "1.0.4",
|
||||
"mongodb": "4.10.0",
|
||||
"mongodb": "4.9.0",
|
||||
"morgan": "1.10.0",
|
||||
"mousetrap": "1.6.5",
|
||||
"multiparty": "4.2.3",
|
||||
"@nodebb/bootswatch": "3.4.2",
|
||||
"nconf": "0.12.0",
|
||||
"nodebb-plugin-2factor": "5.1.1",
|
||||
"nodebb-plugin-composer-default": "9.2.0",
|
||||
"nodebb-plugin-2factor": "5.0.2",
|
||||
"nodebb-plugin-composer-default": "9.1.1",
|
||||
"nodebb-plugin-dbsearch": "5.1.5",
|
||||
"nodebb-plugin-emoji": "4.0.5",
|
||||
"nodebb-plugin-emoji": "4.0.6",
|
||||
"nodebb-plugin-emoji-android": "3.0.0",
|
||||
"nodebb-plugin-markdown": "10.1.0",
|
||||
"nodebb-plugin-mentions": "3.0.11",
|
||||
"nodebb-plugin-spam-be-gone": "1.0.0",
|
||||
"nodebb-plugin-mentions": "3.0.12",
|
||||
"nodebb-plugin-spam-be-gone": "1.0.2",
|
||||
"nodebb-rewards-essentials": "0.2.1",
|
||||
"nodebb-theme-lavender": "6.0.0",
|
||||
"nodebb-theme-persona": "12.1.5",
|
||||
"nodebb-theme-persona": "12.1.1",
|
||||
"nodebb-theme-slick": "2.0.2",
|
||||
"nodebb-theme-vanilla": "12.1.18",
|
||||
"nodebb-widget-essentials": "6.0.0",
|
||||
@@ -107,28 +108,30 @@
|
||||
"passport": "0.6.0",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-local": "1.0.0",
|
||||
"pg": "8.8.0",
|
||||
"pg-cursor": "2.7.4",
|
||||
"postcss": "8.4.16",
|
||||
"pg": "8.7.3",
|
||||
"pg-cursor": "2.7.3",
|
||||
"postcss": "8.4.14",
|
||||
"postcss-clean": "1.2.0",
|
||||
"progress-webpack-plugin": "1.0.16",
|
||||
"prompt": "1.3.0",
|
||||
"ioredis": "5.2.3",
|
||||
"ioredis": "5.2.2",
|
||||
"request": "2.88.2",
|
||||
"request-promise-native": "1.0.9",
|
||||
"rimraf": "3.0.2",
|
||||
"rss": "1.2.2",
|
||||
"sanitize-html": "2.7.2",
|
||||
"sanitize-html": "2.7.1",
|
||||
"semver": "7.3.7",
|
||||
"serve-favicon": "2.5.0",
|
||||
"sharp": "0.31.0",
|
||||
"sharp": "0.30.7",
|
||||
"sitemap": "7.1.1",
|
||||
"slideout": "1.0.1",
|
||||
"socket.io": "4.5.2",
|
||||
"socket.io-client": "4.5.2",
|
||||
"socket.io": "4.5.1",
|
||||
"socket.io-client": "4.5.1",
|
||||
"@socket.io/redis-adapter": "7.2.0",
|
||||
"sortablejs": "1.15.0",
|
||||
"spdx-license-list": "6.6.0",
|
||||
"spider-detector": "2.0.0",
|
||||
"terser-webpack-plugin": "5.3.6",
|
||||
"textcomplete": "0.18.2",
|
||||
"textcomplete.contenteditable": "0.1.1",
|
||||
"timeago": "1.6.7",
|
||||
@@ -138,7 +141,7 @@
|
||||
"validator": "13.7.0",
|
||||
"webpack": "5.74.0",
|
||||
"webpack-merge": "5.8.0",
|
||||
"winston": "3.8.2",
|
||||
"winston": "3.8.1",
|
||||
"xml": "1.0.1",
|
||||
"xregexp": "5.1.1",
|
||||
"yargs": "17.5.1",
|
||||
@@ -146,10 +149,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@apidevtools/swagger-parser": "10.0.3",
|
||||
"@commitlint/cli": "17.1.2",
|
||||
"@commitlint/config-angular": "17.1.0",
|
||||
"@commitlint/cli": "17.0.3",
|
||||
"@commitlint/config-angular": "17.0.3",
|
||||
"coveralls": "3.1.1",
|
||||
"eslint": "8.23.1",
|
||||
"eslint": "8.22.0",
|
||||
"eslint-config-nodebb": "0.1.1",
|
||||
"eslint-plugin-import": "2.26.0",
|
||||
"grunt": "1.5.3",
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
"create.password": "סיסמה",
|
||||
"create.password-confirm": "אשר סיסמה",
|
||||
|
||||
"temp-ban.length": "זמן הרחקה",
|
||||
"temp-ban.length": "Length",
|
||||
"temp-ban.reason": "סיבה <span class=\"text-muted\">(אופציונאלי)</span>",
|
||||
"temp-ban.hours": "שעות",
|
||||
"temp-ban.days": "ימים",
|
||||
|
||||
@@ -26,10 +26,10 @@
|
||||
"hsts.preload": "Allow preloading of HSTS header",
|
||||
"hsts.help": "If enabled, an HSTS header will be set for this site. You can elect to include subdomains and preloading flags in your header. If in doubt, you can leave these unchecked. <a href=\"%1\">More information <i class=\"fa fa-external-link\"></i></a>",
|
||||
"traffic-management": "ניהול תעבורה",
|
||||
"traffic.help": "NodeBB משתמש במודול שדוחה אוטומטית בקשות במצבים עם תעבורה גבוהה. אתה יכול לכוונן את ההגדרות האלה כאן, למרות שברירות המחדל הן נקודת התחלה טובה.",
|
||||
"traffic.enable": "הפעל ניהול תעבורה",
|
||||
"traffic.help": "NodeBB uses a module that automatically denies requests in high-traffic situations. You can tune these settings here, although the defaults are a good starting point.",
|
||||
"traffic.enable": "Enable Traffic Management",
|
||||
"traffic.event-lag": "Event Loop Lag Threshold (in milliseconds)",
|
||||
"traffic.event-lag-help": "הורדת ערך זה מקטינה את זמני ההמתנה לטעינת הדפים, אך גם תציג את ההודעה \"עומס מופרז\" ליותר משתמשים. (אתחול נדרש)",
|
||||
"traffic.event-lag-help": "Lowering this value decreases wait times for page loads, but will also show the \"excessive load\" message to more users. (Restart required)",
|
||||
"traffic.lag-check-interval": "מרווח זמן בין בדיקות (במילישניות)",
|
||||
"traffic.lag-check-interval-help": "Lowering this value causes NodeBB to become more sensitive to spikes in load, but may also cause the check to become too sensitive. (Restart required)",
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"notifications.remove-images": "הסר תמונות מהודעות דוא\"ל",
|
||||
"require-email-address": "דרוש ממשתמשים חדשים כתובת אימייל",
|
||||
"require-email-address-warning": "By default, users can opt-out of entering an email address by leaving the field blank. Enabling this option means they have to enter an email address in order to proceed with registration. <strong>It does not ensure user will enter a real email address, nor even an address they own.</strong>",
|
||||
"send-validation-email": "שלח דוא\"ל אימות כאשר נוסף או משתנה דוא\"ל",
|
||||
"send-validation-email": "Send validation emails when an email is added or changed",
|
||||
"include-unverified-emails": "שלח דוא\"ל גם למשתמשים שלא אימתו את הכתובת שלהם",
|
||||
"include-unverified-warning": "By default, users with emails associated with their account have already been verified, but there are situations where this is not the case (e.g. SSO logins, grandfathered users, etc). <strong>Enable this setting at your own risk</strong> – sending emails to unverified addresses may be a violation of regional anti-spam laws.",
|
||||
"prompt": "בקש מהמשתמשים להגדיר/לאמת את כתובת הדוא\"ל שלהם",
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
"signature.disable": "השבת חתימות",
|
||||
"signature.no-links": "השבת קישורים בחתימות",
|
||||
"signature.no-images": "השבת תמונות בחתימות",
|
||||
"signature.hide-duplicates": "הצג חתימות פעם אחת בלבד בכל נושא",
|
||||
"signature.hide-duplicates": "Hide duplicate signatures in topics",
|
||||
"signature.max-length": "אורך חתימה מרבי",
|
||||
"composer": "הגדרות יצירת פוסט",
|
||||
"composer-help": "ההגדרות הבאות חלות על הפונקציונליות ו/או המראה של יוצר הפוסט המוצג\n\t\t\t\tלמשתמשים בעת יצירת נושאים חדשים, או מענה לנושאים קיימים.",
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
"flags.limit-per-target-help": "כשפוסט או משתמש מסומן כמה פעמים, כל דיווח נוסף נחשב ל "דיווח" ונוסף לדיווח הראשון. הגדר את האופציה הזאת לכל מספר שהוא לא 0 כדי להגביל את כמות הדיווחים שפוסט או משתמש יכול לקבל.",
|
||||
"flags.auto-flag-on-downvote-threshold": "מספר הצבעות למטה כדי ליצור דיווח אטומטי (הגדר ל-0 כדי להשבית; ברירת מחדל: 0)",
|
||||
"flags.auto-resolve-on-ban": "פתור אוטומטי כל כרטיסי משתמש כאשר הוא מוחרם",
|
||||
"flags.action-on-resolve": "בצע את הפעולות הבאות כאשר דיווח נפתר",
|
||||
"flags.action-on-reject": "בצע את הפעולות הבאות כאשר דיווח נדחה",
|
||||
"flags.action-on-resolve": "Do the following when a flag is resolved",
|
||||
"flags.action-on-reject": "Do the following when a flag is rejected",
|
||||
"flags.action.nothing": "Do nothing",
|
||||
"flags.action.rescind": "Rescind the notification send to moderators/administrators"
|
||||
}
|
||||
@@ -29,7 +29,7 @@
|
||||
"session-time-days": "ימים",
|
||||
"session-time-seconds": "שניות",
|
||||
"session-time-help": "ערכים אלו משמשים כדי להגדיר כמה זמן משתמשים יישארו מחוברים כאשר הם סימנו "זכור אותי" בהתחברות. שים לב שייעשה שימוש רק באחד מהערכים האלו. אם אין ערך <i>שניות</i> נשתמש בערך <i>ימים</i>. אם אין ערך <i>ימים</i> הערך יחזור לברירת מחדל <i>14 יום</i>.",
|
||||
"online-cutoff": "אחרי כמה דקות דקות המשתמש ייחשב ללא פעיל",
|
||||
"online-cutoff": "דקות אחרי שהמשתמש נחשב לא פעיל",
|
||||
"online-cutoff-help": "אם משתמש אינו מבצע פעולות במשך זמן זה, הוא נחשב כלא פעיל ואינו מקבל עדכונים בזמן אמת.",
|
||||
"registration": "רישום משתמש",
|
||||
"registration-type": "סוג הרשמה",
|
||||
@@ -40,8 +40,8 @@
|
||||
"registration-type.invite-only": "הזמנה בלבד",
|
||||
"registration-type.admin-invite-only": "הזמנת מנהל בלבד",
|
||||
"registration-type.disabled": "בטל הרשמה",
|
||||
"registration-type.help": "רגיל - משתמשים יכולים להירשם על ידי שימוש בדף ההרשמה (/register).<br/>\nהזמנה בלבד - משתמשים אחרים יכולים להזמין משתמשים מדף <a href=\"%1/users\" target=\"_blank\">המשתמשים.<br/>\nהזמנת מנהל בלבד - רק מנהלים יכולים להזמין משתמשים אחרים מדף <a href=\"%1/users\" target=\"_blank\">המשתמשים</a> ודף ניהול משתמשים</a>.<br/>\nבטל הרשמה - לא ניתן להירשם.<br/>ד",
|
||||
"registration-approval-type.help": "רגיל - משתמשים נרשמים באופן מיידי.<br/>\nאישור מנהל - משתמשים אשר נרשמו מוכנסים לתוך <a href=\"%1/admin/manage/registration\">רשימת אישור</a> למנהלים.<br/>\nאישור מנהל לכתובות IP - רגיל למשתמשים חדשים, אישור מנהל לכתובות IP אשר כבר מקושר אליהם חשבון.<br/>",
|
||||
"registration-type.help": "רגיל - משתמשים יכולים להירשם על ידי שימוש בדף /register.<br/>\nהזמנה בלבד - משתמשים אחרים יכולים להזמין משתמשים מדף <a href=\"%1/users\" target=\"_blank\">המשתמש.<br/>\nהזמנת מנהל בלבד - רק מנהלים יכולים להזמין משתמשים אחרים מדף <a href=\"%1/users\" target=\"_blank\">המשתמש</a> ודף <a href=\"%1/admin/manage/users\">ההנהלת משתמשים</a>.<br/>\nבטל הרשמה - לא ניתן להירשם.<br/>ד",
|
||||
"registration-approval-type.help": "רגיל - משתמשים נרשמים באופן מיידי.<br/>\nאישור מנהל - משתמשים אשר נרשמו מוכנים לתוך <a href=\"%1/admin/manage/registration\">רשימת אישור</a> למנהלים.<br/>\nאישור מנהל לכתובות IP - רגיל למשתמשים חדשים, אישור מנהל לכתובות IP אשר כבר מקושר אליהם חשבון.<br/>",
|
||||
"registration-queue-auto-approve-time": "זמן אישור אוטומטי",
|
||||
"registration-queue-auto-approve-time-help": "שעות לפני שהמשתמש מאושר באופן אוטומטי. רשום 0 על-מנת להשבית.",
|
||||
"registration-queue-show-average-time": "הצג למשתמשים זמן ממוצע שנדרש על-מנת לאשר משתמש חדש",
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"close": "סגור",
|
||||
"pagination": "הגדרות עמוד",
|
||||
"pagination.out_of": "%1 מתוך %2",
|
||||
"pagination.enter_index": "עבור למיקום פוסט",
|
||||
"pagination.enter_index": "Go to post index",
|
||||
"header.admin": "ניהול",
|
||||
"header.categories": "קטגוריות",
|
||||
"header.recent": "פוסטים אחרונים",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"chat.placeholder": "כתבו תוכן הודעת הצ'אט כאן, ניתן לגרור ולשחרר כאן תמונות, הקישו אנטר לשליחה.",
|
||||
"chat.scroll-up-alert": "הנכם צופים כעת בהודעות ישנות. לחצו כאן למעבר להודעה האחרונה.",
|
||||
"chat.send": "שליחה",
|
||||
"chat.no_active": "אין לכם צ'אטים פעילים.",
|
||||
"chat.no_active": "אין לכם צ'אטים פעילים",
|
||||
"chat.user_typing": "%1 מקליד...",
|
||||
"chat.user_has_messaged_you": "ל%1 יש הודעה עבורכם.",
|
||||
"chat.see_all": "צפו בכל הצ'אטים",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"register": "הרשמה",
|
||||
"register": "הרשם",
|
||||
"cancel_registration": "בטל רישום",
|
||||
"help.email": "כברירת מחדל, כתובת האימייל שלך לא גלויה למשתמשים אחרים",
|
||||
"help.username_restrictions": "שם משתמש ייחודי בין %1 ל %2 תווים. משתמשים אחרים יכולים לציין את שמך באמצעות @<span id='yourUsername'>שם המשתמש שלך</span>.",
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
"bookmark": "הוספה למועדפים",
|
||||
"bookmarks": "מועדפים",
|
||||
"bookmarks.has_no_bookmarks": "לא צירפתם פוסט למועדפים עדיין",
|
||||
"copy-permalink": "העתקת קישור פוסט",
|
||||
"copy-permalink": "העתקת קישור ישיר",
|
||||
"loading_more_posts": "טוען פוסטים נוספים",
|
||||
"move_topic": "העברת נושא",
|
||||
"move_topics": "העברת נושאים",
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
"change_password_success": "הסיסמה שלך עודכנה!",
|
||||
"confirm_password": "אימות סיסמה",
|
||||
"password": "סיסמה",
|
||||
"username_taken_workaround": "שם המשתמש שבחרת כבר תפוס, ולכן שינינו אותו מעט. שם המשתמש שלך כעת הוא: <strong>%1</strong>",
|
||||
"username_taken_workaround": "שם המשתמש שבחרת כבר תפוס, ולכן שינינו אותו מעט. שם המשתמש שלך כעת הוא <strong>%1</strong>",
|
||||
"password_same_as_username": "הסיסמה שלך זהה לשם המשתמש, בחר סיסמה שונה.",
|
||||
"password_same_as_email": "הסיסמה שלך זהה לכתובת המייל שלך, בחר סיסמה שונה.",
|
||||
"weak_password": "סיסמה חלשה.",
|
||||
@@ -84,7 +84,7 @@
|
||||
"upload_a_picture": "העלה תמונה",
|
||||
"remove_uploaded_picture": "מחק את התמונה שהועלתה",
|
||||
"upload_cover_picture": "העלה תמונת נושא",
|
||||
"remove_cover_picture_confirm": "האם אתה בטוח שאתה רוצה למחוק את תמונת נושא?",
|
||||
"remove_cover_picture_confirm": "האם אתה בטוח שאתה רוצה למחוק תמונת נושא?",
|
||||
"crop_picture": "חתוך תמונה",
|
||||
"upload_cropped_picture": "חתוך והעלה",
|
||||
"avatar-background-colour": "צבע רקע של תמונת נושא",
|
||||
@@ -92,27 +92,27 @@
|
||||
"show_email": "הצג את כתובת האימייל שלי",
|
||||
"show_fullname": "הצג את שמי המלא",
|
||||
"restrict_chats": "אשר הודעות צ'אט ממשתמשים שאני עוקב אחריהם בלבד",
|
||||
"digest_label": "הרשמה לקבלת תקציר",
|
||||
"digest_description": "הרשמה לקבלת עדכונים בדואר אלקטרוני מפורום זה (הודעות ונושאים חדשים) בהתאם ללוח זמנים מוגדר מראש",
|
||||
"digest_label": "הרשם לקבלת תקציר",
|
||||
"digest_description": "הירשם לקבלת עדכונים בדואר אלקטרוני מפורום זה (הודעות ונושאים חדשים) בהתאם ללוח זמנים מוגדר מראש",
|
||||
"digest_off": "כבוי",
|
||||
"digest_daily": "יומי",
|
||||
"digest_weekly": "שבועי",
|
||||
"digest_biweekly": "דו שבועי",
|
||||
"digest_monthly": "חודשי",
|
||||
"has_no_follower": "למשתמש זה אין עוקבים :(",
|
||||
"follows_no_one": "משתמש זה אינו עוקב אחרי אחרים",
|
||||
"has_no_posts": "משתמש זה טרם יצר פוסטים כלשהם.",
|
||||
"has_no_best_posts": "למשתמש זה אין עדיין פוסטים עם הצבעה בעד.",
|
||||
"follows_no_one": "משתמש זה אינו עוקב אחרי אחרים :(",
|
||||
"has_no_posts": "המשתמש טרם יצר פוסטים כלשהם.",
|
||||
"has_no_best_posts": "למשתמש זה אין עדיין פוסטים נבחרים.",
|
||||
"has_no_topics": "המשתמש טרם יצר נושאים כלשהם.",
|
||||
"has_no_watched_topics": "המשתמש טרם צפה בנושאים כלשהם.",
|
||||
"has_no_ignored_topics": "המשתמש הזה טרם התעלם מנושאים.",
|
||||
"has_no_upvoted_posts": "המשתמש טרם הצביע בעד פוסטים כלשהם.",
|
||||
"has_no_downvoted_posts": "המשתמש טרם הצביע נגד פוסטים כלשהם.",
|
||||
"has_no_controversial_posts": "למשתמש זה אין עדיין פוסטים עם הצבעה למטה.",
|
||||
"has_no_blocks": "לא חסמתם אף משתמש.",
|
||||
"has_no_blocks": "לא חסמת אף משתמש.",
|
||||
"email_hidden": "כתובת אימייל מוסתרת",
|
||||
"hidden": "מוסתר",
|
||||
"paginate_description": "הצגת נושאים ופוסטים בעמודים במקום כרשימת גלילה אין-סופית",
|
||||
"paginate_description": "הצג נושאים ופוסטים בעמודים במקום כרשימת גלילה אין-סופית",
|
||||
"topics_per_page": "כמות נושאים בעמוד",
|
||||
"posts_per_page": "כמות פוסטים בעמוד",
|
||||
"max_items_per_page": "מקסימום %1",
|
||||
@@ -182,10 +182,10 @@
|
||||
"consent.right_to_rectification": "זכותך לתקן טעויות",
|
||||
"consent.right_to_rectification_description": "יש לך זכות לשנות או לעדכן נתונים שנאספו. ניתן לעדכן את הפרופיל שלך וכן לערוך כל תוכן שפורסם. במידת הצורך, אנא צור קשר עם צוות ניהול האתר.",
|
||||
"consent.right_to_erasure": "זכותך למחוק את חשבונך",
|
||||
"consent.right_to_erasure_description": "בכל עת תוכל לבטל את הסכמתך לאיסוף נתונים ו/או עיבודם על ידי מחיקת חשבונך. מחיקת הפרופיל שלך לא תגרום למחיקת התוכנים שפרסמת. על מנת למחוק את חשבונך <strong> ואת </strong> התוכן המקושר לו צור קשר עם צוות הניהול של האתר.",
|
||||
"consent.right_to_erasure_description": "בכל עת תוכל לבטל את הסכמתך לאיסוף נתונים ו / או עיבודם על ידי מחיקת חשבונך. מחיקת הפרופיל שלך לא תגרום למחיקת התוכנים שפרסמת. על מנת למחוק את חשבונך <strong> ואת </strong> התוכן המקושר לו צור קשר עם צוות הניהול של האתר.",
|
||||
"consent.right_to_data_portability": "זכותך לניוד הנתונים",
|
||||
"consent.right_to_data_portability_description": "באפרותך לבקש ייצוא של כל הנתונים שנאספו מחשבונך אודותיך. תוכל לעשות זאת על ידי לחיצה על הלחצן המתאים מטה.",
|
||||
"consent.export_profile": "יצוא פרופיל (json.)",
|
||||
"consent.export_profile": "יצוא פרופיל (.json)",
|
||||
"consent.export-profile-success": "ייצוא הפרופיל מתבצע כעת. תקבל התראה כאשר הייצוא יסתיים.",
|
||||
"consent.export_uploads": "יצוא תוכן שהועלה (ZIP.)",
|
||||
"consent.export-uploads-success": "ייצוא ההעלאות מתבצע כעת. תקבל התראה כאשר הייצוא יסתיים.",
|
||||
|
||||
@@ -205,8 +205,8 @@
|
||||
"no-connection": "Изгледа да постоји проблем са вашом интернет везом",
|
||||
"socket-reconnect-failed": "Тренутно није могуће приступити серверу. Кликните овде да бисте покушали поново или покушајте поново касније",
|
||||
"plugin-not-whitelisted": "Инсталација додатне компоненте &ndash није могућа; преко ACP-а могу се инсталирати само додатне компоненте које је на белој листи ставио NodeBB Package Manager",
|
||||
"plugins-set-in-configuration": "Није вам дозвољено да мењате стање додатне компоненте онако како је дефинисано у време извршавања (config.json, променљиве окружења или аргументи терминала), уместо тога измените конфигурацију.",
|
||||
"theme-not-set-in-configuration": "Приликом дефинисања активних додатних компоненти у конфигурацији, промена тема захтева додавање нове теме на листу активних додатних компоненти пре ажурирања у ACP",
|
||||
"plugins-set-in-configuration": "You are not allowed to change plugin state as they are defined at runtime (config.json, environmental variables or terminal arguments), please modify the configuration instead.",
|
||||
"theme-not-set-in-configuration": "When defining active plugins in configuration, changing themes requires adding the new theme to the list of active plugins before updating it in the ACP",
|
||||
"topic-event-unrecognized": "Догађај из теме „%1“ није препознат",
|
||||
"cant-set-child-as-parent": "Није могуће поставити подређену категорију као надређену",
|
||||
"cant-set-self-as-parent": "Није могуће поставити себе као надређену категорију",
|
||||
|
||||
@@ -195,5 +195,5 @@
|
||||
"emailUpdate.optional": "<strong>Ово поље је опционо</strong>. Нисте обавезни да наведете своју адресу е-поште, али без ваљане е-поште нећете моћи да вратите свој налог или да се пријавите помоћу своје е-поште.",
|
||||
"emailUpdate.required": "<strong>Ово поље је обавезно</strong>.",
|
||||
"emailUpdate.change-instructions": "На унету адресу е-поште биће послата потврдна порука са јединственом везом. Приступ тој вези потврдиће ваше власништво над адресом е-поште и она ће постати активна на вашем налогу. У било ком тренутку можете да ажурирате своју е-пошту на страници налога.",
|
||||
"emailUpdate.password-challenge": "Унесите лозинку да бисте потврдили власништво над налогом."
|
||||
"emailUpdate.password-challenge": "Please enter your password in order to verify account ownership."
|
||||
}
|
||||
@@ -76,7 +76,7 @@
|
||||
"logout": "登出",
|
||||
"view-forum": "查看论坛",
|
||||
|
||||
"search.placeholder": "搜索设置",
|
||||
"search.placeholder": "Search settings",
|
||||
"search.no-results": "没有可用结果…",
|
||||
"search.search-forum": "搜索论坛为<strong></strong>",
|
||||
"search.keep-typing": "输入更多以查看结果...",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"pagination": "分页设置",
|
||||
"enable": "在主题和帖子使用分页替代无限滚动浏览。",
|
||||
"posts": "帖子分页",
|
||||
"posts": "Post Pagination",
|
||||
"topics": "话题分页",
|
||||
"posts-per-page": "每页帖子数",
|
||||
"max-posts-per-page": "每页最多帖子数",
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"close": "关闭",
|
||||
"pagination": "分页",
|
||||
"pagination.out_of": "%1 / %2",
|
||||
"pagination.enter_index": "跳转到帖子",
|
||||
"pagination.enter_index": "Go to post index",
|
||||
"header.admin": "管理",
|
||||
"header.categories": "版块",
|
||||
"header.recent": "最新",
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"chat.no_active": "暂无聊天",
|
||||
"chat.user_typing": "%1 正在输入……",
|
||||
"chat.user_has_messaged_you": "%1 向您发送了消息。",
|
||||
"chat.see_all": "全部对话",
|
||||
"chat.mark_all_read": "标记全部已读",
|
||||
"chat.see_all": "All chats",
|
||||
"chat.mark_all_read": "Mark all read",
|
||||
"chat.no-messages": "请选择接收人,以查看聊天消息历史",
|
||||
"chat.no-users-in-room": "此聊天室中没有用户",
|
||||
"chat.recent-chats": "最近聊天",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"title": "通知",
|
||||
"no_notifs": "您没有新的通知",
|
||||
"see_all": "全部通知",
|
||||
"mark_all_read": "标记全部已读",
|
||||
"see_all": "All notifications",
|
||||
"mark_all_read": "Mark all read",
|
||||
"back_to_home": "返回 %1",
|
||||
"outgoing_link": "站外链接",
|
||||
"outgoing_link_message": "您正在离开 %1",
|
||||
|
||||
@@ -172,10 +172,6 @@ paths:
|
||||
$ref: 'write/admin/analytics.yaml'
|
||||
/admin/analytics/{set}:
|
||||
$ref: 'write/admin/analytics/set.yaml'
|
||||
/admin/chats:
|
||||
$ref: 'write/admin/chats.yaml'
|
||||
/admin/chats/{roomId}:
|
||||
$ref: 'write/admin/chats/roomId.yaml'
|
||||
/files/:
|
||||
$ref: 'write/files.yaml'
|
||||
/files/folder:
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
get:
|
||||
tags:
|
||||
- admin
|
||||
summary: get chat rooms
|
||||
description: This operation returns all chat rooms managed by NodeBB. **For privacy reasons**, only chat room metadata is shown.
|
||||
parameters:
|
||||
- in: query
|
||||
name: perPage
|
||||
schema:
|
||||
type: number
|
||||
description: The number of chat rooms displayed per page
|
||||
example: 20
|
||||
- in: query
|
||||
name: page
|
||||
schema:
|
||||
type: number
|
||||
description: The page number
|
||||
example: 1
|
||||
responses:
|
||||
'200':
|
||||
description: Chat rooms retrieved
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
$ref: ../../components/schemas/Status.yaml#/Status
|
||||
response:
|
||||
type: object
|
||||
properties:
|
||||
rooms:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
owner:
|
||||
type: number
|
||||
roomId:
|
||||
type: number
|
||||
userCount:
|
||||
type: number
|
||||
roomName:
|
||||
type: string
|
||||
groupChat:
|
||||
type: boolean
|
||||
@@ -1,26 +0,0 @@
|
||||
delete:
|
||||
tags:
|
||||
- admin
|
||||
summary: delete chat room
|
||||
description: This operation deletes a chat room from the database
|
||||
parameters:
|
||||
- in: path
|
||||
name: roomId
|
||||
schema:
|
||||
type: number
|
||||
description: The roomId to be deleted
|
||||
example: 1
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
description: Chat room deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
$ref: ../../../components/schemas/Status.yaml#/Status
|
||||
response:
|
||||
type: object
|
||||
properties: {}
|
||||
@@ -212,11 +212,17 @@ define('admin/manage/categories', [
|
||||
const oldParentCid = parseInt(e.from.getAttribute('data-cid'), 10);
|
||||
const newParentCid = parseInt(e.to.getAttribute('data-cid'), 10);
|
||||
if (oldParentCid !== newParentCid) {
|
||||
document.querySelector(`.categories li[data-cid="${newParentCid}"] .toggle`).classList.toggle('hide', false);
|
||||
const toggle = document.querySelector(`.categories li[data-cid="${newParentCid}"] .toggle`);
|
||||
if (toggle) {
|
||||
toggle.classList.toggle('hide', false);
|
||||
}
|
||||
|
||||
const children = document.querySelectorAll(`.categories li[data-cid="${oldParentCid}"] ul[data-cid] li[data-cid]`);
|
||||
if (!children.length) {
|
||||
document.querySelector(`.categories li[data-cid="${oldParentCid}"] .toggle`).classList.toggle('hide', true);
|
||||
const toggle = document.querySelector(`.categories li[data-cid="${oldParentCid}"] .toggle`);
|
||||
if (toggle) {
|
||||
toggle.classList.toggle('hide', true);
|
||||
}
|
||||
}
|
||||
|
||||
e.item.dataset.parentCid = newParentCid;
|
||||
|
||||
@@ -44,7 +44,9 @@ ajaxify.widgets = { render: render };
|
||||
quiet = true;
|
||||
}
|
||||
|
||||
ajaxify.cleanup(url, ajaxify.data.template.name);
|
||||
app.leaveCurrentRoom();
|
||||
|
||||
$(window).off('scroll');
|
||||
|
||||
if ($('#content').hasClass('ajaxifying') && apiXHR) {
|
||||
apiXHR.abort();
|
||||
@@ -454,12 +456,6 @@ ajaxify.widgets = { render: render };
|
||||
});
|
||||
};
|
||||
|
||||
ajaxify.cleanup = (url, tpl_url) => {
|
||||
app.leaveCurrentRoom();
|
||||
$(window).off('scroll');
|
||||
hooks.fire('action:ajaxify.cleanup', { url, tpl_url });
|
||||
};
|
||||
|
||||
require(['translator', 'benchpress'], function (translator, Benchpress) {
|
||||
translator.translate('[[error:no-connection]]');
|
||||
translator.translate('[[error:socket-reconnect-failed]]');
|
||||
|
||||
@@ -26,7 +26,7 @@ define('forum/flags/detail', [
|
||||
return memo;
|
||||
}, {});
|
||||
|
||||
api.put(`/flags/${ajaxify.data.flagId}`, data).then((history) => {
|
||||
api.put(`/flags/${ajaxify.data.flagId}`, data).then(({ history }) => {
|
||||
alerts.success('[[flags:updated]]');
|
||||
Detail.reloadHistory(history);
|
||||
}).catch(alerts.error);
|
||||
|
||||
@@ -73,39 +73,17 @@ define('forum/topic', [
|
||||
};
|
||||
|
||||
function handleTopicSearch() {
|
||||
require(['mousetrap'], (mousetrap) => {
|
||||
if (config.topicSearchEnabled) {
|
||||
require(['search'], function (search) {
|
||||
mousetrap.bind(['command+f', 'ctrl+f'], function (e) {
|
||||
if (config.topicSearchEnabled) {
|
||||
require(['mousetrap', 'search'], function (mousetrap, search) {
|
||||
mousetrap.bind(['command+f', 'ctrl+f'], function (e) {
|
||||
if (ajaxify.data.template.topic) {
|
||||
e.preventDefault();
|
||||
$('#search-fields input').val('in:topic-' + ajaxify.data.tid + ' ');
|
||||
search.showAndFocusInput();
|
||||
});
|
||||
|
||||
hooks.onPage('action:ajaxify.cleanup', () => {
|
||||
mousetrap.unbind(['command+f', 'ctrl+f']);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
mousetrap.bind('j', () => {
|
||||
const index = navigator.getIndex();
|
||||
const count = navigator.getCount();
|
||||
if (index === count) {
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.scrollToIndex(index, true, 0);
|
||||
});
|
||||
|
||||
mousetrap.bind('k', () => {
|
||||
const index = navigator.getIndex();
|
||||
if (index === 1) {
|
||||
return;
|
||||
}
|
||||
navigator.scrollToIndex(index - 2, true, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Topic.toTop = function () {
|
||||
|
||||
@@ -181,7 +181,6 @@ module.exports = function (utils, Benchpress, relative_path) {
|
||||
}
|
||||
|
||||
function renderTopicEvents(index, sort) {
|
||||
console.warn('[renderTopicEvents] deprecated, use a partial at partials/topic/event.tpl');
|
||||
if (sort === 'most_votes') {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ define('iconSelect', ['benchpress', 'bootbox'], function (Benchpress, bootbox) {
|
||||
label: 'Select',
|
||||
className: 'btn-primary',
|
||||
callback: function () {
|
||||
const iconClass = $('.bootbox .selected').attr('class');
|
||||
const iconClass = $('.bootbox .selected').attr('class') || `fa fa-${$('.bootbox #fa-filter').val()}`;
|
||||
const categoryIconClass = $('<div></div>').addClass(iconClass).removeClass('fa').removeClass('selected')
|
||||
.attr('class');
|
||||
const searchElVal = picker.find('input').val();
|
||||
|
||||
@@ -101,11 +101,6 @@ define('messages', ['bootbox', 'translator', 'storage', 'alerts', 'hooks'], func
|
||||
params.delete('register');
|
||||
}
|
||||
|
||||
if (params.has('lang') && params.get('lang') === config.defaultLang) {
|
||||
console.info(`The "lang" parameter was passed in to set the language to "${params.get('lang')}", but that is already the forum default language.`);
|
||||
params.delete('lang');
|
||||
}
|
||||
|
||||
const qs = params.toString();
|
||||
ajaxify.updateHistory(ajaxify.currentPage + (qs ? `?${qs}` : '') + document.location.hash, true);
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ define('navigator', ['forum/pagination', 'components', 'hooks', 'alerts'], funct
|
||||
thumb = $('.scroller-thumb');
|
||||
thumbText = thumb.find('.thumb-text');
|
||||
|
||||
|
||||
$(window).off('scroll', navigator.delayedUpdate).on('scroll', navigator.delayedUpdate);
|
||||
|
||||
paginationBlockEl.find('.dropdown-menu').off('click').on('click', function (e) {
|
||||
@@ -330,8 +331,6 @@ define('navigator', ['forum/pagination', 'components', 'hooks', 'alerts'], funct
|
||||
return parts[1] + '/' + parts[2] + '/' + parts[3] + (index ? '/' + index : '');
|
||||
}
|
||||
|
||||
navigator.getCount = () => count;
|
||||
|
||||
navigator.setCount = function (value) {
|
||||
value = parseInt(value, 10);
|
||||
if (value === count) {
|
||||
@@ -441,14 +440,6 @@ define('navigator', ['forum/pagination', 'components', 'hooks', 'alerts'], funct
|
||||
toggle(!!count);
|
||||
};
|
||||
|
||||
navigator.getIndex = () => index;
|
||||
|
||||
navigator.setIndex = (newIndex) => {
|
||||
index = newIndex + 1;
|
||||
navigator.updateTextAndProgressBar();
|
||||
setThumbToIndex(index);
|
||||
};
|
||||
|
||||
navigator.updateTextAndProgressBar = function () {
|
||||
if (!utils.isNumber(index)) {
|
||||
return;
|
||||
@@ -553,24 +544,22 @@ define('navigator', ['forum/pagination', 'components', 'hooks', 'alerts'], funct
|
||||
|
||||
navigator.scrollToPostIndex = function (postIndex, highlight, duration) {
|
||||
const scrollTo = components.get('post', 'index', postIndex);
|
||||
navigator.scrollToElement(scrollTo, highlight, duration, postIndex);
|
||||
navigator.scrollToElement(scrollTo, highlight, duration);
|
||||
};
|
||||
|
||||
navigator.scrollToTopicIndex = function (topicIndex, highlight, duration) {
|
||||
const scrollTo = $('[component="category/topic"][data-index="' + topicIndex + '"]');
|
||||
navigator.scrollToElement(scrollTo, highlight, duration, topicIndex);
|
||||
navigator.scrollToElement(scrollTo, highlight, duration);
|
||||
};
|
||||
|
||||
navigator.scrollToElement = async (scrollTo, highlight, duration, newIndex = null) => {
|
||||
navigator.scrollToElement = function (scrollTo, highlight, duration) {
|
||||
if (!scrollTo.length) {
|
||||
navigator.scrollActive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
await hooks.fire('filter:navigator.scroll', { scrollTo, highlight, duration, newIndex });
|
||||
|
||||
const postHeight = scrollTo.outerHeight(true);
|
||||
const navbarHeight = components.get('navbar').outerHeight(true);
|
||||
const navbarHeight = components.get('navbar').outerHeight(true) || 0;
|
||||
const topicHeaderHeight = $('.topic-header').outerHeight(true) || 0;
|
||||
const viewportHeight = $(window).height();
|
||||
|
||||
@@ -584,11 +573,9 @@ define('navigator', ['forum/pagination', 'components', 'hooks', 'alerts'], funct
|
||||
function animateScroll() {
|
||||
function reenableScroll() {
|
||||
// Re-enable onScroll behaviour
|
||||
setTimeout(() => { // fixes race condition from jQuery — onAnimateComplete called too quickly
|
||||
$(window).on('scroll', navigator.delayedUpdate);
|
||||
|
||||
hooks.fire('action:navigator.scrolled', { scrollTo, highlight, duration, newIndex });
|
||||
}, 50);
|
||||
$(window).on('scroll', navigator.delayedUpdate);
|
||||
const scrollToRect = scrollTo.get(0).getBoundingClientRect();
|
||||
navigator.update(scrollToRect.top);
|
||||
}
|
||||
function onAnimateComplete() {
|
||||
if (done) {
|
||||
@@ -599,13 +586,8 @@ define('navigator', ['forum/pagination', 'components', 'hooks', 'alerts'], funct
|
||||
|
||||
navigator.scrollActive = false;
|
||||
highlightPost();
|
||||
|
||||
const scrollToRect = scrollTo.get(0).getBoundingClientRect();
|
||||
if (!newIndex) {
|
||||
navigator.update(scrollToRect.top);
|
||||
} else {
|
||||
navigator.setIndex(newIndex);
|
||||
}
|
||||
$('body').scrollTop($('body').scrollTop() - 1);
|
||||
$('html').scrollTop($('html').scrollTop() - 1);
|
||||
}
|
||||
|
||||
let scrollTop = 0;
|
||||
|
||||
@@ -215,14 +215,14 @@ async function isOwner(caller, groupName) {
|
||||
if (typeof groupName !== 'string') {
|
||||
throw new Error('[[error:invalid-group-name]]');
|
||||
}
|
||||
const [isAdmin, isGlobalModerator, isOwner, group] = await Promise.all([
|
||||
user.isAdministrator(caller.uid),
|
||||
const [hasAdminPrivilege, isGlobalModerator, isOwner, group] = await Promise.all([
|
||||
privileges.admin.can('admin:groups', caller.uid),
|
||||
user.isGlobalModerator(caller.uid),
|
||||
groups.ownership.isOwner(caller.uid, groupName),
|
||||
groups.getGroupData(groupName),
|
||||
]);
|
||||
|
||||
const check = isOwner || isAdmin || (isGlobalModerator && !group.system);
|
||||
const check = isOwner || hasAdminPrivilege || (isGlobalModerator && !group.system);
|
||||
if (!check) {
|
||||
throw new Error('[[error:no-privileges]]');
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const winston = require('winston');
|
||||
const _ = require('lodash');
|
||||
|
||||
const db = require('../database');
|
||||
@@ -12,14 +11,11 @@ const plugins = require('../plugins');
|
||||
const batch = require('../batch');
|
||||
|
||||
module.exports = function (Categories) {
|
||||
Categories.getRecentReplies = async function (cid, uid, start, stop) {
|
||||
// backwards compatibility, treat start as count
|
||||
if (stop === undefined && start > 0) {
|
||||
winston.warn('[Categories.getRecentReplies] 3 params deprecated please use Categories.getRecentReplies(cid, uid, start, stop)');
|
||||
stop = start - 1;
|
||||
start = 0;
|
||||
Categories.getRecentReplies = async function (cid, uid, count) {
|
||||
if (!parseInt(count, 10)) {
|
||||
return [];
|
||||
}
|
||||
let pids = await db.getSortedSetRevRange(`cid:${cid}:pids`, start, stop);
|
||||
let pids = await db.getSortedSetRevRange(`cid:${cid}:pids`, 0, count - 1);
|
||||
pids = await privileges.posts.filter('topics:read', pids, uid);
|
||||
return await posts.getPostSummaryByPids(pids, uid, { stripTags: true });
|
||||
};
|
||||
|
||||
@@ -108,7 +108,7 @@ module.exports = function (Categories) {
|
||||
if (currentIndex === -1) {
|
||||
throw new Error('[[error:no-category]]');
|
||||
}
|
||||
// moves cid to index order-1 in the array
|
||||
// moves cid to index order - 1 in the array
|
||||
if (childrenCids.length > 1) {
|
||||
childrenCids.splice(Math.max(0, order - 1), 0, childrenCids.splice(currentIndex, 1)[0]);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ try {
|
||||
checkVersion('commander');
|
||||
checkVersion('chalk');
|
||||
checkVersion('lodash');
|
||||
checkVersion('lru-cache');
|
||||
} catch (e) {
|
||||
if (['ENOENT', 'DEP_WRONG_VERSION', 'MODULE_NOT_FOUND'].includes(e.code)) {
|
||||
console.warn('Dependencies outdated or not yet installed.');
|
||||
@@ -266,10 +267,6 @@ program
|
||||
].join('\n')}`);
|
||||
})
|
||||
.action((scripts, options) => {
|
||||
if (program.opts().dev) {
|
||||
process.env.NODE_ENV = 'development';
|
||||
global.env = 'development';
|
||||
}
|
||||
require('./upgrade').upgrade(scripts.length ? scripts : true, options);
|
||||
});
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ pkgInstall.installAll = () => {
|
||||
command = `cnpm install ${prod ? ' --production' : ''}`;
|
||||
break;
|
||||
default:
|
||||
command += prod ? ' --omit=dev' : '';
|
||||
command += prod ? ' --production' : '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const db = require('../../database');
|
||||
const meta = require('../../meta');
|
||||
const privileges = require('../../privileges');
|
||||
const analytics = require('../../analytics');
|
||||
const messaging = require('../../messaging');
|
||||
const events = require('../../events');
|
||||
|
||||
const helpers = require('../helpers');
|
||||
|
||||
@@ -43,28 +40,3 @@ Admin.getAnalyticsData = async (req, res) => {
|
||||
const getStats = req.query.units === 'days' ? analytics.getDailyStatsForSet : analytics.getHourlyStatsForSet;
|
||||
helpers.formatApiResponse(200, res, await getStats(`analytics:${req.params.set}`, parseInt(req.query.until, 10) || Date.now(), req.query.amount));
|
||||
};
|
||||
|
||||
Admin.chats = {};
|
||||
|
||||
Admin.chats.getRooms = async (req, res) => {
|
||||
const page = (isFinite(req.query.page) && parseInt(req.query.page, 10)) || 1;
|
||||
const perPage = (isFinite(req.query.perPage) && parseInt(req.query.perPage, 10)) || 20;
|
||||
const start = Math.max(0, page - 1) * perPage;
|
||||
const stop = start + perPage;
|
||||
const roomIds = await db.getSortedSetRevRange('chat:rooms', start, stop);
|
||||
|
||||
helpers.formatApiResponse(200, res, {
|
||||
rooms: await messaging.getRoomsData(roomIds),
|
||||
});
|
||||
};
|
||||
|
||||
Admin.chats.deleteRoom = async (req, res) => {
|
||||
await messaging.deleteRooms([req.params.roomId]);
|
||||
|
||||
events.log({
|
||||
type: 'chat-room-deleted',
|
||||
uid: req.uid,
|
||||
ip: req.ip,
|
||||
});
|
||||
helpers.formatApiResponse(200, res);
|
||||
};
|
||||
|
||||
@@ -75,7 +75,6 @@ events.types = [
|
||||
'export:uploads',
|
||||
'account-locked',
|
||||
'getUsersCSV',
|
||||
'chat-room-deleted',
|
||||
// To add new types from plugins, just Array.push() to this array
|
||||
];
|
||||
|
||||
|
||||
@@ -342,6 +342,14 @@ async function createAdmin() {
|
||||
try {
|
||||
User.isPasswordValid(results.password);
|
||||
} catch (err) {
|
||||
const [namespace, key] = err.message.slice(2, -2).split(':', 2);
|
||||
if (namespace && key && err.message.startsWith('[[') && err.message.endsWith(']]')) {
|
||||
const lang = require(path.join(__dirname, `../public/language/en-GB/${namespace}`));
|
||||
if (lang && lang[key]) {
|
||||
err.message = lang[key];
|
||||
}
|
||||
}
|
||||
|
||||
winston.warn(`Password error, please try again. ${err.message}`);
|
||||
return await retryPassword(results);
|
||||
}
|
||||
|
||||
@@ -21,12 +21,6 @@ module.exports = function (Messaging) {
|
||||
|
||||
Messaging.getRoomsData = async (roomIds) => {
|
||||
const roomData = await db.getObjects(roomIds.map(roomId => `chat:room:${roomId}`));
|
||||
|
||||
const userCounts = await db.sortedSetsCard(roomIds.map(roomId => `chat:room:${roomId}:uids`));
|
||||
userCounts.forEach((count, idx) => {
|
||||
roomData[idx].userCount = count;
|
||||
});
|
||||
|
||||
modifyRoomData(roomData);
|
||||
return roomData;
|
||||
};
|
||||
@@ -53,7 +47,6 @@ module.exports = function (Messaging) {
|
||||
|
||||
await Promise.all([
|
||||
db.setObject(`chat:room:${roomId}`, room),
|
||||
db.sortedSetAdd('chat:rooms', now, roomId),
|
||||
db.sortedSetAdd(`chat:room:${roomId}:uids`, now, uid),
|
||||
]);
|
||||
await Promise.all([
|
||||
@@ -66,24 +59,6 @@ module.exports = function (Messaging) {
|
||||
return roomId;
|
||||
};
|
||||
|
||||
Messaging.deleteRooms = async (roomIds) => {
|
||||
// warning: uid:<uid>:chat:room:<roomId>:mids is left behind, along with each message:<mid> obj
|
||||
// deleting them from db requires iterating through all messages; not performant
|
||||
if (!roomIds) {
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
}
|
||||
|
||||
if (!Array.isArray(roomIds)) {
|
||||
roomIds = [roomIds];
|
||||
}
|
||||
|
||||
await Promise.all(roomIds.map(async (roomId) => {
|
||||
const uids = await db.getSortedSetMembers(`chat:room:${roomId}:uids`);
|
||||
await Messaging.leaveRoom(uids, roomId);
|
||||
await db.delete(`chat:room:${roomId}`);
|
||||
}));
|
||||
};
|
||||
|
||||
Messaging.isUserInRoom = async (uid, roomId) => {
|
||||
const inRoom = await db.isSortedSetMember(`chat:room:${roomId}:uids`, uid);
|
||||
const data = await plugins.hooks.fire('filter:messaging.isUserInRoom', { uid: uid, roomId: roomId, inRoom: inRoom });
|
||||
|
||||
@@ -77,20 +77,36 @@ async function beforeBuild(targets) {
|
||||
|
||||
const allTargets = Object.keys(targetHandlers).filter(name => typeof targetHandlers[name] === 'function');
|
||||
|
||||
async function buildTargets(targets, parallel) {
|
||||
async function buildTargets(targets, parallel, options) {
|
||||
const length = Math.max(...targets.map(name => name.length));
|
||||
|
||||
if (parallel) {
|
||||
const jsTargets = targets.filter(target => targetHandlers.javascript.includes(target));
|
||||
const otherTargets = targets.filter(target => !targetHandlers.javascript.includes(target));
|
||||
async function buildJSTargets() {
|
||||
await Promise.all(
|
||||
targets.map(
|
||||
jsTargets.map(
|
||||
target => step(target, parallel, `${_.padStart(target, length)} `)
|
||||
)
|
||||
);
|
||||
// run webpack after jstargets are done, no need to wait for css/templates etc.
|
||||
if (options.webpack || options.watch) {
|
||||
await exports.webpack(options);
|
||||
}
|
||||
}
|
||||
if (parallel) {
|
||||
await Promise.all([
|
||||
buildJSTargets(),
|
||||
...otherTargets.map(
|
||||
target => step(target, parallel, `${_.padStart(target, length)} `)
|
||||
),
|
||||
]);
|
||||
} else {
|
||||
for (const target of targets) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await step(target, parallel, `${_.padStart(target, length)} `);
|
||||
}
|
||||
if (options.webpack || options.watch) {
|
||||
await exports.webpack(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,11 +191,7 @@ exports.build = async function (targets, options) {
|
||||
}
|
||||
|
||||
const startTime = Date.now();
|
||||
await buildTargets(targets, !series);
|
||||
|
||||
if (options.webpack) {
|
||||
await exports.webpack(options);
|
||||
}
|
||||
await buildTargets(targets, !series, options);
|
||||
|
||||
const totalTime = (Date.now() - startTime) / 1000;
|
||||
await cacheBuster.write();
|
||||
@@ -201,7 +213,7 @@ exports.webpack = async function (options) {
|
||||
const util = require('util');
|
||||
const plugins = require('../plugins/data');
|
||||
|
||||
const activePlugins = await plugins.getActive();
|
||||
const activePlugins = (await plugins.getActive()).map(p => p.id);
|
||||
if (!activePlugins.includes('nodebb-plugin-composer-default')) {
|
||||
activePlugins.push('nodebb-plugin-composer-default');
|
||||
}
|
||||
|
||||
@@ -27,14 +27,6 @@ JS.scripts = {
|
||||
modules: { },
|
||||
};
|
||||
|
||||
async function linkIfLinux(srcPath, destPath) {
|
||||
if (process.platform === 'win32') {
|
||||
await fs.promises.copyFile(srcPath, destPath);
|
||||
} else {
|
||||
await file.link(srcPath, destPath, true);
|
||||
}
|
||||
}
|
||||
|
||||
const basePath = path.resolve(__dirname, '../..');
|
||||
|
||||
async function linkModules() {
|
||||
@@ -55,7 +47,7 @@ async function linkModules() {
|
||||
if (stats.isDirectory()) {
|
||||
await file.linkDirs(srcPath, destPath, true);
|
||||
} else {
|
||||
await linkIfLinux(srcPath, destPath);
|
||||
await fs.promises.copyFile(srcPath, destPath);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -95,7 +95,6 @@ Settings.set = async function (hash, values, quiet) {
|
||||
plugins.hooks.fire('action:settings.set', {
|
||||
plugin: hash,
|
||||
settings: { ...values, ...sortedListData }, // Add back sorted list data to values hash
|
||||
quiet,
|
||||
});
|
||||
|
||||
pubsub.publish(`action:settings.set.${hash}`, values);
|
||||
|
||||
@@ -307,11 +307,7 @@ async function generateForRecentPosts(req, res, next) {
|
||||
if (meta.config['feeds:disableRSS']) {
|
||||
return next();
|
||||
}
|
||||
const page = parseInt(req.query.page, 10) || 1;
|
||||
const postsPerPage = 20;
|
||||
const start = Math.max(0, (page - 1) * postsPerPage);
|
||||
const stop = start + postsPerPage - 1;
|
||||
const postData = await posts.getRecentPosts(req.uid, start, stop, 'month');
|
||||
const postData = await posts.getRecentPosts(req.uid, 0, 19, 'month');
|
||||
const feed = generateForPostsFeed({
|
||||
title: 'Recent Posts',
|
||||
description: 'A list of recent posts',
|
||||
@@ -327,14 +323,11 @@ async function generateForCategoryRecentPosts(req, res) {
|
||||
return controllers404.handle404(req, res);
|
||||
}
|
||||
const cid = req.params.category_id;
|
||||
const page = parseInt(req.query.page, 10) || 1;
|
||||
const topicsPerPage = 20;
|
||||
const start = Math.max(0, (page - 1) * topicsPerPage);
|
||||
const stop = start + topicsPerPage - 1;
|
||||
|
||||
const [userPrivileges, category, postData] = await Promise.all([
|
||||
privileges.categories.get(cid, req.uid),
|
||||
categories.getCategoryData(cid),
|
||||
categories.getRecentReplies(cid, req.uid || req.query.uid || 0, start, stop),
|
||||
categories.getRecentReplies(cid, req.uid || req.query.uid || 0, 20),
|
||||
]);
|
||||
|
||||
if (!category) {
|
||||
|
||||
@@ -15,8 +15,5 @@ module.exports = function () {
|
||||
setupApiRoute(router, 'get', '/analytics', [...middlewares], controllers.write.admin.getAnalyticsKeys);
|
||||
setupApiRoute(router, 'get', '/analytics/:set', [...middlewares], controllers.write.admin.getAnalyticsData);
|
||||
|
||||
setupApiRoute(router, 'get', '/chats', [...middlewares], controllers.write.admin.chats.getRooms);
|
||||
setupApiRoute(router, 'delete', '/chats/:roomId', [...middlewares, middleware.assert.room], controllers.write.admin.chats.deleteRoom);
|
||||
|
||||
return router;
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ const SocketCategories = module.exports;
|
||||
require('./categories/search')(SocketCategories);
|
||||
|
||||
SocketCategories.getRecentReplies = async function (socket, cid) {
|
||||
return await categories.getRecentReplies(cid, socket.uid, 0, 4);
|
||||
return await categories.getRecentReplies(cid, socket.uid, 4);
|
||||
};
|
||||
|
||||
SocketCategories.get = async function (socket) {
|
||||
|
||||
@@ -42,13 +42,15 @@ async function isOwner(socket, data) {
|
||||
throw new Error('[[error:invalid-group-name]]');
|
||||
}
|
||||
const results = await utils.promiseParallel({
|
||||
isAdmin: await user.isAdministrator(socket.uid),
|
||||
isGlobalModerator: await user.isGlobalModerator(socket.uid),
|
||||
isOwner: await groups.ownership.isOwner(socket.uid, data.groupName),
|
||||
group: await groups.getGroupData(data.groupName),
|
||||
hasAdminPrivilege: privileges.admin.can('admin:groups', socket.uid),
|
||||
isGlobalModerator: user.isGlobalModerator(socket.uid),
|
||||
isOwner: groups.ownership.isOwner(socket.uid, data.groupName),
|
||||
group: groups.getGroupData(data.groupName),
|
||||
});
|
||||
|
||||
const isOwner = results.isOwner || results.isAdmin || (results.isGlobalModerator && !results.group.system);
|
||||
const isOwner = results.isOwner ||
|
||||
results.hasAdminPrivilege ||
|
||||
(results.isGlobalModerator && !results.group.system);
|
||||
if (!isOwner) {
|
||||
throw new Error('[[error:no-privileges]]');
|
||||
}
|
||||
@@ -220,15 +222,15 @@ SocketGroups.loadMoreMembers = async (socket, data) => {
|
||||
};
|
||||
|
||||
async function canSearchMembers(uid, groupName) {
|
||||
const [isHidden, isMember, isAdmin, isGlobalMod, viewGroups] = await Promise.all([
|
||||
const [isHidden, isMember, hasAdminPrivilege, isGlobalMod, viewGroups] = await Promise.all([
|
||||
groups.isHidden(groupName),
|
||||
groups.isMember(uid, groupName),
|
||||
user.isAdministrator(uid),
|
||||
privileges.admin.can('admin:groups', uid),
|
||||
user.isGlobalModerator(uid),
|
||||
privileges.global.can('view:groups', uid),
|
||||
]);
|
||||
|
||||
if (!viewGroups || (isHidden && !isMember && !isAdmin && !isGlobalMod)) {
|
||||
if (!viewGroups || (isHidden && !isMember && !hasAdminPrivilege && !isGlobalMod)) {
|
||||
throw new Error('[[error:no-privileges]]');
|
||||
}
|
||||
}
|
||||
@@ -268,11 +270,11 @@ async function canModifyGroup(uid, groupName) {
|
||||
const results = await utils.promiseParallel({
|
||||
isOwner: groups.ownership.isOwner(uid, groupName),
|
||||
system: groups.getGroupField(groupName, 'system'),
|
||||
isAdmin: user.isAdministrator(uid),
|
||||
hasAdminPrivilege: privileges.admin.can('admin:groups', uid),
|
||||
isGlobalMod: user.isGlobalModerator(uid),
|
||||
});
|
||||
|
||||
if (!(results.isOwner || results.isAdmin || (results.isGlobalMod && !results.system))) {
|
||||
if (!(results.isOwner || results.hasAdminPrivilege || (results.isGlobalMod && !results.system))) {
|
||||
throw new Error('[[error:no-privileges]]');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,12 +185,6 @@ Topics.getTopicWithPosts = async function (topicData, set, uid, start, stop, rev
|
||||
topicData.thumbs = thumbs[0];
|
||||
topicData.posts = posts;
|
||||
topicData.events = events;
|
||||
topicData.posts.forEach((p) => {
|
||||
p.events = events.filter(
|
||||
event => event.timestamp >= p.eventStart && event.timestamp < p.eventEnd
|
||||
);
|
||||
});
|
||||
|
||||
topicData.category = category;
|
||||
topicData.tagWhitelist = tagWhitelist[0];
|
||||
topicData.minTags = category.minTags;
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const db = require('../../database');
|
||||
|
||||
module.exports = {
|
||||
name: 'Store list of chat rooms',
|
||||
timestamp: Date.UTC(2022, 8, 30),
|
||||
method: async () => {
|
||||
const lastRoomId = await db.getObjectField('global', 'nextChatRoomId');
|
||||
let keys = [];
|
||||
for (let x = 1; x <= lastRoomId; x++) {
|
||||
keys.push(`chat:room:${x}`);
|
||||
}
|
||||
|
||||
const exists = await db.exists(keys);
|
||||
keys = keys.filter((_, idx) => exists[idx]);
|
||||
await db.sortedSetAdd('chat:rooms', keys.map(Date.now), keys.map(key => key.slice(10)));
|
||||
},
|
||||
};
|
||||
@@ -421,6 +421,22 @@ describe('Categories', () => {
|
||||
assert.equal(data.icon, updateData[cid].icon);
|
||||
});
|
||||
|
||||
it('should properly order categories', async () => {
|
||||
const p1 = await Categories.create({ name: 'p1', description: 'd', parentCid: 0, order: 1 });
|
||||
const c1 = await Categories.create({ name: 'c1', description: 'd1', parentCid: p1.cid, order: 1 });
|
||||
const c2 = await Categories.create({ name: 'c2', description: 'd2', parentCid: p1.cid, order: 2 });
|
||||
const c3 = await Categories.create({ name: 'c3', description: 'd3', parentCid: p1.cid, order: 3 });
|
||||
// move c1 to second place
|
||||
await apiCategories.update({ uid: adminUid }, { [c1.cid]: { order: 2 } });
|
||||
let cids = await db.getSortedSetRange(`cid:${p1.cid}:children`, 0, -1);
|
||||
assert.deepStrictEqual(cids.map(Number), [c2.cid, c1.cid, c3.cid]);
|
||||
|
||||
// move c3 to front
|
||||
await apiCategories.update({ uid: adminUid }, { [c3.cid]: { order: 1 } });
|
||||
cids = await db.getSortedSetRange(`cid:${p1.cid}:children`, 0, -1);
|
||||
assert.deepStrictEqual(cids.map(Number), [c3.cid, c2.cid, c1.cid]);
|
||||
});
|
||||
|
||||
it('should not remove category from parent if parent is set again to same category', async () => {
|
||||
const parentCat = await Categories.create({ name: 'parent', description: 'poor parent' });
|
||||
const updateData = {};
|
||||
|
||||
@@ -212,7 +212,7 @@ describe('Upload Controllers', () => {
|
||||
assert.ifError(err);
|
||||
assert.strictEqual(res.statusCode, 500);
|
||||
assert(body && body.status && body.status.message);
|
||||
assert.strictEqual(body.status.message, 'Input file contains unsupported image format');
|
||||
assert(body.status.message.startsWith('Input file has corrupt header: pngload: end of stream'));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
const { merge } = require('webpack-merge');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const ProgressPlugin = require('progress-webpack-plugin');
|
||||
|
||||
const common = require('./webpack.common');
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'production',
|
||||
plugins: [
|
||||
new ProgressPlugin(true),
|
||||
],
|
||||
optimization: {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
minify: TerserPlugin.esbuildMinify,
|
||||
terserOptions: {},
|
||||
}),
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user