DEV: Introduce <DPageHeader /> and <DPageSubheader /> components (#30146)
This converts the `<AdminPageHeader />` component and the `<AdminPageSubheader />` components into new components that can be used outside of admin, and updates the CSS classes. Also introduces a `<DPageActionButton />` component and child components for the header action buttons. I have to keep the old admin-only components around for now until plugins are updated, then we can remove it, and remove the re-exports that are done within admin-page-action-button.gjs
This commit is contained in:
parent
ef754cdd9a
commit
a879bcdc35
|
@ -1,8 +1,8 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { action } from "@ember/object";
|
||||
import { service } from "@ember/service";
|
||||
import DPageSubheader from "discourse/components/d-page-subheader";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import AdminPageSubheader from "admin/components/admin-page-subheader";
|
||||
import InstallThemeModal from "admin/components/modal/install-theme";
|
||||
import ThemesGrid from "admin/components/themes-grid";
|
||||
|
||||
|
@ -47,9 +47,9 @@ export default class AdminConfigAreasLookAndFeelThemes extends Component {
|
|||
}
|
||||
|
||||
<template>
|
||||
<AdminPageSubheader
|
||||
@titleLabel="admin.config_areas.look_and_feel.themes.title"
|
||||
@descriptionLabel="admin.customize.theme.themes_intro_new"
|
||||
<DPageSubheader
|
||||
@titleLabel={{i18n "admin.config_areas.look_and_feel.themes.title"}}
|
||||
@descriptionLabel={{i18n "admin.customize.theme.themes_intro_new"}}
|
||||
@learnMoreUrl="https://meta.discourse.org/t/93648"
|
||||
>
|
||||
<:actions as |actions|>
|
||||
|
@ -60,7 +60,7 @@ export default class AdminConfigAreasLookAndFeelThemes extends Component {
|
|||
class="admin-look-and-feel__install-theme"
|
||||
/>
|
||||
</:actions>
|
||||
</AdminPageSubheader>
|
||||
</DPageSubheader>
|
||||
|
||||
<div class="admin-detail">
|
||||
<ThemesGrid @themes={{@themes}} />
|
||||
|
|
|
@ -1,138 +1,25 @@
|
|||
import { hash } from "@ember/helper";
|
||||
import DButton from "discourse/components/d-button";
|
||||
// TODO (martin) Delete this once we have removed references from plugins.
|
||||
|
||||
export const AdminPageActionButton = <template>
|
||||
<DButton
|
||||
class="admin-page-action-button btn-small"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
||||
import {
|
||||
DangerActionListItem,
|
||||
DangerButton,
|
||||
DefaultActionListItem,
|
||||
DefaultButton,
|
||||
DPageActionButton,
|
||||
DPageActionListItem,
|
||||
PrimaryActionListItem,
|
||||
PrimaryButton,
|
||||
WrappedActionListItem,
|
||||
WrappedButton,
|
||||
} from "discourse/components/d-page-action-button";
|
||||
|
||||
// This is used for cases where there is another component,
|
||||
// e.g. UppyBackupUploader, that is a button which cannot use
|
||||
// PrimaryButton and so on directly. This should be used very rarely,
|
||||
// most cases are covered by the other button types.
|
||||
export const WrappedButton = <template>
|
||||
<span class="admin-page-action-wrapped-button">{{yield}}</span>
|
||||
</template>;
|
||||
|
||||
// No buttons here pass in an @icon by design. They are okay to
|
||||
// use on dropdown list items, but our UI guidelines do not allow them
|
||||
// on regular buttons.
|
||||
export const PrimaryButton = <template>
|
||||
<AdminPageActionButton
|
||||
class="btn-primary"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
||||
|
||||
export const DangerButton = <template>
|
||||
<AdminPageActionButton
|
||||
class="btn-danger"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
||||
|
||||
export const DefaultButton = <template>
|
||||
<AdminPageActionButton
|
||||
class="btn-default"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
||||
|
||||
export const AdminPageActionListItem = <template>
|
||||
<li class="dropdown-menu__item admin-page-action-list-item">
|
||||
<AdminPageActionButton
|
||||
class="btn-transparent"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</li>
|
||||
</template>;
|
||||
|
||||
// This is used for cases where there is another component,
|
||||
// e.g. UppyBackupUploader, that is a button which cannot use
|
||||
// PrimaryActionListItem and so on directly. This should be used very rarely,
|
||||
// most cases are covered by the other list types.
|
||||
export const WrappedActionListItem = <template>
|
||||
<li
|
||||
class="dropdown-menu__item admin-page-action-list-item admin-page-action-wrapped-list-item"
|
||||
>
|
||||
{{yield (hash buttonClass="btn-transparent")}}
|
||||
</li>
|
||||
</template>;
|
||||
|
||||
// It is not a mistake that `btn-default` is used here, in a list
|
||||
// there is no need for blue text.
|
||||
export const PrimaryActionListItem = <template>
|
||||
<AdminPageActionListItem
|
||||
class="btn-default"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
||||
|
||||
export const DefaultActionListItem = <template>
|
||||
<AdminPageActionListItem
|
||||
class="btn-default"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
||||
|
||||
export const DangerActionListItem = <template>
|
||||
<AdminPageActionListItem
|
||||
class="btn-danger"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
||||
export { DangerActionListItem as DangerActionListItem };
|
||||
export { DangerButton as DangerButton };
|
||||
export { DefaultActionListItem as DefaultActionListItem };
|
||||
export { DefaultButton as DefaultButton };
|
||||
export { DPageActionButton as DPageActionButton };
|
||||
export { DPageActionListItem as DPageActionListItem };
|
||||
export { PrimaryActionListItem as PrimaryActionListItem };
|
||||
export { PrimaryButton as PrimaryButton };
|
||||
export { WrappedActionListItem as WrappedActionListItem };
|
||||
export { WrappedButton as WrappedButton };
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { service } from "@ember/service";
|
||||
import DBreadcrumbsItem from "discourse/components/d-breadcrumbs-item";
|
||||
import DPageHeader from "discourse/components/d-page-header";
|
||||
import NavItem from "discourse/components/nav-item";
|
||||
import { headerActionComponentForPlugin } from "discourse/lib/admin-plugin-header-actions";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import AdminPageHeader from "./admin-page-header";
|
||||
import AdminPluginConfigArea from "./admin-plugin-config-area";
|
||||
|
||||
export default class AdminPluginConfigPage extends Component {
|
||||
|
@ -41,14 +41,14 @@ export default class AdminPluginConfigPage extends Component {
|
|||
|
||||
<template>
|
||||
<div class="admin-plugin-config-page">
|
||||
<AdminPageHeader
|
||||
@titleLabelTranslated={{@plugin.nameTitleized}}
|
||||
@descriptionLabelTranslated={{@plugin.about}}
|
||||
<DPageHeader
|
||||
@titleLabel={{@plugin.nameTitleized}}
|
||||
@descriptionLabel={{@plugin.about}}
|
||||
@learnMoreUrl={{@plugin.linkUrl}}
|
||||
@headerActionComponent={{this.headerActionComponent}}
|
||||
>
|
||||
<:breadcrumbs>
|
||||
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/plugins"
|
||||
@label={{i18n "admin.plugins.title"}}
|
||||
|
@ -75,7 +75,7 @@ export default class AdminPluginConfigPage extends Component {
|
|||
{{/each}}
|
||||
{{/if}}
|
||||
</:tabs>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
|
||||
<div class="admin-plugin-config-page__content">
|
||||
<div class={{this.mainAreaClasses}}>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
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-i18n";
|
||||
import {
|
||||
DangerButton,
|
||||
DefaultButton,
|
||||
PrimaryButton,
|
||||
} from "admin/components/admin-page-action-button";
|
||||
} from "discourse/components/d-page-action-button";
|
||||
import concatClass from "discourse/helpers/concat-class";
|
||||
import dIcon from "discourse-common/helpers/d-icon";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
export default class AdminSectionLandingItem extends Component {
|
||||
get title() {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<div class="badges">
|
||||
<AdminPageHeader
|
||||
@titleLabel="admin.badges.title"
|
||||
@descriptionLabel="admin.badges.page_description"
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.badges.title"}}
|
||||
@descriptionLabel={{i18n "admin.badges.page_description"}}
|
||||
@learnMoreUrl="https://meta.discourse.org/t/understanding-and-using-badges/32540"
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/badges"
|
||||
@label={{i18n "admin.badges.title"}}
|
||||
|
@ -35,7 +36,7 @@
|
|||
class="edit-groupings-btn"
|
||||
/>
|
||||
</:actions>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
|
||||
<div class="admin-container">
|
||||
<div class="content-list">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<AdminPageSubheader @titleLabel="admin.backups.files_title">
|
||||
<DPageSubheader @titleLabel={{i18n "admin.backups.files_title"}}>
|
||||
<:actions as |actions|>
|
||||
<actions.Wrapped as |wrapped|>
|
||||
{{#if this.localBackupStorage}}
|
||||
|
@ -15,7 +15,7 @@
|
|||
{{/if}}
|
||||
</actions.Wrapped>
|
||||
</:actions>
|
||||
</AdminPageSubheader>
|
||||
</DPageSubheader>
|
||||
|
||||
{{#if this.status.restoreDisabled}}
|
||||
<div class="backup-message alert alert-info">
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<div class="admin-backups admin-config-page">
|
||||
|
||||
<AdminPageHeader
|
||||
@titleLabel="admin.backups.title"
|
||||
@descriptionLabel="admin.backups.description"
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.backups.title"}}
|
||||
@descriptionLabel={{i18n "admin.backups.description"}}
|
||||
@learnMoreUrl="https://meta.discourse.org/t/create-download-and-restore-a-backup-of-your-discourse-database/122710"
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/backups"
|
||||
@label={{i18n "admin.backups.title"}}
|
||||
|
@ -32,7 +32,7 @@
|
|||
/>
|
||||
<PluginOutlet @name="downloader" @connectorTagName="div" />
|
||||
</:tabs>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
|
||||
<PluginOutlet @name="before-backup-list" @connectorTagName="div" />
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<AdminPageHeader
|
||||
@titleLabel="admin.config_areas.about.header"
|
||||
@descriptionLabelTranslated={{i18n
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.config_areas.about.header"}}
|
||||
@descriptionLabel={{i18n
|
||||
"admin.config_areas.about.description"
|
||||
(hash basePath=(base-path))
|
||||
}}
|
||||
|
@ -8,12 +8,13 @@
|
|||
@learnMoreUrl="https://meta.discourse.org/t/understanding-and-customizing-the-about-page/332161"
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/config/about"
|
||||
@label={{i18n "admin.config_areas.about.header"}}
|
||||
/>
|
||||
</:breadcrumbs>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
|
||||
<div class="admin-container admin-config-page__main-area">
|
||||
<AdminConfigAreas::About @data={{this.model.site_settings}} />
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<AdminPageHeader
|
||||
@titleLabel="admin.config_areas.flags.header"
|
||||
@descriptionLabel="admin.config_areas.flags.subheader"
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.config_areas.flags.header"}}
|
||||
@descriptionLabel={{i18n "admin.config_areas.flags.subheader"}}
|
||||
@learnMoreUrl="https://meta.discourse.org/t/moderation-flags/325589"
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/config/flags"
|
||||
@label={{i18n "admin.config_areas.flags.header"}}
|
||||
|
@ -30,7 +31,7 @@
|
|||
class="admin-flags-tabs__flags"
|
||||
/>
|
||||
</:tabs>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
|
||||
<div class="admin-container admin-config-page__main-area">
|
||||
{{outlet}}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<AdminPageHeader
|
||||
@titleLabel="admin.config_areas.look_and_feel.title"
|
||||
@descriptionLabel="admin.config_areas.look_and_feel.description"
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.config_areas.look_and_feel.title"}}
|
||||
@descriptionLabel={{i18n "admin.config_areas.look_and_feel.description"}}
|
||||
@learnMoreUrl="https://meta.discourse.org/t/beginners-guide-to-using-discourse-themes/91966"
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/config/look-and-feel"
|
||||
@label={{i18n "admin.config_areas.look_and_feel.title"}}
|
||||
|
@ -16,7 +17,7 @@
|
|||
@label="admin.config_areas.look_and_feel.themes.title"
|
||||
/>
|
||||
</:tabs>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
|
||||
<div class="admin-container admin-config-page__main-area">
|
||||
{{outlet}}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
<PluginOutlet @name="admin-dashboard-top" @connectorTagName="div" />
|
||||
</span>
|
||||
|
||||
<AdminPageHeader @hideTabs={{true}}>
|
||||
<DPageHeader @hideTabs={{true}}>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin.dashboard.title"}} />
|
||||
</:breadcrumbs>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
|
||||
{{#if this.showVersionChecks}}
|
||||
<div class="section-top">
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<div class="admin-emojis admin-config-page">
|
||||
<AdminPageHeader
|
||||
@titleLabel="admin.emoji.title"
|
||||
@descriptionLabel="admin.emoji.description"
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.emoji.title"}}
|
||||
@descriptionLabel={{i18n "admin.emoji.description"}}
|
||||
@hideTabs={{this.hideTabs}}
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/customize/emojis"
|
||||
@label={{i18n "admin.emoji.title"}}
|
||||
|
@ -25,7 +26,7 @@
|
|||
class="admin-emojis-tabs__emoji"
|
||||
/>
|
||||
</:tabs>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
|
||||
<div class="admin-container admin-config-page__main-area">
|
||||
{{outlet}}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<div class="admin-permalinks admin-config-page">
|
||||
<AdminPageHeader
|
||||
@titleLabel="admin.permalink.title"
|
||||
@descriptionLabel="admin.permalink.description"
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.permalink.title"}}
|
||||
@descriptionLabel={{i18n "admin.permalink.description"}}
|
||||
@learnMoreUrl="https://meta.discourse.org/t/redirect-old-forum-urls-to-new-discourse-urls/20930"
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/customize/permalinks"
|
||||
@label={{i18n "admin.permalink.title"}}
|
||||
|
@ -19,7 +20,7 @@
|
|||
class="admin-permalinks__header-add-permalink"
|
||||
/>
|
||||
</:actions>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
<div class="admin-container admin-config-page__main-area">
|
||||
<ConditionalLoadingSpinner @condition={{this.loading}}>
|
||||
<div class="permalink-search">
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
<div class="admin-plugins-list-container">
|
||||
|
||||
<AdminPageHeader
|
||||
@titleLabel="admin.plugins.installed"
|
||||
@descriptionLabel="admin.plugins.description"
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.plugins.installed"}}
|
||||
@descriptionLabel={{i18n "admin.plugins.description"}}
|
||||
@learnMoreUrl="https://www.discourse.org/plugins"
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/plugins"
|
||||
@label={{i18n "admin.plugins.title"}}
|
||||
|
@ -32,7 +33,7 @@
|
|||
{{/if}}
|
||||
{{/each}}
|
||||
</:tabs>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
|
||||
<div class="alert alert-info -top-margin admin-plugins-howto">
|
||||
{{dIcon "circle-info"}}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{{#if this.showTopNav}}
|
||||
<div class="admin-page-header">
|
||||
<div class="d-page-header">
|
||||
<DBreadcrumbsContainer />
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/plugins"
|
||||
@label={{i18n "admin.plugins.title"}}
|
||||
/>
|
||||
<div class="admin-nav-submenu">
|
||||
<div class="d-nav-submenu">
|
||||
<HorizontalOverflowNav class="main-nav nav plugin-nav">
|
||||
<NavItem @route="adminPlugins.index" @label="admin.plugins.title" />
|
||||
{{#each this.adminRoutes as |route|}}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
<AdminPageHeader
|
||||
@titleLabel="admin.section_landing_pages.account.title"
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.section_landing_pages.account.title"}}
|
||||
@hideTabs={{true}}
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/section/account"
|
||||
@label={{i18n "admin.section_landing_pages.account.title"}}
|
||||
/>
|
||||
</:breadcrumbs>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
|
||||
<AdminSectionLandingWrapper>
|
||||
<AdminSectionLandingItem
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
<div class="admin-user_fields admin-config-page">
|
||||
<AdminPageHeader
|
||||
@titleLabel="admin.user_fields.title"
|
||||
@descriptionLabel="admin.user_fields.help"
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.user_fields.title"}}
|
||||
@descriptionLabel={{i18n "admin.user_fields.help"}}
|
||||
@hideTabs={{true}}
|
||||
@learnMoreUrl="https://meta.discourse.org/t/creating-and-configuring-custom-user-fields/113192"
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/customize/user_fields"
|
||||
@label={{i18n "admin.user_fields.title"}}
|
||||
|
@ -17,7 +18,7 @@
|
|||
@label="admin.user_fields.add"
|
||||
/>
|
||||
</:actions>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
|
||||
<div class="admin-config-page__main-area">
|
||||
<div class="user-fields">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<AdminPageSubheader @titleLabelTranslated={{this.title}}>
|
||||
<DPageSubheader @titleLabel={{this.title}}>
|
||||
<:actions as |actions|>
|
||||
{{#if this.canCheckEmails}}
|
||||
{{#if this.showEmails}}
|
||||
|
@ -16,7 +16,7 @@
|
|||
{{/if}}
|
||||
{{/if}}
|
||||
</:actions>
|
||||
</AdminPageSubheader>
|
||||
</DPageSubheader>
|
||||
|
||||
<PluginOutlet @name="admin-users-list-show-before" />
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<div class="admin-users admin-config-page">
|
||||
<AdminPageHeader
|
||||
@titleLabel="admin.users.title"
|
||||
@descriptionLabel="admin.users.description"
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.users.title"}}
|
||||
@descriptionLabel={{i18n "admin.users.description"}}
|
||||
@learnMoreUrl="https://meta.discourse.org/t/accessing-a-user-s-admin-page/311859"
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/users/list"
|
||||
@label={{i18n "admin.users.title"}}
|
||||
|
@ -72,7 +73,7 @@
|
|||
class="admin-users-tabs__groups"
|
||||
/>
|
||||
</:tabs>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
<div class="admin-container admin-config-page__main-area">
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<AdminPageHeader
|
||||
@titleLabel="admin.dashboard.new_features.title"
|
||||
@descriptionLabel="admin.dashboard.new_features.subtitle"
|
||||
<DPageHeader
|
||||
@titleLabel={{i18n "admin.dashboard.new_features.title"}}
|
||||
@descriptionLabel={{i18n "admin.dashboard.new_features.subtitle"}}
|
||||
@learnMoreUrl="https://meta.discourse.org/tags/c/announcements/67/release-notes"
|
||||
@hideTabs={{true}}
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/whats-new"
|
||||
@label={{i18n "admin.dashboard.new_features.title"}}
|
||||
|
@ -16,7 +17,7 @@
|
|||
@action={{this.checkForUpdates}}
|
||||
/>
|
||||
</:actions>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
|
||||
<div class="admin-container admin-config-page__main-area">
|
||||
<div class="admin-config-area">
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
import { hash } from "@ember/helper";
|
||||
import DButton from "discourse/components/d-button";
|
||||
|
||||
export const DPageActionButton = <template>
|
||||
<DButton
|
||||
class="d-page-action-button btn-small"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
||||
|
||||
// This is used for cases where there is another component,
|
||||
// e.g. UppyBackupUploader, that is a button which cannot use
|
||||
// PrimaryButton and so on directly. This should be used very rarely,
|
||||
// most cases are covered by the other button types.
|
||||
export const WrappedButton = <template>
|
||||
<span class="d-page-action-wrapped-button">{{yield}}</span>
|
||||
</template>;
|
||||
|
||||
// No buttons here pass in an @icon by design. They are okay to
|
||||
// use on dropdown list items, but our UI guidelines do not allow them
|
||||
// on regular buttons.
|
||||
export const PrimaryButton = <template>
|
||||
<DPageActionButton
|
||||
class="btn-primary"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
||||
|
||||
export const DangerButton = <template>
|
||||
<DPageActionButton
|
||||
class="btn-danger"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
||||
|
||||
export const DefaultButton = <template>
|
||||
<DPageActionButton
|
||||
class="btn-default"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
||||
|
||||
export const DPageActionListItem = <template>
|
||||
<li class="dropdown-menu__item d-page-action-list-item">
|
||||
<DPageActionButton
|
||||
class="btn-transparent"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</li>
|
||||
</template>;
|
||||
|
||||
// This is used for cases where there is another component,
|
||||
// e.g. UppyBackupUploader, that is a button which cannot use
|
||||
// PrimaryActionListItem and so on directly. This should be used very rarely,
|
||||
// most cases are covered by the other list types.
|
||||
export const WrappedActionListItem = <template>
|
||||
<li
|
||||
class="dropdown-menu__item d-page-action-list-item d-page-action-wrapped-list-item"
|
||||
>
|
||||
{{yield (hash buttonClass="btn-transparent")}}
|
||||
</li>
|
||||
</template>;
|
||||
|
||||
// It is not a mistake that there is no PrimaryActionListItem here, in a list
|
||||
// there is no need for blue text.
|
||||
export const DefaultActionListItem = <template>
|
||||
<DPageActionListItem
|
||||
class="btn-default"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
||||
|
||||
export const DangerActionListItem = <template>
|
||||
<DPageActionListItem
|
||||
class="btn-danger"
|
||||
...attributes
|
||||
@action={{@action}}
|
||||
@route={{@route}}
|
||||
@routeModels={{@routeModels}}
|
||||
@label={{@label}}
|
||||
@title={{@title}}
|
||||
@icon={{@icon}}
|
||||
@isLoading={{@isLoading}}
|
||||
/>
|
||||
</template>;
|
|
@ -0,0 +1,145 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { hash } from "@ember/helper";
|
||||
import { service } from "@ember/service";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import { or } from "truth-helpers";
|
||||
import DBreadcrumbsContainer from "discourse/components/d-breadcrumbs-container";
|
||||
import {
|
||||
DangerActionListItem,
|
||||
DangerButton,
|
||||
DefaultActionListItem,
|
||||
DefaultButton,
|
||||
PrimaryButton,
|
||||
WrappedActionListItem,
|
||||
WrappedButton,
|
||||
} from "discourse/components/d-page-action-button";
|
||||
import DropdownMenu from "discourse/components/dropdown-menu";
|
||||
import HorizontalOverflowNav from "discourse/components/horizontal-overflow-nav";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import DMenu from "float-kit/components/d-menu";
|
||||
|
||||
const HEADLESS_ACTIONS = ["new", "edit"];
|
||||
|
||||
export default class DPageHeader extends Component {
|
||||
@service site;
|
||||
@service router;
|
||||
@tracked shouldDisplay = true;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.router.on("routeDidChange", this, this.#checkIfShouldDisplay);
|
||||
this.#checkIfShouldDisplay();
|
||||
}
|
||||
|
||||
willDestroy() {
|
||||
super.willDestroy(...arguments);
|
||||
this.router.off("routeDidChange", this, this.#checkIfShouldDisplay);
|
||||
}
|
||||
|
||||
@bind
|
||||
#checkIfShouldDisplay() {
|
||||
if (this.args.shouldDisplay !== undefined) {
|
||||
return (this.shouldDisplay = this.args.shouldDisplay);
|
||||
}
|
||||
|
||||
const currentPath = this.router._router.currentPath;
|
||||
if (!currentPath) {
|
||||
return (this.shouldDisplay = true);
|
||||
}
|
||||
|
||||
// NOTE: This has a little admin-specific logic in it, in future
|
||||
// we could extract this out and have it a bit more generic,
|
||||
// for now I think it's a fine tradeoff.
|
||||
const pathSegments = currentPath.split(".");
|
||||
this.shouldDisplay =
|
||||
!pathSegments.includes("admin") ||
|
||||
!HEADLESS_ACTIONS.find((segment) => pathSegments.includes(segment));
|
||||
}
|
||||
|
||||
<template>
|
||||
{{#if this.shouldDisplay}}
|
||||
<div class="d-page-header">
|
||||
<div class="d-page-header__breadcrumbs">
|
||||
<DBreadcrumbsContainer />
|
||||
{{yield to="breadcrumbs"}}
|
||||
</div>
|
||||
|
||||
<div class="d-page-header__title-row">
|
||||
{{#if @titleLabel}}
|
||||
<h1 class="d-page-header__title">{{@titleLabel}}</h1>
|
||||
{{/if}}
|
||||
|
||||
{{#if (or (has-block "actions") @headerActionComponent)}}
|
||||
<div class="d-page-header__actions">
|
||||
{{#if this.site.mobileView}}
|
||||
<DMenu
|
||||
@identifier="d-page-header-mobile-actions"
|
||||
@title={{i18n "more_options"}}
|
||||
@icon="ellipsis-vertical"
|
||||
class="btn-small"
|
||||
>
|
||||
<:content>
|
||||
<DropdownMenu class="d-page-header__mobile-actions">
|
||||
{{#let
|
||||
(hash
|
||||
Primary=DefaultActionListItem
|
||||
Default=DefaultActionListItem
|
||||
Danger=DangerActionListItem
|
||||
Wrapped=WrappedActionListItem
|
||||
)
|
||||
as |actions|
|
||||
}}
|
||||
{{#if (has-block "actions")}}
|
||||
{{yield actions to="actions"}}
|
||||
{{else}}
|
||||
<@headerActionComponent @actions={{actions}} />
|
||||
{{/if}}
|
||||
{{/let}}
|
||||
</DropdownMenu>
|
||||
</:content>
|
||||
</DMenu>
|
||||
{{else}}
|
||||
{{#let
|
||||
(hash
|
||||
Primary=PrimaryButton
|
||||
Default=DefaultButton
|
||||
Danger=DangerButton
|
||||
Wrapped=WrappedButton
|
||||
)
|
||||
as |actions|
|
||||
}}
|
||||
{{#if (has-block "actions")}}
|
||||
{{yield actions to="actions"}}
|
||||
{{else}}
|
||||
<@headerActionComponent @actions={{actions}} />
|
||||
{{/if}}
|
||||
{{/let}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#if @descriptionLabel}}
|
||||
<p class="d-page-header__description">
|
||||
{{htmlSafe @descriptionLabel}}
|
||||
{{#if @learnMoreUrl}}
|
||||
<span class="d-page-header__learn-more">{{htmlSafe
|
||||
(i18n "learn_more_with_link" url=@learnMoreUrl)
|
||||
}}</span>
|
||||
{{/if}}
|
||||
</p>
|
||||
{{/if}}
|
||||
|
||||
{{#unless @hideTabs}}
|
||||
<div class="d-nav-submenu">
|
||||
<HorizontalOverflowNav class="d-nav-submenu__tabs">
|
||||
{{yield to="tabs"}}
|
||||
</HorizontalOverflowNav>
|
||||
</div>
|
||||
{{/unless}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { hash } from "@ember/helper";
|
||||
import { service } from "@ember/service";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import {
|
||||
DangerActionListItem,
|
||||
DangerButton,
|
||||
DefaultActionListItem,
|
||||
DefaultButton,
|
||||
PrimaryButton,
|
||||
WrappedActionListItem,
|
||||
WrappedButton,
|
||||
} from "discourse/components/d-page-action-button";
|
||||
import DropdownMenu from "discourse/components/dropdown-menu";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import DMenu from "float-kit/components/d-menu";
|
||||
|
||||
export default class DPageSubheader extends Component {
|
||||
@service site;
|
||||
|
||||
<template>
|
||||
<div class="d-page-subheader">
|
||||
<div class="d-page-subheader__title-row">
|
||||
<h2 class="d-page-subheader__title">{{@titleLabel}}</h2>
|
||||
{{#if (has-block "actions")}}
|
||||
<div class="d-page-subheader__actions">
|
||||
{{#if this.site.mobileView}}
|
||||
<DMenu
|
||||
@identifier="d-page-subheader-mobile-actions"
|
||||
@title={{i18n "more_options"}}
|
||||
@icon="ellipsis-vertical"
|
||||
class="btn-small"
|
||||
>
|
||||
<:content>
|
||||
<DropdownMenu class="d-page-subheader__mobile-actions">
|
||||
{{yield
|
||||
(hash
|
||||
Primary=DefaultActionListItem
|
||||
Default=DefaultActionListItem
|
||||
Danger=DangerActionListItem
|
||||
Wrapped=WrappedActionListItem
|
||||
)
|
||||
to="actions"
|
||||
}}
|
||||
</DropdownMenu>
|
||||
</:content>
|
||||
</DMenu>
|
||||
{{else}}
|
||||
{{yield
|
||||
(hash
|
||||
Primary=PrimaryButton
|
||||
Default=DefaultButton
|
||||
Danger=DangerButton
|
||||
Wrapped=WrappedButton
|
||||
)
|
||||
to="actions"
|
||||
}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#if @descriptionLabel}}
|
||||
<p class="d-page-subheader__description">
|
||||
{{htmlSafe @descriptionLabel}}
|
||||
{{#if @learnMoreUrl}}
|
||||
<span class="d-page-subheader__learn-more">
|
||||
{{htmlSafe
|
||||
(i18n "learn_more_with_link" url=@learnMoreUrl)
|
||||
}}</span>
|
||||
{{/if}}
|
||||
</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
}
|
|
@ -3337,7 +3337,7 @@ class PluginApi {
|
|||
}
|
||||
|
||||
/**
|
||||
* Registers a component class that will be rendered within the AdminPageHeader component
|
||||
* Registers a component class that will be rendered within the DPageHeader component
|
||||
* only on plugins using the AdminPluginConfigPage and the new plugin "show" route.
|
||||
*
|
||||
* This component will be passed an `@actions` argument, with Primary, Default, Danger,
|
||||
|
|
|
@ -71,28 +71,28 @@ acceptance("Admin - Users List", function (needs) {
|
|||
|
||||
await visit("/admin/users/list/active");
|
||||
|
||||
assert.dom(".admin-page-subheader__title").hasText(activeTitle);
|
||||
assert.dom(".d-page-subheader__title").hasText(activeTitle);
|
||||
assert
|
||||
.dom(".users-list .user:nth-child(1) .username")
|
||||
.includesText(activeUser);
|
||||
|
||||
await click('a[href="/admin/users/list/new"]');
|
||||
|
||||
assert.dom(".admin-page-subheader__title").hasText(suspectTitle);
|
||||
assert.dom(".d-page-subheader__title").hasText(suspectTitle);
|
||||
assert
|
||||
.dom(".users-list .user:nth-child(1) .username")
|
||||
.includesText(suspectUser);
|
||||
|
||||
await click(".users-list .sortable:nth-child(4)");
|
||||
|
||||
assert.dom(".admin-page-subheader__title").hasText(suspectTitle);
|
||||
assert.dom(".d-page-subheader__title").hasText(suspectTitle);
|
||||
assert
|
||||
.dom(".users-list .user:nth-child(1) .username")
|
||||
.includesText(suspectUser);
|
||||
|
||||
await click('a[href="/admin/users/list/active"]');
|
||||
|
||||
assert.dom(".admin-page-subheader__title").hasText(activeTitle);
|
||||
assert.dom(".d-page-subheader__title").hasText(activeTitle);
|
||||
assert
|
||||
.dom(".users-list .user:nth-child(1) .username")
|
||||
.includesText(activeUser);
|
||||
|
|
|
@ -1,177 +0,0 @@
|
|||
import { click, render } from "@ember/test-helpers";
|
||||
import { module, test } from "qunit";
|
||||
import { forceMobile } from "discourse/lib/mobile";
|
||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import AdminPageSubheader from "admin/components/admin-page-subheader";
|
||||
|
||||
module("Integration | Component | AdminPageSubheader", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test("@titleLabel", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageSubheader @titleLabel="admin.title" />
|
||||
</template>);
|
||||
assert
|
||||
.dom(".admin-page-subheader__title")
|
||||
.exists()
|
||||
.hasText(i18n("admin.title"));
|
||||
});
|
||||
|
||||
test("@titleLabelTranslated", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageSubheader @titleLabelTranslated="Wow so cool" />
|
||||
</template>);
|
||||
assert.dom(".admin-page-subheader__title").exists().hasText("Wow so cool");
|
||||
});
|
||||
|
||||
test("no @descriptionLabel and no @descriptionLabelTranslated", async function (assert) {
|
||||
await render(<template><AdminPageSubheader /></template>);
|
||||
assert.dom(".admin-page-subheader__description").doesNotExist();
|
||||
});
|
||||
|
||||
test("@descriptionLabel", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageSubheader @descriptionLabel="admin.badges.description" />
|
||||
</template>);
|
||||
assert
|
||||
.dom(".admin-page-subheader__description")
|
||||
.exists()
|
||||
.hasText(i18n("admin.badges.description"));
|
||||
});
|
||||
|
||||
test("@descriptionLabelTranslated", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageSubheader
|
||||
@descriptionLabelTranslated="Some description which supports <strong>HTML</strong>"
|
||||
/>
|
||||
</template>);
|
||||
assert
|
||||
.dom(".admin-page-subheader__description")
|
||||
.exists()
|
||||
.hasText("Some description which supports HTML");
|
||||
assert.dom(".admin-page-subheader__description strong").exists();
|
||||
});
|
||||
|
||||
test("no @learnMoreUrl", async function (assert) {
|
||||
await render(<template><AdminPageSubheader /></template>);
|
||||
assert.dom(".admin-page-subheader__learn-more").doesNotExist();
|
||||
});
|
||||
|
||||
test("@learnMoreUrl", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageSubheader
|
||||
@descriptionLabel="admin.badges.description"
|
||||
@learnMoreUrl="https://meta.discourse.org/t/96331"
|
||||
/>
|
||||
</template>);
|
||||
assert.dom(".admin-page-subheader__learn-more").exists();
|
||||
assert
|
||||
.dom(".admin-page-subheader__learn-more a")
|
||||
.hasText("Learn more…")
|
||||
.hasAttribute("href", "https://meta.discourse.org/t/96331");
|
||||
});
|
||||
|
||||
test("renders all types of action buttons in yielded <:actions>", async function (assert) {
|
||||
let actionCalled = false;
|
||||
const someAction = () => {
|
||||
actionCalled = true;
|
||||
};
|
||||
|
||||
await render(<template>
|
||||
<AdminPageSubheader>
|
||||
<:actions as |actions|>
|
||||
<actions.Primary
|
||||
@route="adminBadges.show"
|
||||
@routeModels="new"
|
||||
@icon="plus"
|
||||
@label="admin.badges.new"
|
||||
class="new-badge"
|
||||
/>
|
||||
|
||||
<actions.Default
|
||||
@route="adminBadges.award"
|
||||
@routeModels="new"
|
||||
@icon="upload"
|
||||
@label="admin.badges.mass_award.title"
|
||||
class="award-badge"
|
||||
/>
|
||||
|
||||
<actions.Danger
|
||||
@action={{someAction}}
|
||||
@title="admin.badges.group_settings"
|
||||
@label="admin.badges.group_settings"
|
||||
@icon="gear"
|
||||
class="edit-groupings-btn"
|
||||
/>
|
||||
</:actions>
|
||||
</AdminPageSubheader>
|
||||
</template>);
|
||||
|
||||
assert
|
||||
.dom(
|
||||
".admin-page-subheader__actions .admin-page-action-button.new-badge.btn.btn-small.btn-primary"
|
||||
)
|
||||
.exists();
|
||||
assert
|
||||
.dom(
|
||||
".admin-page-subheader__actions .admin-page-action-button.award-badge.btn.btn-small.btn-default"
|
||||
)
|
||||
.exists();
|
||||
assert
|
||||
.dom(
|
||||
".admin-page-subheader__actions .admin-page-action-button.edit-groupings-btn.btn.btn-small.btn-danger"
|
||||
)
|
||||
.exists();
|
||||
|
||||
await click(".edit-groupings-btn");
|
||||
assert.true(actionCalled);
|
||||
});
|
||||
});
|
||||
|
||||
module(
|
||||
"Integration | Component | AdminPageSubheader | Mobile",
|
||||
function (hooks) {
|
||||
hooks.beforeEach(function () {
|
||||
forceMobile();
|
||||
});
|
||||
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test("action buttons become a dropdown on mobile", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageSubheader>
|
||||
<:actions as |actions|>
|
||||
<actions.Primary
|
||||
@route="adminBadges.show"
|
||||
@routeModels="new"
|
||||
@icon="plus"
|
||||
@label="admin.badges.new"
|
||||
class="new-badge"
|
||||
/>
|
||||
|
||||
<actions.Default
|
||||
@route="adminBadges.award"
|
||||
@routeModels="new"
|
||||
@icon="upload"
|
||||
@label="admin.badges.mass_award.title"
|
||||
class="award-badge"
|
||||
/>
|
||||
</:actions>
|
||||
</AdminPageSubheader>
|
||||
</template>);
|
||||
|
||||
assert
|
||||
.dom(
|
||||
".admin-page-subheader .fk-d-menu__trigger.admin-page-subheader-mobile-actions-trigger"
|
||||
)
|
||||
.exists();
|
||||
|
||||
await click(".admin-page-subheader-mobile-actions-trigger");
|
||||
|
||||
assert
|
||||
.dom(".dropdown-menu.admin-page-subheader__mobile-actions .new-badge")
|
||||
.exists();
|
||||
});
|
||||
}
|
||||
);
|
|
@ -1,14 +1,14 @@
|
|||
import { click, render } from "@ember/test-helpers";
|
||||
import { module, test } from "qunit";
|
||||
import DBreadcrumbsItem from "discourse/components/d-breadcrumbs-item";
|
||||
import DPageHeader from "discourse/components/d-page-header";
|
||||
import NavItem from "discourse/components/nav-item";
|
||||
import { forceMobile } from "discourse/lib/mobile";
|
||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import AdminPageHeader from "admin/components/admin-page-header";
|
||||
|
||||
const AdminPageHeaderActionsTestComponent = <template>
|
||||
<div class="admin-page-header-actions-test-component">
|
||||
const DPageHeaderActionsTestComponent = <template>
|
||||
<div class="d-page-header-actions-test-component">
|
||||
<@actions.Default
|
||||
@route="adminBadges.award"
|
||||
@routeModels="new"
|
||||
|
@ -19,125 +19,96 @@ const AdminPageHeaderActionsTestComponent = <template>
|
|||
</div>
|
||||
</template>;
|
||||
|
||||
module("Integration | Component | AdminPageHeader", function (hooks) {
|
||||
module("Integration | Component | DPageHeader", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test("no @titleLabel or @titleLabelTranslated", async function (assert) {
|
||||
await render(<template><AdminPageHeader /></template>);
|
||||
assert.dom(".admin-page-header__title").doesNotExist();
|
||||
test("no @titleLabel", async function (assert) {
|
||||
await render(<template><DPageHeader /></template>);
|
||||
assert.dom(".d-page-header__title").doesNotExist();
|
||||
});
|
||||
|
||||
test("@titleLabel", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageHeader @titleLabel="admin.title" />
|
||||
<DPageHeader @titleLabel={{i18n "admin.title"}} />
|
||||
</template>);
|
||||
assert
|
||||
.dom(".admin-page-header__title")
|
||||
.exists()
|
||||
.hasText(i18n("admin.title"));
|
||||
});
|
||||
|
||||
test("@titleLabelTranslated", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageHeader @titleLabelTranslated="Wow so cool" />
|
||||
</template>);
|
||||
assert.dom(".admin-page-header__title").exists().hasText("Wow so cool");
|
||||
assert.dom(".d-page-header__title").exists().hasText(i18n("admin.title"));
|
||||
});
|
||||
|
||||
test("@shouldDisplay", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageHeader
|
||||
@titleLabelTranslated="Wow so cool"
|
||||
@shouldDisplay={{false}}
|
||||
/>
|
||||
<DPageHeader @titleLabel="Wow so cool" @shouldDisplay={{false}} />
|
||||
</template>);
|
||||
assert.dom(".admin-page-header").doesNotExist();
|
||||
});
|
||||
|
||||
test("renders base breadcrumbs and yielded <:breadcrumbs>", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageHeader @titleLabel="admin.titile">
|
||||
<DPageHeader @titleLabel={{i18n "admin.titile"}}>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/badges"
|
||||
@label={{i18n "admin.badges.title"}}
|
||||
/>
|
||||
</:breadcrumbs>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
</template>);
|
||||
|
||||
assert
|
||||
.dom(".admin-page-header__breadcrumbs .d-breadcrumbs__item")
|
||||
.exists({ count: 2 });
|
||||
.dom(".d-page-header__breadcrumbs .d-breadcrumbs__item")
|
||||
.exists({ count: 1 });
|
||||
assert
|
||||
.dom(".admin-page-header__breadcrumbs .d-breadcrumbs__item")
|
||||
.hasText(i18n("admin_title"));
|
||||
assert
|
||||
.dom(".admin-page-header__breadcrumbs .d-breadcrumbs__item:last-child")
|
||||
.dom(".d-page-header__breadcrumbs .d-breadcrumbs__item:last-child")
|
||||
.hasText(i18n("admin.badges.title"));
|
||||
});
|
||||
|
||||
test("no @descriptionLabel and no @descriptionLabelTranslated", async function (assert) {
|
||||
await render(<template><AdminPageHeader /></template>);
|
||||
assert.dom(".admin-page-header__description").doesNotExist();
|
||||
test("no @descriptionLabel", async function (assert) {
|
||||
await render(<template><DPageHeader /></template>);
|
||||
assert.dom(".d-page-header__description").doesNotExist();
|
||||
});
|
||||
|
||||
test("@descriptionLabel", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageHeader @descriptionLabel="admin.badges.description" />
|
||||
<DPageHeader @descriptionLabel={{i18n "admin.badges.description"}} />
|
||||
</template>);
|
||||
assert
|
||||
.dom(".admin-page-header__description")
|
||||
.dom(".d-page-header__description")
|
||||
.exists()
|
||||
.hasText(i18n("admin.badges.description"));
|
||||
});
|
||||
|
||||
test("@descriptionLabelTranslated", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageHeader
|
||||
@descriptionLabelTranslated="Some description which supports <strong>HTML</strong>"
|
||||
/>
|
||||
</template>);
|
||||
assert
|
||||
.dom(".admin-page-header__description")
|
||||
.exists()
|
||||
.hasText("Some description which supports HTML");
|
||||
assert.dom(".admin-page-header__description strong").exists();
|
||||
});
|
||||
|
||||
test("no @learnMoreUrl", async function (assert) {
|
||||
await render(<template><AdminPageHeader /></template>);
|
||||
assert.dom(".admin-page-header__learn-more").doesNotExist();
|
||||
await render(<template><DPageHeader /></template>);
|
||||
assert.dom(".d-page-header__learn-more").doesNotExist();
|
||||
});
|
||||
|
||||
test("@learnMoreUrl", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageHeader
|
||||
@descriptionLabel="admin.badges.description"
|
||||
<DPageHeader
|
||||
@descriptionLabel={{i18n "admin.badges.description"}}
|
||||
@learnMoreUrl="https://meta.discourse.org/t/96331"
|
||||
/>
|
||||
</template>);
|
||||
assert.dom(".admin-page-header__learn-more").exists();
|
||||
assert.dom(".d-page-header__learn-more").exists();
|
||||
assert
|
||||
.dom(".admin-page-header__learn-more a")
|
||||
.dom(".d-page-header__learn-more a")
|
||||
.hasText("Learn more…")
|
||||
.hasAttribute("href", "https://meta.discourse.org/t/96331");
|
||||
});
|
||||
|
||||
test("renders nav tabs in yielded <:tabs>", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageHeader>
|
||||
<DPageHeader>
|
||||
<:tabs>
|
||||
<NavItem
|
||||
@route="admin.backups.settings"
|
||||
@label="settings"
|
||||
class="admin-backups-tabs__settings"
|
||||
class="d-backups-tabs__settings"
|
||||
/>
|
||||
</:tabs>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
</template>);
|
||||
assert
|
||||
.dom(".admin-nav-submenu__tabs .admin-backups-tabs__settings")
|
||||
.dom(".d-nav-submenu__tabs .d-backups-tabs__settings")
|
||||
.exists()
|
||||
.hasText(i18n("settings"));
|
||||
});
|
||||
|
@ -149,7 +120,7 @@ module("Integration | Component | AdminPageHeader", function (hooks) {
|
|||
};
|
||||
|
||||
await render(<template>
|
||||
<AdminPageHeader>
|
||||
<DPageHeader>
|
||||
<:actions as |actions|>
|
||||
<actions.Primary
|
||||
@route="adminBadges.show"
|
||||
|
@ -175,22 +146,22 @@ module("Integration | Component | AdminPageHeader", function (hooks) {
|
|||
class="edit-groupings-btn"
|
||||
/>
|
||||
</:actions>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
</template>);
|
||||
|
||||
assert
|
||||
.dom(
|
||||
".admin-page-header__actions .admin-page-action-button.new-badge.btn.btn-small.btn-primary"
|
||||
".d-page-header__actions .d-page-action-button.new-badge.btn.btn-small.btn-primary"
|
||||
)
|
||||
.exists();
|
||||
assert
|
||||
.dom(
|
||||
".admin-page-header__actions .admin-page-action-button.award-badge.btn.btn-small.btn-default"
|
||||
".d-page-header__actions .d-page-action-button.award-badge.btn.btn-small.btn-default"
|
||||
)
|
||||
.exists();
|
||||
assert
|
||||
.dom(
|
||||
".admin-page-header__actions .admin-page-action-button.edit-groupings-btn.btn.btn-small.btn-danger"
|
||||
".d-page-header__actions .d-page-action-button.edit-groupings-btn.btn.btn-small.btn-danger"
|
||||
)
|
||||
.exists();
|
||||
|
||||
|
@ -200,18 +171,14 @@ module("Integration | Component | AdminPageHeader", function (hooks) {
|
|||
|
||||
test("@headerActionComponent is rendered with actions arg", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageHeader
|
||||
@headerActionComponent={{AdminPageHeaderActionsTestComponent}}
|
||||
/>
|
||||
<DPageHeader @headerActionComponent={{DPageHeaderActionsTestComponent}} />
|
||||
</template>);
|
||||
|
||||
assert
|
||||
.dom(".admin-page-header-actions-test-component .award-badge")
|
||||
.exists();
|
||||
assert.dom(".d-page-header-actions-test-component .award-badge").exists();
|
||||
});
|
||||
});
|
||||
|
||||
module("Integration | Component | AdminPageHeader | Mobile", function (hooks) {
|
||||
module("Integration | Component | DPageHeader | Mobile", function (hooks) {
|
||||
hooks.beforeEach(function () {
|
||||
forceMobile();
|
||||
});
|
||||
|
@ -220,7 +187,7 @@ module("Integration | Component | AdminPageHeader | Mobile", function (hooks) {
|
|||
|
||||
test("action buttons become a dropdown on mobile", async function (assert) {
|
||||
await render(<template>
|
||||
<AdminPageHeader>
|
||||
<DPageHeader>
|
||||
<:actions as |actions|>
|
||||
<actions.Primary
|
||||
@route="adminBadges.show"
|
||||
|
@ -238,19 +205,19 @@ module("Integration | Component | AdminPageHeader | Mobile", function (hooks) {
|
|||
class="award-badge"
|
||||
/>
|
||||
</:actions>
|
||||
</AdminPageHeader>
|
||||
</DPageHeader>
|
||||
</template>);
|
||||
|
||||
assert
|
||||
.dom(
|
||||
".admin-page-header__actions .fk-d-menu__trigger.admin-page-header-mobile-actions-trigger"
|
||||
".d-page-header__actions .fk-d-menu__trigger.d-page-header-mobile-actions-trigger"
|
||||
)
|
||||
.exists();
|
||||
|
||||
await click(".admin-page-header-mobile-actions-trigger");
|
||||
await click(".d-page-header-mobile-actions-trigger");
|
||||
|
||||
assert
|
||||
.dom(".dropdown-menu.admin-page-header__mobile-actions .new-badge")
|
||||
.dom(".dropdown-menu.d-page-header__mobile-actions .new-badge")
|
||||
.exists();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,154 @@
|
|||
import { click, render } from "@ember/test-helpers";
|
||||
import { module, test } from "qunit";
|
||||
import DPageSubheader from "discourse/components/d-page-subheader";
|
||||
import { forceMobile } from "discourse/lib/mobile";
|
||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
module("Integration | Component | DPageSubheader", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test("@titleLabel", async function (assert) {
|
||||
await render(<template>
|
||||
<DPageSubheader @titleLabel={{i18n "admin.title"}} />
|
||||
</template>);
|
||||
assert
|
||||
.dom(".d-page-subheader__title")
|
||||
.exists()
|
||||
.hasText(i18n("admin.title"));
|
||||
});
|
||||
|
||||
test("no @descriptionLabel", async function (assert) {
|
||||
await render(<template><DPageSubheader /></template>);
|
||||
assert.dom(".d-page-subheader__description").doesNotExist();
|
||||
});
|
||||
|
||||
test("@descriptionLabel", async function (assert) {
|
||||
await render(<template>
|
||||
<DPageSubheader @descriptionLabel={{i18n "admin.badges.description"}} />
|
||||
</template>);
|
||||
assert
|
||||
.dom(".d-page-subheader__description")
|
||||
.exists()
|
||||
.hasText(i18n("admin.badges.description"));
|
||||
});
|
||||
|
||||
test("no @learnMoreUrl", async function (assert) {
|
||||
await render(<template><DPageSubheader /></template>);
|
||||
assert.dom(".d-page-subheader__learn-more").doesNotExist();
|
||||
});
|
||||
|
||||
test("@learnMoreUrl", async function (assert) {
|
||||
await render(<template>
|
||||
<DPageSubheader
|
||||
@descriptionLabel={{i18n "admin.badges.description"}}
|
||||
@learnMoreUrl="https://meta.discourse.org/t/96331"
|
||||
/>
|
||||
</template>);
|
||||
assert.dom(".d-page-subheader__learn-more").exists();
|
||||
assert
|
||||
.dom(".d-page-subheader__learn-more a")
|
||||
.hasText("Learn more…")
|
||||
.hasAttribute("href", "https://meta.discourse.org/t/96331");
|
||||
});
|
||||
|
||||
test("renders all types of action buttons in yielded <:actions>", async function (assert) {
|
||||
let actionCalled = false;
|
||||
const someAction = () => {
|
||||
actionCalled = true;
|
||||
};
|
||||
|
||||
await render(<template>
|
||||
<DPageSubheader>
|
||||
<:actions as |actions|>
|
||||
<actions.Primary
|
||||
@route="adminBadges.show"
|
||||
@routeModels="new"
|
||||
@icon="plus"
|
||||
@label="admin.badges.new"
|
||||
class="new-badge"
|
||||
/>
|
||||
|
||||
<actions.Default
|
||||
@route="adminBadges.award"
|
||||
@routeModels="new"
|
||||
@icon="upload"
|
||||
@label="admin.badges.mass_award.title"
|
||||
class="award-badge"
|
||||
/>
|
||||
|
||||
<actions.Danger
|
||||
@action={{someAction}}
|
||||
@title="admin.badges.group_settings"
|
||||
@label="admin.badges.group_settings"
|
||||
@icon="gear"
|
||||
class="edit-groupings-btn"
|
||||
/>
|
||||
</:actions>
|
||||
</DPageSubheader>
|
||||
</template>);
|
||||
|
||||
assert
|
||||
.dom(
|
||||
".d-page-subheader__actions .d-page-action-button.new-badge.btn.btn-small.btn-primary"
|
||||
)
|
||||
.exists();
|
||||
assert
|
||||
.dom(
|
||||
".d-page-subheader__actions .d-page-action-button.award-badge.btn.btn-small.btn-default"
|
||||
)
|
||||
.exists();
|
||||
assert
|
||||
.dom(
|
||||
".d-page-subheader__actions .d-page-action-button.edit-groupings-btn.btn.btn-small.btn-danger"
|
||||
)
|
||||
.exists();
|
||||
|
||||
await click(".edit-groupings-btn");
|
||||
assert.true(actionCalled);
|
||||
});
|
||||
});
|
||||
|
||||
module("Integration | Component | DPageSubheader | Mobile", function (hooks) {
|
||||
hooks.beforeEach(function () {
|
||||
forceMobile();
|
||||
});
|
||||
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test("action buttons become a dropdown on mobile", async function (assert) {
|
||||
await render(<template>
|
||||
<DPageSubheader>
|
||||
<:actions as |actions|>
|
||||
<actions.Primary
|
||||
@route="adminBadges.show"
|
||||
@routeModels="new"
|
||||
@icon="plus"
|
||||
@label="admin.badges.new"
|
||||
class="new-badge"
|
||||
/>
|
||||
|
||||
<actions.Default
|
||||
@route="adminBadges.award"
|
||||
@routeModels="new"
|
||||
@icon="upload"
|
||||
@label="admin.badges.mass_award.title"
|
||||
class="award-badge"
|
||||
/>
|
||||
</:actions>
|
||||
</DPageSubheader>
|
||||
</template>);
|
||||
|
||||
assert
|
||||
.dom(
|
||||
".d-page-subheader .fk-d-menu__trigger.d-page-subheader-mobile-actions-trigger"
|
||||
)
|
||||
.exists();
|
||||
|
||||
await click(".d-page-subheader-mobile-actions-trigger");
|
||||
|
||||
assert
|
||||
.dom(".dropdown-menu.d-page-subheader__mobile-actions .new-badge")
|
||||
.exists();
|
||||
});
|
||||
});
|
|
@ -124,7 +124,7 @@
|
|||
float: left;
|
||||
max-width: 70%;
|
||||
|
||||
&.admin-page-action-button {
|
||||
&.d-page-action-button {
|
||||
margin-top: 0;
|
||||
|
||||
@media (max-width: $mobile-breakpoint) {
|
||||
|
|
|
@ -806,6 +806,7 @@
|
|||
.admin-permalinks {
|
||||
@include breakpoint(tablet) {
|
||||
.admin-page-subheader,
|
||||
.d-page-subheader,
|
||||
.admin-config-area,
|
||||
.admin-config-area__primary-content,
|
||||
.loading-container {
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
margin-bottom: var(--space-6);
|
||||
}
|
||||
|
||||
.admin-nav-submenu {
|
||||
.d-nav-submenu {
|
||||
background: transparent;
|
||||
border-bottom: 1px solid var(--primary-low);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
@import "badges";
|
||||
@import "banner";
|
||||
@import "d-breadcrumbs";
|
||||
@import "d-page-header";
|
||||
@import "d-stat-tiles";
|
||||
@import "bookmark-list";
|
||||
@import "bookmark-modal";
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
$mobile-breakpoint: 700px;
|
||||
|
||||
.d-page-header,
|
||||
.d-page-subheader {
|
||||
&__title-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
margin-bottom: var(--space-2);
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: var(--font-up-2);
|
||||
}
|
||||
|
||||
.d-page-header__actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
|
||||
@media (max-width: $mobile-breakpoint) {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-left: var(--space-2);
|
||||
|
||||
@media (max-width: $mobile-breakpoint) {
|
||||
width: 100%;
|
||||
margin-bottom: var(--space-2);
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.d-nav-submenu {
|
||||
background: transparent;
|
||||
border-bottom: 1px solid var(--primary-low);
|
||||
|
||||
.horizontal-overflow-nav {
|
||||
background: transparent;
|
||||
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-pills {
|
||||
width: auto;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.d-page-header {
|
||||
&__title-row {
|
||||
@media (max-width: $mobile-breakpoint) {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.d-page-header__actions {
|
||||
button {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.d-page-subheader {
|
||||
&__title-row {
|
||||
@media (max-width: $mobile-breakpoint) {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.d-page-action-list-item {
|
||||
.btn-primary {
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
|
@ -4,9 +4,9 @@
|
|||
/>
|
||||
|
||||
<div class="discourse-chat-incoming-webhooks admin-detail">
|
||||
<AdminPageSubheader
|
||||
@titleLabel="chat.incoming_webhooks.title"
|
||||
@descriptionLabel="chat.incoming_webhooks.instructions"
|
||||
<DPageSubheader
|
||||
@titleLabel={{i18n "chat.incoming_webhooks.title"}}
|
||||
@descriptionLabel={{i18n "chat.incoming_webhooks.instructions"}}
|
||||
>
|
||||
<:actions as |actions|>
|
||||
<actions.Primary
|
||||
|
@ -18,7 +18,7 @@
|
|||
class="admin-incoming-webhooks-new"
|
||||
/>
|
||||
</:actions>
|
||||
</AdminPageSubheader>
|
||||
</DPageSubheader>
|
||||
|
||||
<div class="incoming-chat-webhooks">
|
||||
{{#if this.model.incoming_chat_webhooks}}
|
||||
|
|
|
@ -6,7 +6,7 @@ describe "Admin Chat Incoming Webhooks", type: :system do
|
|||
|
||||
let(:dialog) { PageObjects::Components::Dialog.new }
|
||||
let(:admin_incoming_webhooks_page) { PageObjects::Pages::AdminIncomingWebhooks.new }
|
||||
let(:admin_header) { PageObjects::Components::AdminHeader.new }
|
||||
let(:d_page_header) { PageObjects::Components::DPageHeader.new }
|
||||
|
||||
before do
|
||||
chat_system_bootstrap(current_user)
|
||||
|
@ -16,11 +16,11 @@ describe "Admin Chat Incoming Webhooks", type: :system do
|
|||
it "can create incoming webhooks" do
|
||||
admin_incoming_webhooks_page.visit
|
||||
|
||||
expect(admin_header).to be_visible
|
||||
expect(d_page_header).to be_visible
|
||||
|
||||
admin_incoming_webhooks_page.click_new
|
||||
|
||||
expect(admin_header).to be_hidden
|
||||
expect(d_page_header).to be_hidden
|
||||
|
||||
admin_incoming_webhooks_page.form.field("name").fill_in("Test webhook")
|
||||
admin_incoming_webhooks_page.form.field("description").fill_in("Some test content")
|
||||
|
|
|
@ -8,7 +8,7 @@ describe "Admin Flags Page", type: :system do
|
|||
let(:admin_flags_page) { PageObjects::Pages::AdminFlags.new }
|
||||
let(:admin_flag_form_page) { PageObjects::Pages::AdminFlagForm.new }
|
||||
let(:flag_modal) { PageObjects::Modals::Flag.new }
|
||||
let(:admin_header) { PageObjects::Components::AdminHeader.new }
|
||||
let(:d_page_header) { PageObjects::Components::DPageHeader.new }
|
||||
|
||||
before do
|
||||
sign_in(admin)
|
||||
|
@ -27,7 +27,7 @@ describe "Admin Flags Page", type: :system do
|
|||
)
|
||||
|
||||
admin_flags_page.visit
|
||||
expect(admin_header).to be_visible
|
||||
expect(d_page_header).to be_visible
|
||||
|
||||
admin_flags_page.toggle("spam")
|
||||
topic_page.visit_topic(post.topic).open_flag_topic_modal
|
||||
|
@ -81,8 +81,7 @@ describe "Admin Flags Page", type: :system do
|
|||
expect(admin_flags_page).to have_add_flag_button_enabled
|
||||
|
||||
admin_flags_page.click_add_flag
|
||||
|
||||
expect(admin_header).to be_hidden
|
||||
expect(d_page_header).to be_hidden
|
||||
|
||||
admin_flag_form_page
|
||||
.fill_in_name("Vulgar")
|
||||
|
@ -115,7 +114,7 @@ describe "Admin Flags Page", type: :system do
|
|||
|
||||
# update
|
||||
admin_flags_page.visit.click_edit_flag("custom_vulgar")
|
||||
expect(admin_header).to be_hidden
|
||||
expect(d_page_header).to be_hidden
|
||||
admin_flag_form_page.fill_in_name("Tasteless").click_save
|
||||
|
||||
expect(admin_flags_page).to have_flags(
|
||||
|
@ -158,7 +157,7 @@ describe "Admin Flags Page", type: :system do
|
|||
it "has settings tab" do
|
||||
admin_flags_page.visit
|
||||
|
||||
expect(admin_header).to have_tabs(
|
||||
expect(d_page_header).to have_tabs(
|
||||
[I18n.t("admin_js.settings"), I18n.t("admin_js.admin.config_areas.flags.flags_tab")],
|
||||
)
|
||||
|
||||
|
|
|
@ -6,11 +6,11 @@ describe "Admin User Fields", type: :system do
|
|||
before { sign_in(current_user) }
|
||||
|
||||
let(:user_fields_page) { PageObjects::Pages::AdminUserFields.new }
|
||||
let(:admin_header) { PageObjects::Components::AdminHeader.new }
|
||||
let(:page_header) { PageObjects::Components::DPageHeader.new }
|
||||
|
||||
it "correctly saves user fields" do
|
||||
user_fields_page.visit
|
||||
expect(admin_header).to be_visible
|
||||
expect(page_header).to be_visible
|
||||
user_fields_page.add_field(name: "Occupation", description: "What you do for work")
|
||||
|
||||
expect(user_fields_page).to have_user_field("Occupation")
|
||||
|
@ -32,7 +32,7 @@ describe "Admin User Fields", type: :system do
|
|||
user_fields_page.visit
|
||||
user_fields_page.click_add_field
|
||||
|
||||
expect(admin_header).to be_hidden
|
||||
expect(page_header).to be_hidden
|
||||
|
||||
form = page.find(".user-field")
|
||||
editable_label = I18n.t("admin_js.admin.user_fields.editable.title")
|
||||
|
@ -73,7 +73,7 @@ describe "Admin User Fields", type: :system do
|
|||
|
||||
form.find(".user-field-name").fill_in(with: "Favourite Transformer")
|
||||
|
||||
expect(admin_header).to be_hidden
|
||||
expect(page_header).to be_hidden
|
||||
|
||||
form.find(".btn-primary").click
|
||||
|
||||
|
|
|
@ -2,17 +2,18 @@
|
|||
|
||||
module PageObjects
|
||||
module Components
|
||||
# TODO (martin) Delete this after plugins have been updated to use DPageHeader
|
||||
class AdminHeader < PageObjects::Pages::Base
|
||||
def has_tabs?(names)
|
||||
expect(page.all(".admin-nav-submenu__tabs a").map(&:text)).to eq(names)
|
||||
expect(page.all(".d-nav-submenu__tabs a").map(&:text)).to eq(names)
|
||||
end
|
||||
|
||||
def visible?
|
||||
has_css?(".admin-page-header")
|
||||
has_css?(".d-page-header")
|
||||
end
|
||||
|
||||
def hidden?
|
||||
has_no_css?(".admin-page-header")
|
||||
has_no_css?(".d-page-header")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module PageObjects
|
||||
module Components
|
||||
class DPageHeader < PageObjects::Pages::Base
|
||||
def has_tabs?(names)
|
||||
expect(page.all(".d-nav-submenu__tabs a").map(&:text)).to eq(names)
|
||||
end
|
||||
|
||||
def visible?
|
||||
has_css?(".d-page-header")
|
||||
end
|
||||
|
||||
def hidden?
|
||||
has_no_css?(".d-page-header")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -21,7 +21,7 @@ module PageObjects
|
|||
end
|
||||
|
||||
def plugin_nav_tab_selector(plugin)
|
||||
".admin-nav-submenu__tabs .admin-plugin-tab-nav-item[data-plugin-nav-tab-id=\"#{plugin}\"]"
|
||||
".d-nav-submenu__tabs .admin-plugin-tab-nav-item[data-plugin-nav-tab-id=\"#{plugin}\"]"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,7 +19,7 @@ module PageObjects
|
|||
end
|
||||
|
||||
def click_add_field
|
||||
page.find(".admin-page-header__actions .btn-primary").click
|
||||
page.find(".d-page-header__actions .btn-primary").click
|
||||
end
|
||||
|
||||
def click_edit
|
||||
|
|
Loading…
Reference in New Issue