Version bump
This commit is contained in:
commit
f97b6a7dde
@ -1,8 +1,4 @@
|
||||
app/assets/javascripts/browser-update.js
|
||||
app/assets/javascripts/discourse-loader.js
|
||||
app/assets/javascripts/env.js
|
||||
app/assets/javascripts/main_include_admin.js
|
||||
app/assets/javascripts/vendor.js
|
||||
app/assets/javascripts/locales/i18n.js
|
||||
app/assets/javascripts/ember-addons/
|
||||
app/assets/javascripts/discourse/lib/autosize.js
|
||||
@ -13,7 +9,6 @@ lib/pretty_text/
|
||||
plugins/**/lib/javascripts/locale
|
||||
public/
|
||||
vendor/
|
||||
app/assets/javascripts/discourse/tests/test-boot-rails.js
|
||||
app/assets/javascripts/discourse/tests/fixtures
|
||||
node_modules/
|
||||
spec/
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
"fillIn": "off",
|
||||
"find": "off",
|
||||
"getSettledState": "off",
|
||||
"globalThis": "readonly",
|
||||
"hasModule": "off",
|
||||
"invisible": "off",
|
||||
"jQuery": "off",
|
||||
|
||||
21
.github/workflows/tests.yml
vendored
21
.github/workflows/tests.yml
vendored
@ -31,7 +31,7 @@ jobs:
|
||||
fail-fast: false
|
||||
|
||||
matrix:
|
||||
build_type: [backend, frontend, frontend-legacy, annotations]
|
||||
build_type: [backend, frontend, annotations]
|
||||
target: [core, plugins]
|
||||
exclude:
|
||||
- build_type: annotations
|
||||
@ -153,24 +153,9 @@ jobs:
|
||||
if: matrix.build_type == 'backend' && matrix.target == 'plugins'
|
||||
run: bin/rake plugin:spec
|
||||
|
||||
- name: Core QUnit (Legacy)
|
||||
if: matrix.build_type == 'frontend-legacy' && matrix.target == 'core'
|
||||
run: QUNIT_EMBER_CLI=0 bin/rake qunit:test['1200000']
|
||||
timeout-minutes: 30
|
||||
|
||||
- name: Wizard QUnit (Legacy)
|
||||
if: matrix.build_type == 'frontend-legacy' && matrix.target == 'core'
|
||||
run: QUNIT_EMBER_CLI=0 bin/rake qunit:test['600000','/wizard/qunit']
|
||||
timeout-minutes: 10
|
||||
|
||||
- name: Plugin QUnit (Legacy)
|
||||
if: matrix.build_type == 'frontend-legacy' && matrix.target == 'plugins'
|
||||
run: QUNIT_EMBER_CLI=0 bin/rake plugin:qunit['*','1200000']
|
||||
timeout-minutes: 30
|
||||
|
||||
- name: Plugin QUnit (Ember CLI)
|
||||
- name: Plugin QUnit
|
||||
if: matrix.build_type == 'frontend' && (matrix.target == 'plugins' || matrix.target == 'core-plugins')
|
||||
run: QUNIT_EMBER_CLI=1 bin/rake plugin:qunit['*','1200000']
|
||||
run: bin/rake plugin:qunit['*','1200000']
|
||||
timeout-minutes: 30
|
||||
|
||||
- name: Check Annotations
|
||||
|
||||
@ -9,10 +9,6 @@ config/locales/**/*.yml
|
||||
script/import_scripts/**/*.yml
|
||||
|
||||
app/assets/javascripts/browser-update.js
|
||||
app/assets/javascripts/discourse-loader.js
|
||||
app/assets/javascripts/env.js
|
||||
app/assets/javascripts/main_include_admin.js
|
||||
app/assets/javascripts/vendor.js
|
||||
app/assets/javascripts/locales/i18n.js
|
||||
app/assets/javascripts/ember-addons/
|
||||
app/assets/javascripts/discourse/lib/autosize.js
|
||||
@ -22,7 +18,6 @@ lib/highlight_js/
|
||||
plugins/**/lib/javascripts/locale
|
||||
public/
|
||||
vendor/
|
||||
app/assets/javascripts/discourse/tests/test-boot-rails.js
|
||||
app/assets/javascripts/discourse/tests/fixtures
|
||||
spec/
|
||||
node_modules/
|
||||
|
||||
27
Gemfile.lock
27
Gemfile.lock
@ -107,7 +107,7 @@ GEM
|
||||
addressable
|
||||
debug_inspector (1.1.0)
|
||||
diff-lcs (1.5.0)
|
||||
diffy (3.4.1)
|
||||
diffy (3.4.2)
|
||||
digest (3.1.0)
|
||||
discourse-ember-rails (0.18.6)
|
||||
active_model_serializers
|
||||
@ -135,7 +135,7 @@ GEM
|
||||
excon (0.92.3)
|
||||
execjs (2.8.1)
|
||||
exifr (1.3.9)
|
||||
fabrication (2.28.0)
|
||||
fabrication (2.29.0)
|
||||
faker (2.21.0)
|
||||
i18n (>= 1.8.11, < 2)
|
||||
fakeweb (1.3.0)
|
||||
@ -236,12 +236,12 @@ GEM
|
||||
mini_portile2 (2.8.0)
|
||||
mini_racer (0.6.2)
|
||||
libv8-node (~> 16.10.0.0)
|
||||
mini_scheduler (0.13.0)
|
||||
mini_scheduler (0.14.0)
|
||||
sidekiq (>= 4.2.3)
|
||||
mini_sql (1.4.0)
|
||||
mini_suffix (0.3.3)
|
||||
ffi (~> 1.9)
|
||||
minitest (5.15.0)
|
||||
minitest (5.16.1)
|
||||
mocha (1.14.0)
|
||||
msgpack (1.5.2)
|
||||
multi_json (1.15.0)
|
||||
@ -311,11 +311,11 @@ GEM
|
||||
openssl (> 2.0, < 3.1)
|
||||
optimist (3.0.1)
|
||||
parallel (1.22.1)
|
||||
parallel_tests (3.11.0)
|
||||
parallel_tests (3.11.1)
|
||||
parallel
|
||||
parser (3.1.2.0)
|
||||
ast (~> 2.4.1)
|
||||
pg (1.3.5)
|
||||
pg (1.4.1)
|
||||
progress (3.6.0)
|
||||
pry (0.13.1)
|
||||
coderay (~> 1.1)
|
||||
@ -335,8 +335,8 @@ GEM
|
||||
rack (>= 1.2.0)
|
||||
rack-protection (2.2.0)
|
||||
rack
|
||||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rack-test (2.0.2)
|
||||
rack (>= 1.3)
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
nokogiri (>= 1.6)
|
||||
@ -410,7 +410,8 @@ GEM
|
||||
activesupport (>= 3.1, < 7.1)
|
||||
json-schema (~> 2.2)
|
||||
railties (>= 3.1, < 7.1)
|
||||
rubocop (1.30.1)
|
||||
rubocop (1.31.1)
|
||||
json (~> 2.3)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.1.0.0)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
@ -450,7 +451,7 @@ GEM
|
||||
activesupport (>= 3.1)
|
||||
shoulda-matchers (5.1.0)
|
||||
activesupport (>= 5.2.0)
|
||||
sidekiq (6.4.2)
|
||||
sidekiq (6.5.1)
|
||||
connection_pool (>= 2.2.2)
|
||||
rack (~> 2.0)
|
||||
redis (>= 4.2.0)
|
||||
@ -481,7 +482,7 @@ GEM
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.8.2)
|
||||
unicode-display_width (2.1.0)
|
||||
unicode-display_width (2.2.0)
|
||||
unicorn (6.1.0)
|
||||
kgio (~> 2.6)
|
||||
raindrops (~> 0.7)
|
||||
@ -497,7 +498,7 @@ GEM
|
||||
jwt (~> 2.0)
|
||||
xorcist (1.1.2)
|
||||
yaml-lint (0.0.10)
|
||||
zeitwerk (2.5.4)
|
||||
zeitwerk (2.6.0)
|
||||
|
||||
PLATFORMS
|
||||
aarch64-linux
|
||||
@ -637,4 +638,4 @@ DEPENDENCIES
|
||||
yaml-lint
|
||||
|
||||
BUNDLED WITH
|
||||
2.3.13
|
||||
2.3.16
|
||||
|
||||
@ -40,8 +40,6 @@ If you want to set up a Discourse forum for production use, see our [**Discourse
|
||||
|
||||
If you're looking for business class hosting, see [discourse.org/buy](https://www.discourse.org/buy/).
|
||||
|
||||
If you're looking for our remote work solution, see [teams.discourse.com](https://teams.discourse.com/).
|
||||
|
||||
## Requirements
|
||||
|
||||
Discourse is built for the *next* 10 years of the Internet, so our requirements are high.
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
//= require main_include_admin
|
||||
//= require admin-plugins
|
||||
@ -16,6 +16,6 @@ export default Component.extend({
|
||||
|
||||
type: alias("label.type"),
|
||||
property: alias("label.mainProperty"),
|
||||
formatedValue: alias("computedLabel.formatedValue"),
|
||||
formattedValue: alias("computedLabel.formattedValue"),
|
||||
value: alias("computedLabel.value"),
|
||||
});
|
||||
|
||||
@ -3,7 +3,6 @@ import I18n from "I18n";
|
||||
import UppyUploadMixin from "discourse/mixins/uppy-upload";
|
||||
import { alias } from "@ember/object/computed";
|
||||
import bootbox from "bootbox";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend(UppyUploadMixin, {
|
||||
type: "txt",
|
||||
@ -16,9 +15,8 @@ export default Component.extend(UppyUploadMixin, {
|
||||
return { skipValidation: true };
|
||||
},
|
||||
|
||||
@discourseComputed("actionKey")
|
||||
data(actionKey) {
|
||||
return { action_key: actionKey };
|
||||
_perFileData() {
|
||||
return { action_key: this.actionKey };
|
||||
},
|
||||
|
||||
uploadDone() {
|
||||
|
||||
@ -6,7 +6,7 @@ import { bufferedProperty } from "discourse/mixins/buffered-content";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { propertyNotEqual } from "discourse/lib/computed";
|
||||
import { equal, reads } from "@ember/object/computed";
|
||||
import { run } from "@ember/runloop";
|
||||
import { next } from "@ember/runloop";
|
||||
import { action } from "@ember/object";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
|
||||
@ -33,7 +33,7 @@ export default Controller.extend(bufferedProperty("model"), {
|
||||
// this is needed because the model doesnt have default values
|
||||
// and as we are using a bufferedProperty it's not accessible
|
||||
// in any other way
|
||||
run.next(() => {
|
||||
next(() => {
|
||||
if (this.model) {
|
||||
if (!this.model.badge_type_id) {
|
||||
this.model.set(
|
||||
|
||||
@ -150,7 +150,7 @@ export default Mixin.create({
|
||||
"default_categories_tracking",
|
||||
"default_categories_muted",
|
||||
"default_categories_watching_first_post",
|
||||
"default_categories_regular",
|
||||
"default_categories_normal",
|
||||
"default_tags_watching",
|
||||
"default_tags_tracking",
|
||||
"default_tags_muted",
|
||||
|
||||
@ -354,7 +354,7 @@ const Report = EmberObject.extend({
|
||||
value,
|
||||
type,
|
||||
property: mainProperty,
|
||||
formatedValue: value ? escapeExpression(value) : "—",
|
||||
formattedValue: value ? escapeExpression(value) : "—",
|
||||
};
|
||||
},
|
||||
};
|
||||
@ -364,7 +364,7 @@ const Report = EmberObject.extend({
|
||||
_userLabel(properties, row) {
|
||||
const username = row[properties.username];
|
||||
|
||||
const formatedValue = () => {
|
||||
const formattedValue = () => {
|
||||
const userId = row[properties.id];
|
||||
|
||||
const user = EmberObject.create({
|
||||
@ -386,14 +386,14 @@ const Report = EmberObject.extend({
|
||||
|
||||
return {
|
||||
value: username,
|
||||
formatedValue: username ? formatedValue() : "—",
|
||||
formattedValue: username ? formattedValue() : "—",
|
||||
};
|
||||
},
|
||||
|
||||
_topicLabel(properties, row) {
|
||||
const topicTitle = row[properties.title];
|
||||
|
||||
const formatedValue = () => {
|
||||
const formattedValue = () => {
|
||||
const topicId = row[properties.id];
|
||||
const href = getURL(`/t/-/${topicId}`);
|
||||
return `<a href='${href}'>${escapeExpression(topicTitle)}</a>`;
|
||||
@ -401,7 +401,7 @@ const Report = EmberObject.extend({
|
||||
|
||||
return {
|
||||
value: topicTitle,
|
||||
formatedValue: topicTitle ? formatedValue() : "—",
|
||||
formattedValue: topicTitle ? formattedValue() : "—",
|
||||
};
|
||||
},
|
||||
|
||||
@ -414,7 +414,7 @@ const Report = EmberObject.extend({
|
||||
return {
|
||||
property: properties.title,
|
||||
value: postTitle,
|
||||
formatedValue:
|
||||
formattedValue:
|
||||
postTitle && href
|
||||
? `<a href='${href}'>${escapeExpression(postTitle)}</a>`
|
||||
: "—",
|
||||
@ -424,14 +424,14 @@ const Report = EmberObject.extend({
|
||||
_secondsLabel(value) {
|
||||
return {
|
||||
value: toNumber(value),
|
||||
formatedValue: durationTiny(value),
|
||||
formattedValue: durationTiny(value),
|
||||
};
|
||||
},
|
||||
|
||||
_percentLabel(value) {
|
||||
return {
|
||||
value: toNumber(value),
|
||||
formatedValue: value ? `${value}%` : "—",
|
||||
formattedValue: value ? `${value}%` : "—",
|
||||
};
|
||||
},
|
||||
|
||||
@ -440,25 +440,25 @@ const Report = EmberObject.extend({
|
||||
? true
|
||||
: options.formatNumbers;
|
||||
|
||||
const formatedValue = () => (formatNumbers ? number(value) : value);
|
||||
const formattedValue = () => (formatNumbers ? number(value) : value);
|
||||
|
||||
return {
|
||||
value: toNumber(value),
|
||||
formatedValue: value ? formatedValue() : "—",
|
||||
formattedValue: value ? formattedValue() : "—",
|
||||
};
|
||||
},
|
||||
|
||||
_bytesLabel(value) {
|
||||
return {
|
||||
value: toNumber(value),
|
||||
formatedValue: I18n.toHumanSize(value),
|
||||
formattedValue: I18n.toHumanSize(value),
|
||||
};
|
||||
},
|
||||
|
||||
_dateLabel(value, date, format = "LL") {
|
||||
return {
|
||||
value,
|
||||
formatedValue: value ? date.format(format) : "—",
|
||||
formattedValue: value ? date.format(format) : "—",
|
||||
};
|
||||
},
|
||||
|
||||
@ -467,14 +467,14 @@ const Report = EmberObject.extend({
|
||||
|
||||
return {
|
||||
value,
|
||||
formatedValue: value ? escaped : "—",
|
||||
formattedValue: value ? escaped : "—",
|
||||
};
|
||||
},
|
||||
|
||||
_linkLabel(properties, row) {
|
||||
const property = properties[0];
|
||||
const value = getURL(row[property]);
|
||||
const formatedValue = (href, anchor) => {
|
||||
const formattedValue = (href, anchor) => {
|
||||
return `<a href="${escapeExpression(href)}">${escapeExpression(
|
||||
anchor
|
||||
)}</a>`;
|
||||
@ -482,7 +482,7 @@ const Report = EmberObject.extend({
|
||||
|
||||
return {
|
||||
value,
|
||||
formatedValue: value ? formatedValue(value, row[properties[1]]) : "—",
|
||||
formattedValue: value ? formattedValue(value, row[properties[1]]) : "—",
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
{{html-safe formatedValue}}
|
||||
{{html-safe formattedValue}}
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
<tr class="admin-report-table-row">
|
||||
{{#each totalsForSample as |total|}}
|
||||
<td class="admin-report-table-cell {{total.type}} {{total.property}}">
|
||||
{{total.formatedValue}}
|
||||
{{total.formattedValue}}
|
||||
</td>
|
||||
{{/each}}
|
||||
</tr>
|
||||
|
||||
@ -3,7 +3,11 @@
|
||||
const EmberAddon = require("ember-cli/lib/broccoli/ember-addon");
|
||||
|
||||
module.exports = function (defaults) {
|
||||
let app = new EmberAddon(defaults, {});
|
||||
let app = new EmberAddon(defaults, {
|
||||
autoImport: {
|
||||
publicAssetURL: "",
|
||||
},
|
||||
});
|
||||
|
||||
return app.toTree();
|
||||
};
|
||||
|
||||
@ -15,39 +15,30 @@
|
||||
"start": "ember serve"
|
||||
},
|
||||
"dependencies": {
|
||||
"ember-auto-import": "^2.2.4",
|
||||
"ember-cli-babel": "^7.13.0",
|
||||
"ember-cli-htmlbars": "^4.2.0",
|
||||
"xss": "^1.0.8",
|
||||
"webpack": "^5.67.0"
|
||||
"ember-auto-import": "^2.4.2",
|
||||
"ember-cli-babel": "^7.23.1",
|
||||
"ember-cli-htmlbars": "^6.0.1",
|
||||
"webpack": "^5.73.0",
|
||||
"xss": "^1.0.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ember/optional-features": "^1.1.0",
|
||||
"@glimmer/component": "^1.0.0",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"ember-cli": "~3.25.3",
|
||||
"ember-cli-dependency-checker": "^3.2.0",
|
||||
"ember-cli-eslint": "^5.1.0",
|
||||
"ember-cli-inject-live-reload": "^2.0.1",
|
||||
"ember-cli-dependency-checker": "^3.3.1",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-template-lint": "^1.0.0-beta.3",
|
||||
"ember-cli-uglify": "^3.0.0",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
"ember-disable-prototype-extensions": "^1.1.3",
|
||||
"ember-export-application-global": "^2.0.1",
|
||||
"ember-load-initializers": "^2.1.1",
|
||||
"ember-maybe-import-regenerator": "^0.1.6",
|
||||
"ember-resolver": "^7.0.0",
|
||||
"ember-source": "~3.15.0",
|
||||
"ember-source-channel-url": "^2.0.1",
|
||||
"ember-try": "^2.0.0",
|
||||
"eslint": "^7.27.0",
|
||||
"eslint-plugin-ember": "^7.7.1",
|
||||
"eslint-plugin-node": "^10.0.0",
|
||||
"ember-source-channel-url": "^3.0.0",
|
||||
"loader.js": "^4.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "12.* || 14.* || >= 16",
|
||||
"node": "16.* || >= 18",
|
||||
"npm": "please-use-yarn",
|
||||
"yarn": ">= 1.21.1"
|
||||
},
|
||||
|
||||
0
app/assets/javascripts/admin/tests/index.html
Normal file
0
app/assets/javascripts/admin/tests/index.html
Normal file
@ -1,27 +0,0 @@
|
||||
// discourse-skip-module
|
||||
|
||||
(function () {
|
||||
if (window.unsupportedBrowser) {
|
||||
throw "Unsupported browser detected";
|
||||
}
|
||||
|
||||
let Discourse = requirejs("discourse/app").default.create();
|
||||
|
||||
// required for our template compiler
|
||||
window.__DISCOURSE_RAW_TEMPLATES = requirejs(
|
||||
"discourse-common/lib/raw-templates"
|
||||
).__DISCOURSE_RAW_TEMPLATES;
|
||||
|
||||
// required for addons to work without Ember CLI
|
||||
// eslint-disable-next-line no-undef
|
||||
Object.keys(Ember.TEMPLATES).forEach((k) => {
|
||||
if (k.indexOf("select-kit") === 0) {
|
||||
// eslint-disable-next-line no-undef
|
||||
let template = Ember.TEMPLATES[k];
|
||||
define(k, () => template);
|
||||
}
|
||||
});
|
||||
|
||||
// ensure Discourse is added as a global
|
||||
window.Discourse = Discourse;
|
||||
})();
|
||||
@ -1,104 +0,0 @@
|
||||
//= require_tree ./truth-helpers/addon
|
||||
//= require_tree ./discourse-common/addon
|
||||
//= require ./polyfills
|
||||
//= require_tree ./select-kit/addon
|
||||
//= require ./discourse/app/app
|
||||
//= require ./app-boot
|
||||
|
||||
// Stuff we need to load first
|
||||
//= require ./discourse/app/lib/to-markdown
|
||||
//= require ./discourse/app/lib/utilities
|
||||
//= require ./discourse/app/lib/user-presence
|
||||
//= require ./discourse/app/lib/logout
|
||||
//= require ./discourse/app/mixins/singleton
|
||||
//= require ./discourse/app/models/rest
|
||||
//= require ./discourse/app/models/session
|
||||
//= require ./discourse/app/lib/ajax
|
||||
//= require ./discourse/app/lib/text
|
||||
//= require ./discourse/app/lib/hash
|
||||
//= require ./discourse/app/lib/load-script
|
||||
//= require ./discourse/app/lib/notification-levels
|
||||
//= require ./discourse/app/services/app-events
|
||||
//= require ./discourse/app/lib/offset-calculator
|
||||
//= require ./discourse/app/lib/lock-on
|
||||
//= require ./discourse/app/lib/url
|
||||
//= require ./discourse/app/lib/email-provider-default-settings
|
||||
//= require ./discourse/app/lib/debounce
|
||||
//= require ./discourse/app/lib/quote
|
||||
//= require ./discourse/app/lib/key-value-store
|
||||
//= require ./discourse/app/lib/computed
|
||||
//= require ./discourse/app/lib/formatter
|
||||
//= require ./discourse/app/lib/text-direction
|
||||
//= require ./discourse/app/lib/eyeline
|
||||
//= require ./discourse/app/lib/show-modal
|
||||
//= require ./discourse/app/lib/download-calendar
|
||||
//= require ./discourse/app/mixins/scrolling
|
||||
//= require ./discourse/app/lib/ajax-error
|
||||
//= require ./discourse/app/models/result-set
|
||||
//= require ./discourse/app/models/store
|
||||
//= require ./discourse/app/models/action-summary
|
||||
//= require ./discourse/app/models/permission-type
|
||||
//= require ./discourse/app/models/category
|
||||
//= require ./discourse/app/models/topic
|
||||
//= require ./discourse/app/models/draft
|
||||
//= require ./discourse/app/models/composer
|
||||
//= require ./discourse/app/models/badge-grouping
|
||||
//= require ./discourse/app/models/badge
|
||||
//= require ./discourse/app/models/permission-type
|
||||
//= require ./discourse/app/models/user-action-group
|
||||
//= require ./discourse/app/models/trust-level
|
||||
//= require ./discourse/app/lib/search
|
||||
//= require ./discourse/app/lib/user-search
|
||||
//= require ./discourse/app/lib/export-csv
|
||||
//= require ./discourse/app/lib/autocomplete
|
||||
//= require ./discourse/app/lib/after-transition
|
||||
//= require ./discourse/app/lib/safari-hacks
|
||||
//= require ./discourse/app/lib/put-cursor-at-end
|
||||
//= require_tree ./discourse/app/adapters
|
||||
//= require ./discourse/app/models/post-action-type
|
||||
//= require ./discourse/app/models/post
|
||||
//= require ./discourse/app/lib/posts-with-placeholders
|
||||
//= require ./discourse/app/models/post-stream
|
||||
//= require ./discourse/app/models/topic-details
|
||||
//= require ./discourse/app/models/topic
|
||||
//= require ./discourse/app/models/user-action
|
||||
//= require ./discourse/app/models/draft
|
||||
//= require ./discourse/app/models/composer
|
||||
//= require ./discourse/app/models/user-badge
|
||||
//= require_tree ./discourse/app/lib
|
||||
//= require_tree ./discourse/app/mixins
|
||||
//= require ./discourse/app/models/invite
|
||||
//= require ./discourse/app/controllers/discovery-sortable
|
||||
//= require ./discourse/app/controllers/navigation/default
|
||||
//= require ./discourse/app/components/edit-category-panel
|
||||
//= require ./discourse/app/lib/link-mentions
|
||||
//= require ./discourse/app/components/site-header
|
||||
//= require ./discourse/app/components/d-editor
|
||||
//= require ./discourse/app/routes/discourse
|
||||
//= require ./discourse/app/routes/build-topic-route
|
||||
//= require ./discourse/app/routes/restricted-user
|
||||
//= require ./discourse/app/routes/user-topic-list
|
||||
//= require ./discourse/app/routes/user-activity-stream
|
||||
//= require ./discourse/app/routes/topic-from-params
|
||||
//= require ./discourse/app/components/text-field
|
||||
//= require ./discourse/app/components/conditional-loading-spinner
|
||||
//= require ./discourse/app/helpers/user-avatar
|
||||
//= require ./discourse/app/helpers/cold-age-class
|
||||
//= require ./discourse/app/helpers/loading-spinner
|
||||
//= require ./discourse/app/helpers/category-link
|
||||
//= require ./discourse/app/lib/export-result
|
||||
//= require ./discourse/app/mapping-router
|
||||
|
||||
//= require_tree ./discourse/app/controllers
|
||||
//= require_tree ./discourse/app/models
|
||||
//= require_tree ./discourse/app/components
|
||||
//= require_tree ./discourse/app/raw-views
|
||||
//= require_tree ./discourse/app/helpers
|
||||
//= require_tree ./discourse/app/templates
|
||||
//= require_tree ./discourse/app/routes
|
||||
//= require_tree ./discourse/app/pre-initializers
|
||||
//= require_tree ./discourse/app/initializers
|
||||
//= require_tree ./discourse/app/services
|
||||
|
||||
//= require_tree ./discourse/app/widgets
|
||||
//= require ./widget-runtime
|
||||
@ -1,3 +1,5 @@
|
||||
import deprecated from "discourse-common/lib/deprecated";
|
||||
|
||||
export const INPUT_DELAY = 250;
|
||||
|
||||
let environment = "unknown";
|
||||
@ -19,6 +21,9 @@ export function isTesting() {
|
||||
// eslint-disable-next-line no-undef
|
||||
let _isLegacy = Ember.VERSION.startsWith("3.12");
|
||||
export function isLegacyEmber() {
|
||||
deprecated("`isLegacyEmber()` is now deprecated and always returns true", {
|
||||
dropFrom: "3.0.0.beta1",
|
||||
});
|
||||
return _isLegacy;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { debounce, next, run } from "@ember/runloop";
|
||||
import { isLegacyEmber, isTesting } from "discourse-common/config/environment";
|
||||
import { debounce } from "@ember/runloop";
|
||||
import { isTesting } from "discourse-common/config/environment";
|
||||
|
||||
/**
|
||||
Debounce a Javascript function. This means if it's called many times in a time limit it
|
||||
@ -7,13 +7,13 @@ import { isLegacyEmber, isTesting } from "discourse-common/config/environment";
|
||||
Original function will be called with the context and arguments from the last call made.
|
||||
**/
|
||||
|
||||
let testingFunc = isLegacyEmber() ? run : next;
|
||||
|
||||
export default function () {
|
||||
if (isTesting()) {
|
||||
// Don't include the time argument (in ms)
|
||||
// Replace the time argument with 10ms
|
||||
let args = [].slice.call(arguments, 0, -1);
|
||||
return testingFunc.apply(void 0, args);
|
||||
args.push(10);
|
||||
|
||||
return debounce.apply(undefined, args);
|
||||
} else {
|
||||
return debounce(...arguments);
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import attributeHook from "discourse-common/lib/attribute-hook";
|
||||
import { h } from "virtual-dom";
|
||||
import { isDevelopment } from "discourse-common/config/environment";
|
||||
import escape from "discourse-common/lib/escape";
|
||||
import deprecated from "discourse-common/lib/deprecated";
|
||||
|
||||
const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
||||
let _renderers = [];
|
||||
@ -159,9 +160,18 @@ registerIconRenderer({
|
||||
I18n.t(params.title)
|
||||
)}'>${html}</span>`;
|
||||
}
|
||||
|
||||
if (params.translatedtitle) {
|
||||
deprecated(`use 'translatedTitle' option instead of 'translatedtitle'`, {
|
||||
since: "2.9.0.beta6",
|
||||
dropFrom: "2.10.0.beta1",
|
||||
});
|
||||
params.translatedTitle = params.translatedtitle;
|
||||
}
|
||||
|
||||
if (params.translatedTitle) {
|
||||
html = `<span class="svg-icon-title" title='${escape(
|
||||
params.translatedtitle
|
||||
params.translatedTitle
|
||||
)}'>${html}</span>`;
|
||||
}
|
||||
return html;
|
||||
|
||||
@ -93,6 +93,7 @@ export function buildResolver(baseName) {
|
||||
if (split.length > 1) {
|
||||
const appBase = `${baseName}/${split[0]}s/`;
|
||||
const adminBase = "admin/" + split[0] + "s/";
|
||||
const wizardBase = "wizard/" + split[0] + "s/";
|
||||
|
||||
// Allow render 'admin/templates/xyz' too
|
||||
split[1] = split[1].replace(".templates", "").replace("/templates", "");
|
||||
@ -101,7 +102,8 @@ export function buildResolver(baseName) {
|
||||
let dashed = dasherize(split[1].replace(/\./g, "/"));
|
||||
if (
|
||||
requirejs.entries[appBase + dashed] ||
|
||||
requirejs.entries[adminBase + dashed]
|
||||
requirejs.entries[adminBase + dashed] ||
|
||||
requirejs.entries[wizardBase + dashed]
|
||||
) {
|
||||
return split[0] + ":" + dashed;
|
||||
}
|
||||
@ -110,7 +112,8 @@ export function buildResolver(baseName) {
|
||||
dashed = dasherize(split[1].replace(/\./g, "-"));
|
||||
if (
|
||||
requirejs.entries[appBase + dashed] ||
|
||||
requirejs.entries[adminBase + dashed]
|
||||
requirejs.entries[adminBase + dashed] ||
|
||||
requirejs.entries[wizardBase + dashed]
|
||||
) {
|
||||
return split[0] + ":" + dashed;
|
||||
}
|
||||
@ -253,6 +256,7 @@ export function buildResolver(baseName) {
|
||||
templates[decamelized.replace(/\_/, "/")] ||
|
||||
templates[`${baseName}/templates/${withoutType}`] ||
|
||||
this.findAdminTemplate(parsedName) ||
|
||||
this.findWizardTemplate(parsedName) ||
|
||||
this.findUnderscoredTemplate(parsedName)
|
||||
);
|
||||
},
|
||||
@ -296,5 +300,37 @@ export function buildResolver(baseName) {
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
findWizardTemplate(parsedName) {
|
||||
let decamelized = decamelize(parsedName.fullNameWithoutType);
|
||||
if (decamelized.startsWith("components")) {
|
||||
let comPath = `wizard/templates/${decamelized}`;
|
||||
const compTemplate =
|
||||
Ember.TEMPLATES[`javascripts/${comPath}`] || Ember.TEMPLATES[comPath];
|
||||
if (compTemplate) {
|
||||
return compTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
if (decamelized === "javascripts/wizard") {
|
||||
return Ember.TEMPLATES["wizard/templates/wizard"];
|
||||
}
|
||||
|
||||
if (
|
||||
decamelized.startsWith("wizard") ||
|
||||
decamelized.startsWith("javascripts/wizard")
|
||||
) {
|
||||
decamelized = decamelized.replace(/^wizard\_/, "wizard/templates/");
|
||||
decamelized = decamelized.replace(/^wizard\./, "wizard/templates/");
|
||||
decamelized = decamelized.replace(/\./g, "_");
|
||||
|
||||
const dashed = decamelized.replace(/_/g, "-");
|
||||
return (
|
||||
Ember.TEMPLATES[decamelized] ||
|
||||
Ember.TEMPLATES[dashed] ||
|
||||
Ember.TEMPLATES[dashed.replace("wizard-", "wizard/")]
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,5 +1,35 @@
|
||||
import { on as emberOn } from "@ember/object/evented";
|
||||
import { computed, observer } from "@ember/object";
|
||||
import { observer } from "@ember/object";
|
||||
import {
|
||||
alias as EmberAlias,
|
||||
and as EmberAnd,
|
||||
bool as EmberBool,
|
||||
collect as EmberCollect,
|
||||
empty as EmberEmpty,
|
||||
equal as EmberEqual,
|
||||
filter as EmberFilter,
|
||||
filterBy as EmberFilterBy,
|
||||
gt as EmberGt,
|
||||
gte as EmberGte,
|
||||
lt as EmberLt,
|
||||
lte as EmberLte,
|
||||
map as EmberMap,
|
||||
mapBy as EmberMapBy,
|
||||
match as EmberMatch,
|
||||
max as EmberMax,
|
||||
min as EmberMin,
|
||||
none as EmberNone,
|
||||
not as EmberNot,
|
||||
notEmpty as EmberNotEmpty,
|
||||
oneWay as EmberOneWay,
|
||||
or as EmberOr,
|
||||
reads as EmberReads,
|
||||
setDiff as EmberSetDiff,
|
||||
sort as EmberSort,
|
||||
sum as EmberSum,
|
||||
union as EmberUnion,
|
||||
uniq as EmberUniq,
|
||||
} from "@ember/object/computed";
|
||||
import { bind as emberBind, schedule } from "@ember/runloop";
|
||||
import decoratorAlias from "discourse-common/utils/decorator-alias";
|
||||
import extractValue from "discourse-common/utils/extract-value";
|
||||
@ -63,31 +93,31 @@ export const observes = decoratorAlias(
|
||||
"Can not `observe` without property names"
|
||||
);
|
||||
|
||||
export const alias = macroAlias(computed.alias);
|
||||
export const and = macroAlias(computed.and);
|
||||
export const bool = macroAlias(computed.bool);
|
||||
export const collect = macroAlias(computed.collect);
|
||||
export const empty = macroAlias(computed.empty);
|
||||
export const equal = macroAlias(computed.equal);
|
||||
export const filter = macroAlias(computed.filter);
|
||||
export const filterBy = macroAlias(computed.filterBy);
|
||||
export const gt = macroAlias(computed.gt);
|
||||
export const gte = macroAlias(computed.gte);
|
||||
export const lt = macroAlias(computed.lt);
|
||||
export const lte = macroAlias(computed.lte);
|
||||
export const map = macroAlias(computed.map);
|
||||
export const mapBy = macroAlias(computed.mapBy);
|
||||
export const match = macroAlias(computed.match);
|
||||
export const max = macroAlias(computed.max);
|
||||
export const min = macroAlias(computed.min);
|
||||
export const none = macroAlias(computed.none);
|
||||
export const not = macroAlias(computed.not);
|
||||
export const notEmpty = macroAlias(computed.notEmpty);
|
||||
export const oneWay = macroAlias(computed.oneWay);
|
||||
export const or = macroAlias(computed.or);
|
||||
export const reads = macroAlias(computed.reads);
|
||||
export const setDiff = macroAlias(computed.setDiff);
|
||||
export const sort = macroAlias(computed.sort);
|
||||
export const sum = macroAlias(computed.sum);
|
||||
export const union = macroAlias(computed.union);
|
||||
export const uniq = macroAlias(computed.uniq);
|
||||
export const alias = macroAlias(EmberAlias);
|
||||
export const and = macroAlias(EmberAnd);
|
||||
export const bool = macroAlias(EmberBool);
|
||||
export const collect = macroAlias(EmberCollect);
|
||||
export const empty = macroAlias(EmberEmpty);
|
||||
export const equal = macroAlias(EmberEqual);
|
||||
export const filter = macroAlias(EmberFilter);
|
||||
export const filterBy = macroAlias(EmberFilterBy);
|
||||
export const gt = macroAlias(EmberGt);
|
||||
export const gte = macroAlias(EmberGte);
|
||||
export const lt = macroAlias(EmberLt);
|
||||
export const lte = macroAlias(EmberLte);
|
||||
export const map = macroAlias(EmberMap);
|
||||
export const mapBy = macroAlias(EmberMapBy);
|
||||
export const match = macroAlias(EmberMatch);
|
||||
export const max = macroAlias(EmberMax);
|
||||
export const min = macroAlias(EmberMin);
|
||||
export const none = macroAlias(EmberNone);
|
||||
export const not = macroAlias(EmberNot);
|
||||
export const notEmpty = macroAlias(EmberNotEmpty);
|
||||
export const oneWay = macroAlias(EmberOneWay);
|
||||
export const or = macroAlias(EmberOr);
|
||||
export const reads = macroAlias(EmberReads);
|
||||
export const setDiff = macroAlias(EmberSetDiff);
|
||||
export const sort = macroAlias(EmberSort);
|
||||
export const sum = macroAlias(EmberSum);
|
||||
export const union = macroAlias(EmberUnion);
|
||||
export const uniq = macroAlias(EmberUniq);
|
||||
|
||||
@ -3,7 +3,11 @@
|
||||
const EmberAddon = require("ember-cli/lib/broccoli/ember-addon");
|
||||
|
||||
module.exports = function (defaults) {
|
||||
let app = new EmberAddon(defaults, {});
|
||||
let app = new EmberAddon(defaults, {
|
||||
autoImport: {
|
||||
publicAssetURL: "",
|
||||
},
|
||||
});
|
||||
|
||||
return app.toTree();
|
||||
};
|
||||
|
||||
@ -21,43 +21,35 @@
|
||||
"@uppy/drop-target": "^1.1.2",
|
||||
"@uppy/utils": "^4.0.5",
|
||||
"@uppy/xhr-upload": "^2.0.7",
|
||||
"ember-auto-import": "^2.2.4",
|
||||
"ember-cli-babel": "^7.13.0",
|
||||
"ember-cli-htmlbars": "^4.2.0",
|
||||
"ember-auto-import": "^2.4.2",
|
||||
"ember-cli-babel": "^7.23.1",
|
||||
"ember-cli-htmlbars": "^6.0.1",
|
||||
"handlebars": "^4.7.0",
|
||||
"truth-helpers": "^1.0.0",
|
||||
"webpack": "^5.67.0"
|
||||
"webpack": "^5.73.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ember/optional-features": "^1.1.0",
|
||||
"@glimmer/component": "^1.0.0",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"ember-cli": "~3.25.3",
|
||||
"ember-cli-dependency-checker": "^3.2.0",
|
||||
"ember-cli-eslint": "^5.1.0",
|
||||
"ember-cli-inject-live-reload": "^2.0.1",
|
||||
"ember-cli-dependency-checker": "^3.3.1",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-template-lint": "^1.0.0-beta.3",
|
||||
"ember-cli-uglify": "^3.0.0",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
"ember-disable-prototype-extensions": "^1.1.3",
|
||||
"ember-export-application-global": "^2.0.1",
|
||||
"ember-load-initializers": "^2.1.1",
|
||||
"ember-maybe-import-regenerator": "^0.1.6",
|
||||
"ember-resolver": "^7.0.0",
|
||||
"ember-source": "~3.15.0",
|
||||
"ember-source-channel-url": "^2.0.1",
|
||||
"ember-try": "^2.0.0",
|
||||
"eslint-plugin-ember": "^7.7.1",
|
||||
"eslint-plugin-node": "^10.0.0",
|
||||
"ember-source-channel-url": "^3.0.0",
|
||||
"loader.js": "^4.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "12.* || 14.* || >= 16",
|
||||
"node": "16.* || >= 18",
|
||||
"npm": "please-use-yarn",
|
||||
"yarn": ">= 1.21.1"
|
||||
},
|
||||
"ember": {
|
||||
"edition": "octane"
|
||||
"edition": "default"
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Dummy</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{{content-for "head"}}
|
||||
|
||||
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css">
|
||||
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/dummy.css">
|
||||
|
||||
{{content-for "head-footer"}}
|
||||
</head>
|
||||
<body>
|
||||
{{content-for "body"}}
|
||||
|
||||
<script src="{{rootURL}}assets/vendor.js"></script>
|
||||
<script src="{{rootURL}}assets/dummy.js"></script>
|
||||
|
||||
{{content-for "body-footer"}}
|
||||
</body>
|
||||
</html>
|
||||
39
app/assets/javascripts/discourse-common/tests/index.html
Normal file
39
app/assets/javascripts/discourse-common/tests/index.html
Normal file
@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Dummy Tests</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{{content-for "head"}}
|
||||
{{content-for "test-head"}}
|
||||
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/vendor.css">
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/dummy.css">
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/test-support.css">
|
||||
|
||||
{{content-for "head-footer"}}
|
||||
{{content-for "test-head-footer"}}
|
||||
</head>
|
||||
<body>
|
||||
{{content-for "body"}}
|
||||
{{content-for "test-body"}}
|
||||
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture">
|
||||
<div id="ember-testing-container">
|
||||
<div id="ember-testing"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/testem.js" integrity="" data-embroider-ignore></script>
|
||||
<script src="{{rootURL}}assets/vendor.js"></script>
|
||||
<script src="{{rootURL}}assets/test-support.js"></script>
|
||||
<script src="{{rootURL}}assets/dummy.js"></script>
|
||||
<script src="{{rootURL}}assets/tests.js"></script>
|
||||
|
||||
{{content-for "body-footer"}}
|
||||
{{content-for "test-body-footer"}}
|
||||
</body>
|
||||
</html>
|
||||
13
app/assets/javascripts/discourse-hbr/ember-cli-build.js
Normal file
13
app/assets/javascripts/discourse-hbr/ember-cli-build.js
Normal file
@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
const EmberAddon = require("ember-cli/lib/broccoli/ember-addon");
|
||||
|
||||
module.exports = function (defaults) {
|
||||
let app = new EmberAddon(defaults, {
|
||||
autoImport: {
|
||||
publicAssetURL: "",
|
||||
},
|
||||
});
|
||||
|
||||
return app.toTree();
|
||||
};
|
||||
@ -15,43 +15,34 @@
|
||||
"start": "ember serve"
|
||||
},
|
||||
"dependencies": {
|
||||
"ember-auto-import": "^2.2.4",
|
||||
"ember-cli-babel": "^7.13.0",
|
||||
"ember-cli-htmlbars": "^4.2.0",
|
||||
"webpack": "^5.67.0"
|
||||
"ember-auto-import": "^2.4.2",
|
||||
"ember-cli-babel": "^7.23.1",
|
||||
"ember-cli-htmlbars": "^6.0.1",
|
||||
"handlebars": "^4.7.6",
|
||||
"webpack": "^5.73.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ember/optional-features": "^1.1.0",
|
||||
"@glimmer/component": "^1.0.0",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"broccoli-stew": "^3.0.0",
|
||||
"ember-cli": "~3.25.3",
|
||||
"ember-cli-dependency-checker": "^3.2.0",
|
||||
"ember-cli-eslint": "^5.1.0",
|
||||
"ember-cli-inject-live-reload": "^2.0.1",
|
||||
"ember-cli-dependency-checker": "^3.3.1",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-template-lint": "^1.0.0-beta.3",
|
||||
"ember-cli-uglify": "^3.0.0",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
"ember-disable-prototype-extensions": "^1.1.3",
|
||||
"ember-export-application-global": "^2.0.1",
|
||||
"ember-load-initializers": "^2.1.1",
|
||||
"ember-maybe-import-regenerator": "^0.1.6",
|
||||
"ember-resolver": "^7.0.0",
|
||||
"ember-source": "~3.15.0",
|
||||
"ember-source-channel-url": "^2.0.1",
|
||||
"ember-try": "^2.0.0",
|
||||
"eslint-plugin-ember": "^7.7.1",
|
||||
"eslint-plugin-node": "^10.0.0",
|
||||
"handlebars": "^4.7.6",
|
||||
"ember-source-channel-url": "^3.0.0",
|
||||
"loader.js": "^4.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "12.* || 14.* || >= 16",
|
||||
"node": "16.* || >= 18",
|
||||
"npm": "please-use-yarn",
|
||||
"yarn": ">= 1.21.1"
|
||||
},
|
||||
"ember": {
|
||||
"edition": "octane"
|
||||
"edition": "default"
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Dummy</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{{content-for "head"}}
|
||||
|
||||
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css">
|
||||
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/dummy.css">
|
||||
|
||||
{{content-for "head-footer"}}
|
||||
</head>
|
||||
<body>
|
||||
{{content-for "body"}}
|
||||
|
||||
<script src="{{rootURL}}assets/vendor.js"></script>
|
||||
<script src="{{rootURL}}assets/dummy.js"></script>
|
||||
|
||||
{{content-for "body-footer"}}
|
||||
</body>
|
||||
</html>
|
||||
39
app/assets/javascripts/discourse-hbr/tests/index.html
Normal file
39
app/assets/javascripts/discourse-hbr/tests/index.html
Normal file
@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Dummy Tests</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{{content-for "head"}}
|
||||
{{content-for "test-head"}}
|
||||
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/vendor.css">
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/dummy.css">
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/test-support.css">
|
||||
|
||||
{{content-for "head-footer"}}
|
||||
{{content-for "test-head-footer"}}
|
||||
</head>
|
||||
<body>
|
||||
{{content-for "body"}}
|
||||
{{content-for "test-body"}}
|
||||
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture">
|
||||
<div id="ember-testing-container">
|
||||
<div id="ember-testing"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/testem.js" integrity="" data-embroider-ignore></script>
|
||||
<script src="{{rootURL}}assets/vendor.js"></script>
|
||||
<script src="{{rootURL}}assets/test-support.js"></script>
|
||||
<script src="{{rootURL}}assets/dummy.js"></script>
|
||||
<script src="{{rootURL}}assets/tests.js"></script>
|
||||
|
||||
{{content-for "body-footer"}}
|
||||
{{content-for "test-body-footer"}}
|
||||
</body>
|
||||
</html>
|
||||
@ -1,432 +0,0 @@
|
||||
var define, requirejs;
|
||||
|
||||
(function () {
|
||||
var JS_MODULES = {};
|
||||
var ALIASES = {
|
||||
"ember-addons/ember-computed-decorators":
|
||||
"discourse-common/utils/decorators",
|
||||
"discourse/lib/raw-templates": "discourse-common/lib/raw-templates",
|
||||
"preload-store": "discourse/lib/preload-store",
|
||||
"fixtures/user_fixtures": "discourse/tests/fixtures/user-fixtures",
|
||||
};
|
||||
var ALIAS_PREPEND = {
|
||||
fixtures: "discourse/tests/",
|
||||
helpers: "discourse/tests/",
|
||||
};
|
||||
|
||||
// In future versions of ember we don't need this
|
||||
if (typeof Ember !== "undefined") {
|
||||
JS_MODULES = {
|
||||
jquery: { default: $ },
|
||||
"@ember/array": {
|
||||
default: Ember.Array,
|
||||
A: Ember.A,
|
||||
isArray: Ember.isArray,
|
||||
},
|
||||
"@ember/array/proxy": {
|
||||
default: Ember.ArrayProxy,
|
||||
},
|
||||
"@ember/component": {
|
||||
default: Ember.Component,
|
||||
},
|
||||
"@ember/controller": {
|
||||
default: Ember.Controller,
|
||||
inject: Ember.inject.controller,
|
||||
},
|
||||
"@ember/debug": {
|
||||
assert: Ember.assert,
|
||||
runInDebug: Ember.runInDebug,
|
||||
warn: Ember.warn,
|
||||
},
|
||||
"@ember/object": {
|
||||
action: Ember._action,
|
||||
default: Ember.Object,
|
||||
get: Ember.get,
|
||||
getProperties: Ember.getProperties,
|
||||
set: Ember.set,
|
||||
setProperties: Ember.setProperties,
|
||||
computed: Ember.computed,
|
||||
defineProperty: Ember.defineProperty,
|
||||
observer: Ember.observer,
|
||||
},
|
||||
"@ember/object/computed": {
|
||||
alias: Ember.computed.alias,
|
||||
and: Ember.computed.and,
|
||||
bool: Ember.computed.bool,
|
||||
collect: Ember.computed.collect,
|
||||
deprecatingAlias: Ember.computed.deprecatingAlias,
|
||||
empty: Ember.computed.empty,
|
||||
equal: Ember.computed.equal,
|
||||
filter: Ember.computed.filter,
|
||||
filterBy: Ember.computed.filterBy,
|
||||
gt: Ember.computed.gt,
|
||||
gte: Ember.computed.gte,
|
||||
intersect: Ember.computed.intersect,
|
||||
lt: Ember.computed.lt,
|
||||
lte: Ember.computed.lte,
|
||||
map: Ember.computed.map,
|
||||
mapBy: Ember.computed.mapBy,
|
||||
match: Ember.computed.match,
|
||||
max: Ember.computed.max,
|
||||
min: Ember.computed.min,
|
||||
none: Ember.computed.none,
|
||||
not: Ember.computed.not,
|
||||
notEmpty: Ember.computed.notEmpty,
|
||||
oneWay: Ember.computed.oneWay,
|
||||
or: Ember.computed.or,
|
||||
readOnly: Ember.computed.readOnly,
|
||||
reads: Ember.computed.reads,
|
||||
setDiff: Ember.computed.setDiff,
|
||||
sort: Ember.computed.sort,
|
||||
sum: Ember.computed.sum,
|
||||
union: Ember.computed.union,
|
||||
uniq: Ember.computed.uniq,
|
||||
uniqBy: Ember.computed.uniqBy,
|
||||
},
|
||||
"@ember/object/mixin": { default: Ember.Mixin },
|
||||
"@ember/object/proxy": { default: Ember.ObjectProxy },
|
||||
"@ember/object/promise-proxy-mixin": { default: Ember.PromiseProxyMixin },
|
||||
"@ember/object/evented": {
|
||||
default: Ember.Evented,
|
||||
on: Ember.on,
|
||||
},
|
||||
"@ember/routing/route": { default: Ember.Route },
|
||||
"@ember/routing/router": { default: Ember.Router },
|
||||
"@ember/runloop": {
|
||||
bind: Ember.run.bind,
|
||||
cancel: Ember.run.cancel,
|
||||
debounce: Ember.testing ? Ember.run : Ember.run.debounce,
|
||||
later: Ember.run.later,
|
||||
next: Ember.run.next,
|
||||
once: Ember.run.once,
|
||||
run: Ember.run,
|
||||
schedule: Ember.run.schedule,
|
||||
scheduleOnce: Ember.run.scheduleOnce,
|
||||
throttle: Ember.run.throttle,
|
||||
},
|
||||
"@ember/service": {
|
||||
default: Ember.Service,
|
||||
inject: Ember.inject.service,
|
||||
},
|
||||
"@ember/utils": {
|
||||
isBlank: Ember.isBlank,
|
||||
isEmpty: Ember.isEmpty,
|
||||
isNone: Ember.isNone,
|
||||
isPresent: Ember.isPresent,
|
||||
},
|
||||
rsvp: {
|
||||
asap: Ember.RSVP.asap,
|
||||
all: Ember.RSVP.all,
|
||||
allSettled: Ember.RSVP.allSettled,
|
||||
race: Ember.RSVP.race,
|
||||
hash: Ember.RSVP.hash,
|
||||
hashSettled: Ember.RSVP.hashSettled,
|
||||
rethrow: Ember.RSVP.rethrow,
|
||||
defer: Ember.RSVP.defer,
|
||||
denodeify: Ember.RSVP.denodeify,
|
||||
resolve: Ember.RSVP.resolve,
|
||||
reject: Ember.RSVP.reject,
|
||||
map: Ember.RSVP.map,
|
||||
filter: Ember.RSVP.filter,
|
||||
default: Ember.RSVP,
|
||||
Promise: Ember.RSVP.Promise,
|
||||
EventTarget: Ember.RSVP.EventTarget,
|
||||
},
|
||||
"@ember/string": {
|
||||
w: Ember.String.w,
|
||||
dasherize: Ember.String.dasherize,
|
||||
decamelize: Ember.String.decamelize,
|
||||
camelize: Ember.String.camelize,
|
||||
classify: Ember.String.classify,
|
||||
underscore: Ember.String.underscore,
|
||||
capitalize: Ember.String.capitalize,
|
||||
},
|
||||
"@ember/template": {
|
||||
htmlSafe: Ember.String.htmlSafe,
|
||||
},
|
||||
"@ember/application": {
|
||||
default: Ember.Application,
|
||||
setOwner: Ember.setOwner,
|
||||
getOwner: Ember.getOwner,
|
||||
},
|
||||
"@ember/component/helper": {
|
||||
default: Ember.Helper,
|
||||
},
|
||||
"@ember/component/text-field": {
|
||||
default: Ember.TextField,
|
||||
},
|
||||
"@ember/component/text-area": {
|
||||
default: Ember.TextArea,
|
||||
},
|
||||
"@ember/error": {
|
||||
default: Ember.error,
|
||||
},
|
||||
"@ember/object/internals": {
|
||||
guidFor: Ember.guidFor,
|
||||
},
|
||||
"@ember/test": {
|
||||
registerWaiter: Ember.Test && Ember.Test.registerWaiter,
|
||||
unregisterWaiter: Ember.Test && Ember.Test.unregisterWaiter,
|
||||
},
|
||||
I18n: {
|
||||
// eslint-disable-next-line
|
||||
default: I18n,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
var _isArray;
|
||||
if (!Array.isArray) {
|
||||
_isArray = function (x) {
|
||||
return Object.prototype.toString.call(x) === "[object Array]";
|
||||
};
|
||||
} else {
|
||||
_isArray = Array.isArray;
|
||||
}
|
||||
|
||||
var registry = {};
|
||||
var seen = {};
|
||||
var FAILED = false;
|
||||
|
||||
var uuid = 0;
|
||||
|
||||
function tryFinally(tryable, finalizer) {
|
||||
try {
|
||||
return tryable();
|
||||
} finally {
|
||||
finalizer();
|
||||
}
|
||||
}
|
||||
|
||||
function unsupportedModule(length) {
|
||||
throw new Error(
|
||||
"an unsupported module was defined, expected `define(name, deps, module)` instead got: `" +
|
||||
length +
|
||||
"` arguments to define`"
|
||||
);
|
||||
}
|
||||
|
||||
function deprecatedModule(depricated, useInstead) {
|
||||
var warning = "[DEPRECATION] `" + depricated + "` is deprecated.";
|
||||
if (useInstead) {
|
||||
warning += " Please use `" + useInstead + "` instead.";
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(warning);
|
||||
}
|
||||
|
||||
var defaultDeps = ["require", "exports", "module"];
|
||||
|
||||
function Module(name, deps, callback, exports) {
|
||||
this.id = uuid++;
|
||||
this.name = name;
|
||||
this.deps = !deps.length && callback.length ? defaultDeps : deps;
|
||||
this.exports = exports || {};
|
||||
this.callback = callback;
|
||||
this.state = undefined;
|
||||
this._require = undefined;
|
||||
}
|
||||
|
||||
Module.prototype.makeRequire = function () {
|
||||
var name = transformForAliases(this.name);
|
||||
|
||||
return (
|
||||
this._require ||
|
||||
(this._require = function (dep) {
|
||||
return requirejs(resolve(dep, name));
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
define = function (name, deps, callback) {
|
||||
if (arguments.length < 2) {
|
||||
unsupportedModule(arguments.length);
|
||||
}
|
||||
|
||||
if (!_isArray(deps)) {
|
||||
callback = deps;
|
||||
deps = [];
|
||||
}
|
||||
|
||||
registry[name] = new Module(name, deps, callback);
|
||||
};
|
||||
|
||||
// we don't support all of AMD
|
||||
// define.amd = {};
|
||||
// we will support petals...
|
||||
define.petal = {};
|
||||
|
||||
function Alias(path) {
|
||||
this.name = path;
|
||||
}
|
||||
|
||||
define.alias = function (path) {
|
||||
return new Alias(path);
|
||||
};
|
||||
|
||||
function reify(mod, name, rseen) {
|
||||
var deps = mod.deps;
|
||||
var length = deps.length;
|
||||
var reified = new Array(length);
|
||||
var dep;
|
||||
// TODO: new Module
|
||||
// TODO: seen refactor
|
||||
var module = {};
|
||||
|
||||
for (var i = 0, l = length; i < l; i++) {
|
||||
dep = deps[i];
|
||||
if (dep === "exports") {
|
||||
module.exports = reified[i] = rseen;
|
||||
} else if (dep === "require") {
|
||||
reified[i] = mod.makeRequire();
|
||||
} else if (dep === "module") {
|
||||
mod.exports = rseen;
|
||||
module = reified[i] = mod;
|
||||
} else {
|
||||
reified[i] = requireFrom(resolve(dep, name), name);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
deps: reified,
|
||||
module: module,
|
||||
};
|
||||
}
|
||||
|
||||
function requireFrom(name, origin) {
|
||||
name = transformForAliases(name);
|
||||
|
||||
if (name === "discourse") {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
"discourse has been moved to `discourse/app` - please update your code"
|
||||
);
|
||||
name = "discourse/app";
|
||||
}
|
||||
|
||||
if (name === "discourse/models/input-validation") {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
"input-validation has been removed and should be replaced with `@ember/object`"
|
||||
);
|
||||
name = "@ember/object";
|
||||
}
|
||||
|
||||
var mod = JS_MODULES[name] || registry[name];
|
||||
if (!mod) {
|
||||
throw new Error(
|
||||
"Could not find module `" + name + "` imported from `" + origin + "`"
|
||||
);
|
||||
}
|
||||
return requirejs(name);
|
||||
}
|
||||
|
||||
function missingModule(name) {
|
||||
throw new Error("Could not find module " + name);
|
||||
}
|
||||
|
||||
function transformForAliases(name) {
|
||||
var alias = ALIASES[name];
|
||||
if (!alias) {
|
||||
var segment = name.split("/")[0];
|
||||
var prepend = ALIAS_PREPEND[segment];
|
||||
if (!prepend) {
|
||||
return name;
|
||||
}
|
||||
alias = prepend + name;
|
||||
}
|
||||
deprecatedModule(name, alias);
|
||||
return alias;
|
||||
}
|
||||
|
||||
requirejs = require = function (name) {
|
||||
name = transformForAliases(name);
|
||||
if (JS_MODULES[name]) {
|
||||
return JS_MODULES[name];
|
||||
}
|
||||
|
||||
var mod = registry[name];
|
||||
|
||||
if (mod && mod.callback instanceof Alias) {
|
||||
mod = registry[mod.callback.name];
|
||||
}
|
||||
|
||||
if (!mod) {
|
||||
missingModule(name);
|
||||
}
|
||||
|
||||
if (mod.state !== FAILED && seen.hasOwnProperty(name)) {
|
||||
return seen[name];
|
||||
}
|
||||
|
||||
var reified;
|
||||
var module;
|
||||
var loaded = false;
|
||||
|
||||
seen[name] = {}; // placeholder for run-time cycles
|
||||
|
||||
tryFinally(
|
||||
function () {
|
||||
reified = reify(mod, name, seen[name]);
|
||||
module = mod.callback.apply(this, reified.deps);
|
||||
loaded = true;
|
||||
},
|
||||
function () {
|
||||
if (!loaded) {
|
||||
mod.state = FAILED;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
var obj;
|
||||
if (module === undefined && reified.module.exports) {
|
||||
obj = reified.module.exports;
|
||||
} else {
|
||||
obj = seen[name] = module;
|
||||
}
|
||||
|
||||
if (
|
||||
obj !== null &&
|
||||
(typeof obj === "object" || typeof obj === "function") &&
|
||||
obj["default"] === undefined
|
||||
) {
|
||||
obj["default"] = obj;
|
||||
}
|
||||
|
||||
return (seen[name] = obj);
|
||||
};
|
||||
window.requireModule = requirejs;
|
||||
|
||||
function resolve(child, name) {
|
||||
if (child.charAt(0) !== ".") {
|
||||
return child;
|
||||
}
|
||||
|
||||
var parts = child.split("/");
|
||||
var nameParts = name.split("/");
|
||||
var parentBase = nameParts.slice(0, -1);
|
||||
|
||||
for (var i = 0, l = parts.length; i < l; i++) {
|
||||
var part = parts[i];
|
||||
|
||||
if (part === "..") {
|
||||
if (parentBase.length === 0) {
|
||||
throw new Error("Cannot access parent module of root");
|
||||
}
|
||||
parentBase.pop();
|
||||
} else if (part === ".") {
|
||||
continue;
|
||||
} else {
|
||||
parentBase.push(part);
|
||||
}
|
||||
}
|
||||
|
||||
return parentBase.join("/");
|
||||
}
|
||||
|
||||
requirejs.entries = requirejs._eak_seen = registry;
|
||||
requirejs.clear = function () {
|
||||
requirejs.entries = requirejs._eak_seen = registry = {};
|
||||
seen = {};
|
||||
};
|
||||
})();
|
||||
@ -1,67 +0,0 @@
|
||||
define("message-bus-client", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.MessageBus;
|
||||
});
|
||||
|
||||
define("ember-buffered-proxy/proxy", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.BufferedProxy;
|
||||
});
|
||||
|
||||
define("bootbox", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.bootbox;
|
||||
});
|
||||
|
||||
define("xss", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.filterXSS;
|
||||
});
|
||||
|
||||
define("@discourse/itsatrap", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.ItsATrap;
|
||||
});
|
||||
|
||||
define("@popperjs/core", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.Popper;
|
||||
__exports__.createPopper = window.Popper.createPopper;
|
||||
__exports__.defaultModifiers = window.Popper.defaultModifiers;
|
||||
__exports__.popperGenerator = window.Popper.popperGenerator;
|
||||
});
|
||||
|
||||
define("tippy.js", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.tippy;
|
||||
});
|
||||
|
||||
define("@uppy/core", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.Uppy.Core;
|
||||
__exports__.BasePlugin = window.Uppy.Core.BasePlugin;
|
||||
});
|
||||
|
||||
define("@uppy/aws-s3", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.Uppy.AwsS3;
|
||||
});
|
||||
|
||||
define("@uppy/aws-s3-multipart", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.Uppy.AwsS3Multipart;
|
||||
});
|
||||
|
||||
define("@uppy/xhr-upload", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.Uppy.XHRUpload;
|
||||
});
|
||||
|
||||
define("@uppy/drop-target", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.Uppy.DropTarget;
|
||||
});
|
||||
|
||||
define("@uppy/utils/lib/delay", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.Uppy.Utils.delay;
|
||||
});
|
||||
|
||||
define("@uppy/utils/lib/EventTracker", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.Uppy.Utils.EventTracker;
|
||||
});
|
||||
|
||||
define("@uppy/utils/lib/AbortController", ["exports"], function (__exports__) {
|
||||
__exports__.AbortController =
|
||||
window.Uppy.Utils.AbortControllerLib.AbortController;
|
||||
__exports__.AbortSignal = window.Uppy.Utils.AbortControllerLib.AbortSignal;
|
||||
__exports__.createAbortError =
|
||||
window.Uppy.Utils.AbortControllerLib.createAbortError;
|
||||
});
|
||||
@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
const EmberAddon = require("ember-cli/lib/broccoli/ember-addon");
|
||||
|
||||
module.exports = function (defaults) {
|
||||
let app = new EmberAddon(defaults, {
|
||||
autoImport: {
|
||||
publicAssetURL: "",
|
||||
},
|
||||
});
|
||||
|
||||
return app.toTree();
|
||||
};
|
||||
@ -15,43 +15,34 @@
|
||||
"start": "ember serve"
|
||||
},
|
||||
"dependencies": {
|
||||
"ember-auto-import": "^2.2.4",
|
||||
"ember-cli-babel": "^7.13.0",
|
||||
"ember-cli-htmlbars": "^4.2.0",
|
||||
"webpack": "^5.67.0"
|
||||
"ember-auto-import": "^2.4.2",
|
||||
"ember-cli-babel": "^7.23.1",
|
||||
"ember-cli-htmlbars": "^6.0.1",
|
||||
"handlebars": "^4.7.6",
|
||||
"webpack": "^5.73.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ember/optional-features": "^1.1.0",
|
||||
"@glimmer/component": "^1.0.0",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"broccoli-stew": "^3.0.0",
|
||||
"ember-cli": "~3.25.3",
|
||||
"ember-cli-dependency-checker": "^3.2.0",
|
||||
"ember-cli-eslint": "^5.1.0",
|
||||
"ember-cli-inject-live-reload": "^2.0.1",
|
||||
"ember-cli-dependency-checker": "^3.3.1",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-template-lint": "^1.0.0-beta.3",
|
||||
"ember-cli-uglify": "^3.0.0",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
"ember-disable-prototype-extensions": "^1.1.3",
|
||||
"ember-export-application-global": "^2.0.1",
|
||||
"ember-load-initializers": "^2.1.1",
|
||||
"ember-maybe-import-regenerator": "^0.1.6",
|
||||
"ember-resolver": "^7.0.0",
|
||||
"ember-source": "~3.15.0",
|
||||
"ember-source-channel-url": "^2.0.1",
|
||||
"ember-try": "^2.0.0",
|
||||
"eslint-plugin-ember": "^7.7.1",
|
||||
"eslint-plugin-node": "^10.0.0",
|
||||
"handlebars": "^4.7.6",
|
||||
"ember-source-channel-url": "^3.0.0",
|
||||
"loader.js": "^4.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "12.* || 14.* || >= 16",
|
||||
"node": "16.* || >= 18",
|
||||
"npm": "please-use-yarn",
|
||||
"yarn": ">= 1.21.1"
|
||||
},
|
||||
"ember": {
|
||||
"edition": "octane"
|
||||
"edition": "default"
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Dummy</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{{content-for "head"}}
|
||||
|
||||
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css">
|
||||
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/dummy.css">
|
||||
|
||||
{{content-for "head-footer"}}
|
||||
</head>
|
||||
<body>
|
||||
{{content-for "body"}}
|
||||
|
||||
<script src="{{rootURL}}assets/vendor.js"></script>
|
||||
<script src="{{rootURL}}assets/dummy.js"></script>
|
||||
|
||||
{{content-for "body-footer"}}
|
||||
</body>
|
||||
</html>
|
||||
39
app/assets/javascripts/discourse-widget-hbs/tests/index.html
Normal file
39
app/assets/javascripts/discourse-widget-hbs/tests/index.html
Normal file
@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Dummy Tests</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{{content-for "head"}}
|
||||
{{content-for "test-head"}}
|
||||
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/vendor.css">
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/dummy.css">
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/test-support.css">
|
||||
|
||||
{{content-for "head-footer"}}
|
||||
{{content-for "test-head-footer"}}
|
||||
</head>
|
||||
<body>
|
||||
{{content-for "body"}}
|
||||
{{content-for "test-body"}}
|
||||
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture">
|
||||
<div id="ember-testing-container">
|
||||
<div id="ember-testing"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/testem.js" integrity="" data-embroider-ignore></script>
|
||||
<script src="{{rootURL}}assets/vendor.js"></script>
|
||||
<script src="{{rootURL}}assets/test-support.js"></script>
|
||||
<script src="{{rootURL}}assets/dummy.js"></script>
|
||||
<script src="{{rootURL}}assets/tests.js"></script>
|
||||
|
||||
{{content-for "body-footer"}}
|
||||
{{content-for "test-body-footer"}}
|
||||
</body>
|
||||
</html>
|
||||
@ -81,6 +81,15 @@ const Discourse = Application.extend({
|
||||
initialize: () => withPluginApi(cb.version, cb.code),
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener(
|
||||
"load",
|
||||
() => {
|
||||
// The app booted. Remove the splash screen
|
||||
document.querySelector("#d-splash")?.remove();
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
},
|
||||
|
||||
_registerPluginCode(version, code) {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import Component from "@ember/component";
|
||||
import cookie from "discourse/lib/cookie";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ["create-account-body"],
|
||||
@ -21,6 +22,7 @@ export default Component.extend({
|
||||
}
|
||||
},
|
||||
|
||||
@bind
|
||||
actionOnEnter(event) {
|
||||
if (!this.disabled && event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
@ -30,6 +32,7 @@ export default Component.extend({
|
||||
}
|
||||
},
|
||||
|
||||
@bind
|
||||
selectKitFocus(event) {
|
||||
const target = document.getElementById(event.target.getAttribute("for"));
|
||||
if (target?.classList.contains("select-kit")) {
|
||||
|
||||
@ -672,6 +672,13 @@ export default Component.extend(TextareaTextManipulation, {
|
||||
return true;
|
||||
},
|
||||
|
||||
@action
|
||||
onEmojiPickerClose() {
|
||||
if (!(this.isDestroyed || this.isDestroying)) {
|
||||
this.set("emojiPickerIsActive", false);
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
emoji() {
|
||||
if (this.disabled) {
|
||||
|
||||
@ -80,12 +80,18 @@ export default class DiscoursePopover extends Component {
|
||||
},
|
||||
};
|
||||
|
||||
const target = document
|
||||
.getElementById(this.componentId)
|
||||
.querySelector(
|
||||
':scope > .d-popover-trigger, :scope > .btn, :scope > [role="button"]'
|
||||
);
|
||||
|
||||
if (!target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const instance = tippy(
|
||||
document
|
||||
.getElementById(this.componentId)
|
||||
.querySelector(
|
||||
':scope > .d-popover-trigger, :scope > .btn, :scope > [role="button"]'
|
||||
),
|
||||
target,
|
||||
Object.assign({}, baseOptions, this.options || {})
|
||||
);
|
||||
|
||||
|
||||
@ -50,6 +50,8 @@ const Notice = EmberObject.extend({
|
||||
});
|
||||
|
||||
export default Component.extend({
|
||||
tagName: "",
|
||||
router: service(),
|
||||
logsNoticeService: service("logsNotice"),
|
||||
logNotice: null,
|
||||
|
||||
@ -70,6 +72,10 @@ export default Component.extend({
|
||||
);
|
||||
},
|
||||
|
||||
get visible() {
|
||||
return !this.router.currentRouteName.startsWith("wizard.");
|
||||
},
|
||||
|
||||
@discourseComputed(
|
||||
"site.isReadOnly",
|
||||
"site.wizard_required",
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
import I18n from "I18n";
|
||||
|
||||
import { cached } from "@glimmer/tracking";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
import GlimmerComponent from "discourse/components/glimmer";
|
||||
import CategorySectionLink from "discourse/lib/sidebar/categories-section/category-section-link";
|
||||
|
||||
export default class SidebarCategoriesSection extends GlimmerComponent {
|
||||
@service router;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
@ -20,11 +26,32 @@ export default class SidebarCategoriesSection extends GlimmerComponent {
|
||||
|
||||
@cached
|
||||
get sectionLinks() {
|
||||
return this.site.trackedCategoriesList.map((trackedCategory) => {
|
||||
return new CategorySectionLink({
|
||||
category: trackedCategory,
|
||||
topicTrackingState: this.topicTrackingState,
|
||||
});
|
||||
});
|
||||
const links = [];
|
||||
|
||||
for (const category of this.currentUser.sidebarCategories) {
|
||||
links.push(
|
||||
new CategorySectionLink({
|
||||
category,
|
||||
topicTrackingState: this.topicTrackingState,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
get noCategoriesText() {
|
||||
const url = `/u/${this.currentUser.username}/preferences/sidebar`;
|
||||
|
||||
return `${I18n.t(
|
||||
"sidebar.sections.categories.none"
|
||||
)} <a href="${url}">${I18n.t(
|
||||
"sidebar.sections.categories.click_to_get_started"
|
||||
)}</a>`;
|
||||
}
|
||||
|
||||
@action
|
||||
editTracked() {
|
||||
this.router.transitionTo("preferences.sidebar", this.currentUser);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,142 @@
|
||||
import { cached } from "@glimmer/tracking";
|
||||
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
import GlimmerComponent from "discourse/components/glimmer";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
import GroupMessageSectionLink from "discourse/lib/sidebar/messages-section/group-message-section-link";
|
||||
import PersonalMessageSectionLink from "discourse/lib/sidebar/messages-section/personal-message-section-link";
|
||||
|
||||
export const INBOX = "inbox";
|
||||
export const UNREAD = "unread";
|
||||
const SENT = "sent";
|
||||
export const NEW = "new";
|
||||
const ARCHIVE = "archive";
|
||||
|
||||
export const PERSONAL_MESSAGES_INBOX_FILTERS = [
|
||||
INBOX,
|
||||
NEW,
|
||||
UNREAD,
|
||||
SENT,
|
||||
ARCHIVE,
|
||||
];
|
||||
|
||||
export const GROUP_MESSAGES_INBOX_FILTERS = [INBOX, NEW, UNREAD, ARCHIVE];
|
||||
|
||||
export default class SidebarMessagesSection extends GlimmerComponent {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
this.appEvents.on(
|
||||
"page:changed",
|
||||
this,
|
||||
this._refreshSectionLinksDisplayState
|
||||
);
|
||||
|
||||
this.pmTopicTrackingState
|
||||
.startTracking()
|
||||
.then(this._refreshSectionLinkCounts);
|
||||
|
||||
this._pmTopicTrackingStateKey = "messages-section";
|
||||
|
||||
this.pmTopicTrackingState.onStateChange(
|
||||
this._pmTopicTrackingStateKey,
|
||||
this._refreshSectionLinkCounts
|
||||
);
|
||||
}
|
||||
|
||||
@bind
|
||||
_refreshSectionLinkCounts() {
|
||||
for (const sectionLink of this.allSectionLinks) {
|
||||
sectionLink.refreshCount();
|
||||
}
|
||||
}
|
||||
|
||||
willDestroy() {
|
||||
this.appEvents.off(
|
||||
"page:changed",
|
||||
this,
|
||||
this._refreshSectionLinksDisplayState
|
||||
);
|
||||
|
||||
this.pmTopicTrackingState.offStateChange(
|
||||
this._pmTopicTrackingStateKey,
|
||||
this._refreshSectionLinkCounts
|
||||
);
|
||||
}
|
||||
|
||||
_refreshSectionLinksDisplayState({
|
||||
currentRouteName,
|
||||
currentRouteParentName,
|
||||
currentRouteParams,
|
||||
}) {
|
||||
if (
|
||||
currentRouteParentName !== "userPrivateMessages" &&
|
||||
currentRouteParentName !== "topic"
|
||||
) {
|
||||
for (const sectionLink of this.allSectionLinks) {
|
||||
sectionLink.collapse();
|
||||
}
|
||||
} else {
|
||||
const attrs = {
|
||||
currentRouteName,
|
||||
currentRouteParams,
|
||||
};
|
||||
|
||||
if (currentRouteParentName === "topic") {
|
||||
const topicController = getOwner(this).lookup("controller:topic");
|
||||
|
||||
if (topicController.model.isPrivateMessage) {
|
||||
attrs.privateMessageTopic = topicController.model;
|
||||
}
|
||||
}
|
||||
|
||||
for (const sectionLink of this.allSectionLinks) {
|
||||
sectionLink.pageChanged(attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@cached
|
||||
get personalMessagesSectionLinks() {
|
||||
const links = [];
|
||||
|
||||
PERSONAL_MESSAGES_INBOX_FILTERS.forEach((type) => {
|
||||
links.push(
|
||||
new PersonalMessageSectionLink({
|
||||
currentUser: this.currentUser,
|
||||
type,
|
||||
pmTopicTrackingState: this.pmTopicTrackingState,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
@cached
|
||||
get groupMessagesSectionLinks() {
|
||||
const links = [];
|
||||
|
||||
this.currentUser.groupsWithMessages.forEach((group) => {
|
||||
GROUP_MESSAGES_INBOX_FILTERS.forEach((groupMessageLink) => {
|
||||
links.push(
|
||||
new GroupMessageSectionLink({
|
||||
group,
|
||||
type: groupMessageLink,
|
||||
currentUser: this.currentUser,
|
||||
pmTopicTrackingState: this.pmTopicTrackingState,
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
get allSectionLinks() {
|
||||
return [
|
||||
...this.groupMessagesSectionLinks,
|
||||
...this.personalMessagesSectionLinks,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -4,11 +4,27 @@ import { action } from "@ember/object";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
|
||||
export default class SidebarSection extends GlimmerComponent {
|
||||
@tracked displaySection = true;
|
||||
@tracked displaySection;
|
||||
collapsedSidebarSectionKey = `sidebar-section-${this.args.sectionName}-collapsed`;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
this.displaySection =
|
||||
this.keyValueStore.getItem(this.collapsedSidebarSectionKey) === undefined
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
|
||||
@action
|
||||
toggleSectionDisplay() {
|
||||
this.displaySection = !this.displaySection;
|
||||
|
||||
if (this.displaySection) {
|
||||
this.keyValueStore.remove(this.collapsedSidebarSectionKey);
|
||||
} else {
|
||||
this.keyValueStore.setItem(this.collapsedSidebarSectionKey, true);
|
||||
}
|
||||
}
|
||||
|
||||
get headerCaretIcon() {
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
import I18n from "I18n";
|
||||
|
||||
import { cached } from "@glimmer/tracking";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
import GlimmerComponent from "discourse/components/glimmer";
|
||||
import TagSectionLink from "discourse/lib/sidebar/tags-section/tag-section-link";
|
||||
|
||||
export default class SidebarTagsSection extends GlimmerComponent {
|
||||
@service router;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
@ -20,11 +26,30 @@ export default class SidebarTagsSection extends GlimmerComponent {
|
||||
|
||||
@cached
|
||||
get sectionLinks() {
|
||||
return this.currentUser.trackedTags.map((trackedTag) => {
|
||||
return new TagSectionLink({
|
||||
tag: trackedTag,
|
||||
topicTrackingState: this.topicTrackingState,
|
||||
});
|
||||
});
|
||||
const links = [];
|
||||
|
||||
for (const tagName of this.currentUser.sidebarTagNames) {
|
||||
links.push(
|
||||
new TagSectionLink({
|
||||
tagName,
|
||||
topicTrackingState: this.topicTrackingState,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
get noTagsText() {
|
||||
const url = `/u/${this.currentUser.username}/preferences/sidebar`;
|
||||
|
||||
return `${I18n.t("sidebar.sections.tags.none")} <a href="${url}">${I18n.t(
|
||||
"sidebar.sections.tags.click_to_get_started"
|
||||
)}</a>`;
|
||||
}
|
||||
|
||||
@action
|
||||
editTracked() {
|
||||
this.router.transitionTo("preferences.sidebar", this.currentUser);
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import { isEmpty } from "@ember/utils";
|
||||
import { prioritizeNameInUx } from "discourse/lib/settings";
|
||||
import { dasherize } from "@ember/string";
|
||||
import { emojiUnescape } from "discourse/lib/text";
|
||||
import { escapeExpression } from "discourse/lib/utilities";
|
||||
|
||||
export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
|
||||
elementId: "user-card",
|
||||
@ -55,10 +56,9 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
|
||||
return this.siteSettings.enable_user_status && this.user.status;
|
||||
},
|
||||
|
||||
@discourseComputed("user.status")
|
||||
userStatusEmoji() {
|
||||
const emoji = this.user.status.emoji ?? "mega";
|
||||
return emojiUnescape(`:${emoji}:`);
|
||||
@discourseComputed("user.status.emoji")
|
||||
userStatusEmoji(emoji) {
|
||||
return emojiUnescape(escapeExpression(`:${emoji}:`));
|
||||
},
|
||||
|
||||
isSuspendedOrHasBio: or("user.suspend_reason", "user.bio_excerpt"),
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
import Component from "@ember/component";
|
||||
import { action, computed } from "@ember/object";
|
||||
import { scheduleOnce } from "@ember/runloop";
|
||||
import { emojiUnescape } from "discourse/lib/text";
|
||||
import { escapeExpression } from "discourse/lib/utilities";
|
||||
|
||||
export default class UserStatusPicker extends Component {
|
||||
tagName = "";
|
||||
isFocused = false;
|
||||
emojiPickerIsActive = false;
|
||||
emoji = null;
|
||||
description = null;
|
||||
|
||||
@computed("emoji")
|
||||
get emojiHtml() {
|
||||
const emoji = escapeExpression(`:${this.emoji}:`);
|
||||
return emojiUnescape(emoji);
|
||||
}
|
||||
|
||||
@action
|
||||
blur() {
|
||||
this.set("isFocused", false);
|
||||
}
|
||||
|
||||
@action
|
||||
emojiSelected(emoji) {
|
||||
this.set("emoji", emoji);
|
||||
this.set("emojiPickerIsActive", false);
|
||||
|
||||
scheduleOnce("afterRender", () => {
|
||||
document.querySelector(".btn-emoji")?.focus();
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
focus() {
|
||||
this.set("isFocused", true);
|
||||
}
|
||||
|
||||
@action
|
||||
onEmojiPickerOutsideClick() {
|
||||
this.set("emojiPickerIsActive", false);
|
||||
}
|
||||
|
||||
@action
|
||||
setDefaultEmoji() {
|
||||
if (!this.emoji) {
|
||||
this.set("emoji", "speech_balloon");
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
toggleEmojiPicker(event) {
|
||||
event.stopPropagation();
|
||||
this.set("emojiPickerIsActive", !this.emojiPickerIsActive);
|
||||
}
|
||||
}
|
||||
@ -8,11 +8,6 @@ export default Controller.extend({
|
||||
router: service(),
|
||||
showSidebar: true,
|
||||
|
||||
@discourseComputed("showSidebar", "currentUser.experimental_sidebar_enabled")
|
||||
mainOutletWrapperClasses(showSidebar, experimentalSidebarEnabled) {
|
||||
return showSidebar && experimentalSidebarEnabled ? "has-sidebar" : "";
|
||||
},
|
||||
|
||||
@discourseComputed
|
||||
canSignUp() {
|
||||
return (
|
||||
|
||||
@ -136,7 +136,7 @@ export default Controller.extend({
|
||||
},
|
||||
|
||||
set disableSubmit(value) {
|
||||
this.set("_disableSubmit", value);
|
||||
return this.set("_disableSubmit", value);
|
||||
},
|
||||
|
||||
@discourseComputed("showPreview")
|
||||
@ -233,6 +233,7 @@ export default Controller.extend({
|
||||
},
|
||||
|
||||
isStaffUser: reads("currentUser.staff"),
|
||||
whisperer: reads("currentUser.whisperer"),
|
||||
|
||||
canUnlistTopic: and("model.creatingTopic", "isStaffUser"),
|
||||
|
||||
@ -289,12 +290,12 @@ export default Controller.extend({
|
||||
return SAVE_LABELS[modelAction];
|
||||
},
|
||||
|
||||
@discourseComputed("isStaffUser", "model.action")
|
||||
canWhisper(isStaffUser, modelAction) {
|
||||
@discourseComputed("whisperer", "model.action")
|
||||
canWhisper(whisperer, modelAction) {
|
||||
return (
|
||||
this.siteSettings.enable_whispers &&
|
||||
isStaffUser &&
|
||||
Composer.REPLY === modelAction
|
||||
Composer.REPLY === modelAction &&
|
||||
whisperer
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
import Controller from "@ember/controller";
|
||||
import { action } from "@ember/object";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
|
||||
export default class extends Controller {
|
||||
@tracked saved = false;
|
||||
@tracked selectedSiderbarCategories = [];
|
||||
@tracked selectedSidebarTagNames = [];
|
||||
|
||||
@action
|
||||
tagUpdated(tagNames) {
|
||||
this.selectedSidebarTagNames = tagNames;
|
||||
this.model.set("sidebar_tag_names", tagNames);
|
||||
this.saved = false;
|
||||
}
|
||||
|
||||
@action
|
||||
categoryUpdated(categories) {
|
||||
this.selectedSiderbarCategories = categories;
|
||||
this.model.set("sidebarCategoryIds", categories.mapBy("id"));
|
||||
this.saved = false;
|
||||
}
|
||||
|
||||
@action
|
||||
save() {
|
||||
this.model
|
||||
.save()
|
||||
.then(() => {
|
||||
this.saved = true;
|
||||
this.initialSidebarCategoryIds = this.model.sidebarCategoryIds;
|
||||
this.initialSidebarTagNames = this.model.initialSidebarTagNames;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.model.set("sidebarCategoryIds", this.initialSidebarCategoryIds);
|
||||
this.model.set("sidebar_tag_names", this.initialSidebarTagNames);
|
||||
popupAjaxError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -181,14 +181,15 @@ export default DiscoverySortableController.extend(
|
||||
this.tagNotification
|
||||
.update({ notification_level: notificationLevel })
|
||||
.then((response) => {
|
||||
this.currentUser.set(
|
||||
"muted_tag_ids",
|
||||
this.currentUser.calculateMutedIds(
|
||||
notificationLevel,
|
||||
response.responseJson.tag_id,
|
||||
"muted_tag_ids"
|
||||
)
|
||||
);
|
||||
const payload = response.responseJson;
|
||||
|
||||
this.currentUser.setProperties({
|
||||
watched_tags: payload.watched_tags,
|
||||
watching_first_post_tags: payload.watching_first_post_tags,
|
||||
tracked_tags: payload.tracked_tags,
|
||||
muted_tags: payload.muted_tags,
|
||||
regular_tags: payload.regular_tags,
|
||||
});
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
@ -890,7 +890,8 @@ export default Controller.extend(bufferedProperty("model"), {
|
||||
selectReplies(post) {
|
||||
ajax(`/posts/${post.id}/reply-ids.json`).then((replies) => {
|
||||
const replyIds = replies.map((r) => r.id);
|
||||
this.selectedPostIds.pushObjects([post.id, ...replyIds]);
|
||||
const postIds = [...this.selectedPostIds, post.id, ...replyIds];
|
||||
this.set("selectedPostIds", [...new Set(postIds)]);
|
||||
this._forceRefreshPostStream();
|
||||
});
|
||||
},
|
||||
@ -1699,6 +1700,30 @@ export default Controller.extend(bufferedProperty("model"), {
|
||||
topic.set("message_archived", true);
|
||||
break;
|
||||
}
|
||||
case "stats": {
|
||||
let updateStream = false;
|
||||
["last_posted_at", "like_count", "posts_count"].forEach(
|
||||
(property) => {
|
||||
const value = data[property];
|
||||
if (typeof value !== "undefined") {
|
||||
topic.set(property, value);
|
||||
updateStream = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (data["last_poster"]) {
|
||||
topic.details.set("last_poster", data["last_poster"]);
|
||||
updateStream = true;
|
||||
}
|
||||
|
||||
if (updateStream) {
|
||||
postStream
|
||||
.triggerChangedTopicStats()
|
||||
.then((firstPostId) => refresh({ id: firstPostId }));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
let callback = customPostMessageCallbacks[data.type];
|
||||
if (callback) {
|
||||
|
||||
@ -1,49 +1,49 @@
|
||||
import Controller from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import { action } from "@ember/object";
|
||||
import { notEmpty } from "@ember/object/computed";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import bootbox from "bootbox";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
userStatusService: service("user-status"),
|
||||
|
||||
emoji: null,
|
||||
description: null,
|
||||
statusIsSet: notEmpty("description"),
|
||||
showDeleteButton: false,
|
||||
|
||||
onShow() {
|
||||
if (this.currentUser.status) {
|
||||
this.setProperties({
|
||||
description: this.currentUser.status.description,
|
||||
showDeleteButton: true,
|
||||
});
|
||||
}
|
||||
const status = this.currentUser.status;
|
||||
this.setProperties({
|
||||
emoji: status?.emoji,
|
||||
description: status?.description,
|
||||
showDeleteButton: !!status,
|
||||
});
|
||||
},
|
||||
|
||||
@discourseComputed("emoji", "description")
|
||||
statusIsSet(emoji, description) {
|
||||
return !!emoji && !!description;
|
||||
},
|
||||
|
||||
@action
|
||||
delete() {
|
||||
this.userStatusService
|
||||
.clear()
|
||||
.then(() => {
|
||||
this._resetModal();
|
||||
this.send("closeModal");
|
||||
})
|
||||
.then(() => this.send("closeModal"))
|
||||
.catch((e) => this._handleError(e));
|
||||
},
|
||||
|
||||
@action
|
||||
saveAndClose() {
|
||||
if (this.description) {
|
||||
const status = { description: this.description };
|
||||
this.userStatusService
|
||||
.set(status)
|
||||
.then(() => {
|
||||
this.send("closeModal");
|
||||
})
|
||||
.catch((e) => this._handleError(e));
|
||||
}
|
||||
const status = { description: this.description, emoji: this.emoji };
|
||||
this.userStatusService
|
||||
.set(status)
|
||||
.then(() => {
|
||||
this.send("closeModal");
|
||||
})
|
||||
.catch((e) => this._handleError(e));
|
||||
},
|
||||
|
||||
_handleError(e) {
|
||||
@ -53,9 +53,4 @@ export default Controller.extend(ModalFunctionality, {
|
||||
popupAjaxError(e);
|
||||
}
|
||||
},
|
||||
|
||||
_resetModal() {
|
||||
this.set("description", null);
|
||||
this.set("showDeleteButton", false);
|
||||
},
|
||||
});
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { categoryLinkHTML } from "discourse/helpers/category-link";
|
||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||
import { isPresent } from "@ember/utils";
|
||||
|
||||
registerUnbound("category-badge", function (cat, options) {
|
||||
return categoryLinkHTML(cat, {
|
||||
hideParent: options.hideParent,
|
||||
allowUncategorized: options.allowUncategorized,
|
||||
categoryStyle: options.categoryStyle,
|
||||
link: false,
|
||||
link: isPresent(options.link) ? options.link : false,
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,7 +2,7 @@ import { A } from "@ember/array";
|
||||
import Helper from "@ember/component/helper";
|
||||
import { computed, get } from "@ember/object";
|
||||
import { getOwner } from "@ember/application";
|
||||
import { run } from "@ember/runloop";
|
||||
import { join } from "@ember/runloop";
|
||||
import { assert, runInDebug } from "@ember/debug";
|
||||
|
||||
function getCurrentRouteInfos(router) {
|
||||
@ -40,7 +40,7 @@ export function routeAction(actionName, router, ...params) {
|
||||
return function (...invocationArgs) {
|
||||
let { action, handler } = getRouteWithAction(router, actionName);
|
||||
let args = params.concat(invocationArgs);
|
||||
return run.join(handler, action, ...args);
|
||||
return join(handler, action, ...args);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -11,13 +11,26 @@
|
||||
<bootstrap-content key="before-script-load">
|
||||
{{content-for "before-script-load"}}
|
||||
|
||||
<script src="{{rootURL}}assets/vendor.js"></script>
|
||||
<script src="{{rootURL}}assets/discourse.js"></script>
|
||||
<script defer src="{{rootURL}}assets/vendor.js"></script>
|
||||
<script defer src="{{rootURL}}assets/discourse.js"></script>
|
||||
|
||||
<ember-auto-import-scripts defer entrypoint="app"></ember-auto-import-scripts>
|
||||
|
||||
<bootstrap-content key="head">
|
||||
{{content-for "head"}}
|
||||
</head>
|
||||
<body>
|
||||
<discourse-assets>
|
||||
<discourse-assets-stylesheets>
|
||||
<bootstrap-content key="discourse-stylesheets">
|
||||
{{content-for "discourse-stylesheets"}}
|
||||
</discourse-assets-stylesheets>
|
||||
<discourse-assets-json>
|
||||
<bootstrap-content key="preloaded">
|
||||
</discourse-assets-json>
|
||||
<discourse-assets-icons></discourse-assets-icons>
|
||||
</discourse-assets>
|
||||
|
||||
<bootstrap-content key="body">
|
||||
{{content-for "body"}}
|
||||
|
||||
@ -25,9 +38,8 @@
|
||||
</section>
|
||||
|
||||
<bootstrap-content key="hidden-login-form">
|
||||
<bootstrap-content key="preloaded">
|
||||
|
||||
<script src="{{rootURL}}assets/start-discourse.js"></script>
|
||||
<script defer src="{{rootURL}}assets/start-discourse.js"></script>
|
||||
|
||||
<bootstrap-content key="body-footer">
|
||||
{{content-for "body-footer"}}
|
||||
|
||||
@ -1,54 +1,50 @@
|
||||
import { setDefaultOwner } from "discourse-common/lib/get-owner";
|
||||
import { isLegacyEmber } from "discourse-common/config/environment";
|
||||
import User from "discourse/models/user";
|
||||
import Site from "discourse/models/site";
|
||||
import deprecated from "discourse-common/lib/deprecated";
|
||||
|
||||
export default {
|
||||
name: "inject-objects",
|
||||
after: isLegacyEmber() ? null : "export-application-global",
|
||||
after: "export-application-global",
|
||||
initialize(container, app) {
|
||||
// This is required for Ember CLI tests to work
|
||||
setDefaultOwner(app.__container__);
|
||||
|
||||
// Backwards compatibility for Discourse.SiteSettings and Discourse.User
|
||||
if (!isLegacyEmber()) {
|
||||
Object.defineProperty(app, "SiteSettings", {
|
||||
get() {
|
||||
deprecated(
|
||||
`use injected siteSettings instead of Discourse.SiteSettings`,
|
||||
{
|
||||
since: "2.8",
|
||||
dropFrom: "2.9",
|
||||
}
|
||||
);
|
||||
return container.lookup("site-settings:main");
|
||||
},
|
||||
});
|
||||
Object.defineProperty(app, "User", {
|
||||
get() {
|
||||
deprecated(
|
||||
`import discourse/models/user instead of using Discourse.User`,
|
||||
{
|
||||
since: "2.8",
|
||||
dropFrom: "2.9",
|
||||
}
|
||||
);
|
||||
return User;
|
||||
},
|
||||
});
|
||||
Object.defineProperty(app, "Site", {
|
||||
get() {
|
||||
deprecated(
|
||||
`import discourse/models/site instead of using Discourse.Site`,
|
||||
{
|
||||
since: "2.8",
|
||||
dropFrom: "2.9",
|
||||
}
|
||||
);
|
||||
return Site;
|
||||
},
|
||||
});
|
||||
}
|
||||
Object.defineProperty(app, "SiteSettings", {
|
||||
get() {
|
||||
deprecated(
|
||||
`use injected siteSettings instead of Discourse.SiteSettings`,
|
||||
{
|
||||
since: "2.8",
|
||||
dropFrom: "2.9",
|
||||
}
|
||||
);
|
||||
return container.lookup("site-settings:main");
|
||||
},
|
||||
});
|
||||
Object.defineProperty(app, "User", {
|
||||
get() {
|
||||
deprecated(
|
||||
`import discourse/models/user instead of using Discourse.User`,
|
||||
{
|
||||
since: "2.8",
|
||||
dropFrom: "2.9",
|
||||
}
|
||||
);
|
||||
return User;
|
||||
},
|
||||
});
|
||||
Object.defineProperty(app, "Site", {
|
||||
get() {
|
||||
deprecated(
|
||||
`import discourse/models/site instead of using Discourse.Site`,
|
||||
{
|
||||
since: "2.8",
|
||||
dropFrom: "2.9",
|
||||
}
|
||||
);
|
||||
return Site;
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@ -108,19 +108,17 @@ export default {
|
||||
user.notification_channel_position
|
||||
);
|
||||
|
||||
bus.subscribe(`/user-updates/${user.id}`, (data) => {
|
||||
switch (data.type) {
|
||||
case "drafts":
|
||||
user.updateDraftProperties(data.payload);
|
||||
break;
|
||||
case "do_not_disturb":
|
||||
user.updateDoNotDisturbStatus(data.payload.ends_at);
|
||||
break;
|
||||
case "user_status":
|
||||
user.set("status", data.payload);
|
||||
appEvents.trigger("user-status:changed");
|
||||
break;
|
||||
}
|
||||
bus.subscribe(`/user-drafts/${user.id}`, (data) => {
|
||||
user.updateDraftProperties(data);
|
||||
});
|
||||
|
||||
bus.subscribe(`/do-not-disturb/${user.get("id")}`, (data) => {
|
||||
user.updateDoNotDisturbStatus(data.ends_at);
|
||||
});
|
||||
|
||||
bus.subscribe(`/user-status/${user.id}`, (data) => {
|
||||
user.set("status", data);
|
||||
appEvents.trigger("user-status:changed");
|
||||
});
|
||||
|
||||
const site = container.lookup("site:main");
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import { isLegacyEmber } from "discourse-common/config/environment";
|
||||
import { run } from "@ember/runloop";
|
||||
import tippy from "tippy.js";
|
||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
|
||||
@ -39,14 +37,6 @@ export function showPopover(event, options = {}) {
|
||||
? event.target._tippy
|
||||
: setup(event.target, options);
|
||||
|
||||
// hangs on legacy ember
|
||||
if (!isLegacyEmber) {
|
||||
run.begin();
|
||||
instance.popper.addEventListener("transitionend", run.end, {
|
||||
once: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (instance.state.isShown) {
|
||||
instance.hide();
|
||||
} else {
|
||||
@ -72,8 +62,7 @@ export default function setup(target, options) {
|
||||
options
|
||||
);
|
||||
|
||||
// legacy support
|
||||
delete tippyOptions.textContent;
|
||||
// legacy support delete tippyOptions.textContent;
|
||||
delete tippyOptions.htmlContent;
|
||||
|
||||
return tippy(target, tippyOptions);
|
||||
|
||||
@ -119,7 +119,7 @@ export function cacheBuster(url) {
|
||||
if (PUBLIC_JS_VERSIONS) {
|
||||
let [folder, ...lib] = url.split("/").filter(Boolean);
|
||||
if (folder === "javascripts") {
|
||||
lib = lib.join("/");
|
||||
lib = lib.join("/").toLowerCase();
|
||||
const versionedPath = PUBLIC_JS_VERSIONS[lib];
|
||||
if (versionedPath) {
|
||||
return `/javascripts/${versionedPath}`;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
const MUTED = 0;
|
||||
const REGULAR = 1;
|
||||
const NORMAL = 1; // alias for REGULAR
|
||||
const TRACKING = 2;
|
||||
const WATCHING = 3;
|
||||
const WATCHING_FIRST_POST = 4;
|
||||
@ -9,6 +10,7 @@ export const NotificationLevels = {
|
||||
WATCHING,
|
||||
TRACKING,
|
||||
REGULAR,
|
||||
NORMAL,
|
||||
MUTED,
|
||||
};
|
||||
|
||||
|
||||
@ -42,6 +42,8 @@ export function startPageTracking(router, appEvents, documentTitle) {
|
||||
url,
|
||||
title: documentTitle.getTitle(),
|
||||
currentRouteName: router.currentRouteName,
|
||||
currentRouteParams: router.currentRoute.params,
|
||||
currentRouteParentName: router.currentRoute.parent?.name,
|
||||
replacedOnlyQueryParams,
|
||||
});
|
||||
});
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
export const PUBLIC_JS_VERSIONS = {
|
||||
"ace/ace.js": "ace.js/1.4.13/ace.js",
|
||||
"jsoneditor.js": "@json-editor/json-editor/2.6.1/jsoneditor.js",
|
||||
"Chart.min.js": "chart.js/3.5.1/Chart.min.js",
|
||||
"chart.min.js": "chart.js/3.5.1/chart.min.js",
|
||||
"chartjs-plugin-datalabels.min.js":
|
||||
"chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.min.js",
|
||||
"diffhtml.min.js": "diffhtml/1.0.0-beta.20/diffhtml.min.js",
|
||||
|
||||
@ -0,0 +1,70 @@
|
||||
import I18n from "I18n";
|
||||
|
||||
import { capitalize } from "@ember/string";
|
||||
import MessageSectionLink from "discourse/lib/sidebar/messages-section/message-section-link";
|
||||
|
||||
export default class GroupMessageSectionLink extends MessageSectionLink {
|
||||
routeNames = new Set([
|
||||
"userPrivateMessages.group",
|
||||
"userPrivateMessages.groupUnread",
|
||||
"userPrivateMessages.groupNew",
|
||||
"userPrivateMessages.groupArchive",
|
||||
]);
|
||||
|
||||
get name() {
|
||||
return `group-messages-${this.type}`;
|
||||
}
|
||||
|
||||
get class() {
|
||||
return this.group.name;
|
||||
}
|
||||
|
||||
get route() {
|
||||
if (this._isInbox) {
|
||||
return "userPrivateMessages.group";
|
||||
} else {
|
||||
return `userPrivateMessages.group${capitalize(this.type)}`;
|
||||
}
|
||||
}
|
||||
|
||||
get currentWhen() {
|
||||
if (this._isInbox) {
|
||||
return [...this.routeNames].join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
get models() {
|
||||
return [this.currentUser, this.group.name];
|
||||
}
|
||||
|
||||
get text() {
|
||||
if (this._isInbox) {
|
||||
return this.group.name;
|
||||
} else if (this.count > 0) {
|
||||
return I18n.t(`sidebar.sections.messages.links.${this.type}_with_count`, {
|
||||
count: this.count,
|
||||
});
|
||||
} else {
|
||||
return I18n.t(`sidebar.sections.messages.links.${this.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
pageChanged({ currentRouteName, currentRouteParams, privateMessageTopic }) {
|
||||
if (this._isInbox) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
privateMessageTopic?.allowedGroups?.some(
|
||||
(g) => g.name === this.group.name
|
||||
)
|
||||
) {
|
||||
this.setDisplayState = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.setDisplayState =
|
||||
this.routeNames.has(currentRouteName) &&
|
||||
currentRouteParams.name.toLowerCase() === this.group.name.toLowerCase();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
|
||||
import {
|
||||
INBOX,
|
||||
NEW,
|
||||
UNREAD,
|
||||
} from "discourse/components/sidebar/messages-section";
|
||||
|
||||
export default class MessageSectionLink {
|
||||
@tracked shouldDisplay = this._isInbox;
|
||||
@tracked count = 0;
|
||||
|
||||
constructor({ group, currentUser, type, pmTopicTrackingState }) {
|
||||
this.group = group;
|
||||
this.currentUser = currentUser;
|
||||
this.type = type;
|
||||
this.pmTopicTrackingState = pmTopicTrackingState;
|
||||
}
|
||||
|
||||
refreshCount() {
|
||||
this._refreshCount();
|
||||
}
|
||||
|
||||
_refreshCount() {
|
||||
if (this.shouldDisplay && this._shouldTrack) {
|
||||
this.count = this.pmTopicTrackingState.lookupCount(this.type, {
|
||||
inboxFilter: this.group ? "group" : "user",
|
||||
groupName: this.group?.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
set setDisplayState(value) {
|
||||
const changed = this.shouldDisplay !== value;
|
||||
this.shouldDisplay = value;
|
||||
|
||||
if (changed) {
|
||||
this._refreshCount();
|
||||
}
|
||||
}
|
||||
|
||||
get inboxFilter() {
|
||||
throw "not implemented";
|
||||
}
|
||||
|
||||
expand() {
|
||||
if (this._isInbox) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setDisplayState = true;
|
||||
}
|
||||
|
||||
collapse() {
|
||||
if (this._isInbox) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setDisplayState = false;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
pageChanged({ currentRouteName, currentRouteParams, privateMessageTopic }) {
|
||||
throw "not implemented";
|
||||
}
|
||||
|
||||
get _isInbox() {
|
||||
return this.type === INBOX;
|
||||
}
|
||||
|
||||
get _shouldTrack() {
|
||||
return this.type === NEW || this.type === UNREAD;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
import I18n from "I18n";
|
||||
|
||||
import MessageSectionLink from "discourse/lib/sidebar/messages-section/message-section-link";
|
||||
|
||||
export default class PersonalMessageSectionLink extends MessageSectionLink {
|
||||
routeNames = new Set([
|
||||
"userPrivateMessages.index",
|
||||
"userPrivateMessages.unread",
|
||||
"userPrivateMessages.sent",
|
||||
"userPrivateMessages.new",
|
||||
"userPrivateMessages.archive",
|
||||
]);
|
||||
|
||||
get name() {
|
||||
return `personal-messages-${this.type}`;
|
||||
}
|
||||
|
||||
get class() {
|
||||
return `personal-messages`;
|
||||
}
|
||||
|
||||
get route() {
|
||||
if (this._isInbox) {
|
||||
return "userPrivateMessages.index";
|
||||
} else {
|
||||
return `userPrivateMessages.${this.type}`;
|
||||
}
|
||||
}
|
||||
|
||||
get currentWhen() {
|
||||
if (this._isInbox) {
|
||||
return [...this.routeNames].join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
get model() {
|
||||
return this.currentUser;
|
||||
}
|
||||
|
||||
get text() {
|
||||
if (this.count > 0) {
|
||||
return I18n.t(`sidebar.sections.messages.links.${this.type}_with_count`, {
|
||||
count: this.count,
|
||||
});
|
||||
} else {
|
||||
return I18n.t(`sidebar.sections.messages.links.${this.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
pageChanged({ currentRouteName, privateMessageTopic }) {
|
||||
if (this._isInbox) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (privateMessageTopic?.allowedGroups?.length === 0) {
|
||||
this.setDisplayState = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.setDisplayState = this.routeNames.has(currentRouteName);
|
||||
}
|
||||
}
|
||||
@ -8,8 +8,8 @@ export default class TagSectionLink {
|
||||
@tracked totalUnread = 0;
|
||||
@tracked totalNew = 0;
|
||||
|
||||
constructor({ tag, topicTrackingState }) {
|
||||
this.tag = tag;
|
||||
constructor({ tagName, topicTrackingState }) {
|
||||
this.tagName = tagName;
|
||||
this.topicTrackingState = topicTrackingState;
|
||||
this.refreshCounts();
|
||||
}
|
||||
@ -17,22 +17,22 @@ export default class TagSectionLink {
|
||||
@bind
|
||||
refreshCounts() {
|
||||
this.totalUnread = this.topicTrackingState.countUnread({
|
||||
tagId: this.tag,
|
||||
tagId: this.tagName,
|
||||
});
|
||||
|
||||
if (this.totalUnread === 0) {
|
||||
this.totalNew = this.topicTrackingState.countNew({
|
||||
tagId: this.tag,
|
||||
tagId: this.tagName,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.tag;
|
||||
return this.tagName;
|
||||
}
|
||||
|
||||
get model() {
|
||||
return this.tag;
|
||||
return this.tagName;
|
||||
}
|
||||
|
||||
get currentWhen() {
|
||||
@ -44,7 +44,7 @@ export default class TagSectionLink {
|
||||
}
|
||||
|
||||
get text() {
|
||||
return this.tag;
|
||||
return this.tagName;
|
||||
}
|
||||
|
||||
get badgeText() {
|
||||
|
||||
@ -7,7 +7,8 @@ export function loadSprites(spritePath, spriteName) {
|
||||
if (!spriteContainer) {
|
||||
spriteContainer = document.createElement("div");
|
||||
spriteContainer.id = SVG_CONTAINER_ID;
|
||||
document.body.appendChild(spriteContainer);
|
||||
const spriteWrapper = document.querySelector("discourse-assets-icons");
|
||||
spriteWrapper?.appendChild(spriteContainer);
|
||||
}
|
||||
|
||||
let sprites = spriteContainer.querySelector(`.${spriteName}`);
|
||||
|
||||
@ -6,9 +6,11 @@ const MSO_LIST_CLASSES = [
|
||||
|
||||
let tagDecorateCallbacks = [];
|
||||
let blockDecorateCallbacks = [];
|
||||
let textDecorateCallbacks = [];
|
||||
|
||||
/**
|
||||
* Allows to add support for custom inline markdown/bbcode
|
||||
* Allows to add support for custom inline markdown/bbcode prefixes
|
||||
* to convert nodes back to bbcode.
|
||||
*
|
||||
* ```
|
||||
* addTagDecorateCallback(function (text) {
|
||||
@ -29,7 +31,8 @@ export function clearTagDecorateCallbacks() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to add support for custom block markdown/bbcode
|
||||
* Allows to add support for custom block markdown/bbcode prefixes
|
||||
* to convert nodes back to bbcode.
|
||||
*
|
||||
* ```
|
||||
* addBlockDecorateCallback(function (text) {
|
||||
@ -48,6 +51,30 @@ export function clearBlockDecorateCallbacks() {
|
||||
blockDecorateCallbacks = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to add support for custom text node transformations
|
||||
* based on the next/previous elements.
|
||||
*
|
||||
* ```
|
||||
* addTextDecorateCallback(function (text, nextElement, previousElement) {
|
||||
* if (
|
||||
* startRangeOpts &&
|
||||
* nextElement?.attributes.class?.includes("discourse-local-date") &&
|
||||
* text === "→"
|
||||
* ) {
|
||||
* return "";
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function addTextDecorateCallback(callback) {
|
||||
textDecorateCallbacks.push(callback);
|
||||
}
|
||||
|
||||
export function clearTextDecorateCallbacks() {
|
||||
textDecorateCallbacks = [];
|
||||
}
|
||||
|
||||
export class Tag {
|
||||
static named(name) {
|
||||
const klass = class NamedTag extends Tag {};
|
||||
@ -657,9 +684,10 @@ function tagByName(name) {
|
||||
}
|
||||
|
||||
class Element {
|
||||
constructor(element, parent, previous, next) {
|
||||
constructor(element, parent, previous, next, metadata) {
|
||||
this.name = element.name;
|
||||
this.data = element.data;
|
||||
this.metadata = metadata;
|
||||
this.children = element.children;
|
||||
this.attributes = element.attributes;
|
||||
|
||||
@ -682,6 +710,7 @@ class Element {
|
||||
tag() {
|
||||
const tag = new (tagByName(this.name) || Tag)();
|
||||
tag.element = this;
|
||||
tag.metadata = this.metadata;
|
||||
return tag;
|
||||
}
|
||||
|
||||
@ -709,6 +738,19 @@ class Element {
|
||||
}
|
||||
|
||||
text = text.replace(/[\s\t]+/g, " ");
|
||||
textDecorateCallbacks.forEach((callback) => {
|
||||
const result = callback.call(
|
||||
this,
|
||||
text,
|
||||
this.next,
|
||||
this.previous,
|
||||
this.metadata
|
||||
);
|
||||
|
||||
if (typeof result !== "undefined") {
|
||||
text = result;
|
||||
}
|
||||
});
|
||||
|
||||
return text;
|
||||
}
|
||||
@ -721,8 +763,8 @@ class Element {
|
||||
return this.parentNames.filter((p) => names.includes(p));
|
||||
}
|
||||
|
||||
static toMarkdown(element, parent, prev, next) {
|
||||
return new Element(element, parent, prev, next).toMarkdown();
|
||||
static toMarkdown(element, parent, prev, next, metadata) {
|
||||
return new Element(element, parent, prev, next, metadata).toMarkdown();
|
||||
}
|
||||
|
||||
static parseChildren(parent) {
|
||||
@ -732,12 +774,15 @@ class Element {
|
||||
static parse(elements, parent = null) {
|
||||
if (elements) {
|
||||
let result = [];
|
||||
let metadata = {};
|
||||
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
const prev = i === 0 ? null : elements[i - 1];
|
||||
const next = i === elements.length ? null : elements[i + 1];
|
||||
|
||||
result.push(Element.toMarkdown(elements[i], parent, prev, next));
|
||||
result.push(
|
||||
Element.toMarkdown(elements[i], parent, prev, next, metadata)
|
||||
);
|
||||
}
|
||||
|
||||
return result.join("");
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { BasePlugin } from "@uppy/core";
|
||||
import { Promise } from "rsvp";
|
||||
import { warn } from "@ember/debug";
|
||||
import { isTesting } from "discourse-common/config/environment";
|
||||
|
||||
export class UppyPluginBase extends BasePlugin {
|
||||
constructor(uppy, opts) {
|
||||
@ -9,7 +10,9 @@ export class UppyPluginBase extends BasePlugin {
|
||||
}
|
||||
|
||||
_consoleWarn(msg) {
|
||||
warn(`[${this.id}] ${msg}`, { id: `discourse.${this.id}` });
|
||||
if (!isTesting()) {
|
||||
warn(`[${this.id}] ${msg}`, { id: `discourse.${this.id}` });
|
||||
}
|
||||
}
|
||||
|
||||
_consoleDebug(msg) {
|
||||
|
||||
@ -24,7 +24,6 @@ const SERVER_SIDE_ONLY = [
|
||||
/^\/raw\//,
|
||||
/^\/posts\/\d+\/raw/,
|
||||
/^\/raw\/\d+/,
|
||||
/^\/wizard/,
|
||||
/\.rss$/,
|
||||
/\.json$/,
|
||||
/^\/admin\/upgrade$/,
|
||||
|
||||
@ -570,14 +570,12 @@ export default Mixin.create({
|
||||
this.addText(selected, `:${code}:`);
|
||||
}
|
||||
} else {
|
||||
let numOfRemovedChars = selected.pre.length - captures[1].length;
|
||||
selected.pre = selected.pre.slice(
|
||||
0,
|
||||
selected.pre.length - captures[1].length
|
||||
let numOfRemovedChars = captures[1].length;
|
||||
this._insertAt(
|
||||
selected.start - numOfRemovedChars,
|
||||
selected.end,
|
||||
`${code}:`
|
||||
);
|
||||
selected.start -= numOfRemovedChars;
|
||||
selected.end -= numOfRemovedChars;
|
||||
this.addText(selected, `${code}:`);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@ -27,7 +27,7 @@ const NavItem = EmberObject.extend({
|
||||
},
|
||||
|
||||
set(value) {
|
||||
this.set("_title", value);
|
||||
return this.set("_title", value);
|
||||
},
|
||||
},
|
||||
|
||||
@ -56,7 +56,7 @@ const NavItem = EmberObject.extend({
|
||||
},
|
||||
|
||||
set(value) {
|
||||
this.set("_displayName", value);
|
||||
return this.set("_displayName", value);
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@ -872,6 +872,17 @@ export default RestModel.extend({
|
||||
return resolved;
|
||||
},
|
||||
|
||||
triggerChangedTopicStats() {
|
||||
if (this.firstPostNotLoaded) {
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
return Promise.resolve().then(() => {
|
||||
const firstPost = this.posts.findBy("post_number", 1);
|
||||
return firstPost.id;
|
||||
});
|
||||
},
|
||||
|
||||
postForPostNumber(postNumber) {
|
||||
if (!this.hasPosts) {
|
||||
return;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { Promise } from "rsvp";
|
||||
|
||||
import EmberObject from "@ember/object";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { bind, on } from "discourse-common/utils/decorators";
|
||||
@ -25,16 +27,20 @@ const PrivateMessageTopicTrackingState = EmberObject.extend({
|
||||
this.statesModificationCounter = 0;
|
||||
this.isTracking = false;
|
||||
this.newIncoming = [];
|
||||
this.stateChangeCallbacks = {};
|
||||
this.stateChangeCallbacks = new Map();
|
||||
},
|
||||
|
||||
onStateChange(name, callback) {
|
||||
this.stateChangeCallbacks[name] = callback;
|
||||
onStateChange(key, callback) {
|
||||
this.stateChangeCallbacks.set(key, callback);
|
||||
},
|
||||
|
||||
offStateChange(key) {
|
||||
this.stateChangeCallbacks.delete(key);
|
||||
},
|
||||
|
||||
startTracking() {
|
||||
if (this.isTracking) {
|
||||
return;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
this._establishChannels();
|
||||
@ -46,13 +52,13 @@ const PrivateMessageTopicTrackingState = EmberObject.extend({
|
||||
|
||||
_establishChannels() {
|
||||
this.messageBus.subscribe(
|
||||
this._userChannel(),
|
||||
this.userChannel(),
|
||||
this._processMessage.bind(this)
|
||||
);
|
||||
|
||||
this.currentUser.groupsWithMessages?.forEach((group) => {
|
||||
this.messageBus.subscribe(
|
||||
this._groupChannel(group.id),
|
||||
this.groupChannel(group.id),
|
||||
this._processMessage.bind(this)
|
||||
);
|
||||
});
|
||||
@ -111,11 +117,11 @@ const PrivateMessageTopicTrackingState = EmberObject.extend({
|
||||
return this.states.get(topicId);
|
||||
},
|
||||
|
||||
_userChannel() {
|
||||
userChannel() {
|
||||
return `${this.CHANNEL_PREFIX}/user/${this.currentUser.id}`;
|
||||
},
|
||||
|
||||
_groupChannel(groupId) {
|
||||
groupChannel(groupId) {
|
||||
return `${this.CHANNEL_PREFIX}/group/${groupId}`;
|
||||
},
|
||||
|
||||
@ -263,7 +269,7 @@ const PrivateMessageTopicTrackingState = EmberObject.extend({
|
||||
|
||||
_afterStateChange() {
|
||||
this.incrementProperty("statesModificationCounter");
|
||||
Object.values(this.stateChangeCallbacks).forEach((callback) => callback());
|
||||
this.stateChangeCallbacks.forEach((callback) => callback());
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -32,15 +32,15 @@ function isUnseen(topic) {
|
||||
return !topic.is_seen;
|
||||
}
|
||||
|
||||
function hasMutedTags(topicTagIds, mutedTagIds, siteSettings) {
|
||||
if (!mutedTagIds || !topicTagIds) {
|
||||
function hasMutedTags(topicTags, mutedTags, siteSettings) {
|
||||
if (!mutedTags || !topicTags) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
(siteSettings.remove_muted_tags_from_latest === "always" &&
|
||||
topicTagIds.any((tagId) => mutedTagIds.includes(tagId))) ||
|
||||
topicTags.any((topicTag) => mutedTags.includes(topicTag))) ||
|
||||
(siteSettings.remove_muted_tags_from_latest === "only_muted" &&
|
||||
topicTagIds.every((tagId) => mutedTagIds.includes(tagId)))
|
||||
topicTags.every((topicTag) => mutedTags.includes(topicTag)))
|
||||
);
|
||||
}
|
||||
|
||||
@ -876,10 +876,9 @@ const TopicTrackingState = EmberObject.extend({
|
||||
}
|
||||
|
||||
if (["new_topic", "latest"].includes(data.message_type)) {
|
||||
const mutedTagIds = User.currentProp("muted_tag_ids");
|
||||
if (
|
||||
hasMutedTags(data.payload.topic_tag_ids, mutedTagIds, this.siteSettings)
|
||||
) {
|
||||
const mutedTags = User.currentProp("muted_tags");
|
||||
|
||||
if (hasMutedTags(data.payload.tags, mutedTags, this.siteSettings)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,6 +70,7 @@ const Topic = RestModel.extend({
|
||||
|
||||
lastPosterUser: alias("lastPoster.user"),
|
||||
lastPosterGroup: alias("lastPoster.primary_group"),
|
||||
allowedGroups: alias("details.allowed_groups"),
|
||||
|
||||
@discourseComputed("posters.[]", "participants.[]", "allowed_user_count")
|
||||
featuredUsers(posters, participants, allowedUserCount) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import EmberObject, { computed, get, getProperties } from "@ember/object";
|
||||
import cookie, { removeCookie } from "discourse/lib/cookie";
|
||||
import { defaultHomepage, escapeExpression } from "discourse/lib/utilities";
|
||||
import { equal, filterBy, gt, or } from "@ember/object/computed";
|
||||
import { alias, equal, filterBy, gt, or } from "@ember/object/computed";
|
||||
import getURL, { getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import { A } from "@ember/array";
|
||||
import Badge from "discourse/models/badge";
|
||||
@ -62,6 +62,8 @@ let userFields = [
|
||||
"primary_group_id",
|
||||
"flair_group_id",
|
||||
"user_notification_schedule",
|
||||
"sidebar_category_ids",
|
||||
"sidebar_tag_names",
|
||||
];
|
||||
|
||||
export function addSaveableUserField(fieldName) {
|
||||
@ -307,6 +309,35 @@ const User = RestModel.extend({
|
||||
@discourseComputed("silenced_till")
|
||||
silencedTillDate: longDate,
|
||||
|
||||
sidebarCategoryIds: alias("sidebar_category_ids"),
|
||||
|
||||
@discourseComputed("sidebar_tag_names.[]")
|
||||
sidebarTagNames(sidebarTagNames) {
|
||||
if (!sidebarTagNames || sidebarTagNames.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return sidebarTagNames;
|
||||
},
|
||||
|
||||
@discourseComputed("sidebar_category_ids.[]")
|
||||
sidebarCategories(sidebarCategoryIds) {
|
||||
if (!sidebarCategoryIds || sidebarCategoryIds.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Site.current().categoriesList.filter((category) => {
|
||||
if (
|
||||
this.siteSettings.suppress_uncategorized_badge &&
|
||||
category.isUncategorizedCategory
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return sidebarCategoryIds.includes(category.id);
|
||||
});
|
||||
},
|
||||
|
||||
changeUsername(new_username) {
|
||||
return ajax(userPath(`${this.username_lower}/preferences/username`), {
|
||||
type: "PUT",
|
||||
@ -385,6 +416,12 @@ const User = RestModel.extend({
|
||||
}
|
||||
});
|
||||
|
||||
["sidebar_category_ids", "sidebar_tag_names"].forEach((prop) => {
|
||||
if (data[prop]?.length === 0) {
|
||||
data[prop] = null;
|
||||
}
|
||||
});
|
||||
|
||||
return this._saveUserData(data, updatedState);
|
||||
},
|
||||
|
||||
|
||||
@ -70,9 +70,8 @@ export default {
|
||||
}
|
||||
|
||||
session.darkModeAvailable =
|
||||
document.head.querySelectorAll(
|
||||
'link[media="(prefers-color-scheme: dark)"]'
|
||||
).length > 0;
|
||||
document.querySelectorAll('link[media="(prefers-color-scheme: dark)"]')
|
||||
.length > 0;
|
||||
|
||||
session.defaultColorSchemeIsDark = setupData.colorSchemeIsDark === "true";
|
||||
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
import Application from "@ember/application";
|
||||
import { isLegacyEmber } from "discourse-common/config/environment";
|
||||
import { registerRouter, teardownRouter } from "discourse/mapping-router";
|
||||
|
||||
let originalBuildInstance;
|
||||
|
||||
export default {
|
||||
name: "map-routes",
|
||||
after: "inject-discourse-objects",
|
||||
@ -12,17 +8,6 @@ export default {
|
||||
let routerClass = registerRouter(app);
|
||||
container.registry.register("router:main", routerClass);
|
||||
this.routerClass = routerClass;
|
||||
|
||||
if (isLegacyEmber()) {
|
||||
// HACK to fix: https://github.com/emberjs/ember.js/issues/10310
|
||||
originalBuildInstance =
|
||||
originalBuildInstance || Application.prototype.buildInstance;
|
||||
|
||||
Application.prototype.buildInstance = function () {
|
||||
this.buildRegistry();
|
||||
return originalBuildInstance.apply(this);
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
teardown() {
|
||||
|
||||
@ -166,6 +166,7 @@ export default function () {
|
||||
this.route("tags");
|
||||
this.route("interface");
|
||||
this.route("apps");
|
||||
this.route("sidebar");
|
||||
|
||||
this.route("username");
|
||||
this.route("email");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user