Merge branch 'main' into ux/automatically-mobile-buttons-admin-header
This commit is contained in:
commit
ef89dbadb2
|
@ -135,7 +135,7 @@ GEM
|
|||
dry-initializer (3.1.1)
|
||||
email_reply_trimmer (0.1.13)
|
||||
erubi (1.13.0)
|
||||
excon (0.111.0)
|
||||
excon (0.112.0)
|
||||
execjs (2.9.1)
|
||||
exifr (1.4.0)
|
||||
extralite-bundle (2.8.2)
|
||||
|
@ -480,7 +480,7 @@ GEM
|
|||
rack (>= 1.1)
|
||||
rubocop (>= 1.52.0, < 2.0)
|
||||
rubocop-ast (>= 1.31.1, < 2.0)
|
||||
rubocop-rspec (3.0.5)
|
||||
rubocop-rspec (3.1.0)
|
||||
rubocop (~> 1.61)
|
||||
rubocop-rspec_rails (2.30.0)
|
||||
rubocop (~> 1.61)
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { hash } from "@ember/helper";
|
||||
import { LinkTo } from "@ember/routing";
|
||||
import concatClass from "discourse/helpers/concat-class";
|
||||
import dIcon from "discourse-common/helpers/d-icon";
|
||||
import i18n from "discourse-common/helpers/i18n";
|
||||
import {
|
||||
DangerButton,
|
||||
DefaultButton,
|
||||
PrimaryButton,
|
||||
} from "admin/components/admin-page-action-button";
|
||||
|
||||
export default class AdminSectionLandingItem extends Component {
|
||||
get title() {
|
||||
if (this.args.titleLabelTranslated) {
|
||||
return this.args.titleLabelTranslated;
|
||||
} else if (this.args.titleLabel) {
|
||||
return i18n(this.args.titleLabel);
|
||||
}
|
||||
}
|
||||
|
||||
get description() {
|
||||
if (this.args.descriptionLabelTranslated) {
|
||||
return this.args.descriptionLabelTranslated;
|
||||
} else if (this.args.descriptionLabel) {
|
||||
return i18n(this.args.descriptionLabel);
|
||||
}
|
||||
}
|
||||
|
||||
get tagline() {
|
||||
if (this.args.taglineLabelTranslated) {
|
||||
return this.args.taglineLabelTranslated;
|
||||
} else if (this.args.taglineLabel) {
|
||||
return i18n(this.args.taglineLabel);
|
||||
}
|
||||
}
|
||||
|
||||
<template>
|
||||
<div
|
||||
class={{concatClass "admin-section-landing-item" (if @icon "-has-icon")}}
|
||||
...attributes
|
||||
>
|
||||
{{#if @imageUrl}}
|
||||
<img class="admin-section-landing-item__image" src={{@imageUrl}} />
|
||||
{{/if}}
|
||||
{{#if @icon}}
|
||||
<div class="admin-section-landing-item__icon">
|
||||
{{dIcon @icon}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="admin-section-landing-item__content">
|
||||
{{#if this.tagline}}
|
||||
<h4 class="admin-section-landing-item__tagline">{{this.tagline}}</h4>
|
||||
{{/if}}
|
||||
|
||||
{{#if @titleRoute}}
|
||||
<LinkTo @route={{@titleRoute}}><h3
|
||||
class="admin-section-landing-item__title"
|
||||
>{{this.title}}</h3></LinkTo>
|
||||
{{else}}
|
||||
<h3 class="admin-section-landing-item__title">{{this.title}}</h3>
|
||||
{{/if}}
|
||||
|
||||
<p
|
||||
class="admin-section-landing-item__description"
|
||||
>{{this.description}}</p>
|
||||
</div>
|
||||
|
||||
<div class="admin-section-landing-item__buttons">
|
||||
{{yield
|
||||
(hash Primary=PrimaryButton Default=DefaultButton Danger=DangerButton)
|
||||
to="buttons"
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
const AdminSectionLandingWrapper = <template>
|
||||
<div class="admin-section-landing-wrapper" ...attributes>
|
||||
{{yield}}
|
||||
</div>
|
||||
</template>;
|
||||
|
||||
export default AdminSectionLandingWrapper;
|
|
@ -236,5 +236,13 @@ export default function () {
|
|||
path: "/whats-new",
|
||||
resetNamespace: true,
|
||||
});
|
||||
|
||||
this.route(
|
||||
"adminSection",
|
||||
{ path: "/section", resetNamespace: true },
|
||||
function () {
|
||||
this.route("account");
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<AdminPageHeader
|
||||
@titleLabel="admin.section_landing_pages.account.title"
|
||||
@hideTabs={{true}}
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/section/account"
|
||||
@label={{i18n "admin.section_landing_pages.account.title"}}
|
||||
/>
|
||||
</:breadcrumbs>
|
||||
</AdminPageHeader>
|
||||
|
||||
<AdminSectionLandingWrapper>
|
||||
<AdminSectionLandingItem
|
||||
@icon="box-archive"
|
||||
@titleLabel="admin.section_landing_pages.account.backups.title"
|
||||
@descriptionLabel="admin.section_landing_pages.account.backups.description"
|
||||
@titleRoute="admin.backups"
|
||||
/>
|
||||
<AdminSectionLandingItem
|
||||
@icon="gift"
|
||||
@titleLabel="admin.section_landing_pages.account.whats_new.title"
|
||||
@descriptionLabel="admin.section_landing_pages.account.whats_new.description"
|
||||
@titleRoute="admin.whatsNew"
|
||||
/>
|
||||
</AdminSectionLandingWrapper>
|
|
@ -29,7 +29,7 @@
|
|||
"@types/qunit": "^2.19.10",
|
||||
"@types/rsvp": "^4.0.9",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"ember-cli": "~5.11.0",
|
||||
"ember-cli": "~5.12.0",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
"@types/qunit": "^2.19.10",
|
||||
"@types/rsvp": "^4.0.9",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"ember-cli": "~5.11.0",
|
||||
"ember-cli": "~5.12.0",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
"ember-this-fallback": "^0.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ember-cli": "~5.11.0",
|
||||
"ember-cli": "~5.12.0",
|
||||
"webpack": "^5.95.0"
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
"@glimmer/component": "^1.1.2",
|
||||
"@glimmer/syntax": "^0.92.3",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"ember-cli": "~5.11.0",
|
||||
"ember-cli": "~5.12.0",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
|
|
|
@ -49,7 +49,7 @@ export default class ReviewableItem extends Component {
|
|||
@service siteSettings;
|
||||
@service currentUser;
|
||||
@service composer;
|
||||
@optionalService("admin-tools") adminTools;
|
||||
@optionalService adminTools;
|
||||
|
||||
updating = null;
|
||||
editing = false;
|
||||
|
|
|
@ -2,7 +2,6 @@ import Component from "@glimmer/component";
|
|||
import { tracked } from "@glimmer/tracking";
|
||||
import { action } from "@ember/object";
|
||||
import { service } from "@ember/service";
|
||||
import optionalService from "discourse/lib/optional-service";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
|
||||
export default class TopicTimeline extends Component {
|
||||
|
@ -13,8 +12,6 @@ export default class TopicTimeline extends Component {
|
|||
@tracked docked = false;
|
||||
@tracked dockedBottom = false;
|
||||
|
||||
adminTools = optionalService();
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ export default class UserController extends Controller.extend(CanCheckEmails) {
|
|||
@service currentUser;
|
||||
@service router;
|
||||
@service dialog;
|
||||
@optionalService("admin-tools") adminTools;
|
||||
@optionalService adminTools;
|
||||
|
||||
@controller("user-notifications") userNotifications;
|
||||
|
||||
|
|
|
@ -2,8 +2,16 @@ import { computed } from "@ember/object";
|
|||
import { getOwner } from "@ember/owner";
|
||||
import { dasherize } from "@ember/string";
|
||||
|
||||
export default function (name) {
|
||||
return computed(function (defaultName) {
|
||||
export default function (target, name, descriptor) {
|
||||
name ??= target;
|
||||
|
||||
const decorator = computed(function (defaultName) {
|
||||
return getOwner(this).lookup(`service:${name || dasherize(defaultName)}`);
|
||||
});
|
||||
|
||||
if (descriptor) {
|
||||
return decorator(target, name, descriptor);
|
||||
} else {
|
||||
return decorator;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,11 +47,11 @@
|
|||
"@ember/string": "^4.0.0",
|
||||
"@ember/test-helpers": "^4.0.4",
|
||||
"@ember/test-waiters": "^3.1.0",
|
||||
"@embroider/compat": "^3.6.1",
|
||||
"@embroider/core": "^3.4.16",
|
||||
"@embroider/macros": "^1.13.1",
|
||||
"@embroider/compat": "^3.6.2",
|
||||
"@embroider/core": "^3.4.17",
|
||||
"@embroider/macros": "^1.16.7",
|
||||
"@embroider/router": "^2.1.8",
|
||||
"@embroider/webpack": "^4.0.5",
|
||||
"@embroider/webpack": "^4.0.6",
|
||||
"@floating-ui/dom": "^1.6.11",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
"@glimmer/tracking": "^1.1.2",
|
||||
|
@ -84,7 +84,7 @@
|
|||
"ember-auto-import": "^2.8.1",
|
||||
"ember-buffered-proxy": "^2.1.1",
|
||||
"ember-cached-decorator-polyfill": "^1.0.2",
|
||||
"ember-cli": "~5.11.0",
|
||||
"ember-cli": "~5.12.0",
|
||||
"ember-cli-app-version": "^7.0.0",
|
||||
"ember-cli-babel": "^8.2.0",
|
||||
"ember-cli-deprecation-workflow": "^3.0.2",
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
import Component from "@ember/component";
|
||||
import Service from "@ember/service";
|
||||
import { render } from "@ember/test-helpers";
|
||||
import { hbs } from "ember-cli-htmlbars";
|
||||
import { module, test } from "qunit";
|
||||
import optionalService from "discourse/lib/optional-service";
|
||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||
|
||||
class FooService extends Service {
|
||||
name = "foo";
|
||||
}
|
||||
|
||||
class BarService extends Service {
|
||||
name = "bar";
|
||||
}
|
||||
|
||||
const EmberObjectComponent = Component.extend({
|
||||
name: "",
|
||||
layout: hbs`<span class="ember-object-component">{{this.foo.name}} {{this.baz.name}}</span>`,
|
||||
|
||||
foo: optionalService(),
|
||||
baz: optionalService("bar"),
|
||||
});
|
||||
|
||||
class NativeComponent extends Component {
|
||||
@optionalService foo;
|
||||
@optionalService("bar") baz;
|
||||
|
||||
name = "";
|
||||
layout = hbs`<span class="native-component">{{this.foo.name}} {{this.baz.name}}</span>`;
|
||||
}
|
||||
|
||||
module("Unit | Utils | optional-service", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
this.registry.register("service:foo", FooService);
|
||||
this.registry.register("service:bar", BarService);
|
||||
});
|
||||
|
||||
test("optionalService works in EmberObject classes", async function (assert) {
|
||||
this.registry.register(
|
||||
"component:ember-object-component",
|
||||
EmberObjectComponent
|
||||
);
|
||||
|
||||
await render(hbs`<EmberObjectComponent />`);
|
||||
|
||||
assert.dom(".ember-object-component").hasText("foo bar");
|
||||
});
|
||||
|
||||
test("optionalService works in native classes", async function (assert) {
|
||||
this.registry.register("component:native-component", NativeComponent);
|
||||
|
||||
await render(hbs`<NativeComponent />`);
|
||||
|
||||
assert.dom(".native-component").hasText("foo bar");
|
||||
});
|
||||
});
|
|
@ -29,7 +29,7 @@
|
|||
"@types/qunit": "^2.19.10",
|
||||
"@types/rsvp": "^4.0.9",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"ember-cli": "~5.11.0",
|
||||
"ember-cli": "~5.12.0",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
"@types/qunit": "^2.19.10",
|
||||
"@types/rsvp": "^4.0.9",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"ember-cli": "~5.11.0",
|
||||
"ember-cli": "~5.12.0",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
"@types/qunit": "^2.19.10",
|
||||
"@types/rsvp": "^4.0.9",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"ember-cli": "~5.11.0",
|
||||
"ember-cli": "~5.12.0",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
|
|
|
@ -1094,6 +1094,7 @@ a.inline-editable-field {
|
|||
@import "common/admin/admin_report_stacked_line_chart";
|
||||
@import "common/admin/admin_report_table";
|
||||
@import "common/admin/admin_report_inline_table";
|
||||
@import "common/admin/admin_section_landing_page";
|
||||
@import "common/admin/admin_page_header";
|
||||
@import "common/admin/admin_intro";
|
||||
@import "common/admin/admin_emojis";
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
.admin-section-landing-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(16em, 1fr));
|
||||
gap: 1em 2em;
|
||||
margin-top: 1em;
|
||||
padding-top: 1em;
|
||||
|
||||
.admin-section-landing-item {
|
||||
display: grid;
|
||||
grid-template-rows: subgrid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-row: span 2;
|
||||
gap: 0;
|
||||
margin-bottom: 2em;
|
||||
|
||||
@include breakpoint("mobile-extra-large", min-width) {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
&.-has-icon {
|
||||
grid-template-columns: 1fr 8fr;
|
||||
|
||||
.admin-section-landing-item__buttons {
|
||||
grid-column: 2;
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
&__tagline {
|
||||
font-size: var(--font-down-1);
|
||||
font-weight: normal;
|
||||
color: var(--primary-high);
|
||||
margin: 0;
|
||||
letter-spacing: 0.1px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin: 0;
|
||||
line-height: var(--line-height-medium);
|
||||
}
|
||||
|
||||
&__description {
|
||||
color: var(--primary-high);
|
||||
margin: 0.25em 0 0.5em;
|
||||
line-height: var(--line-height-large);
|
||||
align-self: start;
|
||||
|
||||
@include breakpoint("mobile-extra-large", min-width) {
|
||||
max-width: 17em;
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
font-size: var(--font-up-3);
|
||||
color: var(--primary-low-mid);
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
&__buttons {
|
||||
grid-row: 2;
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
button {
|
||||
justify-self: start;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Admin::SectionController < Admin::AdminController
|
||||
def show
|
||||
end
|
||||
end
|
|
@ -5563,6 +5563,16 @@ en:
|
|||
spam: "Spam settings"
|
||||
staff_action_logs: "Staff Action Logs"
|
||||
|
||||
section_landing_pages:
|
||||
account:
|
||||
title: "Account"
|
||||
backups:
|
||||
title: "Backups"
|
||||
description: "Take a backup of your site's data"
|
||||
whats_new:
|
||||
title: "What's New"
|
||||
description: "Discover new releases and improvements to Discourse"
|
||||
|
||||
config_areas:
|
||||
about:
|
||||
header: "About your site"
|
||||
|
|
|
@ -403,6 +403,7 @@ Discourse::Application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
get "section/:section_id" => "section#show", :constraints => AdminConstraint.new
|
||||
resources :admin_notices, only: %i[destroy], constraints: AdminConstraint.new
|
||||
end # admin namespace
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ module CategoryGuardian
|
|||
|
||||
def can_see_category?(category)
|
||||
return false unless category
|
||||
return true if is_admin?
|
||||
return true if is_admin? && !SiteSetting.suppress_secured_categories_from_admin
|
||||
return true if !category.read_restricted
|
||||
return true if is_staged? && category.email_in.present? && category.email_in_allow_strangers
|
||||
secure_category_ids.include?(category.id)
|
||||
|
|
|
@ -224,7 +224,7 @@ module TopicGuardian
|
|||
def can_see_topic_ids(topic_ids: [], hide_deleted: true)
|
||||
topic_ids = topic_ids.compact
|
||||
|
||||
return topic_ids if is_admin?
|
||||
return topic_ids if is_admin? && !SiteSetting.suppress_secured_categories_from_admin
|
||||
return [] if topic_ids.blank?
|
||||
|
||||
default_scope = Topic.unscoped.where(id: topic_ids)
|
||||
|
@ -268,7 +268,7 @@ module TopicGuardian
|
|||
|
||||
def can_see_topic?(topic, hide_deleted = true)
|
||||
return false unless topic
|
||||
return true if is_admin?
|
||||
return true if is_admin? && !SiteSetting.suppress_secured_categories_from_admin
|
||||
return false if hide_deleted && topic.deleted_at && !can_see_deleted_topics?(topic.category)
|
||||
|
||||
if topic.private_message?
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
"jsdoc": "^4.0.0",
|
||||
"lefthook": "^1.7.18",
|
||||
"licensee": "^11.1.0",
|
||||
"lint-to-the-future": "^2.0.0",
|
||||
"lint-to-the-future": "^2.1.0",
|
||||
"lint-to-the-future-ember-template": "^1.1.1",
|
||||
"lint-to-the-future-eslint": "^2.0.1",
|
||||
"lint-to-the-future-eslint": "^2.1.2",
|
||||
"magnific-popup": "1.1.0",
|
||||
"moment": "2.30.1",
|
||||
"moment-timezone": "0.5.45",
|
||||
|
|
|
@ -14,7 +14,6 @@ import { modifier } from "ember-modifier";
|
|||
import { eq, not } from "truth-helpers";
|
||||
import DButton from "discourse/components/d-button";
|
||||
import concatClass from "discourse/helpers/concat-class";
|
||||
import optionalService from "discourse/lib/optional-service";
|
||||
import { applyValueTransformer } from "discourse/lib/transformer";
|
||||
import { updateUserStatusOnMention } from "discourse/lib/update-user-status-on-mention";
|
||||
import isZoomed from "discourse/lib/zoom-check";
|
||||
|
@ -65,7 +64,6 @@ export default class ChatMessage extends Component {
|
|||
@service router;
|
||||
@service toasts;
|
||||
@service modal;
|
||||
@optionalService adminTools;
|
||||
|
||||
@tracked isActive = false;
|
||||
|
||||
|
|
906
pnpm-lock.yaml
906
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -291,6 +291,8 @@ RSpec.describe TopicGuardian do
|
|||
list = guardian.filter_allowed_categories(list)
|
||||
|
||||
expect(list.count).to eq(0)
|
||||
|
||||
expect(guardian.can_see?(private_topic)).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue