Version bump
This commit is contained in:
commit
21252f9a4d
1
.github/workflows/tests.yml
vendored
1
.github/workflows/tests.yml
vendored
@ -30,6 +30,7 @@ jobs:
|
||||
PGUSER: discourse
|
||||
PGPASSWORD: discourse
|
||||
USES_PARALLEL_DATABASES: ${{ matrix.build_type == 'backend' }}
|
||||
CAPBYARA_DEFAULT_MAX_WAIT_TIME: 4
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
12
Gemfile.lock
12
Gemfile.lock
@ -92,7 +92,7 @@ GEM
|
||||
bootsnap (1.15.0)
|
||||
msgpack (~> 1.2)
|
||||
builder (3.2.4)
|
||||
bullet (7.0.5)
|
||||
bullet (7.0.7)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11)
|
||||
byebug (11.1.3)
|
||||
@ -138,7 +138,7 @@ GEM
|
||||
regexp_parser (~> 2.2)
|
||||
email_reply_trimmer (0.1.13)
|
||||
erubi (1.11.0)
|
||||
excon (0.95.0)
|
||||
excon (0.96.0)
|
||||
execjs (2.8.1)
|
||||
exifr (1.3.10)
|
||||
fabrication (2.30.0)
|
||||
@ -298,7 +298,7 @@ GEM
|
||||
parallel (1.22.1)
|
||||
parallel_tests (4.0.0)
|
||||
parallel
|
||||
parser (3.1.3.0)
|
||||
parser (3.2.0.0)
|
||||
ast (~> 2.4.1)
|
||||
pg (1.4.5)
|
||||
progress (3.6.0)
|
||||
@ -314,7 +314,7 @@ GEM
|
||||
puma (6.0.2)
|
||||
nio4r (~> 2.0)
|
||||
r2 (0.2.7)
|
||||
racc (1.6.1)
|
||||
racc (1.6.2)
|
||||
rack (2.2.5)
|
||||
rack-mini-profiler (3.0.0)
|
||||
rack (>= 1.2.0)
|
||||
@ -442,7 +442,7 @@ GEM
|
||||
connection_pool (>= 2.2.5, < 3)
|
||||
rack (~> 2.0)
|
||||
redis (>= 4.5.0, < 5)
|
||||
simplecov (0.21.2)
|
||||
simplecov (0.22.0)
|
||||
docile (~> 1.1)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
@ -471,7 +471,7 @@ GEM
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.8.2)
|
||||
unicode-display_width (2.3.0)
|
||||
unicode-display_width (2.4.2)
|
||||
unicorn (6.1.0)
|
||||
kgio (~> 2.6)
|
||||
raindrops (~> 0.7)
|
||||
|
||||
@ -91,7 +91,7 @@ The original Discourse code contributors can be found in [**AUTHORS.MD**](docs/A
|
||||
|
||||
## Copyright / License
|
||||
|
||||
Copyright 2014 - 2022 Civilized Discourse Construction Kit, Inc.
|
||||
Copyright 2014 - 2023 Civilized Discourse Construction Kit, Inc.
|
||||
|
||||
Licensed under the GNU General Public License Version 2.0 (or later);
|
||||
you may not use this work except in compliance with the License.
|
||||
|
||||
@ -106,7 +106,7 @@
|
||||
}}
|
||||
@action={{action "revert" c}}
|
||||
@title="admin.customize.colors.revert_title"
|
||||
@label="revert"
|
||||
@label="admin.customize.colors.revert"
|
||||
/>
|
||||
<DButton
|
||||
@class={{concat
|
||||
@ -115,7 +115,7 @@
|
||||
}}
|
||||
@action={{action "undo" c}}
|
||||
@title="admin.customize.colors.undo_title"
|
||||
@label="undo"
|
||||
@label="admin.customize.colors.undo"
|
||||
/>
|
||||
{{/unless}}
|
||||
</td>
|
||||
@ -127,4 +127,4 @@
|
||||
<p>{{i18n "search.no_results"}}</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
"xss": "^1.0.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.7",
|
||||
"@babel/core": "^7.20.12",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@embroider/test-setup": "^2.0.2",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@
|
||||
"webpack": "^5.75.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.7",
|
||||
"@babel/core": "^7.20.12",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@embroider/test-setup": "^2.0.2",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
"webpack": "^5.75.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.7",
|
||||
"@babel/core": "^7.20.12",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@embroider/test-setup": "^2.0.2",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
"webpack": "^5.75.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.7"
|
||||
"@babel/core": "^7.20.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.* || >= 18",
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
"webpack": "^5.75.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.7",
|
||||
"@babel/core": "^7.20.12",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@embroider/test-setup": "^2.0.2",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
|
||||
@ -60,7 +60,9 @@ export default Component.extend({
|
||||
userTimezone: this.currentUser.user_option.timezone,
|
||||
showOptions: false,
|
||||
_itsatrap: new ItsATrap(),
|
||||
autoDeletePreference: this.model.autoDeletePreference || 0,
|
||||
autoDeletePreference:
|
||||
this.model.autoDeletePreference ||
|
||||
AUTO_DELETE_PREFERENCES.CLEAR_REMINDER,
|
||||
});
|
||||
|
||||
this.registerOnCloseHandler(this._onModalClose);
|
||||
|
||||
@ -2,7 +2,10 @@
|
||||
@sectionName="messages"
|
||||
@headerActionIcon="plus"
|
||||
@headerActions={{array
|
||||
(hash action=(fn (route-action "composePrivateMessage") null null))
|
||||
(hash
|
||||
action=(fn (route-action "composePrivateMessage") null null)
|
||||
title=(i18n "sidebar.sections.messages.header_action_title")
|
||||
)
|
||||
}}
|
||||
@headerActionsIcon="plus"
|
||||
@headerLinkText={{i18n "sidebar.sections.messages.header_link_text"}}
|
||||
|
||||
@ -836,12 +836,7 @@ export default Controller.extend(bufferedProperty("model"), {
|
||||
);
|
||||
return this._modifyPostBookmark(
|
||||
bookmarkForPost ||
|
||||
Bookmark.create({
|
||||
bookmarkable_id: post.id,
|
||||
bookmarkable_type: "Post",
|
||||
auto_delete_preference:
|
||||
this.currentUser.user_option.bookmark_auto_delete_preference,
|
||||
}),
|
||||
Bookmark.createFor(this.currentUser, "Post", post.id),
|
||||
post
|
||||
);
|
||||
} else {
|
||||
@ -1349,12 +1344,7 @@ export default Controller.extend(bufferedProperty("model"), {
|
||||
|
||||
if (this.model.bookmarkCount === 0) {
|
||||
return this._modifyTopicBookmark(
|
||||
Bookmark.create({
|
||||
bookmarkable_id: this.model.id,
|
||||
bookmarkable_type: "Topic",
|
||||
auto_delete_preference:
|
||||
this.currentUser.user_option.bookmark_auto_delete_preference,
|
||||
})
|
||||
Bookmark.createFor(this.currentUser, "Topic", this.model.id)
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@ -12,12 +12,23 @@ export default {
|
||||
initialize(container) {
|
||||
this.messageBus = container.lookup("service:message-bus");
|
||||
this.dialog = container.lookup("service:dialog");
|
||||
this.currentUser = container.lookup("service:current-user");
|
||||
|
||||
this.messageBus.subscribe("/logout", this.onMessage);
|
||||
if (this.currentUser) {
|
||||
this.messageBus.subscribe(
|
||||
`/logout/${this.currentUser.id}`,
|
||||
this.onMessage
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
teardown() {
|
||||
this.messageBus.unsubscribe("/logout", this.onMessage);
|
||||
if (this.currentUser) {
|
||||
this.messageBus.unsubscribe(
|
||||
`/logout/${this.currentUser.id}`,
|
||||
this.onMessage
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@bind
|
||||
|
||||
@ -94,7 +94,7 @@ export default function (options) {
|
||||
let completeEnd = null;
|
||||
let me = this;
|
||||
let div = null;
|
||||
let fadeoutDiv = null;
|
||||
let scrollElement = null;
|
||||
let prevTerm = null;
|
||||
|
||||
// By default, when the autocomplete popup is rendered it has the
|
||||
@ -119,28 +119,29 @@ export default function (options) {
|
||||
}
|
||||
|
||||
function scrollAutocomplete() {
|
||||
if (!fadeoutDiv && !div) {
|
||||
if (!scrollElement && !div) {
|
||||
return;
|
||||
}
|
||||
|
||||
const scrollingDivElement = fadeoutDiv?.length > 0 ? fadeoutDiv[0] : div[0];
|
||||
const scrollingElement =
|
||||
scrollElement?.length > 0 ? scrollElement[0] : div[0];
|
||||
const selectedElement = getSelectedOptionElement();
|
||||
const selectedElementTop = selectedElement.offsetTop;
|
||||
const selectedElementBottom =
|
||||
selectedElementTop + selectedElement.clientHeight;
|
||||
|
||||
// the top of the item is above the top of the fadeoutDiv, so scroll UP
|
||||
if (selectedElementTop <= scrollingDivElement.scrollTop) {
|
||||
scrollingDivElement.scrollTo(0, selectedElementTop);
|
||||
// the top of the item is above the top of the scrollElement, so scroll UP
|
||||
if (selectedElementTop <= scrollingElement.scrollTop) {
|
||||
scrollingElement.scrollTo(0, selectedElementTop);
|
||||
|
||||
// the bottom of the item is below the bottom of the div, so scroll DOWN
|
||||
} else if (
|
||||
selectedElementBottom >=
|
||||
scrollingDivElement.scrollTop + scrollingDivElement.clientHeight
|
||||
scrollingElement.scrollTop + scrollingElement.clientHeight
|
||||
) {
|
||||
scrollingDivElement.scrollTo(
|
||||
scrollingElement.scrollTo(
|
||||
0,
|
||||
scrollingDivElement.scrollTop + selectedElement.clientHeight
|
||||
scrollingElement.scrollTop + selectedElement.clientHeight
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -152,7 +153,7 @@ export default function (options) {
|
||||
div.hide().remove();
|
||||
}
|
||||
div = null;
|
||||
fadeoutDiv = null;
|
||||
scrollElement = null;
|
||||
completeStart = null;
|
||||
autocompleteOptions = null;
|
||||
prevTerm = null;
|
||||
@ -377,7 +378,9 @@ export default function (options) {
|
||||
me.parent().append(div);
|
||||
}
|
||||
|
||||
fadeoutDiv = div.find(".hashtag-autocomplete__fadeout");
|
||||
if (options.scrollElementSelector) {
|
||||
scrollElement = div.find(options.scrollElementSelector);
|
||||
}
|
||||
|
||||
if (isInput || options.treatAsTextarea) {
|
||||
_autoCompletePopper && _autoCompletePopper.destroy();
|
||||
|
||||
@ -123,6 +123,7 @@ function _setupExperimental(
|
||||
key: "#",
|
||||
afterComplete: autocompleteOptions.afterComplete,
|
||||
treatAsTextarea: autocompleteOptions.treatAsTextarea,
|
||||
scrollElementSelector: ".hashtag-autocomplete__fadeout",
|
||||
autoSelectFirstSuggestion: true,
|
||||
transformComplete: (obj) => obj.ref,
|
||||
dataSource: (term) => {
|
||||
|
||||
@ -12,12 +12,13 @@ export default class AboutSectionLink extends BaseSectionLink {
|
||||
}
|
||||
|
||||
get title() {
|
||||
return I18n.t("sidebar.sections.community.links.about.content");
|
||||
return I18n.t("sidebar.sections.community.links.about.title");
|
||||
}
|
||||
|
||||
get text() {
|
||||
return I18n.t("sidebar.sections.community.links.about.content");
|
||||
}
|
||||
|
||||
get prefixValue() {
|
||||
return "info-circle";
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ export default class BadgesSectionLink extends BaseSectionLink {
|
||||
}
|
||||
|
||||
get title() {
|
||||
return I18n.t("sidebar.sections.community.links.badges.content");
|
||||
return I18n.t("sidebar.sections.community.links.badges.title");
|
||||
}
|
||||
|
||||
get text() {
|
||||
|
||||
@ -16,7 +16,7 @@ export default class FAQSectionLink extends BaseSectionLink {
|
||||
}
|
||||
|
||||
get title() {
|
||||
return I18n.t("sidebar.sections.community.links.faq.content");
|
||||
return I18n.t("sidebar.sections.community.links.faq.title");
|
||||
}
|
||||
|
||||
get text() {
|
||||
|
||||
@ -166,6 +166,15 @@ Bookmark.reopenClass({
|
||||
return this._super(args);
|
||||
},
|
||||
|
||||
createFor(user, bookmarkableType, bookmarkableId) {
|
||||
return Bookmark.create({
|
||||
bookmarkable_type: bookmarkableType,
|
||||
bookmarkable_id: bookmarkableId,
|
||||
user_id: user.id,
|
||||
auto_delete_preference: user.user_option.bookmark_auto_delete_preference,
|
||||
});
|
||||
},
|
||||
|
||||
async applyTransformations(bookmarks) {
|
||||
await applyModelTransformations("bookmark", bookmarks);
|
||||
},
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
<DButton
|
||||
@action={{action "undoAcceptRequest"}}
|
||||
@actionParam={{m}}
|
||||
@label="undo"
|
||||
@label="groups.requests.undo"
|
||||
/>
|
||||
{{else if m.request_denied}}
|
||||
{{i18n "groups.requests.denied"}}
|
||||
@ -80,4 +80,4 @@
|
||||
<div>{{i18n "groups.empty.requests"}}</div>
|
||||
{{/if}}
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@ -16,8 +16,8 @@
|
||||
"test": "ember test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.20.7",
|
||||
"@babel/standalone": "^7.20.11",
|
||||
"@babel/core": "^7.20.12",
|
||||
"@babel/standalone": "^7.20.12",
|
||||
"@discourse/backburner.js": "^2.7.1-0",
|
||||
"@discourse/itsatrap": "^2.0.10",
|
||||
"@ember-compat/tracked-built-ins": "^0.9.1",
|
||||
|
||||
@ -8,7 +8,10 @@ import { test } from "qunit";
|
||||
|
||||
acceptance("Category and Tag Hashtags", function (needs) {
|
||||
needs.user();
|
||||
needs.settings({ tagging_enabled: true });
|
||||
needs.settings({
|
||||
tagging_enabled: true,
|
||||
enable_experimental_hashtag_autocomplete: false,
|
||||
});
|
||||
needs.pretender((server, helper) => {
|
||||
server.get("/hashtags", () => {
|
||||
return helper.response({
|
||||
|
||||
@ -31,7 +31,8 @@ acceptance("Password Reset", function (needs) {
|
||||
} else {
|
||||
return helper.response({
|
||||
success: "OK",
|
||||
message: I18n.t("password_reset.success"),
|
||||
message:
|
||||
"You successfully changed your password and are now logged in.",
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -44,7 +45,8 @@ acceptance("Password Reset", function (needs) {
|
||||
) {
|
||||
return helper.response({
|
||||
success: "OK",
|
||||
message: I18n.t("password_reset.success"),
|
||||
message:
|
||||
"You successfully changed your password and are now logged in.",
|
||||
});
|
||||
} else if (body.second_factor_token === "123123") {
|
||||
return helper.response({
|
||||
|
||||
@ -335,7 +335,7 @@ acceptance("User - Logout", function (needs) {
|
||||
test("Dialog works", async function (assert) {
|
||||
sinon.stub(logout, "default");
|
||||
await visit("/u/eviltrout");
|
||||
await publishToMessageBus("/logout");
|
||||
await publishToMessageBus("/logout/19");
|
||||
|
||||
assert.ok(exists(".dialog-body"));
|
||||
assert.ok(
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
"xss": "^1.0.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.7",
|
||||
"@babel/core": "^7.20.12",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@embroider/test-setup": "^2.0.2",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
"webpack": "^5.75.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.7",
|
||||
"@babel/core": "^7.20.12",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@embroider/test-setup": "^2.0.2",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
"webpack": "^5.75.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.7",
|
||||
"@babel/core": "^7.20.12",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@embroider/test-setup": "^2.0.2",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
"xss": "^1.0.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.7",
|
||||
"@babel/core": "^7.20.12",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@embroider/test-setup": "^2.0.2",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
|
||||
@ -17,35 +17,30 @@
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.18.6"
|
||||
|
||||
"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8":
|
||||
version "7.20.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30"
|
||||
integrity sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==
|
||||
|
||||
"@babel/compat-data@^7.20.5":
|
||||
"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.20.5":
|
||||
version "7.20.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.10.tgz#9d92fa81b87542fff50e848ed585b4212c1d34ec"
|
||||
integrity sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==
|
||||
|
||||
"@babel/core@^7.12.0", "@babel/core@^7.13.8", "@babel/core@^7.16.7", "@babel/core@^7.20.7", "@babel/core@^7.3.4":
|
||||
version "7.20.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.7.tgz#37072f951bd4d28315445f66e0ec9f6ae0c8c35f"
|
||||
integrity sha512-t1ZjCluspe5DW24bn2Rr1CDb2v9rn/hROtg9a2tmd0+QYf4bsloYfLQzjG4qHPNMhWtKdGC33R5AxGR2Af2cBw==
|
||||
"@babel/core@^7.12.0", "@babel/core@^7.13.8", "@babel/core@^7.16.7", "@babel/core@^7.20.12", "@babel/core@^7.3.4":
|
||||
version "7.20.12"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.12.tgz#7930db57443c6714ad216953d1356dac0eb8496d"
|
||||
integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==
|
||||
dependencies:
|
||||
"@ampproject/remapping" "^2.1.0"
|
||||
"@babel/code-frame" "^7.18.6"
|
||||
"@babel/generator" "^7.20.7"
|
||||
"@babel/helper-compilation-targets" "^7.20.7"
|
||||
"@babel/helper-module-transforms" "^7.20.7"
|
||||
"@babel/helper-module-transforms" "^7.20.11"
|
||||
"@babel/helpers" "^7.20.7"
|
||||
"@babel/parser" "^7.20.7"
|
||||
"@babel/template" "^7.20.7"
|
||||
"@babel/traverse" "^7.20.7"
|
||||
"@babel/traverse" "^7.20.12"
|
||||
"@babel/types" "^7.20.7"
|
||||
convert-source-map "^1.7.0"
|
||||
debug "^4.1.0"
|
||||
gensync "^1.0.0-beta.2"
|
||||
json5 "^2.2.1"
|
||||
json5 "^2.2.2"
|
||||
semver "^6.3.0"
|
||||
|
||||
"@babel/generator@^7.20.7":
|
||||
@ -173,7 +168,7 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.18.6"
|
||||
|
||||
"@babel/helper-module-transforms@^7.16.7", "@babel/helper-module-transforms@^7.20.7":
|
||||
"@babel/helper-module-transforms@^7.16.7", "@babel/helper-module-transforms@^7.20.11":
|
||||
version "7.20.11"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0"
|
||||
integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==
|
||||
@ -961,10 +956,10 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/standalone@^7.20.11":
|
||||
version "7.20.11"
|
||||
resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.20.11.tgz#8baf940746546e312f39539bdeefa3240108f3ec"
|
||||
integrity sha512-WUPlwwXFk3iViGE7QFVVp423eVtT+eoXu1940Xu4QJgqgHBF6WWtlwO1Ip5rIWQnp7OHrGdwrwKLtLhUVfOZbA==
|
||||
"@babel/standalone@^7.20.12":
|
||||
version "7.20.12"
|
||||
resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.20.12.tgz#ae882b8642b4efb1ddd80c8a64a929e028095562"
|
||||
integrity sha512-hK/X+m1il3w1tYS4H8LDaGCEdiT47SVqEXY8RiEAgou26BystipSU8ZL6EvBR6t5l7lTv0ilBiChXWblKJ5iUA==
|
||||
|
||||
"@babel/template@^7.16.7", "@babel/template@^7.18.10", "@babel/template@^7.20.7":
|
||||
version "7.20.7"
|
||||
@ -975,10 +970,10 @@
|
||||
"@babel/parser" "^7.20.7"
|
||||
"@babel/types" "^7.20.7"
|
||||
|
||||
"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.20.10", "@babel/traverse@^7.20.7", "@babel/traverse@^7.4.5":
|
||||
version "7.20.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.10.tgz#2bf98239597fcec12f842756f186a9dde6d09230"
|
||||
integrity sha512-oSf1juCgymrSez8NI4A2sr4+uB/mFd9MXplYGPEBnfAuWmmyeVcHa6xLPiaRBcXkcb/28bgxmQLTVwFKE1yfsg==
|
||||
"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.20.10", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.7", "@babel/traverse@^7.4.5":
|
||||
version "7.20.12"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.12.tgz#7f0f787b3a67ca4475adef1f56cb94f6abd4a4b5"
|
||||
integrity sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.18.6"
|
||||
"@babel/generator" "^7.20.7"
|
||||
@ -6358,10 +6353,10 @@ json5@^1.0.1:
|
||||
dependencies:
|
||||
minimist "^1.2.0"
|
||||
|
||||
json5@^2.1.2, json5@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
|
||||
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
|
||||
json5@^2.1.2, json5@^2.2.2:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||
|
||||
jsonfile@^2.1.0:
|
||||
version "2.4.0"
|
||||
|
||||
@ -439,6 +439,7 @@ html.composer-open {
|
||||
}
|
||||
|
||||
.name {
|
||||
display: contents;
|
||||
font-size: var(--font-down-1);
|
||||
color: var(--primary-high);
|
||||
}
|
||||
|
||||
@ -150,7 +150,8 @@ $topic-progress-height: 42px;
|
||||
&.docked {
|
||||
position: initial;
|
||||
.topic-admin-popup-menu.right-side {
|
||||
bottom: -150px; // Prevents menu from being too high when a topic is very short
|
||||
bottom: unset;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1497,7 +1497,7 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def logged_out
|
||||
MessageBus.publish "/logout", self.id, user_ids: [self.id]
|
||||
MessageBus.publish "/logout/#{self.id}", self.id, user_ids: [self.id]
|
||||
DiscourseEvent.trigger(:user_logged_out, self)
|
||||
end
|
||||
|
||||
|
||||
@ -248,7 +248,7 @@ class SiteSerializer < ApplicationSerializer
|
||||
end
|
||||
|
||||
def whispers_allowed_groups_names
|
||||
SiteSetting.whispers_allowed_groups_map&.map { |id| Group.where(id: id).pluck_first(:name) }
|
||||
Group.where(id: SiteSetting.whispers_allowed_groups_map).pluck(:name)
|
||||
end
|
||||
|
||||
def include_whispers_allowed_groups_names?
|
||||
|
||||
@ -103,7 +103,7 @@ class UserDestroyer
|
||||
StaffActionLogger.new(deleted_by).log_user_deletion(user, opts.slice(:context))
|
||||
Rails.logger.warn("User destroyed without context from: #{caller_locations(14, 1)[0]}") if opts.slice(:context).blank?
|
||||
end
|
||||
MessageBus.publish "/logout", result.id, user_ids: [result.id]
|
||||
MessageBus.publish "/logout/#{result.id}", result.id, user_ids: [result.id]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -429,7 +429,6 @@ en:
|
||||
enable: "Enable"
|
||||
disable: "Disable"
|
||||
continue: "Continue"
|
||||
undo: "Undo"
|
||||
|
||||
switch_to_anon: "Enter Anonymous Mode"
|
||||
switch_from_anon: "Exit Anonymous Mode"
|
||||
@ -747,6 +746,7 @@ en:
|
||||
denied: "denied"
|
||||
undone: "request undone"
|
||||
handle: "handle membership request"
|
||||
undo: "Undo"
|
||||
manage:
|
||||
title: "Manage"
|
||||
name: "Name"
|
||||
@ -3581,7 +3581,6 @@ en:
|
||||
create_for_topic: "Create bookmark for topic"
|
||||
edit: "Edit bookmark"
|
||||
edit_for_topic: "Edit bookmark for topic"
|
||||
created: "Created"
|
||||
updated: "Updated"
|
||||
name: "Name"
|
||||
name_placeholder: "What is this bookmark for?"
|
||||
@ -3907,7 +3906,6 @@ en:
|
||||
category_title: "Category"
|
||||
history_capped_revisions: "History, last 100 revisions"
|
||||
history: "History"
|
||||
changed_by: "by %{author}"
|
||||
|
||||
raw_email:
|
||||
title: "Incoming Email"
|
||||
@ -4355,7 +4353,7 @@ en:
|
||||
new_count:
|
||||
one: "%{count} new"
|
||||
other: "%{count} new"
|
||||
toggle_section: "toggle section"
|
||||
toggle_section: "Toggle section"
|
||||
more: "More"
|
||||
all_categories: "All categories"
|
||||
all_tags: "All tags"
|
||||
@ -4364,7 +4362,7 @@ en:
|
||||
header_link_text: "About"
|
||||
messages:
|
||||
header_link_text: "Messages"
|
||||
header_action_title: "create a personal message"
|
||||
header_action_title: "Create a personal message"
|
||||
links:
|
||||
inbox: "Inbox"
|
||||
sent: "Sent"
|
||||
@ -4381,7 +4379,7 @@ en:
|
||||
none: "You have not added any tags."
|
||||
click_to_get_started: "Click here to get started."
|
||||
header_link_text: "Tags"
|
||||
header_action_title: "edit your sidebar tags"
|
||||
header_action_title: "Edit your sidebar tags"
|
||||
configure_defaults: "Configure defaults"
|
||||
categories:
|
||||
links:
|
||||
@ -4391,29 +4389,33 @@ en:
|
||||
none: "You have not added any categories."
|
||||
click_to_get_started: "Click here to get started."
|
||||
header_link_text: "Categories"
|
||||
header_action_title: "edit your sidebar categories"
|
||||
header_action_title: "Edit your sidebar categories"
|
||||
configure_defaults: "Configure defaults"
|
||||
community:
|
||||
header_link_text: "Community"
|
||||
header_action_title: "create a new topic"
|
||||
header_action_title: "Create a topic"
|
||||
links:
|
||||
about:
|
||||
content: "About"
|
||||
title: "More details about this site"
|
||||
admin:
|
||||
content: "Admin"
|
||||
title: "Site settings and reports"
|
||||
badges:
|
||||
content: "Badges"
|
||||
title: "All the badges available to earn"
|
||||
everything:
|
||||
content: "Everything"
|
||||
title: "All topics"
|
||||
faq:
|
||||
content: "FAQ"
|
||||
title: "Guidelines for using this site"
|
||||
groups:
|
||||
content: "Groups"
|
||||
title: "All groups"
|
||||
title: "List of available user groups"
|
||||
users:
|
||||
content: "Users"
|
||||
title: "All users"
|
||||
title: "List of all users"
|
||||
my_posts:
|
||||
content: "My Posts"
|
||||
title: "My recent topic activity"
|
||||
@ -4423,7 +4425,7 @@ en:
|
||||
other: "%{count} drafts"
|
||||
review:
|
||||
content: "Review"
|
||||
title: "review"
|
||||
title: "Flagged posts and other queued items"
|
||||
pending_count: "%{count} pending"
|
||||
|
||||
welcome_topic_banner:
|
||||
@ -5107,9 +5109,9 @@ en:
|
||||
new_name: "New Color Palette"
|
||||
copy_name_prefix: "Copy of"
|
||||
delete_confirm: "Delete this color palette?"
|
||||
undo: "undo"
|
||||
undo: "Undo"
|
||||
undo_title: "Undo your changes to this color since the last time it was saved."
|
||||
revert: "revert"
|
||||
revert: "Revert"
|
||||
revert_title: "Reset this color to Discourse's default color palette."
|
||||
primary:
|
||||
name: "primary"
|
||||
|
||||
@ -833,10 +833,6 @@ en:
|
||||
|
||||
password_reset:
|
||||
no_token: 'Oops! The link you used no longer works. You can <a href="%{base_url}/login">Log In</a> now. If you forgot your password, you can <a href="%{base_url}/password-reset">request a link</a> to reset it.'
|
||||
choose_new: "Choose a new password"
|
||||
choose: "Choose a password"
|
||||
update: "Update Password"
|
||||
save: "Set Password"
|
||||
title: "Reset Password"
|
||||
success: "You successfully changed your password and are now logged in."
|
||||
success_unapproved: "You successfully changed your password."
|
||||
@ -1049,7 +1045,7 @@ en:
|
||||
mailing_list_mode: "Turn off mailing list mode"
|
||||
all: "Don’t send me any mail from %{sitename}"
|
||||
different_user_description: "You are currently logged in as a different user than the one we emailed. Please log out, or enter anonymous mode, and try again."
|
||||
not_found_description: Sorry, we couldn't find that subscription. It's possible the link in your email is too old and has expired?"
|
||||
not_found_description: "Sorry, we couldn't find that subscription. It's possible the link in your email is too old and has expired?"
|
||||
user_not_found_description: "Sorry, we couldn't find a user for this subscription. You are probably attempting to unsubscribe an account that no longer exists."
|
||||
log_out: "Log Out"
|
||||
submit: "Save preferences"
|
||||
|
||||
@ -901,7 +901,7 @@ ru:
|
||||
linux: "Linux"
|
||||
macos: "macOS"
|
||||
windows: "Microsoft Windows"
|
||||
unknown: "неизвестная операционная система"
|
||||
unknown: "Неизвестная операционная система"
|
||||
change_email:
|
||||
wrong_account_error: "Вы вошли не в тот аккаунт — выйдите и повторите попытку."
|
||||
confirmed: "Адрес электронной почты обновлён."
|
||||
@ -929,11 +929,11 @@ ru:
|
||||
connected: "(связанный)"
|
||||
activation:
|
||||
action: "Нажмите сюда, чтобы активировать аккаунт"
|
||||
already_done: "Ссылка на подтверждение аккаунта устарела. Возможно, ваш аккаунт уже активирован?"
|
||||
please_continue: "Ваш новый аккаунт подтвержден; вы будете перенаправлены на главную страницу."
|
||||
already_done: "Ссылка на подтверждение аккаунта устарела. Возможно, аккаунт уже активирован?"
|
||||
please_continue: "Новый аккаунт подтвержден; вы будете перенаправлены на главную страницу."
|
||||
continue_button: "Перейти на сайт %{site_name}"
|
||||
welcome_to: "Добро пожаловать на сайт %{site_name}!"
|
||||
approval_required: "Ваш аккаунт должен быть вручную подтвержден модератором, чтобы вы смогли зайти на форум. Когда аккаунт будет одобрен, вы получите письмо!"
|
||||
approval_required: "Чтобы вы смогли зайти на форум, ваш аккаунт должен быть вручную подтвержден модератором. Когда аккаунт будет одобрен, вы получите письмо!"
|
||||
missing_session: "Мы не можем определить, был ли создан аккаунт. Убедитесь, что в браузере включены файлы cookie."
|
||||
activated: "Этот аккаунт уже активирован."
|
||||
admin_confirm:
|
||||
@ -947,7 +947,7 @@ ru:
|
||||
title: "Требуется одобрение"
|
||||
post_action_types:
|
||||
off_topic:
|
||||
title: "Оффтопик (не по теме)"
|
||||
title: "Офтопик (не по теме)"
|
||||
description: "Эта запись не имеет отношения к обсуждению, судя по названию и содержанию первой записи. Возможно, ее стоит перенести."
|
||||
short_description: "Не относится к обсуждению"
|
||||
spam:
|
||||
@ -978,13 +978,13 @@ ru:
|
||||
like:
|
||||
title: "Лайк"
|
||||
description: "Поставить лайк записи"
|
||||
short_description: "Мне нравится"
|
||||
short_description: "Поставить лайк записи"
|
||||
draft:
|
||||
sequence_conflict_error:
|
||||
title: "Ошибка черновика"
|
||||
title: "ошибка черновика"
|
||||
description: "Черновик редактируется в другом окне. Перезагрузите эту страницу."
|
||||
draft_backup:
|
||||
pm_title: "Резервное копирование черновиков из текущих тем"
|
||||
pm_title: "Резервные копии черновиков из текущих тем"
|
||||
pm_body: "Тема, содержащая резервные копии черновиков"
|
||||
user_activity:
|
||||
no_log_search_queries: "Поиск запросов журнала в настоящее время отключен (администратор может включить их в настройках сайта)."
|
||||
@ -996,7 +996,7 @@ ru:
|
||||
authentication_error_gmail_app_password: 'Требуется пароль для конкретного приложения. Дополнительные сведения см. в <a target="_blank" href="https://support.google.com/accounts/answer/185833">этой статье</a>.'
|
||||
smtp_server_busy_error: "SMTP-сервер сейчас занят, повторите попытку позже."
|
||||
smtp_unhandled_error: "Произошла необработанная ошибка при подключении к SMTP-серверу. %{message}"
|
||||
imap_unhandled_error: "Произошла неизвестная ошибка при подключении к IMAP-серверу. %{message}"
|
||||
imap_unhandled_error: "Произошла необработанная ошибка при подключении к IMAP-серверу. %{message}"
|
||||
connection_error: "При подключении к серверу возникла проблема, проверьте имя сервера, порт и повторите попытку."
|
||||
timeout_error: "Время подключения к серверу истекло, проверьте имя сервера, порт и повторите попытку."
|
||||
unhandled_error: "Необработанная ошибка при тестировании настроек электронной почты. %{message}"
|
||||
@ -1033,7 +1033,7 @@ ru:
|
||||
email_title: 'Тема «%{title}» требует внимания модератора'
|
||||
email_body: "%{link}\n\n%{message}"
|
||||
flagging:
|
||||
you_must_edit: '<p>На вашу запись поступила жалоба от сообщества. <a href="%{path}">Проверьте личные сообщения</a>.</p>'
|
||||
you_must_edit: '<p>На вашу запись поступила жалоба от сообщества. <a href="%{path}">Проверьте сообщения</a>.</p>'
|
||||
user_must_edit: "<p>На эту запись поступили жалобы от сообщества, поэтому она временно скрыта.</p>"
|
||||
ignored:
|
||||
hidden_content: "<p>Проигнорированный контент</p>"
|
||||
@ -1043,8 +1043,8 @@ ru:
|
||||
banner:
|
||||
title: "Тема для баннера"
|
||||
message:
|
||||
make: "Это тема для баннера. Он будет отображаться у каждого пользователя сверху на всех страницах, пока он скроет ее."
|
||||
remove: "Это тема больше не является баннером Он не будет отображаться вверху каждой страницы."
|
||||
make: "Это тема для баннера, который будет отображаться у каждого пользователя сверху на всех страницах, пока он скроет ее."
|
||||
remove: "Это тема больше не является баннером и не будет отображаться вверху каждой страницы."
|
||||
unsubscribed:
|
||||
title: "Настройки эл. писем обновлены!"
|
||||
description: "Настройки электронной почты для <b>%{email}</b> были обновлены. Чтобы изменить настройки электронной почты, зайдите в <a href='%{url}'>настройки пользователя</a>."
|
||||
@ -1064,20 +1064,20 @@ ru:
|
||||
submit: "Сохранить настройки"
|
||||
digest_frequency:
|
||||
title: "Вы получаете письма со сводками %{frequency}"
|
||||
never_title: "Вы не получаете Email-дайджест"
|
||||
never_title: "Вы не получаете письма со сводками"
|
||||
select_title: "Частота писем со сводками:"
|
||||
never: "Никогда"
|
||||
every_30_minutes: "Каждые 30 минут"
|
||||
every_hour: "Каждый час"
|
||||
daily: "Ежедневно"
|
||||
weekly: "Еженедельно"
|
||||
every_month: "Каждый месяц"
|
||||
every_six_months: "Каждые шесть месяцев"
|
||||
never: "никогда"
|
||||
every_30_minutes: "каждые 30 минут"
|
||||
every_hour: "каждый час"
|
||||
daily: "ежедневно"
|
||||
weekly: "еженедельно"
|
||||
every_month: "каждый месяц"
|
||||
every_six_months: "каждые шесть месяцев"
|
||||
user_api_key:
|
||||
title: "Разрешить доступ для приложения"
|
||||
authorize: "Разрешить"
|
||||
read: "чтение"
|
||||
read_write: "чтение/запись"
|
||||
read_write: "чтение и запись"
|
||||
description: 'Приложение «%{application_name}» запрашивает доступ к вашему аккаунту:'
|
||||
instructions: 'Мы сгенерировали новый API-ключ пользователя для приложения «%{application_name}». Вставьте этот ключ в приложение:'
|
||||
otp_description: 'Разрешить приложению «%{application_name}» доступ к этому сайту?'
|
||||
|
||||
@ -2035,7 +2035,7 @@ developer:
|
||||
default: true
|
||||
client: true
|
||||
enable_experimental_hashtag_autocomplete:
|
||||
default: false
|
||||
default: true
|
||||
client: true
|
||||
experimental_hashtag_search_result_limit:
|
||||
default: 20
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class MakeExperimentalHashtagFeatureDefaultForNewSites < ActiveRecord::Migration[7.0]
|
||||
def up
|
||||
execute(<<~SQL)
|
||||
INSERT INTO site_settings (name, data_type, value, created_at, updated_at)
|
||||
VALUES ('enable_experimental_hashtag_autocomplete', 5, 'f', now(), now())
|
||||
ON CONFLICT DO NOTHING
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
@ -32,7 +32,7 @@ class Auth::ManagedAuthenticator < Auth::Authenticator
|
||||
def primary_email_verified?(auth_token)
|
||||
# Omniauth providers should only provide verified emails in the :info hash.
|
||||
# This method allows additional checks to be added
|
||||
true
|
||||
false
|
||||
end
|
||||
|
||||
def can_revoke?
|
||||
|
||||
@ -41,18 +41,24 @@ class BookmarkManager
|
||||
# automatically.
|
||||
def create_for(bookmarkable_id:, bookmarkable_type:, name: nil, reminder_at: nil, options: {})
|
||||
registered_bookmarkable = Bookmark.registered_bookmarkable_from_type(bookmarkable_type)
|
||||
|
||||
if registered_bookmarkable.blank?
|
||||
return add_error(I18n.t("bookmarks.errors.invalid_bookmarkable", type: bookmarkable_type))
|
||||
end
|
||||
|
||||
bookmarkable = registered_bookmarkable.model.find_by(id: bookmarkable_id)
|
||||
registered_bookmarkable.validate_before_create(@guardian, bookmarkable)
|
||||
|
||||
bookmark = Bookmark.create(
|
||||
{
|
||||
user_id: @user.id,
|
||||
bookmarkable: bookmarkable,
|
||||
name: name,
|
||||
reminder_at: reminder_at,
|
||||
reminder_set_at: Time.zone.now
|
||||
}.merge(bookmark_model_options_with_defaults(options))
|
||||
)
|
||||
bookmark =
|
||||
Bookmark.create(
|
||||
{
|
||||
user_id: @user.id,
|
||||
bookmarkable: bookmarkable,
|
||||
name: name,
|
||||
reminder_at: reminder_at,
|
||||
reminder_set_at: Time.zone.now,
|
||||
}.merge(bookmark_model_options_with_defaults(options)),
|
||||
)
|
||||
|
||||
return add_errors_from(bookmark) if bookmark.errors.any?
|
||||
|
||||
@ -97,16 +103,14 @@ class BookmarkManager
|
||||
bookmark.reminder_last_sent_at = nil
|
||||
end
|
||||
|
||||
success = bookmark.update(
|
||||
{
|
||||
name: name,
|
||||
reminder_set_at: Time.zone.now,
|
||||
}.merge(bookmark_model_options_with_defaults(options))
|
||||
)
|
||||
success =
|
||||
bookmark.update(
|
||||
{ name: name, reminder_set_at: Time.zone.now }.merge(
|
||||
bookmark_model_options_with_defaults(options),
|
||||
),
|
||||
)
|
||||
|
||||
if bookmark.errors.any?
|
||||
return add_errors_from(bookmark)
|
||||
end
|
||||
return add_errors_from(bookmark) if bookmark.errors.any?
|
||||
|
||||
success
|
||||
end
|
||||
@ -116,9 +120,7 @@ class BookmarkManager
|
||||
bookmark.pinned = !bookmark.pinned
|
||||
success = bookmark.save
|
||||
|
||||
if bookmark.errors.any?
|
||||
return add_errors_from(bookmark)
|
||||
end
|
||||
return add_errors_from(bookmark) if bookmark.errors.any?
|
||||
|
||||
success
|
||||
end
|
||||
@ -136,20 +138,30 @@ class BookmarkManager
|
||||
# PostCreator can specify whether auto_track is enabled or not, don't want to
|
||||
# create a TopicUser in that case
|
||||
return if opts.key?(:auto_track) && !opts[:auto_track]
|
||||
TopicUser.change(@user.id, topic, bookmarked: Bookmark.for_user_in_topic(@user.id, topic.id).exists?)
|
||||
TopicUser.change(
|
||||
@user.id,
|
||||
topic,
|
||||
bookmarked: Bookmark.for_user_in_topic(@user.id, topic.id).exists?,
|
||||
)
|
||||
end
|
||||
|
||||
def bookmark_model_options_with_defaults(options)
|
||||
model_options = {
|
||||
pinned: options[:pinned]
|
||||
}
|
||||
model_options = { pinned: options[:pinned] }
|
||||
|
||||
if options[:auto_delete_preference].blank?
|
||||
model_options[:auto_delete_preference] = Bookmark.auto_delete_preferences[:never]
|
||||
model_options[:auto_delete_preference] = if user_auto_delete_preference.present?
|
||||
user_auto_delete_preference
|
||||
else
|
||||
Bookmark.auto_delete_preferences[:clear_reminder]
|
||||
end
|
||||
else
|
||||
model_options[:auto_delete_preference] = options[:auto_delete_preference]
|
||||
end
|
||||
|
||||
model_options
|
||||
end
|
||||
|
||||
def user_auto_delete_preference
|
||||
@guardian.user.user_option&.bookmark_auto_delete_preference
|
||||
end
|
||||
end
|
||||
|
||||
@ -149,7 +149,7 @@ module CookedProcessorMixin
|
||||
return unless image_sizes.present?
|
||||
image_sizes.each do |image_size|
|
||||
url, size = image_size[0], image_size[1]
|
||||
if url && url.include?(src) &&
|
||||
if url && src && url.include?(src) &&
|
||||
size && size["width"].to_i > 0 && size["height"].to_i > 0
|
||||
return [size["width"], size["height"]]
|
||||
end
|
||||
|
||||
@ -10,7 +10,7 @@ module Discourse
|
||||
MAJOR = 3
|
||||
MINOR = 0
|
||||
TINY = 0
|
||||
PRE = 'beta15'
|
||||
PRE = 'beta16'
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
||||
end
|
||||
|
||||
@ -723,11 +723,7 @@ export default Component.extend({
|
||||
toggleBookmark() {
|
||||
return openBookmarkModal(
|
||||
this.message.bookmark ||
|
||||
Bookmark.create({
|
||||
bookmarkable_type: "ChatMessage",
|
||||
bookmarkable_id: this.message.id,
|
||||
user_id: this.currentUser.id,
|
||||
}),
|
||||
Bookmark.createFor(this.currentUser, "ChatMessage", this.message.id),
|
||||
{
|
||||
onAfterSave: (savedData) => {
|
||||
const bookmark = Bookmark.create(savedData);
|
||||
|
||||
@ -345,7 +345,7 @@ en:
|
||||
|
||||
direct_messages:
|
||||
title: "Personal chat"
|
||||
new: "New personal chat"
|
||||
new: "Create a personal chat"
|
||||
create: "Go"
|
||||
leave: "Leave this personal chat"
|
||||
cannot_create: "Sorry, you cannot send direct messages."
|
||||
|
||||
@ -69,7 +69,7 @@ module Chat::UserNotificationsExtension
|
||||
|
||||
# Prioritize messages from regular channels over direct messages
|
||||
if channels.any?
|
||||
channel_notification_text(channels, dm_users)
|
||||
channel_notification_text(channels.sort_by(&:last_message_sent_at), dm_users)
|
||||
else
|
||||
direct_message_notification_text(dm_users)
|
||||
end
|
||||
|
||||
@ -53,9 +53,9 @@ RSpec.describe "Archive channel", type: :system, js: true do
|
||||
end
|
||||
|
||||
context "when archiving" do
|
||||
# before { Jobs.run_immediately! }
|
||||
it "works" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
xit "works" do
|
||||
chat.visit_channel_settings(channel_1)
|
||||
click_button(I18n.t("js.chat.channel_settings.archive_channel"))
|
||||
find("#split-topic-name").fill_in(with: "An interesting topic for cats")
|
||||
@ -66,18 +66,19 @@ RSpec.describe "Archive channel", type: :system, js: true do
|
||||
end
|
||||
|
||||
context "when archived channels had unreads" do
|
||||
before do
|
||||
before { channel_1.add(current_user) }
|
||||
|
||||
it "clears unread indicators" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
other_user = Fabricate(:user)
|
||||
channel_1.add(other_user)
|
||||
channel_1.add(current_user)
|
||||
Chat::ChatMessageCreator.create(
|
||||
chat_channel: channel_1,
|
||||
user: other_user,
|
||||
content: "this is fine @#{current_user.username}",
|
||||
)
|
||||
end
|
||||
|
||||
xit "clears unread indicators" do
|
||||
visit("/")
|
||||
expect(page.find(".chat-channel-unread-indicator")).to have_content(1)
|
||||
|
||||
@ -92,10 +93,7 @@ RSpec.describe "Archive channel", type: :system, js: true do
|
||||
end
|
||||
|
||||
context "when archiving failed" do
|
||||
before do
|
||||
# Jobs.run_immediately!
|
||||
channel_1.update!(status: :read_only)
|
||||
end
|
||||
before { channel_1.update!(status: :read_only) }
|
||||
|
||||
fab!(:archive) do
|
||||
ChatChannelArchive.create!(
|
||||
@ -108,7 +106,9 @@ RSpec.describe "Archive channel", type: :system, js: true do
|
||||
)
|
||||
end
|
||||
|
||||
xit "can be retried" do
|
||||
it "can be retried" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
chat.visit_channel(channel_1)
|
||||
click_button(I18n.t("js.chat.channel_archive.retry"))
|
||||
|
||||
|
||||
@ -5,6 +5,8 @@ RSpec.describe "Bookmark message", type: :system, js: true do
|
||||
|
||||
let(:chat) { PageObjects::Pages::Chat.new }
|
||||
let(:channel) { PageObjects::Pages::ChatChannel.new }
|
||||
let(:bookmark_modal) { PageObjects::Modals::Bookmark.new }
|
||||
|
||||
fab!(:category_channel_1) { Fabricate(:category_channel) }
|
||||
fab!(:message_1) { Fabricate(:chat_message, chat_channel: category_channel_1) }
|
||||
|
||||
@ -19,13 +21,32 @@ RSpec.describe "Bookmark message", type: :system, js: true do
|
||||
chat.visit_channel(category_channel_1)
|
||||
channel.bookmark_message(message_1)
|
||||
|
||||
expect(page).to have_css("#bookmark-reminder-modal")
|
||||
|
||||
find("#bookmark-name").fill_in(with: "Check this out later")
|
||||
find("#tap_tile_next_month").click
|
||||
bookmark_modal.fill_name("Check this out later")
|
||||
bookmark_modal.select_preset_reminder(:next_month)
|
||||
|
||||
expect(channel).to have_bookmarked_message(message_1)
|
||||
end
|
||||
|
||||
context "when the user has a bookmark auto_delete_preference" do
|
||||
before do
|
||||
current_user.user_option.update!(
|
||||
bookmark_auto_delete_preference: Bookmark.auto_delete_preferences[:on_owner_reply],
|
||||
)
|
||||
end
|
||||
|
||||
it "is respected when the user creates a new bookmark" do
|
||||
chat.visit_channel(category_channel_1)
|
||||
channel.bookmark_message(message_1)
|
||||
|
||||
bookmark_modal.save
|
||||
expect(channel).to have_bookmarked_message(message_1)
|
||||
|
||||
bookmark = Bookmark.find_by(bookmarkable: message_1, user: current_user)
|
||||
expect(bookmark.auto_delete_preference).to eq(
|
||||
Bookmark.auto_delete_preferences[:on_owner_reply],
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when mobile", mobile: true do
|
||||
@ -34,10 +55,9 @@ RSpec.describe "Bookmark message", type: :system, js: true do
|
||||
|
||||
channel.message_by_id(message_1.id).click(delay: 0.5)
|
||||
find(".bookmark-btn").click
|
||||
expect(page).to have_css("#bookmark-reminder-modal")
|
||||
|
||||
find("#bookmark-name").fill_in(with: "Check this out later")
|
||||
find("#tap_tile_next_month").click
|
||||
bookmark_modal.fill_name("Check this out later")
|
||||
bookmark_modal.select_preset_reminder(:next_month)
|
||||
|
||||
expect(channel).to have_bookmarked_message(message_1)
|
||||
end
|
||||
|
||||
@ -37,13 +37,13 @@ RSpec.describe "Channel - Info - Members page", type: :system, js: true do
|
||||
channel_1.add(current_user)
|
||||
channel_1.add(Fabricate(:user, username: "cat"))
|
||||
98.times { channel_1.add(Fabricate(:user)) }
|
||||
|
||||
channel_1.update!(user_count_stale: true)
|
||||
# Jobs.run_immediately!
|
||||
Jobs::UpdateChannelUserCount.new.execute(chat_channel_id: channel_1.id)
|
||||
end
|
||||
|
||||
xit "shows all members" do
|
||||
it "shows all members" do
|
||||
Jobs.run_immediately!
|
||||
channel_1.update!(user_count_stale: true)
|
||||
Jobs::UpdateChannelUserCount.new.execute(chat_channel_id: channel_1.id)
|
||||
|
||||
chat_page.visit_channel_members(channel_1)
|
||||
|
||||
expect(page).to have_selector(".channel-members-view__list-item", count: 50)
|
||||
@ -58,7 +58,11 @@ RSpec.describe "Channel - Info - Members page", type: :system, js: true do
|
||||
end
|
||||
|
||||
context "with filter" do
|
||||
xit "filters members" do
|
||||
it "filters members" do
|
||||
Jobs.run_immediately!
|
||||
channel_1.update!(user_count_stale: true)
|
||||
Jobs::UpdateChannelUserCount.new.execute(chat_channel_id: channel_1.id)
|
||||
|
||||
chat_page.visit_channel_members(channel_1)
|
||||
find(".channel-members-view__search-input").fill_in(with: "cat")
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ RSpec.describe "JIT messages", type: :system, js: true do
|
||||
end
|
||||
|
||||
context "when mentioning a user not on the channel" do
|
||||
xit "displays a mention warning" do
|
||||
it "displays a mention warning" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
chat.visit_channel(channel_1)
|
||||
@ -23,6 +23,7 @@ RSpec.describe "JIT messages", type: :system, js: true do
|
||||
|
||||
expect(page).to have_content(
|
||||
I18n.t("js.chat.mention_warning.without_membership.one", username: other_user.username),
|
||||
wait: 5,
|
||||
)
|
||||
end
|
||||
end
|
||||
@ -36,7 +37,7 @@ RSpec.describe "JIT messages", type: :system, js: true do
|
||||
private_channel_1.add(current_user)
|
||||
end
|
||||
|
||||
xit "displays a mention warning" do
|
||||
it "displays a mention warning" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
chat.visit_channel(private_channel_1)
|
||||
@ -44,6 +45,7 @@ RSpec.describe "JIT messages", type: :system, js: true do
|
||||
|
||||
expect(page).to have_content(
|
||||
I18n.t("js.chat.mention_warning.cannot_see.one", username: other_user.username),
|
||||
wait: 5,
|
||||
)
|
||||
end
|
||||
end
|
||||
@ -52,7 +54,7 @@ RSpec.describe "JIT messages", type: :system, js: true do
|
||||
context "when group can't be mentioned" do
|
||||
fab!(:group_1) { Fabricate(:group, mentionable_level: Group::ALIAS_LEVELS[:nobody]) }
|
||||
|
||||
xit "displays a mention warning" do
|
||||
it "displays a mention warning" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
chat.visit_channel(channel_1)
|
||||
@ -60,6 +62,7 @@ RSpec.describe "JIT messages", type: :system, js: true do
|
||||
|
||||
expect(page).to have_content(
|
||||
I18n.t("js.chat.mention_warning.group_mentions_disabled.one", group_name: group_1.name),
|
||||
wait: 5,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@ -32,6 +32,8 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||
context "when not member of the channel" do
|
||||
context "when a message is created" do
|
||||
it "doesn't show anything" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
visit("/chat")
|
||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
||||
|
||||
@ -48,7 +50,6 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||
|
||||
context "when user is in DnD" do
|
||||
before do
|
||||
# Jobs.run_immediately!
|
||||
Fabricate(
|
||||
:do_not_disturb_timing,
|
||||
user: current_user,
|
||||
@ -57,7 +58,9 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||
)
|
||||
end
|
||||
|
||||
xit "doesn’t show indicator in header" do
|
||||
it "doesn’t show indicator in header" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
visit("/chat")
|
||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
||||
|
||||
@ -70,7 +73,9 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||
before { channel_1.membership_for(current_user).update!(muted: true) }
|
||||
|
||||
context "when a message is created" do
|
||||
xit "doesn't show anything" do
|
||||
it "doesn't show anything" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
visit("/chat")
|
||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
||||
|
||||
@ -84,6 +89,8 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||
|
||||
context "when a message is created" do
|
||||
it "correctly renders notifications" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
visit("/chat")
|
||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
||||
|
||||
@ -97,6 +104,8 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||
|
||||
context "when a message with mentions is created" do
|
||||
it "correctly renders notifications" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
visit("/chat")
|
||||
using_session(:user_1) do
|
||||
create_message(
|
||||
@ -126,6 +135,8 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||
|
||||
context "when a message is created" do
|
||||
it "correctly renders notifications" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
visit("/chat")
|
||||
using_session(:user_1) { create_message(channel: dm_channel_1, creator: user_1) }
|
||||
|
||||
@ -134,12 +145,14 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||
".chat-channel-row[data-chat-channel-id=\"#{dm_channel_1.id}\"] .chat-channel-unread-indicator",
|
||||
)
|
||||
|
||||
using_session(:user_1) { create_message(channel: dm_channel_1, creator: user_1) }
|
||||
using_session(:user_1) { create_message(channel: dm_channel_1, creator: user_1) }
|
||||
|
||||
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "2")
|
||||
end
|
||||
|
||||
it "reorders channels" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
visit("/chat")
|
||||
|
||||
expect(page).to have_css(
|
||||
@ -174,6 +187,8 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||
|
||||
context "when messages are created" do
|
||||
it "correctly renders notifications" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
visit("/chat")
|
||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
||||
|
||||
|
||||
@ -46,7 +46,6 @@ RSpec.describe "Message notifications - with sidebar", type: :system, js: true d
|
||||
|
||||
context "when user is in DnD" do
|
||||
before do
|
||||
# Jobs.run_immediately!
|
||||
Fabricate(
|
||||
:do_not_disturb_timing,
|
||||
user: current_user,
|
||||
@ -55,7 +54,9 @@ RSpec.describe "Message notifications - with sidebar", type: :system, js: true d
|
||||
)
|
||||
end
|
||||
|
||||
xit "doesn’t show indicator in header" do
|
||||
it "doesn’t show indicator in header" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
visit("/")
|
||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
||||
|
||||
@ -89,9 +90,9 @@ RSpec.describe "Message notifications - with sidebar", type: :system, js: true d
|
||||
end
|
||||
|
||||
context "when a message with mentions is created" do
|
||||
# before { Jobs.run_immediately! }
|
||||
it "correctly renders notifications" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
xit "correctly renders notifications" do
|
||||
visit("/")
|
||||
using_session(:user_1) do
|
||||
create_message(
|
||||
|
||||
@ -34,6 +34,22 @@ describe "Uploading files in chat messages", type: :system, js: true do
|
||||
expect(ChatMessage.last.uploads.count).to eq(1)
|
||||
end
|
||||
|
||||
it "allows uploading multiple files" do
|
||||
chat.visit_channel(channel_1)
|
||||
file_path_1 = file_from_fixtures("logo.png", "images").path
|
||||
file_path_2 = file_from_fixtures("logo.jpg", "images").path
|
||||
attach_file([file_path_1, file_path_2]) do
|
||||
channel.open_action_menu
|
||||
channel.click_action_button("chat-upload-btn")
|
||||
end
|
||||
expect(page).to have_css(".chat-composer-upload .preview .preview-img", count: 2)
|
||||
channel.send_message("upload testing")
|
||||
|
||||
expect(page).not_to have_css(".chat-composer-upload")
|
||||
expect(channel).to have_message(text: "upload testing")
|
||||
expect(ChatMessage.last.uploads.count).to eq(2)
|
||||
end
|
||||
|
||||
it "allows uploading a huge image file with preprocessing" do
|
||||
SiteSetting.composer_media_optimization_image_bytes_optimization_threshold = 200.kilobytes
|
||||
chat.visit_channel(channel_1)
|
||||
|
||||
@ -39,10 +39,10 @@ RSpec.describe "User menu notifications | sidebar", type: :system, js: true do
|
||||
context "when dm channel" do
|
||||
fab!(:dm_channel_1) { Fabricate(:direct_message_channel, users: [current_user, other_user]) }
|
||||
|
||||
# before { Jobs.run_immediately! }
|
||||
|
||||
context "when @username" do
|
||||
xit "shows a mention notification" do
|
||||
it "shows a mention notification" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
message =
|
||||
Chat::ChatMessageCreator.create(
|
||||
chat_channel: dm_channel_1,
|
||||
@ -106,7 +106,9 @@ RSpec.describe "User menu notifications | sidebar", type: :system, js: true do
|
||||
end
|
||||
|
||||
context "when @username" do
|
||||
xit "shows a mention notification" do
|
||||
it "shows a mention notification" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
message =
|
||||
Chat::ChatMessageCreator.create(
|
||||
chat_channel: channel_1,
|
||||
|
||||
@ -13,10 +13,11 @@ RSpec.describe "User status | sidebar", type: :system, js: true do
|
||||
chat_system_bootstrap
|
||||
current_user.set_status!("online", "heart")
|
||||
sign_in(current_user)
|
||||
# Jobs.run_immediately!
|
||||
end
|
||||
|
||||
xit "shows user status" do
|
||||
it "shows user status" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
visit("/")
|
||||
|
||||
expect(find(".user-status .emoji")["title"]).to eq("online")
|
||||
@ -24,7 +25,9 @@ RSpec.describe "User status | sidebar", type: :system, js: true do
|
||||
end
|
||||
|
||||
context "when changing status" do
|
||||
xit "updates status" do
|
||||
it "updates status" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
visit("/")
|
||||
current_user.set_status!("offline", "tooth")
|
||||
|
||||
@ -34,7 +37,9 @@ RSpec.describe "User status | sidebar", type: :system, js: true do
|
||||
end
|
||||
|
||||
context "when removing status" do
|
||||
xit "removes status" do
|
||||
it "removes status" do
|
||||
Jobs.run_immediately!
|
||||
|
||||
visit("/")
|
||||
current_user.clear_status!
|
||||
|
||||
|
||||
@ -6,6 +6,10 @@ RSpec.describe Auth::ManagedAuthenticator do
|
||||
def name
|
||||
"myauth"
|
||||
end
|
||||
|
||||
def primary_email_verified?(auth_token)
|
||||
auth_token[:info][:email_verified]
|
||||
end
|
||||
end.new
|
||||
}
|
||||
|
||||
@ -16,7 +20,8 @@ RSpec.describe Auth::ManagedAuthenticator do
|
||||
info: {
|
||||
name: "Best Display Name",
|
||||
email: "awesome@example.com",
|
||||
nickname: "IAmGroot"
|
||||
nickname: "IAmGroot",
|
||||
email_verified: true
|
||||
},
|
||||
credentials: {
|
||||
token: "supersecrettoken"
|
||||
@ -59,16 +64,21 @@ RSpec.describe Auth::ManagedAuthenticator do
|
||||
|
||||
it 'only sets email valid for present strings' do
|
||||
# (Twitter sometimes sends empty email strings)
|
||||
result = authenticator.after_authenticate(create_hash.merge(info: { email: "email@example.com" }))
|
||||
result = authenticator.after_authenticate(create_hash.merge(info: { email: "email@example.com", email_verified: true }))
|
||||
expect(result.email_valid).to eq(true)
|
||||
|
||||
result = authenticator.after_authenticate(create_hash.merge(info: { email: "" }))
|
||||
result = authenticator.after_authenticate(create_hash.merge(info: { email: "", email_verified: true }))
|
||||
expect(result.email_valid).to be_falsey
|
||||
|
||||
result = authenticator.after_authenticate(create_hash.merge(info: { email: nil }))
|
||||
result = authenticator.after_authenticate(create_hash.merge(info: { email: nil, email_verified: true }))
|
||||
expect(result.email_valid).to be_falsey
|
||||
end
|
||||
|
||||
it 'does not set email valid if email_verified is false' do
|
||||
result = authenticator.after_authenticate(create_hash.merge(info: { email: "email@example.com", email_verified: false }))
|
||||
expect(result.email_valid).to eq(false)
|
||||
end
|
||||
|
||||
describe 'connecting to another user account' do
|
||||
fab!(:user1) { Fabricate(:user) }
|
||||
fab!(:user2) { Fabricate(:user) }
|
||||
|
||||
@ -213,7 +213,14 @@ RSpec.describe BookmarkManager do
|
||||
|
||||
it "when post is deleted it raises invalid access from guardian check" do
|
||||
post.trash!
|
||||
expect { subject.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: name) }.to raise_error(Discourse::InvalidAccess)
|
||||
expect do
|
||||
subject.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: name)
|
||||
end.to raise_error(Discourse::InvalidAccess)
|
||||
end
|
||||
|
||||
it "adds a validation error when the bookmarkable_type is not registered" do
|
||||
subject.create_for(bookmarkable_id: post.id, bookmarkable_type: "BlahFactory", name: name)
|
||||
expect(subject.errors.full_messages).to include(I18n.t("bookmarks.errors.invalid_bookmarkable", type: "BlahFactory"))
|
||||
end
|
||||
|
||||
it "updates the topic user bookmarked column to true if any post is bookmarked" do
|
||||
@ -227,9 +234,31 @@ RSpec.describe BookmarkManager do
|
||||
expect(tu.bookmarked).to eq(true)
|
||||
end
|
||||
|
||||
it "sets auto_delete_preference to never by default" do
|
||||
it "sets auto_delete_preference to clear_reminder by default" do
|
||||
bookmark = subject.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: name, reminder_at: reminder_at)
|
||||
expect(bookmark.auto_delete_preference).to eq(Bookmark.auto_delete_preferences[:never])
|
||||
expect(bookmark.auto_delete_preference).to eq(Bookmark.auto_delete_preferences[:clear_reminder])
|
||||
end
|
||||
|
||||
context "when the user has set their bookmark_auto_delete_preference" do
|
||||
before do
|
||||
user.user_option.update!(bookmark_auto_delete_preference: Bookmark.auto_delete_preferences[:on_owner_reply])
|
||||
end
|
||||
|
||||
it "sets auto_delete_preferences to the user's user_option.bookmark_auto_delete_preference" do
|
||||
bookmark = subject.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: name, reminder_at: reminder_at)
|
||||
expect(bookmark.auto_delete_preference).to eq(Bookmark.auto_delete_preferences[:on_owner_reply])
|
||||
end
|
||||
|
||||
it "uses the passed in auto_delete_preference option instead of the user's one" do
|
||||
bookmark = subject.create_for(
|
||||
bookmarkable_id: post.id,
|
||||
bookmarkable_type: "Post",
|
||||
name: name,
|
||||
reminder_at: reminder_at,
|
||||
options: { auto_delete_preference: Bookmark.auto_delete_preferences[:when_reminder_sent] }
|
||||
)
|
||||
expect(bookmark.auto_delete_preference).to eq(Bookmark.auto_delete_preferences[:when_reminder_sent])
|
||||
end
|
||||
end
|
||||
|
||||
context "when a reminder time is provided" do
|
||||
|
||||
@ -870,10 +870,17 @@ RSpec.describe CookedPostProcessor do
|
||||
let(:post) { build(:post) }
|
||||
let(:cpp) { CookedPostProcessor.new(post) }
|
||||
|
||||
let(:image_sizes) do
|
||||
{ "http://my.discourse.org/image.png" => { "width" => 111, "height" => 222 } }
|
||||
end
|
||||
|
||||
it "returns the size" do
|
||||
image_sizes = { "http://my.discourse.org/image.png" => { "width" => 111, "height" => 222 } }
|
||||
expect(cpp.get_size_from_image_sizes("/image.png", image_sizes)).to eq([111, 222])
|
||||
end
|
||||
|
||||
it "returns nil whe img node has no src" do
|
||||
expect(cpp.get_size_from_image_sizes(nil, image_sizes)).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#get_size" do
|
||||
|
||||
@ -2020,7 +2020,7 @@ RSpec.describe User do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
||||
it 'should publish the right message' do
|
||||
message = MessageBus.track_publish('/logout') { user.logged_out }.first
|
||||
message = MessageBus.track_publish("/logout/#{user.id}") { user.logged_out }.first
|
||||
|
||||
expect(message.data).to eq(user.id)
|
||||
end
|
||||
|
||||
@ -245,6 +245,10 @@ RSpec.configure do |config|
|
||||
allow: [Webdrivers::Chromedriver.base_url]
|
||||
)
|
||||
|
||||
if ENV["CAPBYARA_DEFAULT_MAX_WAIT_TIME"].present?
|
||||
Capybara.default_max_wait_time = ENV["CAPBYARA_DEFAULT_MAX_WAIT_TIME"].to_i
|
||||
end
|
||||
|
||||
Capybara.threadsafe = true
|
||||
Capybara.disable_animation = true
|
||||
|
||||
|
||||
@ -247,7 +247,7 @@ RSpec.describe SiteSerializer do
|
||||
SiteSetting.whispers_allowed_groups = "#{group1.id}|#{group2.id}"
|
||||
|
||||
serialized = described_class.new(Site.new(admin_guardian), scope: admin_guardian, root: false).as_json
|
||||
expect(serialized[:whispers_allowed_groups_names]).to eq(["whisperers1", "whisperers2"])
|
||||
expect(serialized[:whispers_allowed_groups_names]).to contain_exactly("whisperers1", "whisperers2")
|
||||
end
|
||||
|
||||
it "returns correct group names for automatic groups" do
|
||||
@ -255,7 +255,7 @@ RSpec.describe SiteSerializer do
|
||||
SiteSetting.whispers_allowed_groups = "#{Group::AUTO_GROUPS[:staff]}|#{Group::AUTO_GROUPS[:trust_level_4]}"
|
||||
|
||||
serialized = described_class.new(Site.new(admin_guardian), scope: admin_guardian, root: false).as_json
|
||||
expect(serialized[:whispers_allowed_groups_names]).to eq(["staff", "trust_level_4"])
|
||||
expect(serialized[:whispers_allowed_groups_names]).to contain_exactly("trust_level_4", "staff")
|
||||
end
|
||||
|
||||
it "returns group names when user is allowed to whisper" do
|
||||
@ -263,7 +263,7 @@ RSpec.describe SiteSerializer do
|
||||
SiteSetting.whispers_allowed_groups = "#{group1.id}|#{group2.id}"
|
||||
|
||||
serialized = described_class.new(Site.new(user_guardian), scope: user_guardian, root: false).as_json
|
||||
expect(serialized[:whispers_allowed_groups_names]).to eq(["whisperers1", "whisperers2"])
|
||||
expect(serialized[:whispers_allowed_groups_names]).to contain_exactly("whisperers1", "whisperers2")
|
||||
end
|
||||
|
||||
it "returns nil when user is not allowed to whisper" do
|
||||
|
||||
@ -2,30 +2,34 @@
|
||||
|
||||
describe "Bookmarking posts and topics", type: :system, js: true do
|
||||
fab!(:topic) { Fabricate(:topic) }
|
||||
fab!(:user) { Fabricate(:user, username: "bookmarkguy") }
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
fab!(:post) { Fabricate(:post, topic: topic, raw: "This is some post to bookmark") }
|
||||
fab!(:post2) { Fabricate(:post, topic: topic, raw: "Some interesting post content") }
|
||||
|
||||
it "allows logged in user to create bookmarks with and without reminders" do
|
||||
sign_in user
|
||||
visit "/t/#{topic.id}"
|
||||
topic_page = PageObjects::Pages::Topic.new
|
||||
expect(topic_page).to have_post_content(post)
|
||||
let(:topic_page) { PageObjects::Pages::Topic.new }
|
||||
let(:bookmark_modal) { PageObjects::Modals::Bookmark.new }
|
||||
|
||||
before { sign_in user }
|
||||
|
||||
def visit_topic_and_open_bookmark_modal(post)
|
||||
topic_page.visit_topic(topic)
|
||||
topic_page.expand_post_actions(post)
|
||||
topic_page.click_post_action_button(post, :bookmark)
|
||||
end
|
||||
|
||||
it "allows the user to create bookmarks with and without reminders" do
|
||||
visit_topic_and_open_bookmark_modal(post)
|
||||
|
||||
bookmark_modal = PageObjects::Modals::Bookmark.new
|
||||
bookmark_modal.fill_name("something important")
|
||||
bookmark_modal.save
|
||||
|
||||
expect(topic_page).to have_post_bookmarked(post)
|
||||
bookmark = Bookmark.find_by(bookmarkable: post, user: user)
|
||||
expect(bookmark.name).to eq("something important")
|
||||
expect(bookmark.reminder_at).to eq(nil)
|
||||
|
||||
topic_page.expand_post_actions(post2)
|
||||
topic_page.click_post_action_button(post2, :bookmark)
|
||||
visit_topic_and_open_bookmark_modal(post2)
|
||||
|
||||
bookmark_modal = PageObjects::Modals::Bookmark.new
|
||||
bookmark_modal.select_preset_reminder(:tomorrow)
|
||||
expect(topic_page).to have_post_bookmarked(post2)
|
||||
bookmark = Bookmark.find_by(bookmarkable: post2, user: user)
|
||||
@ -34,13 +38,8 @@ describe "Bookmarking posts and topics", type: :system, js: true do
|
||||
end
|
||||
|
||||
it "does not create a bookmark if the modal is closed with the cancel button" do
|
||||
sign_in user
|
||||
visit "/t/#{topic.id}"
|
||||
topic_page = PageObjects::Pages::Topic.new
|
||||
topic_page.expand_post_actions(post)
|
||||
topic_page.click_post_action_button(post, :bookmark)
|
||||
visit_topic_and_open_bookmark_modal(post)
|
||||
|
||||
bookmark_modal = PageObjects::Modals::Bookmark.new
|
||||
bookmark_modal.fill_name("something important")
|
||||
bookmark_modal.cancel
|
||||
|
||||
@ -48,20 +47,57 @@ describe "Bookmarking posts and topics", type: :system, js: true do
|
||||
expect(Bookmark.exists?(bookmarkable: post, user: user)).to eq(false)
|
||||
end
|
||||
|
||||
it "creates a bookmark if the modal is closed by clicking outside the modal window" do
|
||||
visit_topic_and_open_bookmark_modal(post)
|
||||
|
||||
bookmark_modal.fill_name("something important")
|
||||
bookmark_modal.click_outside
|
||||
|
||||
expect(topic_page).to have_post_bookmarked(post)
|
||||
end
|
||||
|
||||
it "allows the topic to be bookmarked" do
|
||||
sign_in user
|
||||
visit "/t/#{topic.id}"
|
||||
topic_page = PageObjects::Pages::Topic.new
|
||||
topic_page.visit_topic(topic)
|
||||
topic_page.click_topic_footer_button(:bookmark)
|
||||
|
||||
bookmark_modal = PageObjects::Modals::Bookmark.new
|
||||
bookmark_modal.fill_name("something important")
|
||||
bookmark_modal.save
|
||||
|
||||
expect(topic_page).to have_topic_bookmarked
|
||||
bookmark = try_until_success do
|
||||
expect(Bookmark.exists?(bookmarkable: topic, user: user)).to eq(true)
|
||||
end
|
||||
bookmark =
|
||||
try_until_success { expect(Bookmark.exists?(bookmarkable: topic, user: user)).to eq(true) }
|
||||
expect(bookmark).not_to eq(nil)
|
||||
end
|
||||
|
||||
context "when the user has a bookmark auto_delete_preference" do
|
||||
before do
|
||||
user.user_option.update!(
|
||||
bookmark_auto_delete_preference: Bookmark.auto_delete_preferences[:on_owner_reply],
|
||||
)
|
||||
end
|
||||
|
||||
it "is respected when the user creates a new bookmark" do
|
||||
visit_topic_and_open_bookmark_modal(post)
|
||||
|
||||
bookmark_modal.save
|
||||
expect(topic_page).to have_post_bookmarked(post)
|
||||
|
||||
bookmark = Bookmark.find_by(bookmarkable: post, user: user)
|
||||
expect(bookmark.auto_delete_preference).to eq(
|
||||
Bookmark.auto_delete_preferences[:on_owner_reply],
|
||||
)
|
||||
end
|
||||
|
||||
it "allows the user to choose a different auto delete preference for a bookmark" do
|
||||
visit_topic_and_open_bookmark_modal(post)
|
||||
|
||||
bookmark_modal.save
|
||||
expect(topic_page).to have_post_bookmarked(post)
|
||||
|
||||
bookmark = Bookmark.find_by(bookmarkable: post, user: user)
|
||||
expect(bookmark.auto_delete_preference).to eq(
|
||||
Bookmark.auto_delete_preferences[:on_owner_reply],
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -13,6 +13,10 @@ module PageObjects
|
||||
def cancel
|
||||
find(".d-modal-cancel").click
|
||||
end
|
||||
|
||||
def click_outside
|
||||
find(".modal-outer-container").click(x: 0, y: 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1605,9 +1605,9 @@ json-stable-stringify-without-jsonify@^1.0.1:
|
||||
integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
|
||||
|
||||
json5@^2.2.1:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.2.tgz#64471c5bdcc564c18f7c1d4df2e2297f2457c5ab"
|
||||
integrity sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||
|
||||
jsonfile@^6.0.1:
|
||||
version "6.1.0"
|
||||
|
||||
Reference in New Issue
Block a user