Version bump

This commit is contained in:
OsamaSayegh 2022-06-30 12:45:07 +03:00
commit f97b6a7dde
No known key found for this signature in database
GPG Key ID: 060E5AC82223685F
712 changed files with 27411 additions and 78194 deletions

View File

@ -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/

View File

@ -21,6 +21,7 @@
"fillIn": "off",
"find": "off",
"getSettledState": "off",
"globalThis": "readonly",
"hasModule": "off",
"invisible": "off",
"jQuery": "off",

View File

@ -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

View File

@ -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/

View File

@ -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

View File

@ -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.

View File

@ -1,2 +0,0 @@
//= require main_include_admin
//= require admin-plugins

View File

@ -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"),
});

View File

@ -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() {

View File

@ -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(

View File

@ -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",

View File

@ -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]]) : "—",
};
},

View File

@ -1 +1 @@
{{html-safe formatedValue}}
{{html-safe formattedValue}}

View File

@ -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>

View File

@ -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();
};

View File

@ -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"
},

View 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;
})();

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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/")]
);
}
},
});
}

View File

@ -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);

View File

@ -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();
};

View File

@ -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"
}
}

View File

@ -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>

View 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>

View 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();
};

View File

@ -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"
}
}

View File

@ -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>

View 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>

View File

@ -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 = {};
};
})();

View File

@ -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;
});

View 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();
};

View File

@ -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"
}
}

View File

@ -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>

View 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>

View File

@ -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) {

View File

@ -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")) {

View File

@ -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) {

View File

@ -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 || {})
);

View File

@ -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",

View File

@ -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);
}
}

View File

@ -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,
];
}
}

View File

@ -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() {

View File

@ -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);
}
}

View File

@ -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"),

View File

@ -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);
}
}

View File

@ -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 (

View File

@ -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
);
},

View File

@ -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);
});
}
}

View File

@ -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,
});
});
},
}

View File

@ -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) {

View File

@ -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);
},
});

View File

@ -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,
});
});

View File

@ -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);
};
}

View File

@ -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"}}

View File

@ -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;
},
});
},
};

View File

@ -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");

View File

@ -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);

View File

@ -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}`;

View File

@ -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,
};

View File

@ -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,
});
});

View File

@ -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",

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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() {

View File

@ -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}`);

View File

@ -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("");

View File

@ -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) {

View File

@ -24,7 +24,6 @@ const SERVER_SIDE_ONLY = [
/^\/raw\//,
/^\/posts\/\d+\/raw/,
/^\/raw\/\d+/,
/^\/wizard/,
/\.rss$/,
/\.json$/,
/^\/admin\/upgrade$/,

View File

@ -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}:`);
}
},
});

View File

@ -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);
},
},

View File

@ -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;

View File

@ -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());
},
});

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -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);
},

View File

@ -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";

View File

@ -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() {

View File

@ -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