Version bump
This commit is contained in:
commit
234b5780c3
@ -1,7 +1,8 @@
|
||||
{
|
||||
"extends": "eslint-config-discourse",
|
||||
"rules": {
|
||||
"discourse-ember/global-ember": 2
|
||||
"discourse-ember/global-ember": 2,
|
||||
"no-duplicate-imports": 2
|
||||
},
|
||||
"globals": {
|
||||
"moduleFor": "off",
|
||||
|
||||
@ -49,3 +49,6 @@ bc97c79a35d8acd283d4d8b79aa079bce9d127c6
|
||||
|
||||
# REFACTOR: Move javascript tests inside discourse app
|
||||
23f24bfb510edb25b18b6a0d5485270c88df9b24
|
||||
|
||||
# DEV: Tidy up imports. (#11364)
|
||||
1c2358ba162eb9f9ba9095c9afe30cf51dd85e04
|
||||
|
||||
23
Gemfile.lock
23
Gemfile.lock
@ -172,7 +172,7 @@ GEM
|
||||
logstash-logger (0.26.1)
|
||||
logstash-event (~> 1.2)
|
||||
logster (2.9.4)
|
||||
loofah (2.7.0)
|
||||
loofah (2.8.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
lru_redux (1.1.0)
|
||||
@ -235,7 +235,7 @@ GEM
|
||||
omniauth-twitter (1.4.0)
|
||||
omniauth-oauth (~> 1.1)
|
||||
rack
|
||||
onebox (2.1.6)
|
||||
onebox (2.1.7)
|
||||
addressable (~> 2.7.0)
|
||||
htmlentities (~> 4.3)
|
||||
multi_json (~> 1.11)
|
||||
@ -244,8 +244,8 @@ GEM
|
||||
sanitize
|
||||
openssl-signature_algorithm (1.0.0)
|
||||
optimist (3.0.1)
|
||||
parallel (1.20.0)
|
||||
parallel_tests (3.3.0)
|
||||
parallel (1.20.1)
|
||||
parallel_tests (3.4.0)
|
||||
parallel
|
||||
parser (2.7.2.0)
|
||||
ast (~> 2.4.1)
|
||||
@ -275,8 +275,9 @@ GEM
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.3.0)
|
||||
loofah (~> 2.3)
|
||||
rails_failover (0.6.0)
|
||||
rails_failover (0.6.2)
|
||||
activerecord (~> 6.0)
|
||||
concurrent-ruby
|
||||
railties (~> 6.0)
|
||||
rails_multisite (2.5.0)
|
||||
activerecord (> 5.0, < 7)
|
||||
@ -298,10 +299,10 @@ GEM
|
||||
msgpack (>= 0.4.3)
|
||||
optimist (>= 3.0.0)
|
||||
rchardet (1.8.0)
|
||||
redis (4.2.2)
|
||||
redis (4.2.5)
|
||||
redis-namespace (1.8.0)
|
||||
redis (>= 3.0.4)
|
||||
regexp_parser (1.8.2)
|
||||
regexp_parser (2.0.0)
|
||||
request_store (1.5.0)
|
||||
rack (>= 1.4)
|
||||
rexml (3.2.4)
|
||||
@ -340,7 +341,7 @@ GEM
|
||||
json-schema (~> 2.2)
|
||||
railties (>= 3.1, < 7.0)
|
||||
rtlit (0.0.5)
|
||||
rubocop (1.3.1)
|
||||
rubocop (1.4.2)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.7.1.5)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
@ -349,7 +350,7 @@ GEM
|
||||
rubocop-ast (>= 1.1.1)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 2.0)
|
||||
rubocop-ast (1.1.1)
|
||||
rubocop-ast (1.2.0)
|
||||
parser (>= 2.7.1.5)
|
||||
rubocop-discourse (2.4.1)
|
||||
rubocop (>= 1.1.0)
|
||||
@ -386,10 +387,12 @@ GEM
|
||||
connection_pool (>= 2.2.2)
|
||||
rack (~> 2.0)
|
||||
redis (>= 4.2.0)
|
||||
simplecov (0.19.1)
|
||||
simplecov (0.20.0)
|
||||
docile (~> 1.1)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-html (0.12.3)
|
||||
simplecov_json_formatter (0.1.2)
|
||||
sprockets (3.7.2)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
|
||||
@ -6,8 +6,7 @@ import Component from "@ember/component";
|
||||
import UserField from "admin/models/user-field";
|
||||
import { bufferedProperty } from "discourse/mixins/buffered-content";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { propertyEqual } from "discourse/lib/computed";
|
||||
import { i18n } from "discourse/lib/computed";
|
||||
import { propertyEqual, i18n } from "discourse/lib/computed";
|
||||
import discourseComputed, {
|
||||
observes,
|
||||
on,
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import I18n from "I18n";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import discourseComputed, {
|
||||
on,
|
||||
observes,
|
||||
} from "discourse-common/utils/decorators";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { or } from "@ember/object/computed";
|
||||
import { schedule } from "@ember/runloop";
|
||||
import Component from "@ember/component";
|
||||
import { bufferedProperty } from "discourse/mixins/buffered-content";
|
||||
import { on, observes } from "discourse-common/utils/decorators";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import Category from "discourse/models/category";
|
||||
import bootbox from "bootbox";
|
||||
|
||||
@ -1,42 +1,44 @@
|
||||
import I18n from "I18n";
|
||||
import Component from "@ember/component";
|
||||
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
import { action } from "@ember/object";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ["inline-edit"],
|
||||
|
||||
checked: null,
|
||||
checkedInternal: null,
|
||||
buffer: null,
|
||||
bufferModelId: null,
|
||||
|
||||
init() {
|
||||
didReceiveAttrs() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.set("checkedInternal", this.checked);
|
||||
if (this.modelId !== this.bufferModelId) {
|
||||
// HACK: The condition above ensures this method is called only when its
|
||||
// attributes are changed (i.e. only when `checked` changes).
|
||||
//
|
||||
// Reproduction steps: navigate to theme #1, switch to theme #2 from the
|
||||
// left-side panel, then switch back to theme #1 and click on the <input>
|
||||
// element wrapped by this component. It will call `didReceiveAttrs` even
|
||||
// though none of the attributes have changed (only `buffer` does).
|
||||
this.setProperties({
|
||||
buffer: this.checked,
|
||||
bufferModelId: this.modelId,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@observes("checked")
|
||||
checkedChanged() {
|
||||
this.set("checkedInternal", this.checked);
|
||||
@discourseComputed("checked", "buffer")
|
||||
changed(checked, buffer) {
|
||||
return !!checked !== !!buffer;
|
||||
},
|
||||
|
||||
@discourseComputed("labelKey")
|
||||
label(key) {
|
||||
return I18n.t(key);
|
||||
@action
|
||||
apply() {
|
||||
this.set("checked", this.buffer);
|
||||
this.action();
|
||||
},
|
||||
|
||||
@discourseComputed("checked", "checkedInternal")
|
||||
changed(checked, checkedInternal) {
|
||||
return !!checked !== !!checkedInternal;
|
||||
},
|
||||
|
||||
actions: {
|
||||
cancelled() {
|
||||
this.set("checkedInternal", this.checked);
|
||||
},
|
||||
|
||||
finished() {
|
||||
this.set("checked", this.checkedInternal);
|
||||
this.action();
|
||||
},
|
||||
@action
|
||||
cancel() {
|
||||
this.set("buffer", this.checked);
|
||||
},
|
||||
});
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import I18n from "I18n";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import discourseComputed, {
|
||||
afterRender,
|
||||
} from "discourse-common/utils/decorators";
|
||||
import { equal } from "@ember/object/computed";
|
||||
import Component from "@ember/component";
|
||||
import { afterRender } from "discourse-common/utils/decorators";
|
||||
|
||||
const ACTIONS = ["delete", "delete_replies", "edit", "none"];
|
||||
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import I18n from "I18n";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import discourseComputed, { on } from "discourse-common/utils/decorators";
|
||||
import { schedule } from "@ember/runloop";
|
||||
import Component from "@ember/component";
|
||||
import bootbox from "bootbox";
|
||||
import ScreenedIpAddress from "admin/models/screened-ip-address";
|
||||
|
||||
/**
|
||||
A form to create an IP address that will be blocked or allowed.
|
||||
@ -15,9 +16,6 @@ import bootbox from "bootbox";
|
||||
as an argument.
|
||||
**/
|
||||
|
||||
import ScreenedIpAddress from "admin/models/screened-ip-address";
|
||||
import { on } from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ["screened-ip-address-form"],
|
||||
formSubmitted: false,
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import discourseComputed, { on } from "discourse-common/utils/decorators";
|
||||
import { makeArray } from "discourse-common/lib/helpers";
|
||||
import { empty, reads } from "@ember/object/computed";
|
||||
import Component from "@ember/component";
|
||||
import { on } from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
classNameBindings: [":value-list"],
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import I18n from "I18n";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import Controller from "@ember/controller";
|
||||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { bufferedProperty } from "discourse/mixins/buffered-content";
|
||||
import { action } from "@ember/object";
|
||||
import { inject as controller } from "@ember/controller";
|
||||
import bootbox from "bootbox";
|
||||
|
||||
export default Controller.extend(bufferedProperty("emailTemplate"), {
|
||||
|
||||
@ -151,6 +151,15 @@ export default Controller.extend({
|
||||
|
||||
hasTranslations: notEmpty("translations"),
|
||||
|
||||
@discourseComputed(
|
||||
"model.remote_theme.local_version",
|
||||
"model.remote_theme.remote_version",
|
||||
"model.remote_theme.commits_behind"
|
||||
)
|
||||
hasOverwrittenHistory(localVersion, remoteVersion, commitsBehind) {
|
||||
return localVersion !== remoteVersion && commitsBehind === -1;
|
||||
},
|
||||
|
||||
@discourseComputed("model.remoteError", "updatingRemote")
|
||||
showRemoteError(errorMessage, updating) {
|
||||
return errorMessage && !updating;
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import I18n from "I18n";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { makeArray } from "discourse-common/lib/helpers";
|
||||
import { inject } from "@ember/controller";
|
||||
import Controller from "@ember/controller";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
import { setting } from "discourse/lib/computed";
|
||||
import AdminDashboard from "admin/models/admin-dashboard";
|
||||
import Report from "admin/models/report";
|
||||
|
||||
@ -4,11 +4,10 @@ import { inject as service } from "@ember/service";
|
||||
import Controller from "@ember/controller";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import CanCheckEmails from "discourse/mixins/can-check-emails";
|
||||
import { propertyNotEqual, setting } from "discourse/lib/computed";
|
||||
import { propertyNotEqual, setting, fmt } from "discourse/lib/computed";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { fmt } from "discourse/lib/computed";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
import bootbox from "bootbox";
|
||||
|
||||
@ -4,13 +4,13 @@ import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { makeArray } from "discourse-common/lib/helpers";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import EmberObject from "@ember/object";
|
||||
import { escapeExpression } from "discourse/lib/utilities";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import round from "discourse/lib/round";
|
||||
import {
|
||||
fillMissingDates,
|
||||
formatUsername,
|
||||
toNumber,
|
||||
escapeExpression,
|
||||
} from "discourse/lib/utilities";
|
||||
import { number, durationTiny } from "discourse/lib/formatter";
|
||||
import { renderAvatar } from "discourse/helpers/user-avatar";
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<label class="checkbox-label">
|
||||
{{input type="checkbox" disabled=disabled checked=checkedInternal}}
|
||||
{{label}}
|
||||
{{input type="checkbox" disabled=disabled checked=buffer}}
|
||||
{{i18n labelKey}}
|
||||
</label>
|
||||
{{#if changed}}
|
||||
{{d-button action=(action "finished") class="btn-primary btn-small submit-edit" icon="check"}}
|
||||
{{d-button action=(action "cancelled") class="btn-small cancel-edit" icon="times"}}
|
||||
{{d-button action=(action "apply") class="btn-primary btn-small submit-edit" icon="check"}}
|
||||
{{d-button action=(action "cancel") class="btn-small cancel-edit" icon="times"}}
|
||||
{{/if}}
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
|
||||
<div class="admin-controls">
|
||||
{{#if model.theme_id}}
|
||||
{{inline-edit-checkbox action=(action "applyUserSelectable") labelKey="admin.customize.theme.color_scheme_user_selectable" checked=model.user_selectable}}
|
||||
{{inline-edit-checkbox action=(action "applyUserSelectable") labelKey="admin.customize.theme.color_scheme_user_selectable" checked=model.user_selectable modelId=model.id}}
|
||||
{{else}}
|
||||
<label>
|
||||
{{input type="checkbox" checked=model.user_selectable}}
|
||||
|
||||
@ -105,7 +105,11 @@
|
||||
{{i18n "admin.customize.theme.updating"}}
|
||||
{{else}}
|
||||
{{#if model.remote_theme.commits_behind}}
|
||||
{{i18n "admin.customize.theme.commits_behind" count=model.remote_theme.commits_behind}}
|
||||
{{#if hasOverwrittenHistory}}
|
||||
{{i18n "admin.customize.theme.has_overwritten_history"}}
|
||||
{{else}}
|
||||
{{i18n "admin.customize.theme.commits_behind" count=model.remote_theme.commits_behind}}
|
||||
{{/if}}
|
||||
{{#if model.remote_theme.github_diff_link}}
|
||||
<a href={{model.remote_theme.github_diff_link}}>
|
||||
{{i18n "admin.customize.theme.compare_commits"}}
|
||||
@ -137,11 +141,11 @@
|
||||
{{#if showCheckboxes}}
|
||||
<div class="control-unit">
|
||||
{{#unless model.component}}
|
||||
{{inline-edit-checkbox action=(action "applyDefault") labelKey="admin.customize.theme.is_default" checked=model.default}}
|
||||
{{inline-edit-checkbox action=(action "applyUserSelectable") labelKey="admin.customize.theme.user_selectable" checked=model.user_selectable}}
|
||||
{{inline-edit-checkbox action=(action "applyDefault") labelKey="admin.customize.theme.is_default" checked=model.default modelId=model.id}}
|
||||
{{inline-edit-checkbox action=(action "applyUserSelectable") labelKey="admin.customize.theme.user_selectable" checked=model.user_selectable modelId=model.id}}
|
||||
{{/unless}}
|
||||
{{#if model.remote_theme}}
|
||||
{{inline-edit-checkbox action=(action "applyAutoUpdateable") labelKey="admin.customize.theme.auto_update" checked=model.auto_update}}
|
||||
{{inline-edit-checkbox action=(action "applyAutoUpdateable") labelKey="admin.customize.theme.auto_update" checked=model.auto_update modelId=model.id}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
@ -50,6 +50,13 @@ export const POPULAR_THEMES = [
|
||||
meta_url: "https://meta.discourse.org/t/custom-header-links/90588",
|
||||
component: true,
|
||||
},
|
||||
{
|
||||
name: "Gifs Search",
|
||||
value: "https://github.com/discourse/discourse-gifs",
|
||||
description: "Adds a button to easily search and insert GIFs in posts.",
|
||||
meta_url: "https://meta.discourse.org/t/discourse-gifs-component/158738",
|
||||
component: true,
|
||||
},
|
||||
{
|
||||
name: "Category Banners",
|
||||
value: "https://github.com/discourse/discourse-category-banners",
|
||||
@ -85,14 +92,6 @@ export const POPULAR_THEMES = [
|
||||
meta_url: "https://meta.discourse.org/t/header-submenus/94584",
|
||||
component: true,
|
||||
},
|
||||
{
|
||||
name: "Alternative Logos",
|
||||
value: "https://github.com/discourse/discourse-alt-logo",
|
||||
description: "Add alternative logos for dark / light themes.",
|
||||
meta_url:
|
||||
"https://meta.discourse.org/t/alternative-logo-for-dark-themes/88502",
|
||||
component: true,
|
||||
},
|
||||
{
|
||||
name: "Automatic Table of Contents",
|
||||
value: "https://github.com/discourse/DiscoTOC",
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import I18n from "I18n";
|
||||
import { h } from "virtual-dom";
|
||||
import attributeHook from "discourse-common/lib/attribute-hook";
|
||||
import { isDevelopment } from "discourse-common/config/environment";
|
||||
|
||||
const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
||||
let _renderers = [];
|
||||
@ -114,8 +115,12 @@ export function setIconList(iconList) {
|
||||
_iconList = iconList;
|
||||
}
|
||||
|
||||
export function isExistingIconId(id) {
|
||||
return _iconList && _iconList.indexOf(id) >= 0;
|
||||
}
|
||||
|
||||
function warnIfMissing(id) {
|
||||
if (warnMissingIcons && _iconList && _iconList.indexOf(id) === -1) {
|
||||
if (warnMissingIcons && isDevelopment() && !isExistingIconId(id)) {
|
||||
console.warn(`The icon "${id}" is missing from the SVG subset.`); // eslint-disable-line no-console
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,8 +3,7 @@ import isDescriptor from "discourse-common/utils/is-descriptor";
|
||||
import extractValue from "discourse-common/utils/extract-value";
|
||||
import decoratorAlias from "discourse-common/utils/decorator-alias";
|
||||
import macroAlias from "discourse-common/utils/macro-alias";
|
||||
import { schedule, next } from "@ember/runloop";
|
||||
import { bind as emberBind } from "@ember/runloop";
|
||||
import { schedule, next, bind as emberBind } from "@ember/runloop";
|
||||
|
||||
export default function discourseComputedDecorator(...params) {
|
||||
// determine if user called as @discourseComputed('blah', 'blah') or @discourseComputed
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import RestAdapter from "discourse/adapters/rest";
|
||||
import { Result } from "discourse/adapters/rest";
|
||||
import RestAdapter, { Result } from "discourse/adapters/rest";
|
||||
import { underscore } from "@ember/string";
|
||||
|
||||
export default RestAdapter.extend({
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import I18n from "I18n";
|
||||
import { computed } from "@ember/object";
|
||||
import { computed, action } from "@ember/object";
|
||||
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default DropdownSelectBoxComponent.extend({
|
||||
classNames: ["bookmark-actions-dropdown"],
|
||||
|
||||
@ -0,0 +1,123 @@
|
||||
import I18n from "I18n";
|
||||
import Component from "@ember/component";
|
||||
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
import PermissionType from "discourse/models/permission-type";
|
||||
import { equal, alias } from "@ember/object/computed";
|
||||
|
||||
const EVERYONE = "everyone";
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ["permission-row", "row-body"],
|
||||
canCreate: equal("type", PermissionType.FULL),
|
||||
everyonePermissionType: alias("everyonePermission.permission_type"),
|
||||
|
||||
@discourseComputed("type")
|
||||
canReply(value) {
|
||||
return (
|
||||
value === PermissionType.CREATE_POST || value === PermissionType.FULL
|
||||
);
|
||||
},
|
||||
|
||||
@discourseComputed("type")
|
||||
canReplyIcon() {
|
||||
return this.canReply ? "check-square" : "far-square";
|
||||
},
|
||||
|
||||
@discourseComputed("type")
|
||||
canCreateIcon() {
|
||||
return this.canCreate ? "check-square" : "far-square";
|
||||
},
|
||||
|
||||
@discourseComputed("type")
|
||||
replyGranted() {
|
||||
return this.type <= PermissionType.CREATE_POST ? "reply-granted" : "";
|
||||
},
|
||||
|
||||
@discourseComputed("type")
|
||||
createGranted() {
|
||||
return this.type === PermissionType.FULL ? "create-granted" : "";
|
||||
},
|
||||
|
||||
@observes("everyonePermissionType")
|
||||
inheritFromEveryone() {
|
||||
if (this.group_name === EVERYONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// groups cannot have a lesser permission than "everyone"
|
||||
if (this.everyonePermissionType < this.type) {
|
||||
this.updatePermission(this.everyonePermissionType);
|
||||
}
|
||||
},
|
||||
|
||||
@discourseComputed("everyonePermissionType", "type")
|
||||
replyDisabled(everyonePermissionType) {
|
||||
if (
|
||||
this.group_name !== EVERYONE &&
|
||||
everyonePermissionType &&
|
||||
everyonePermissionType <= PermissionType.CREATE_POST
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
@discourseComputed("replyDisabled")
|
||||
replyTooltip() {
|
||||
return this.replyDisabled
|
||||
? I18n.t("category.permissions.inherited")
|
||||
: I18n.t("category.permissions.toggle_reply");
|
||||
},
|
||||
|
||||
@discourseComputed("everyonePermissionType", "type")
|
||||
createDisabled(everyonePermissionType) {
|
||||
if (
|
||||
this.group_name !== EVERYONE &&
|
||||
everyonePermissionType &&
|
||||
everyonePermissionType === PermissionType.FULL
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
@discourseComputed("createDisabled")
|
||||
createTooltip() {
|
||||
return this.createDisabled
|
||||
? I18n.t("category.permissions.inherited")
|
||||
: I18n.t("category.permissions.toggle_full");
|
||||
},
|
||||
|
||||
updatePermission(type) {
|
||||
this.category.updatePermission(this.group_name, type);
|
||||
},
|
||||
|
||||
actions: {
|
||||
removeRow() {
|
||||
this.category.removePermission(this.group_name);
|
||||
},
|
||||
|
||||
setPermissionReply() {
|
||||
if (this.type <= PermissionType.CREATE_POST) {
|
||||
this.updatePermission(PermissionType.READONLY);
|
||||
} else {
|
||||
this.updatePermission(PermissionType.CREATE_POST);
|
||||
}
|
||||
},
|
||||
|
||||
setPermissionFull() {
|
||||
if (
|
||||
this.group_name !== EVERYONE &&
|
||||
this.everyonePermissionType === PermissionType.FULL
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.type === PermissionType.FULL) {
|
||||
this.updatePermission(PermissionType.CREATE_POST);
|
||||
} else {
|
||||
this.updatePermission(PermissionType.FULL);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -3,8 +3,7 @@ import { next } from "@ember/runloop";
|
||||
import Component from "@ember/component";
|
||||
import discourseDebounce from "discourse/lib/debounce";
|
||||
import { searchForTerm } from "discourse/lib/search";
|
||||
import { observes } from "discourse-common/utils/decorators";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
loading: null,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import I18n from "I18n";
|
||||
import { debounce, later, next, schedule, throttle } from "@ember/runloop";
|
||||
import { run, debounce, later, next, schedule, throttle } from "@ember/runloop";
|
||||
import Component from "@ember/component";
|
||||
import userSearch from "discourse/lib/user-search";
|
||||
import discourseComputed, {
|
||||
@ -693,63 +693,73 @@ export default Component.extend({
|
||||
|
||||
const isUploading = validateUploadedFiles(data.files, opts);
|
||||
|
||||
this.setProperties({ uploadProgress: 0, isUploading });
|
||||
run(() => {
|
||||
this.setProperties({ uploadProgress: 0, isUploading });
|
||||
});
|
||||
|
||||
return isUploading;
|
||||
});
|
||||
|
||||
$element.on("fileuploadprogressall", (e, data) => {
|
||||
this.set(
|
||||
"uploadProgress",
|
||||
parseInt((data.loaded / data.total) * 100, 10)
|
||||
);
|
||||
run(() => {
|
||||
this.set(
|
||||
"uploadProgress",
|
||||
parseInt((data.loaded / data.total) * 100, 10)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
$element.on("fileuploadsend", (e, data) => {
|
||||
this._pasted = false;
|
||||
this._validUploads++;
|
||||
run(() => {
|
||||
this._pasted = false;
|
||||
this._validUploads++;
|
||||
|
||||
this._setUploadPlaceholderSend(data);
|
||||
this._setUploadPlaceholderSend(data);
|
||||
|
||||
this.appEvents.trigger("composer:insert-text", this.uploadPlaceholder);
|
||||
this.appEvents.trigger("composer:insert-text", this.uploadPlaceholder);
|
||||
|
||||
if (data.xhr && data.originalFiles.length === 1) {
|
||||
this.set("isCancellable", true);
|
||||
this._xhr = data.xhr();
|
||||
}
|
||||
if (data.xhr && data.originalFiles.length === 1) {
|
||||
this.set("isCancellable", true);
|
||||
this._xhr = data.xhr();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$element.on("fileuploaddone", (e, data) => {
|
||||
let upload = data.result;
|
||||
this._setUploadPlaceholderDone(data);
|
||||
if (!this._xhr || !this._xhr._userCancelled) {
|
||||
const markdown = uploadMarkdownResolvers.reduce(
|
||||
(md, resolver) => resolver(upload) || md,
|
||||
getUploadMarkdown(upload)
|
||||
);
|
||||
run(() => {
|
||||
let upload = data.result;
|
||||
this._setUploadPlaceholderDone(data);
|
||||
if (!this._xhr || !this._xhr._userCancelled) {
|
||||
const markdown = uploadMarkdownResolvers.reduce(
|
||||
(md, resolver) => resolver(upload) || md,
|
||||
getUploadMarkdown(upload)
|
||||
);
|
||||
|
||||
cacheShortUploadUrl(upload.short_url, upload);
|
||||
this.appEvents.trigger(
|
||||
"composer:replace-text",
|
||||
this.uploadPlaceholder.trim(),
|
||||
markdown
|
||||
);
|
||||
this._resetUpload(false);
|
||||
} else {
|
||||
this._resetUpload(true);
|
||||
}
|
||||
cacheShortUploadUrl(upload.short_url, upload);
|
||||
this.appEvents.trigger(
|
||||
"composer:replace-text",
|
||||
this.uploadPlaceholder.trim(),
|
||||
markdown
|
||||
);
|
||||
this._resetUpload(false);
|
||||
} else {
|
||||
this._resetUpload(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$element.on("fileuploadfail", (e, data) => {
|
||||
this._setUploadPlaceholderDone(data);
|
||||
this._resetUpload(true);
|
||||
run(() => {
|
||||
this._setUploadPlaceholderDone(data);
|
||||
this._resetUpload(true);
|
||||
|
||||
const userCancelled = this._xhr && this._xhr._userCancelled;
|
||||
this._xhr = null;
|
||||
const userCancelled = this._xhr && this._xhr._userCancelled;
|
||||
this._xhr = null;
|
||||
|
||||
if (!userCancelled) {
|
||||
displayErrorForUpload(data, this.siteSettings);
|
||||
}
|
||||
if (!userCancelled) {
|
||||
displayErrorForUpload(data, this.siteSettings);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (this.site.mobileView) {
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import I18n from "I18n";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
import { alias } from "@ember/object/computed";
|
||||
import Component from "@ember/component";
|
||||
import { observes } from "discourse-common/utils/decorators";
|
||||
import LivePostCounts from "discourse/models/live-post-counts";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@ import discourseComputed, {
|
||||
} from "discourse-common/utils/decorators";
|
||||
import { categoryHashtagTriggerRule } from "discourse/lib/category-hashtags";
|
||||
import { search as searchCategoryTag } from "discourse/lib/category-tag-search";
|
||||
import { generateCookFunction } from "discourse/lib/text";
|
||||
import { getRegister } from "discourse-common/lib/get-owner";
|
||||
import { findRawTemplate } from "discourse-common/lib/raw-templates";
|
||||
import { siteDir } from "discourse/lib/text-direction";
|
||||
@ -26,7 +25,7 @@ import deprecated from "discourse-common/lib/deprecated";
|
||||
import { wantsNewWindow } from "discourse/lib/intercept-click";
|
||||
import { translations } from "pretty-text/emoji/data";
|
||||
import { emojiSearch, isSkinTonableEmoji } from "pretty-text/emoji";
|
||||
import { emojiUrlFor } from "discourse/lib/text";
|
||||
import { emojiUrlFor, generateCookFunction } from "discourse/lib/text";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
import { Promise } from "rsvp";
|
||||
import { isTesting } from "discourse-common/config/environment";
|
||||
|
||||
@ -1,78 +1,38 @@
|
||||
import { buildCategoryPanel } from "discourse/components/edit-category-panel";
|
||||
import PermissionType from "discourse/models/permission-type";
|
||||
import { on } from "discourse-common/utils/decorators";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { not } from "@ember/object/computed";
|
||||
|
||||
export default buildCategoryPanel("security", {
|
||||
editingPermissions: false,
|
||||
selectedGroup: null,
|
||||
selectedPermission: null,
|
||||
showPendingGroupChangesAlert: false,
|
||||
interactedWithDropdowns: false,
|
||||
noGroupSelected: not("selectedGroup"),
|
||||
|
||||
@on("init")
|
||||
_setup() {
|
||||
this.setProperties({
|
||||
selectedGroup: this.get("category.availableGroups.firstObject"),
|
||||
selectedPermission: this.get(
|
||||
"category.availablePermissions.firstObject.id"
|
||||
),
|
||||
});
|
||||
@discourseComputed("category.permissions.@each.permission_type")
|
||||
everyonePermission(permissions) {
|
||||
return permissions.findBy("group_name", "everyone");
|
||||
},
|
||||
|
||||
@on("init")
|
||||
_registerValidator() {
|
||||
this.registerValidator(() => {
|
||||
if (
|
||||
!this.showPendingGroupChangesAlert &&
|
||||
this.interactedWithDropdowns &&
|
||||
this.activeTab
|
||||
) {
|
||||
this.set("showPendingGroupChangesAlert", true);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@discourseComputed("category.permissions.@each.permission_type")
|
||||
everyoneGrantedFull() {
|
||||
return (
|
||||
this.everyonePermission &&
|
||||
this.everyonePermission.permission_type === PermissionType.FULL
|
||||
);
|
||||
},
|
||||
|
||||
@discourseComputed("everyonePermission")
|
||||
minimumPermission(everyonePermission) {
|
||||
return everyonePermission
|
||||
? everyonePermission.permission_type
|
||||
: PermissionType.READONLY;
|
||||
},
|
||||
|
||||
actions: {
|
||||
onSelectGroup(selectedGroup) {
|
||||
this.setProperties({
|
||||
interactedWithDropdowns: true,
|
||||
selectedGroup,
|
||||
onSelectGroup(group_name) {
|
||||
this.category.addPermission({
|
||||
group_name,
|
||||
permission_type: this.minimumPermission,
|
||||
});
|
||||
},
|
||||
|
||||
onSelectPermission(selectedPermission) {
|
||||
this.setProperties({
|
||||
interactedWithDropdowns: true,
|
||||
selectedPermission,
|
||||
});
|
||||
},
|
||||
|
||||
editPermissions() {
|
||||
if (!this.get("category.is_special")) {
|
||||
this.set("editingPermissions", true);
|
||||
}
|
||||
},
|
||||
|
||||
addPermission(group, id) {
|
||||
if (!this.get("category.is_special")) {
|
||||
this.category.addPermission({
|
||||
group_name: group + "",
|
||||
permission: PermissionType.create({ id: parseInt(id, 10) }),
|
||||
});
|
||||
}
|
||||
|
||||
this.setProperties({
|
||||
selectedGroup: this.get("category.availableGroups.firstObject"),
|
||||
showPendingGroupChangesAlert: false,
|
||||
interactedWithDropdowns: false,
|
||||
});
|
||||
},
|
||||
|
||||
removePermission(permission) {
|
||||
if (!this.get("category.is_special")) {
|
||||
this.category.removePermission(permission);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -6,6 +6,7 @@ import { propertyEqual } from "discourse/lib/computed";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import { empty } from "@ember/object/computed";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import { underscore } from "@ember/string";
|
||||
|
||||
export default Component.extend({
|
||||
tagName: "li",
|
||||
@ -21,7 +22,7 @@ export default Component.extend({
|
||||
|
||||
@discourseComputed("tab")
|
||||
title(tab) {
|
||||
return I18n.t("category." + tab.replace("-", "_"));
|
||||
return I18n.t(`category.${underscore(tab)}`);
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
|
||||
@ -1,20 +1,17 @@
|
||||
import { observes } from "discourse-common/utils/decorators";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
import { observes, bind } from "discourse-common/utils/decorators";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import { emojiUnescape } from "discourse/lib/text";
|
||||
import { escapeExpression } from "discourse/lib/utilities";
|
||||
import { emojiUnescape, emojiUrlFor } from "discourse/lib/text";
|
||||
import { action, computed } from "@ember/object";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { schedule, later } from "@ember/runloop";
|
||||
import Component from "@ember/component";
|
||||
import { emojiUrlFor } from "discourse/lib/text";
|
||||
import { createPopper } from "@popperjs/core";
|
||||
import {
|
||||
extendedEmojiList,
|
||||
isSkinTonableEmoji,
|
||||
emojiSearch,
|
||||
} from "pretty-text/emoji";
|
||||
import { safariHacksDisabled } from "discourse/lib/utilities";
|
||||
import { safariHacksDisabled, escapeExpression } from "discourse/lib/utilities";
|
||||
|
||||
function customEmojis() {
|
||||
const list = extendedEmojiList();
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import I18n from "I18n";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import discourseComputed, {
|
||||
on,
|
||||
observes,
|
||||
} from "discourse-common/utils/decorators";
|
||||
import { debounce } from "@ember/runloop";
|
||||
import Component from "@ember/component";
|
||||
import { on, observes } from "discourse-common/utils/decorators";
|
||||
import { escapeExpression } from "discourse/lib/utilities";
|
||||
import { convertIconClass } from "discourse-common/lib/icon-library";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import I18n from "I18n";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { on } from "discourse-common/utils/decorators";
|
||||
import discourseComputed, { on } from "discourse-common/utils/decorators";
|
||||
import TextField from "discourse/components/text-field";
|
||||
import { applySearchAutocomplete } from "discourse/lib/search";
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@ import DiscourseURL from "discourse/lib/url";
|
||||
import { findRawTemplate } from "discourse-common/lib/raw-templates";
|
||||
import { wantsNewWindow } from "discourse/lib/intercept-click";
|
||||
import { on } from "@ember/object/evented";
|
||||
|
||||
import { topicTitleDecorators } from "discourse/components/topic-title";
|
||||
|
||||
export function showEntrance(e) {
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import I18n from "I18n";
|
||||
import { schedule } from "@ember/runloop";
|
||||
import { schedule, next } from "@ember/runloop";
|
||||
import { and, or } from "@ember/object/computed";
|
||||
import { next } from "@ember/runloop";
|
||||
import { action } from "@ember/object";
|
||||
import { isPresent } from "@ember/utils";
|
||||
import { isPresent, isEmpty } from "@ember/utils";
|
||||
import Controller from "@ember/controller";
|
||||
import { Promise } from "rsvp";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
@ -14,7 +13,6 @@ import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
|
||||
import { formattedReminderTime, REMINDER_TYPES } from "discourse/lib/bookmark";
|
||||
import { AUTO_DELETE_PREFERENCES } from "discourse/models/bookmark";
|
||||
import bootbox from "bootbox";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
|
||||
// global shortcuts that interfere with these modal shortcuts, they are rebound when the
|
||||
// modal is closed
|
||||
|
||||
@ -3,8 +3,7 @@ import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { alias } from "@ember/object/computed";
|
||||
import { next } from "@ember/runloop";
|
||||
import { inject } from "@ember/controller";
|
||||
import Controller from "@ember/controller";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import Topic from "discourse/models/topic";
|
||||
|
||||
@ -2,8 +2,7 @@ import I18n from "I18n";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { next } from "@ember/runloop";
|
||||
import { inject } from "@ember/controller";
|
||||
import Controller from "@ember/controller";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import Topic from "discourse/models/topic";
|
||||
|
||||
@ -2,14 +2,12 @@ import getURL from "discourse-common/lib/get-url";
|
||||
import I18n from "I18n";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { and, or, alias, reads } from "@ember/object/computed";
|
||||
import { cancel, debounce } from "@ember/runloop";
|
||||
import { cancel, debounce, run } from "@ember/runloop";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { inject } from "@ember/controller";
|
||||
import Controller from "@ember/controller";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import { buildQuote } from "discourse/lib/quote";
|
||||
import Draft from "discourse/models/draft";
|
||||
import Composer from "discourse/models/composer";
|
||||
import discourseComputed, {
|
||||
observes,
|
||||
on,
|
||||
@ -22,7 +20,7 @@ import {
|
||||
} from "discourse/lib/uploads";
|
||||
import { emojiUnescape } from "discourse/lib/text";
|
||||
import { shortDate } from "discourse/lib/formatter";
|
||||
import { SAVE_LABELS, SAVE_ICONS } from "discourse/models/composer";
|
||||
import Composer, { SAVE_LABELS, SAVE_ICONS } from "discourse/models/composer";
|
||||
import { Promise } from "rsvp";
|
||||
import { isTesting } from "discourse-common/config/environment";
|
||||
import EmberObject, { computed, action } from "@ember/object";
|
||||
@ -1190,7 +1188,8 @@ export default Controller.extend({
|
||||
if (Date.now() - this._lastDraftSaved > 15000) {
|
||||
this._saveDraft();
|
||||
} else {
|
||||
this._saveDraftDebounce = debounce(this, this._saveDraft, 2000);
|
||||
let method = isTesting() ? run : debounce;
|
||||
this._saveDraftDebounce = method(this, this._saveDraft, 2000);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { inject } from "@ember/controller";
|
||||
import Controller from "@ember/controller";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
|
||||
// Just add query params here to have them automatically passed to topic list filters.
|
||||
export const queryParams = {
|
||||
|
||||
@ -7,6 +7,7 @@ import DiscourseURL from "discourse/lib/url";
|
||||
import { readOnly } from "@ember/object/computed";
|
||||
import PermissionType from "discourse/models/permission-type";
|
||||
import { NotificationLevels } from "discourse/lib/notification-levels";
|
||||
import { underscore } from "@ember/string";
|
||||
|
||||
export default Controller.extend({
|
||||
selectedTab: "general",
|
||||
@ -69,6 +70,11 @@ export default Controller.extend({
|
||||
: I18n.t("category.create");
|
||||
},
|
||||
|
||||
@discourseComputed("selectedTab")
|
||||
selectedTabTitle(tab) {
|
||||
return I18n.t(`category.${underscore(tab)}`);
|
||||
},
|
||||
|
||||
actions: {
|
||||
registerValidator(validator) {
|
||||
this.validators.push(validator);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import I18n from "I18n";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { inject } from "@ember/controller";
|
||||
import Controller from "@ember/controller";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import { categoryLinkHTML } from "discourse/helpers/category-link";
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import I18n from "I18n";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { inject } from "@ember/controller";
|
||||
import Controller from "@ember/controller";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
import { extractError } from "discourse/lib/ajax-error";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import GrantBadgeController from "discourse/mixins/grant-badge-controller";
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import I18n from "I18n";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import discourseComputed, {
|
||||
on,
|
||||
observes,
|
||||
} from "discourse-common/utils/decorators";
|
||||
import { alias, gt, not, or, equal } from "@ember/object/computed";
|
||||
import Controller from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import { categoryBadgeHTML } from "discourse/helpers/category-link";
|
||||
import { propertyGreaterThan, propertyLessThan } from "discourse/lib/computed";
|
||||
import { on, observes } from "discourse-common/utils/decorators";
|
||||
import { sanitizeAsync } from "discourse/lib/text";
|
||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
import Post from "discourse/models/post";
|
||||
|
||||
@ -2,8 +2,7 @@ import I18n from "I18n";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { alias, equal } from "@ember/object/computed";
|
||||
import { next } from "@ember/runloop";
|
||||
import { inject } from "@ember/controller";
|
||||
import Controller from "@ember/controller";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import { movePosts, mergeTopic } from "discourse/models/topic";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
|
||||
@ -3,10 +3,9 @@ import I18n from "I18n";
|
||||
import { alias, or, readOnly } from "@ember/object/computed";
|
||||
import Controller from "@ember/controller";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import DiscourseURL, { userPath } from "discourse/lib/url";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import PasswordValidation from "discourse/mixins/password-validation";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import { SECOND_FACTOR_METHODS } from "discourse/models/user";
|
||||
import { getWebauthnCredential } from "discourse/lib/webauthn";
|
||||
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import I18n from "I18n";
|
||||
import { inject } from "@ember/controller";
|
||||
import Controller from "@ember/controller";
|
||||
import { setDefaultHomepage } from "discourse/lib/utilities";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { listThemes, setLocalTheme } from "discourse/lib/theme-selector";
|
||||
import {
|
||||
@ -15,6 +13,7 @@ import {
|
||||
safariHacksDisabled,
|
||||
isiPad,
|
||||
iOSWithVisualViewport,
|
||||
setDefaultHomepage,
|
||||
} from "discourse/lib/utilities";
|
||||
import { computed } from "@ember/object";
|
||||
import { reads } from "@ember/object/computed";
|
||||
|
||||
@ -4,8 +4,7 @@ import { empty, or } from "@ember/object/computed";
|
||||
import Controller from "@ember/controller";
|
||||
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
import { setting, propertyEqual } from "discourse/lib/computed";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import DiscourseURL, { userPath } from "discourse/lib/url";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import User from "discourse/models/user";
|
||||
import bootbox from "bootbox";
|
||||
|
||||
@ -6,7 +6,7 @@ import { next, schedule, later } from "@ember/runloop";
|
||||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import { bufferedProperty } from "discourse/mixins/buffered-content";
|
||||
import Composer from "discourse/models/composer";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import DiscourseURL, { userPath } from "discourse/lib/url";
|
||||
import Post from "discourse/models/post";
|
||||
import { buildQuote } from "discourse/lib/quote";
|
||||
import QuoteState from "discourse/lib/quote-state";
|
||||
@ -18,7 +18,6 @@ import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
import { extractLinkMeta } from "discourse/lib/render-topic-featured-link";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { spinnerHTML } from "discourse/helpers/loading-spinner";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
import TopicTimer from "discourse/models/topic-timer";
|
||||
import { Promise } from "rsvp";
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import I18n from "I18n";
|
||||
import Controller from "@ember/controller";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
import { Promise } from "rsvp";
|
||||
import { inject } from "@ember/controller";
|
||||
import { action } from "@ember/object";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import Bookmark from "discourse/models/bookmark";
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { alias } from "@ember/object/computed";
|
||||
import { inject } from "@ember/controller";
|
||||
import Controller from "@ember/controller";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
import { durationTiny } from "discourse/lib/formatter";
|
||||
|
||||
// should be kept in sync with 'UserSummary::MAX_BADGES'
|
||||
|
||||
@ -3,8 +3,7 @@ import { isEmpty } from "@ember/utils";
|
||||
import { alias, or, gt, not, and } from "@ember/object/computed";
|
||||
import EmberObject, { set, computed } from "@ember/object";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { inject } from "@ember/controller";
|
||||
import Controller from "@ember/controller";
|
||||
import Controller, { inject } from "@ember/controller";
|
||||
import CanCheckEmails from "discourse/mixins/can-check-emails";
|
||||
import User from "discourse/models/user";
|
||||
import optionalService from "discourse/lib/optional-service";
|
||||
|
||||
@ -54,8 +54,11 @@ export function categoryBadgeHTML(category, opts) {
|
||||
const depth = (opts.depth || 1) + 1;
|
||||
if (opts.recursive && depth <= siteSettings.max_category_nesting) {
|
||||
const parentCategory = Category.findById(category.parent_category_id);
|
||||
const lastSubcategory = !opts.depth;
|
||||
opts.depth = depth;
|
||||
return categoryBadgeHTML(parentCategory, opts) + _renderer(category, opts);
|
||||
const parentBadges = categoryBadgeHTML(parentCategory, opts);
|
||||
opts.lastSubcategory = lastSubcategory;
|
||||
return parentBadges + _renderer(category, opts);
|
||||
}
|
||||
|
||||
return _renderer(category, opts);
|
||||
@ -183,5 +186,11 @@ function defaultCategoryLinkRenderer(category, opts) {
|
||||
if (opts.topicCount && categoryStyle === "box") {
|
||||
afterBadgeWrapper += buildTopicCount(opts.topicCount);
|
||||
}
|
||||
if (opts.plusSubcategories && opts.lastSubcategory) {
|
||||
afterBadgeWrapper += `<span class="plus-subcategories">${I18n.t(
|
||||
"category_row.plus_subcategories",
|
||||
{ count: opts.plusSubcategories }
|
||||
)}</span>`;
|
||||
}
|
||||
return `<${tagName} class="badge-wrapper ${extraClasses}" ${href}>${html}</${tagName}>${afterBadgeWrapper}`;
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { h } from "virtual-dom";
|
||||
import { relativeAge, longDate } from "discourse/lib/formatter";
|
||||
import { number } from "discourse/lib/formatter";
|
||||
import { relativeAge, longDate, number } from "discourse/lib/formatter";
|
||||
|
||||
export function dateNode(dt) {
|
||||
if (typeof dt === "string") {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { isAbsoluteURL } from "discourse-common/lib/get-url";
|
||||
import getAbsoluteURL from "discourse-common/lib/get-url";
|
||||
import getAbsoluteURL, { isAbsoluteURL } from "discourse-common/lib/get-url";
|
||||
|
||||
export default {
|
||||
name: "register-service-worker",
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { later, run } from "@ember/runloop";
|
||||
import { later, run, throttle, schedule } from "@ember/runloop";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import Composer from "discourse/models/composer";
|
||||
import { minimumOffset } from "discourse/lib/offset-calculator";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { throttle, schedule } from "@ember/runloop";
|
||||
import { INPUT_DELAY } from "discourse-common/config/environment";
|
||||
import {
|
||||
nextTopicUrl,
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import I18n from "I18n";
|
||||
import loadScript from "discourse/lib/load-script";
|
||||
import { escapeExpression } from "discourse/lib/utilities";
|
||||
import {
|
||||
escapeExpression,
|
||||
isAppWebview,
|
||||
postRNWebviewMessage,
|
||||
} from "discourse/lib/utilities";
|
||||
import { renderIcon } from "discourse-common/lib/icon-library";
|
||||
import { isAppWebview, postRNWebviewMessage } from "discourse/lib/utilities";
|
||||
import { spinnerHTML } from "discourse/helpers/loading-spinner";
|
||||
import User from "discourse/models/user";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { default as getURL, getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import getURL, { getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import { run } from "@ember/runloop";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { PUBLIC_JS_VERSIONS } from "discourse/lib/public-js-versions";
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
import deprecated from "discourse-common/lib/deprecated";
|
||||
import { iconNode } from "discourse-common/lib/icon-library";
|
||||
import { addDecorator } from "discourse/widgets/post-cooked";
|
||||
import { addPluginOutletDecorator } from "discourse/components/plugin-connector";
|
||||
import { addTopicTitleDecorator } from "discourse/components/topic-title";
|
||||
import ComposerEditor from "discourse/components/composer-editor";
|
||||
import DiscourseBanner from "discourse/components/discourse-banner";
|
||||
import { addButton, removeButton } from "discourse/widgets/post-menu";
|
||||
import { includeAttributes } from "discourse/lib/transform-post";
|
||||
@ -16,8 +14,12 @@ import {
|
||||
reopenWidget,
|
||||
decorateWidget,
|
||||
changeSetting,
|
||||
queryRegistry,
|
||||
} from "discourse/widgets/widget";
|
||||
import { preventCloak } from "discourse/widgets/post-stream";
|
||||
import {
|
||||
preventCloak,
|
||||
addPostTransformCallback,
|
||||
} from "discourse/widgets/post-stream";
|
||||
import { h } from "virtual-dom";
|
||||
import { addPopupMenuOptionsCallback } from "discourse/controllers/composer";
|
||||
import { extraConnectorClass } from "discourse/lib/plugin-connectors";
|
||||
@ -27,7 +29,6 @@ import { addDiscoveryQueryParam } from "discourse/controllers/discovery-sortable
|
||||
import { addTagsHtmlCallback } from "discourse/lib/render-tags";
|
||||
import { addUserMenuGlyph } from "discourse/widgets/user-menu";
|
||||
import { addPostClassesCallback } from "discourse/widgets/post";
|
||||
import { addPostTransformCallback } from "discourse/widgets/post-stream";
|
||||
import {
|
||||
attachAdditionalPanel,
|
||||
addToHeaderIcons,
|
||||
@ -35,8 +36,8 @@ import {
|
||||
import {
|
||||
registerIconRenderer,
|
||||
replaceIcon,
|
||||
iconNode,
|
||||
} from "discourse-common/lib/icon-library";
|
||||
import { replaceCategoryLinkRenderer } from "discourse/helpers/category-link";
|
||||
import { replaceTagRenderer } from "discourse/lib/render-tag";
|
||||
import { addNavItem } from "discourse/models/nav-item";
|
||||
import { replaceFormatter } from "discourse/lib/utilities";
|
||||
@ -47,13 +48,15 @@ import { addUsernameSelectorDecorator } from "discourse/helpers/decorate-usernam
|
||||
import { disableNameSuppression } from "discourse/widgets/poster-name";
|
||||
import { registerCustomPostMessageCallback as registerCustomPostMessageCallback1 } from "discourse/controllers/topic";
|
||||
import Sharing from "discourse/lib/sharing";
|
||||
import {
|
||||
import ComposerEditor, {
|
||||
addComposerUploadHandler,
|
||||
addComposerUploadMarkdownResolver,
|
||||
} from "discourse/components/composer-editor";
|
||||
import { addCategorySortCriteria } from "discourse/components/edit-category-settings";
|
||||
import { addExtraIconRenderer } from "discourse/helpers/category-link";
|
||||
import { queryRegistry } from "discourse/widgets/widget";
|
||||
import {
|
||||
addExtraIconRenderer,
|
||||
replaceCategoryLinkRenderer,
|
||||
} from "discourse/helpers/category-link";
|
||||
import Composer from "discourse/models/composer";
|
||||
import { on } from "@ember/object/evented";
|
||||
import { addQuickAccessProfileItem } from "discourse/widgets/quick-access-profile";
|
||||
@ -67,7 +70,7 @@ import {
|
||||
} from "discourse/models/user";
|
||||
|
||||
// If you add any methods to the API ensure you bump up this number
|
||||
const PLUGIN_API_VERSION = "0.11.0";
|
||||
const PLUGIN_API_VERSION = "0.11.1";
|
||||
|
||||
class PluginApi {
|
||||
constructor(version, container) {
|
||||
|
||||
@ -273,7 +273,13 @@ export class Tag {
|
||||
|
||||
if (attr.href && text !== attr.href) {
|
||||
text = text.replace(/\n{2,}/g, "\n");
|
||||
return "[" + text + "](" + attr.href + ")";
|
||||
|
||||
let linkModifier = "";
|
||||
if (attr.class && attr.class.includes("attachment")) {
|
||||
linkModifier = "|attachment";
|
||||
}
|
||||
|
||||
return "[" + text + linkModifier + "](" + attr.href + ")";
|
||||
}
|
||||
|
||||
return text;
|
||||
|
||||
@ -5,7 +5,7 @@ import offsetCalculator from "discourse/lib/offset-calculator";
|
||||
import LockOn from "discourse/lib/lock-on";
|
||||
import { defaultHomepage } from "discourse/lib/utilities";
|
||||
import User from "discourse/models/user";
|
||||
import { default as getURL, withoutPrefix } from "discourse-common/lib/get-url";
|
||||
import getURL, { withoutPrefix } from "discourse-common/lib/get-url";
|
||||
import Session from "discourse/models/session";
|
||||
import { setOwner } from "@ember/application";
|
||||
|
||||
@ -16,6 +16,7 @@ const TOPIC_REGEXP = /\/t\/([^\/]+)\/(\d+)\/?(\d+)?/;
|
||||
const SERVER_SIDE_ONLY = [
|
||||
/^\/assets\//,
|
||||
/^\/uploads\//,
|
||||
/^\/secure-media-uploads\//,
|
||||
/^\/stylesheets\//,
|
||||
/^\/site_customizations\//,
|
||||
/^\/raw\//,
|
||||
|
||||
@ -2,7 +2,7 @@ import I18n from "I18n";
|
||||
import { escape } from "pretty-text/sanitizer";
|
||||
import toMarkdown from "discourse/lib/to-markdown";
|
||||
import Handlebars from "handlebars";
|
||||
import { default as getURL, getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import getURL, { getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import { helperContext } from "discourse-common/lib/helpers";
|
||||
import { deepMerge } from "discourse-common/lib/object";
|
||||
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import discourseComputed, { on } from "discourse-common/utils/decorators";
|
||||
import { get } from "@ember/object";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import RestModel from "discourse/models/rest";
|
||||
import { on } from "discourse-common/utils/decorators";
|
||||
import PermissionType from "discourse/models/permission-type";
|
||||
import { NotificationLevels } from "discourse/lib/notification-levels";
|
||||
import Site from "discourse/models/site";
|
||||
import User from "discourse/models/user";
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
|
||||
const STAFF_GROUP_NAME = "staff";
|
||||
|
||||
const Category = RestModel.extend({
|
||||
permissions: null,
|
||||
|
||||
@ -22,15 +23,13 @@ const Category = RestModel.extend({
|
||||
this.set("availableGroups", availableGroups);
|
||||
|
||||
const groupPermissions = this.group_permissions;
|
||||
|
||||
if (groupPermissions) {
|
||||
this.set(
|
||||
"permissions",
|
||||
groupPermissions.map((elem) => {
|
||||
availableGroups.removeObject(elem.group_name);
|
||||
return {
|
||||
group_name: elem.group_name,
|
||||
permission: PermissionType.create({ id: elem.permission_type }),
|
||||
};
|
||||
return elem;
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -231,7 +230,12 @@ const Category = RestModel.extend({
|
||||
_permissionsForUpdate() {
|
||||
const permissions = this.permissions;
|
||||
let rval = {};
|
||||
permissions.forEach((p) => (rval[p.group_name] = p.permission.id));
|
||||
if (permissions.length) {
|
||||
permissions.forEach((p) => (rval[p.group_name] = p.permission_type));
|
||||
} else {
|
||||
// empty permissions => staff-only access
|
||||
rval[STAFF_GROUP_NAME] = PermissionType.FULL;
|
||||
}
|
||||
return rval;
|
||||
},
|
||||
|
||||
@ -246,9 +250,20 @@ const Category = RestModel.extend({
|
||||
this.availableGroups.removeObject(permission.group_name);
|
||||
},
|
||||
|
||||
removePermission(permission) {
|
||||
this.permissions.removeObject(permission);
|
||||
this.availableGroups.addObject(permission.group_name);
|
||||
removePermission(group_name) {
|
||||
const permission = this.permissions.findBy("group_name", group_name);
|
||||
if (permission) {
|
||||
this.permissions.removeObject(permission);
|
||||
this.availableGroups.addObject(group_name);
|
||||
}
|
||||
},
|
||||
|
||||
updatePermission(group_name, type) {
|
||||
this.permissions.forEach((p, i) => {
|
||||
if (p.group_name === group_name) {
|
||||
this.set(`permissions.${i}.permission_type`, type);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@discourseComputed("topics")
|
||||
|
||||
@ -194,12 +194,7 @@ const Topic = RestModel.extend({
|
||||
@discourseComputed("suggested_topics")
|
||||
suggestedTopics(suggestedTopics) {
|
||||
if (suggestedTopics) {
|
||||
const store = this.store;
|
||||
|
||||
return this.set(
|
||||
"suggested_topics",
|
||||
suggestedTopics.map((st) => store.createRecord("topic", st))
|
||||
);
|
||||
return suggestedTopics.map((st) => this.store.createRecord("topic", st));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import discourseComputed, { on } from "discourse-common/utils/decorators";
|
||||
import { or, equal, and } from "@ember/object/computed";
|
||||
import RestModel from "discourse/models/rest";
|
||||
import { on } from "discourse-common/utils/decorators";
|
||||
import UserActionGroup from "discourse/models/user-action-group";
|
||||
import { postUrl } from "discourse/lib/utilities";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import getURL, { getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import I18n from "I18n";
|
||||
import { A } from "@ember/array";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
@ -22,14 +21,13 @@ import UserDraftsStream from "discourse/models/user-drafts-stream";
|
||||
import Group from "discourse/models/group";
|
||||
import { emojiUnescape } from "discourse/lib/text";
|
||||
import PreloadStore from "discourse/lib/preload-store";
|
||||
import { defaultHomepage } from "discourse/lib/utilities";
|
||||
import { defaultHomepage, escapeExpression } from "discourse/lib/utilities";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import Category from "discourse/models/category";
|
||||
import { Promise } from "rsvp";
|
||||
import deprecated from "discourse-common/lib/deprecated";
|
||||
import Site from "discourse/models/site";
|
||||
import { NotificationLevels } from "discourse/lib/notification-levels";
|
||||
import { escapeExpression } from "discourse/lib/utilities";
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
import cookie, { removeCookie } from "discourse/lib/cookie";
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ export default {
|
||||
session.userDarkSchemeId = parseInt(setupData.userDarkSchemeId, 10) || -1;
|
||||
|
||||
if (isDevelopment()) {
|
||||
setIconList(setupData.svgIconList);
|
||||
setIconList(JSON.parse(setupData.svgIconList));
|
||||
}
|
||||
|
||||
if (setupData.s3BaseUrl) {
|
||||
|
||||
@ -185,7 +185,8 @@ export default DiscourseRoute.extend(FilterModeMixin, {
|
||||
if (controller.get("list.draft")) {
|
||||
this.openTopicDraft(controller.get("list"));
|
||||
} else {
|
||||
this.controllerFor("composer")
|
||||
const composerController = this.controllerFor("composer");
|
||||
composerController
|
||||
.open({
|
||||
categoryId: controller.get("category.id"),
|
||||
action: Composer.CREATE_TOPIC,
|
||||
@ -194,7 +195,7 @@ export default DiscourseRoute.extend(FilterModeMixin, {
|
||||
})
|
||||
.then(() => {
|
||||
// Pre-fill the tags input field
|
||||
if (controller.get("model.id")) {
|
||||
if (composerController.canEditTags && controller.get("model.id")) {
|
||||
const composerModel = this.controllerFor("composer").get("model");
|
||||
composerModel.set(
|
||||
"tags",
|
||||
|
||||
@ -6,11 +6,10 @@ import DiscourseURL from "discourse/lib/url";
|
||||
import { ID_CONSTRAINT } from "discourse/models/topic";
|
||||
import { setTopicId } from "discourse/lib/topic-list-tracker";
|
||||
import { inject as service } from "@ember/service";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
|
||||
const SCROLL_DELAY = 500;
|
||||
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
|
||||
const TopicRoute = DiscourseRoute.extend({
|
||||
screenTrack: service(),
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import Service from "@ember/service";
|
||||
import { inject as service } from "@ember/service";
|
||||
import Service, { inject as service } from "@ember/service";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import updateTabCount from "discourse/lib/update-tab-count";
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
{{category-drop
|
||||
category=breadcrumb.category
|
||||
categories=breadcrumb.options
|
||||
tagId=tagId
|
||||
tagId=tag.id
|
||||
options=(hash
|
||||
parentCategory=breadcrumb.parentCategory
|
||||
subCategory=breadcrumb.isSubcategory
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
<span class="group-name">
|
||||
<span class="group-name-label">{{group_name}}</span>
|
||||
<a class="remove-permission" href {{action "removeRow"}}>
|
||||
{{d-icon "far-trash-alt"}}
|
||||
</a>
|
||||
</span>
|
||||
<span class="options actionable">
|
||||
{{d-button
|
||||
icon="check-square"
|
||||
class="btn btn-flat see"
|
||||
disabled=true
|
||||
}}
|
||||
|
||||
{{d-button
|
||||
icon=canReplyIcon
|
||||
action=(action "setPermissionReply")
|
||||
translatedTitle=replyTooltip
|
||||
class=(concat "btn btn-flat reply-toggle " replyGranted)
|
||||
disabled=replyDisabled
|
||||
}}
|
||||
|
||||
{{d-button
|
||||
icon=canCreateIcon
|
||||
action=(action "setPermissionFull")
|
||||
translatedTitle=createTooltip
|
||||
class=(concat "btn btn-flat create-toggle " createGranted)
|
||||
disabled=createDisabled
|
||||
}}
|
||||
</span>
|
||||
@ -12,14 +12,16 @@
|
||||
<section class="field">
|
||||
<label>{{i18n "category.parent"}}</label>
|
||||
{{category-chooser
|
||||
rootNone=true
|
||||
value=category.parent_category_id
|
||||
excludeCategoryId=category.id
|
||||
categories=parentCategories
|
||||
allowSubCategories=true
|
||||
allowUncategorized=false
|
||||
allowRestrictedCategories=true
|
||||
onChange=(action (mut category.parent_category_id))
|
||||
options=(hash
|
||||
excludeCategoryId=category.id
|
||||
none=true
|
||||
)
|
||||
}}
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
@ -6,62 +6,50 @@
|
||||
<p class="warning">{{i18n "category.special_warning"}}</p>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#unless category.isUncategorizedCategory}}
|
||||
<ul class="permission-list">
|
||||
|
||||
{{#unless category.is_special}}
|
||||
<div class="category-permissions-table">
|
||||
<div class="permission-row row-header">
|
||||
<span class="group-name">{{i18n "category.permissions.group"}}</span>
|
||||
<span class="options">
|
||||
<span class="cell">{{i18n "category.permissions.see"}}</span>
|
||||
<span class="cell">{{i18n "category.permissions.reply"}}</span>
|
||||
<span class="cell">{{i18n "category.permissions.create"}}</span>
|
||||
</span>
|
||||
</div>
|
||||
{{#each category.permissions as |p|}}
|
||||
<li>
|
||||
<span class="name"><span class="badge-group">{{p.group_name}}</span></span>
|
||||
{{html-safe (i18n "category.can")}}
|
||||
<span class="permission">{{p.permission.description}}</span>
|
||||
{{#if editingPermissions}}
|
||||
<a class="remove-permission" href {{action "removePermission" p}}>{{d-icon "times-circle"}}</a>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{category-permission-row group_name=p.group_name type=p.permission_type category=category everyonePermission=everyonePermission}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/unless}}
|
||||
{{#if editingPermissions}}
|
||||
{{#if category.availableGroups}}
|
||||
{{combo-box
|
||||
class="available-groups"
|
||||
content=category.availableGroups
|
||||
onChange=(action "onSelectGroup")
|
||||
value=selectedGroup
|
||||
valueProperty=null
|
||||
nameProperty=null
|
||||
options=(hash
|
||||
placementStrategy="absolute"
|
||||
)
|
||||
}}
|
||||
{{combo-box
|
||||
class="permission-selector"
|
||||
nameProperty="description"
|
||||
content=category.availablePermissions
|
||||
onChange=(action "onSelectPermission")
|
||||
value=selectedPermission
|
||||
options=(hash
|
||||
placementStrategy="absolute"
|
||||
)
|
||||
}}
|
||||
{{d-button
|
||||
action=(action "addPermission" selectedGroup selectedPermission)
|
||||
class="btn-primary add-permission"
|
||||
icon="plus"}}
|
||||
{{#if showPendingGroupChangesAlert}}
|
||||
<div class="pending-permission-change-alert">
|
||||
<div class="arrow-div"></div>
|
||||
{{i18n "category.pending_permission_change_alert" group=selectedGroup}}
|
||||
|
||||
{{#unless category.permissions}}
|
||||
<div class="permission-row row-empty">
|
||||
{{i18n "category.permissions.no_groups_selected"}}
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
{{#if category.availableGroups}}
|
||||
<div class="add-group">
|
||||
<span class="group-name">
|
||||
{{combo-box
|
||||
class="available-groups"
|
||||
content=category.availableGroups
|
||||
onChange=(action "onSelectGroup")
|
||||
value=null
|
||||
valueProperty=null
|
||||
nameProperty=null
|
||||
options=(hash
|
||||
none="category.security_add_group"
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#if everyoneGrantedFull}}
|
||||
<p class="warning">{{i18n "category.permissions.everyone_has_access"}}</p>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#unless category.is_special}}
|
||||
{{d-button
|
||||
action=(action "editPermissions")
|
||||
class="btn-default edit-permission"
|
||||
label="category.edit_permissions"}}
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
</section>
|
||||
|
||||
{{plugin-outlet name="category-custom-security" args=(hash category=category) connectorTagName="" tagName="section"}}
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
<section>
|
||||
<h3>{{i18n "category.settings_sections.general"}}</h3>
|
||||
|
||||
{{#if showPositionInput}}
|
||||
<section class="field position-fields">
|
||||
<label for="category-position">
|
||||
|
||||
@ -1,2 +1 @@
|
||||
<label>{{i18n "category.topic_template"}}</label>
|
||||
{{d-editor value=category.topic_template showLink=showInsertLinkButton}}
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
{{!-- DO NOT EDIT THIS FILE!!! --}}
|
||||
{{!-- Update it by running `rake javascript:update_constants` --}}
|
||||
|
||||
<button type="button" data-section="smileys_&_emotion" {{action onCategorySelection "smileys_&_emotion"}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji ":grinning:"}}
|
||||
</button>
|
||||
<button type="button" data-section="people_&_body" {{action onCategorySelection "people_&_body"}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji ":wave:"}}
|
||||
</button>
|
||||
<button type="button" data-section="animals_&_nature" {{action onCategorySelection "animals_&_nature"}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji ":evergreen_tree:"}}
|
||||
</button>
|
||||
<button type="button" data-section="food_&_drink" {{action onCategorySelection "food_&_drink"}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji ":hamburger:"}}
|
||||
</button>
|
||||
<button type="button" data-section="travel_&_places" {{action onCategorySelection "travel_&_places"}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji ":airplane:"}}
|
||||
</button>
|
||||
<button type="button" data-section="activities" {{action onCategorySelection "activities"}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji ":soccer:"}}
|
||||
</button>
|
||||
<button type="button" data-section="objects" {{action onCategorySelection "objects"}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji ":eyeglasses:"}}
|
||||
</button>
|
||||
<button type="button" data-section="symbols" {{action onCategorySelection "symbols"}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji ":white_check_mark:"}}
|
||||
</button>
|
||||
<button type="button" data-section="flags" {{action onCategorySelection "flags"}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji ":checkered_flag:"}}
|
||||
</button>
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,20 +1,16 @@
|
||||
{{#if isActive}}
|
||||
<div class="emoji-picker {{if @isActive 'opened'}}">
|
||||
<div class="emoji-picker {{if @isActive "opened"}}">
|
||||
<div class="emoji-picker-category-buttons">
|
||||
{{#if recentEmojis.length}}
|
||||
<button data-section="recent" {{action "onCategorySelection" "recent"}} class="btn btn-default category-button emoji">
|
||||
<button type="button" data-section="recent" {{action "onCategorySelection" "recent"}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji ":star:"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
|
||||
<% JSON.parse(File.read("lib/emoji/groups.json")).each.with_index do |group, group_index| %>
|
||||
<button data-section="<%= group["name"] %>" {{action "onCategorySelection" "<%= group["name"] %>"}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji ":<%= group["tabicon"] %>:"}}
|
||||
</button>
|
||||
<% end %>
|
||||
{{emoji-group-buttons onCategorySelection=(action "onCategorySelection")}}
|
||||
|
||||
{{#each-in customEmojis as |group emojis|}}
|
||||
<button data-section={{concat "custom-" group}} {{action "onCategorySelection" (concat "custom-" group)}} class="btn btn-default category-button emoji">
|
||||
<button type="button" data-section={{concat "custom-" group}} {{action "onCategorySelection" (concat "custom-" group)}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji (concat ":" emojis.firstObject.code ":")}}
|
||||
</button>
|
||||
{{/each-in}}
|
||||
@ -35,18 +31,18 @@
|
||||
{{d-icon "search"}}
|
||||
</div>
|
||||
|
||||
<div class="emoji-picker-emoji-area" {{on "click" this.onEmojiSelection}} {{on "mouseover" this.onEmojiHover}}>
|
||||
<div class='results'></div>
|
||||
<div class="emoji-picker-emoji-area" role="button" {{on "click" this.onEmojiSelection}} {{on "mouseover" this.onEmojiHover}}>
|
||||
<div class="results"></div>
|
||||
|
||||
{{#conditional-loading-spinner condition=isLoading}}
|
||||
<div class="emojis-container">
|
||||
{{#if recentEmojis.length}}
|
||||
<div class='section recent' data-section='recent'>
|
||||
<div class='section-header'>
|
||||
<span class="title">{{i18n 'emoji_picker.recent'}}</span>
|
||||
<div class="section recent" data-section="recent">
|
||||
<div class="section-header">
|
||||
<span class="title">{{i18n "emoji_picker.recent"}}</span>
|
||||
{{d-button icon="trash-alt" action=(action "onClearRecents") class="trash-recent"}}
|
||||
</div>
|
||||
<div class='section-group'>
|
||||
<div class="section-group">
|
||||
{{#each recentEmojis as |emoji|}}
|
||||
{{replace-emoji (concat ":" emoji ":") (hash lazy=true)}}
|
||||
{{/each}}
|
||||
@ -54,30 +50,19 @@
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<% JSON.parse(File.read("lib/emoji/groups.json")).each.with_index do |group, group_index| %>
|
||||
<div class='section' data-section='<%= group["name"] %>'>
|
||||
<div class='section-header'>
|
||||
<span class="title">{{i18n 'emoji_picker.<%= group["name"] %>'}}</span>
|
||||
</div>
|
||||
<div class='section-group'>
|
||||
<% group["icons"].each do |icon| %>
|
||||
{{replace-emoji ":<%= icon['name'] %>:" (hash lazy=true class="<%= "diversity" if icon["diversity"] %>")}}
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
{{emoji-group-sections}}
|
||||
|
||||
{{#each-in customEmojis as |group emojis|}}
|
||||
<div class='section' data-section='custom-{{group}}'>
|
||||
<div class='section-header'>
|
||||
<div class="section" data-section="custom-{{group}}">
|
||||
<div class="section-header">
|
||||
<span class="title">
|
||||
{{i18n (concat 'emoji_picker.' group)}}
|
||||
{{i18n (concat "emoji_picker." group)}}
|
||||
</span>
|
||||
</div>
|
||||
{{#if emojis.length}}
|
||||
<div class='section-group'>
|
||||
<div class="section-group">
|
||||
{{#each emojis as |emoji|}}
|
||||
<img title="{{emoji.code}}" width="20" height="20" loading="lazy" class="emoji" src="{{emoji.src}}">
|
||||
<img title={{emoji.code}} width="20" height="20" loading="lazy" class="emoji" src={{emoji.src}}>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
@ -109,6 +94,6 @@
|
||||
</div>
|
||||
|
||||
{{#if site.mobileView}}
|
||||
<div class="emoji-picker-modal-overlay" {{on "click" this.onClose}}></div>
|
||||
<div role="button" class="emoji-picker-modal-overlay" {{on "click" this.onClose}}></div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
@ -5,9 +5,9 @@
|
||||
{{d-icon "envelope" class="private-message-glyph"}}
|
||||
</span>
|
||||
</a>
|
||||
{{else}}
|
||||
{{~else}}
|
||||
<span class="private-message-glyph-wrapper">
|
||||
{{d-icon "envelope" class="private-message-glyph"}}
|
||||
</span>
|
||||
{{/if}}
|
||||
{{~/if}}
|
||||
{{/if}}
|
||||
|
||||
@ -26,9 +26,13 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{{#each panels as |tab|}}
|
||||
{{component tab selectedTab=selectedTab category=model registerValidator=(action "registerValidator")}}
|
||||
{{/each}}
|
||||
<div class="edit-category-content">
|
||||
<h3>{{selectedTabTitle}}</h3>
|
||||
|
||||
{{#each panels as |tab|}}
|
||||
{{component tab selectedTab=selectedTab category=model registerValidator=(action "registerValidator")}}
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
<div class="edit-category-footer">
|
||||
{{d-button id="save-category" class="btn-primary" disabled=disabled action=(action "saveCategory") label=saveLabel}}
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
{{#topic-title cancelled=(action "cancelEditingTopic") save=(action "finishedEditingTopic") model=model}}
|
||||
{{#if editingTopic}}
|
||||
<div class="edit-topic-title">
|
||||
{{private-message-glyph shouldShow=model.isPrivateMessage}}
|
||||
{{private-message-glyph shouldShow=model.isPrivateMessage tagName=""}}
|
||||
|
||||
{{text-field id="edit-title" value=buffered.title maxlength=siteSettings.max_topic_title_length autofocus="true"}}
|
||||
|
||||
@ -65,9 +65,10 @@
|
||||
href=pmPath
|
||||
title="topic_statuses.personal_message.title"
|
||||
ariaLabel="user.messages.inbox"
|
||||
tagName=""
|
||||
}}
|
||||
{{else}}
|
||||
{{private-message-glyph shouldShow=model.isPrivateMessage}}
|
||||
{{private-message-glyph shouldShow=model.isPrivateMessage tagName=""}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
|
||||
@ -299,7 +300,7 @@
|
||||
removeTopicTimer=(action "removeTopicTimer" model.topic_timer.status_type "topic_timer")}}
|
||||
|
||||
{{#if showSelectedPostsAtBottom}}
|
||||
<div class="selected-posts {{unless multiSelect "hidden"}}">
|
||||
<div class="selected-posts {{unless multiSelect "hidden"}} {{if showSelectedPostsAtBottom "hidden"}}">
|
||||
{{selected-posts
|
||||
selectedPostsCount=selectedPostsCount
|
||||
canSelectAll=canSelectAll
|
||||
|
||||
@ -3,7 +3,6 @@ import { isEmpty } from "@ember/utils";
|
||||
import { wantsNewWindow } from "discourse/lib/intercept-click";
|
||||
import RawHtml from "discourse/widgets/raw-html";
|
||||
import { createWidget } from "discourse/widgets/widget";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import { h } from "virtual-dom";
|
||||
import { emojiUnescape } from "discourse/lib/text";
|
||||
import {
|
||||
@ -11,10 +10,9 @@ import {
|
||||
escapeExpression,
|
||||
formatUsername,
|
||||
} from "discourse/lib/utilities";
|
||||
import { setTransientHeader } from "discourse/lib/ajax";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import DiscourseURL, { userPath } from "discourse/lib/url";
|
||||
import { iconNode } from "discourse-common/lib/icon-library";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { ajax, setTransientHeader } from "discourse/lib/ajax";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
|
||||
export const DefaultNotificationItem = createWidget(
|
||||
|
||||
@ -3,9 +3,8 @@ import I18n from "I18n";
|
||||
import { later } from "@ember/runloop";
|
||||
import { createWidget, applyDecorators } from "discourse/widgets/widget";
|
||||
import { h } from "virtual-dom";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import DiscourseURL, { userPath } from "discourse/lib/url";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import { wantsNewWindow } from "discourse/lib/intercept-click";
|
||||
import { NotificationLevels } from "discourse/lib/notification-levels";
|
||||
|
||||
|
||||
@ -141,7 +141,7 @@ export function buildManageButtons(attrs, currentUser, siteSettings) {
|
||||
|
||||
if (attrs.canManage) {
|
||||
contents.push({
|
||||
icon: "cog",
|
||||
icon: "sync-alt",
|
||||
label: "post.controls.rebake",
|
||||
action: "rebakePost",
|
||||
className: "popup-menu-button rebuild-html",
|
||||
|
||||
@ -4,10 +4,7 @@ import { ajax } from "discourse/lib/ajax";
|
||||
import { isValidLink } from "discourse/lib/click-track";
|
||||
import { number } from "discourse/lib/formatter";
|
||||
import highlightSearch from "discourse/lib/highlight-search";
|
||||
import {
|
||||
default as highlightHTML,
|
||||
unhighlightHTML,
|
||||
} from "discourse/lib/highlight-html";
|
||||
import highlightHTML, { unhighlightHTML } from "discourse/lib/highlight-html";
|
||||
import { spinnerHTML } from "discourse/helpers/loading-spinner";
|
||||
|
||||
let _beforeAdoptDecorators = [];
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { default as getURL, getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import getURL, { getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import I18n from "I18n";
|
||||
import PostCooked from "discourse/widgets/post-cooked";
|
||||
import DecoratorHelper from "discourse/widgets/decorator-helper";
|
||||
|
||||
@ -44,7 +44,7 @@ createWidget("quick-access-item", {
|
||||
}
|
||||
}
|
||||
|
||||
return h("a", { attributes: { href } }, [
|
||||
return h("a", { attributes: this._linkAttributes(href) }, [
|
||||
iconNode(icon),
|
||||
new RawHtml({
|
||||
html: `<div>${this._usernameHtml()}${content}</div>`,
|
||||
@ -60,6 +60,10 @@ createWidget("quick-access-item", {
|
||||
}
|
||||
},
|
||||
|
||||
_linkAttributes(href) {
|
||||
return { href };
|
||||
},
|
||||
|
||||
_contentHtml() {
|
||||
const content =
|
||||
this.attrs.escapedContent || escapeExpression(this.attrs.content);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { exists, acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
acceptance("About", function () {
|
||||
test("viewing", async function (assert) {
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
import {
|
||||
queryAll,
|
||||
exists,
|
||||
acceptance,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import { visit, click, fillIn, currentRouteName } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import PreloadStore from "discourse/lib/preload-store";
|
||||
|
||||
acceptance("Account Created", function () {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { queryAll, acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { fillIn, click, visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
const EMAIL = `
|
||||
From: "somebody" <somebody@example.com>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { exists, acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
acceptance("Admin - Search Log Term", function (needs) {
|
||||
needs.user();
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { exists, acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { click, visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
acceptance("Admin - Search Logs", function (needs) {
|
||||
needs.user();
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
import {
|
||||
fillIn,
|
||||
click,
|
||||
@ -8,7 +6,12 @@ import {
|
||||
currentURL,
|
||||
} from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { acceptance, count } from "discourse/tests/helpers/qunit-helpers";
|
||||
import {
|
||||
acceptance,
|
||||
count,
|
||||
queryAll,
|
||||
exists,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import siteSettingFixture from "discourse/tests/fixtures/site-settings";
|
||||
|
||||
acceptance("Admin - Site Settings", function (needs) {
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
import {
|
||||
queryAll,
|
||||
exists,
|
||||
acceptance,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import { fillIn, click, visit, currentURL } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
acceptance("Admin - Site Texts", function (needs) {
|
||||
needs.user();
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
import {
|
||||
queryAll,
|
||||
exists,
|
||||
acceptance,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import { visit, click, fillIn } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
acceptance("Admin - Suspend User", function (needs) {
|
||||
needs.user();
|
||||
@ -42,7 +44,7 @@ acceptance("Admin - Suspend User", function (needs) {
|
||||
|
||||
assert.equal(queryAll(".suspend-user-modal:visible").length, 1);
|
||||
|
||||
await fillIn(".suspend-reason", "for breaking the rules");
|
||||
await fillIn("input.suspend-reason", "for breaking the rules");
|
||||
await fillIn(".suspend-message", "this is an email reason why");
|
||||
|
||||
await click(".d-modal-cancel");
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { exists, acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
acceptance("Admin - Users Badges", function (needs) {
|
||||
needs.user();
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { queryAll, acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { click, visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import I18n from "I18n";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
function assertNoSecondary(assert) {
|
||||
assert.equal(
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { queryAll, acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { click, fillIn, visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
acceptance("Admin - User Index", function (needs) {
|
||||
needs.user();
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
import {
|
||||
queryAll,
|
||||
exists,
|
||||
acceptance,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import { click, visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import I18n from "I18n";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
acceptance("Admin - Users List", function (needs) {
|
||||
needs.user();
|
||||
@ -12,7 +14,7 @@ acceptance("Admin - Users List", function (needs) {
|
||||
await visit("/admin/users/list/active");
|
||||
|
||||
assert.ok(exists(".users-list .user"));
|
||||
assert.ok(!exists(".user:eq(0) .email small"), "escapes email");
|
||||
assert.ok(!exists(".user:nth-of-type(1) .email small"), "escapes email");
|
||||
});
|
||||
|
||||
test("sorts users", async function (assert) {
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
import {
|
||||
queryAll,
|
||||
exists,
|
||||
acceptance,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import { fillIn, click, visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
acceptance("Admin - Watched Words", function (needs) {
|
||||
needs.user();
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { exists, acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { visit, currentRouteName } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
acceptance("Auth Complete", function (needs) {
|
||||
needs.hooks.beforeEach(() => {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user