일관된 관리자 인터페이스 만들기

이 가이드라인은 일관된 관리자 인터페이스를 만들기 위해 사용성, 접근성 및 구조화된 레이아웃에 초점을 맞춥니다. 포함되는 내용과 각 섹션으로 쉽게 이동하려면 목차를 참조하세요.

참고: 여기서 사용되는 용어는 관리자 인터페이스 용어집에서 정의되어 있습니다.

0. 서문 - 설정 페이지 구조 및 사이드바 링크

관리자 인터페이스에 새로운 설정 페이지를 추가할 때, 각 페이지에는 사이드바 링크가 필요하며, 각 페이지에는 제목과 헤더 설명이 모두 필요합니다. 이를 통해 모든 곳에서 일관성을 유지하고, 향후 관리자 검색 기능의 향상이 관리자 인터페이스의 전체 레이아웃을 표시할 수 있습니다.

일반적으로 관리자 인터페이스의 구조는 다음과 같습니다:

  • 관리자 인터페이스
    • 설정 페이지 (사이드바에 표시됨)
      • 설정 탭
      • 선택적 기타 3차 탭
        • 리소스를 위한 편집/신규 3차 페이지

궁극적으로, 루트 인터페이스와 설정 페이지 사이에 "섹션 개요"가 삽입될 것입니다.

사이드바 링크

모든 관리자 페이지는 discourse/frontend/discourse/app/lib/sidebar/admin-nav-map.js at main · discourse/discourse · GitHubADMIN_NAV_MAP에 추가되어야 합니다. 각 항목은 최소한 다음 키를 가져야 합니다:

  • name - 링크의 고유 식별자, snake_case여야 합니다.
  • route 또는 href - routeadminUsers와 같은 Ember 라우트 식별자입니다. 관리자의 경우, 이들은 관리자 라우트 맵에서 정의됩니다. 대신 href를 사용할 수 있지만, route가 권장됩니다.
  • label 또는 text - label은 일반적으로 admin.config.page_name.title이어야 하는 I18n 키입니다 (아래 번역 섹션 참조). text를 사용하면 이미 번역된 텍스트가 됩니다.

다음과 같은 선택적 키도 제공할 수 있습니다:

  • description - 이것도 제공되는 것이 권장됩니다. 이는 I18n 키이며, 일반적으로 admin.config.page_name.header_description이어야 합니다.
  • icon - 이것도 권장되며, 사이드바에서 링크 옆에 표시됩니다.
  • routeModels - 라우트 매개변수의 경우를 위한 URL 데이터 배열. 예를 들어 adminCustomizeThemes에는 :type 라우트 매개변수가 있으므로 routeModels: ["components"]를 전달할 수 있습니다. 배열 항목은 라우트 매개변수가 나타나는 순서와 동일한 순서로 사용됩니다.
  • moderator: 이 페이지가 사이드바에서 모더레이터에게도 표시되어야 한다면 true로 설정합니다.
  • keywords: 사이드바 링크를 위한 |로 구분된 키워드 목록의 I18n 키로, 페이지를 필터링/검색할 때 추가적인 "검색 용이성"을 위해 사용됩니다.
  • links: 사이드바에서 페이지 아래에 있는 3차 라우트 목록입니다. 이들은 사이드바 자체에는 표시되지 않습니다. 이는 향후 관리자 검색 기능에 사용될 것입니다.
  • settings_areasettings_category: 페이지가 필터링된 사이트 설정 목록만 표시하는 경우, 이 중 하나를 채워야 합니다. 사이트 설정에 AdminAreaSettings에서 사용되는 area가 정의되어 있다면 settings_area를 사용해야 합니다. 페이지에서 설정의 전체 카테고리가 표시되고 AdminAreaSettings에서도 사용되는 경우, settings_category를 사용해야 합니다.
  • multi_tabbed: 페이지에 설정 탭 기타 탭이 있는 경우, 이 값을 true로 설정해야 합니다. 이는 관리자 검색 시스템을 위한 링크 생성에 도움이 됩니다.

번역

모든 설정 페이지의 제목과 헤더 설명은 아래 위치에 있어야 합니다:

  • admin
    • config
      • page_name
        • title: “페이지 제목”
        • header_description: “이 페이지는 xyz를 위한 것입니다”

여기서 이를 확인할 수 있습니다:

1. 브레드크럼

브레드크럼은 사용자가 관리자 인터페이스 내에서 현재 위치, 콘텐츠 구조 및 계층 구조를 이해하도록 돕는 탐색 도구입니다.

Admin > Breadcrumb > Trail
페이지 제목

:art: 디자인

구조

  1. Admin: 모든 브레드크럼 트레일의 시작 부분에 나타나며 /admin으로 연결되는 고정 접두사입니다.
  2. 링크: 같은 창에서 페이지를 엽니다.
  3. 구분자: 각 링크를 구분하는 angle-right 아이콘입니다.

사용법

사용할 때:

  • 모든 관리자 페이지에 존재합니다.
  • 콘텐츠(제목, 설명, 탭) 위에 위치합니다.
  • 현재 선택된 페이지를 표시합니다.

사용하지 않을 때:

  • 신규 또는 편집 라우트를 방문할 때

콘텐츠

  • 각 항목에는 해당 페이지로의 링크가 포함됩니다.
  • 현재 선택된 페이지를 표시합니다.

접근성

  • aria-label="Breadcrumb"가 있는 nav 요소가 순서 있는 목록을 감싸서 탐색 랜드마크를 제공합니다.
  • 현재 페이지임을 나타내기 위해 마지막 링크에 aria-current="page"를 적용합니다.
  • 자세한 내용은 WAI-ARIA Authoring Practices Breadcrumb Example을 참조하세요.

:hammer_and_wrench: 구현

DBreadcrumbsContainer 컴포넌트는 페이지 어딘가에 배치되어야 합니다:

<DBreadcrumbsContainer />

그런 다음, 라우트 또는 하위 라우트의 모든 컴포넌트에 추가되는 모든 DBreadcrumbsItem 요소는 이 컨테이너에 렌더링됩니다. 각 DBreadcrumbsItem에는 제공되어야 하는 @label@path가 있습니다:

<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
<DBreadcrumbsItem
  @path="/admin/plugins"
  @label={{i18n "admin.plugins.title"}}
/>
<DBreadcrumbsItem
  @path="/admin/plugins/{{@plugin.name}}"
  @label={{@plugin.nameTitleized}}
/>
```\n
Discourse AI 플러그인을 사용하여 시각적 예제로 이렇게 보입니다:

![An example of breadcrumbs|690x302, 75%](upload://2jbYauteEJY2b6OimlKlW1TDJyq.jpeg)

# 2. 페이지 헤더 및 제목

관리자 페이지의 상단 섹션으로, 페이지 제목과 함께 선택적 작업 및 설명을 포함합니다.

![A page title example|690x114](upload://iBs3rxNAlF6s0xrUj2XFIVvMsBC.png)

## :art: 디자인

**구조**

* **페이지 제목:** 페이지의 제목

* **페이지 설명:** 콘텐츠가 다루는 내용에 대한 도입부 또는 설명 *(선택적)*

* **주 작업:** 페이지 제목의 주 작업 *(선택적)*

* **보조 작업:** 페이지 제목의 보조 작업 버튼 설정 *(선택적)*

**사용법 및 콘텐츠**

* **페이지 제목:** 페이지의 주요 주제를 문장 체(senctence case)로 설명하기 위해 헤딩 레벨 1을 사용하세요. 일반적으로 I18n 번역은 `admin.config.your_page.title` 아래에 있어야 합니다.

* **페이지 설명:** `_italic_`, `**bold**`, `[link name](url)`과 같은 기본 마크다운 노드를 지원합니다.

* **주 작업:** `btn-primary`를 사용하세요. 아이콘을 포함하지 마세요. 일반적으로 I18n 번역은 `admin.config.your_page.header_description` 아래에 있어야 합니다.

* **보조 작업:** `btn-default` 버튼 설정을 사용하며, 주 작업이 존재할 때만 표시됩니다. 아이콘을 포함하지 마세요.

  > :point_right: 작업 버튼은 명확해야 합니다. 예를 들어, 모호성을 줄이기 위해 단순히 "추가" 대신 "이모지 추가"와 같은 설명적인 라벨을 사용하세요.

## :hammer_and_wrench: 구현

여기서는 `DPageHeader` 컴포넌트가 사용됩니다. 이는 `@titleLabel`, `@descriptionLabel`, `@learnMoreUrl`, `@shouldDisplay` 인수를 받아들입니다. 이는 Ember에서 명명된 `yields`를 사용하여 콘텐츠에 5개의 명명된 블록을 제공합니다:

1. `breadcrumbs` - 페이지를 위한 추가 `DBreadcrumbsItem` 컴포넌트는 여기에 배치해야 합니다.
2. `actions` - 제목 오른쪽의 버튼을 정의하는 데 사용됩니다. `Default`, `Primary`, `Danger`, `Wrapped` 버튼을 렌더링하는 데 사용할 수 있는 `actions`라는 이름의 객체를 yield합니다.
3. `title` - `@titleLabel`의 대안으로, 헤딩 내부에 사용자 정의 마크업을 허용합니다.
4. `drawer` - `@showDrawer`가 true일 때 표시되는 선택적 접이식 드로어 섹션입니다.
5. `tabs` - `NavItem` 컴포넌트를 사용하여 페이지의 탭을 정의하는 데 사용됩니다. 필요하지 않다면 `@hideTabs`를 사용하여 헤더의 이 부분을 제거할 수 있습니다.

완전한 예제는 아래와 같습니다:

```gjs
<DPageHeader
  @titleLabel={{i18n "admin.config.backups.title"}}
  @descriptionLabel={{i18n "admin.config.backups.header_description"}}
  @learnMoreUrl="https://meta.discourse.org/t/create-download-and-restore-a-backup-of-your-discourse-database/122710"
>
  <:breadcrumbs>
    <DBreadcrumbsItem
      @path="/admin/backups"
      @label={{i18n "admin.backups.title"}}
    />
  </:breadcrumbs>
  <:actions as |actions|>
    <actions.Primary
      @action={{routeAction "showStartBackupModal"}}
      @title="admin.backups.operations.backup.title"
      @label="admin.backups.operations.backup.label"
      class="admin-backups__start"
    />
  </:actions>
  <:tabs>
    <NavItem
      @route="admin.backups.settings"
      @label="settings"
      class="admin-backups-tabs__settings"
    />
    <NavItem
      @route="admin.backups.index"
      @label="admin.backups.menu.backup_files"
      class="admin-backups-tabs__files"
    />
    <NavItem
      @route="admin.backups.logs"
      @label="admin.backups.menu.logs"
      class="admin-backups-tabs__logs"
    />
    <PluginOutlet @name="downloader" @connectorTagName="div" />
  </:tabs>
</DPageHeader>

브라우저 탭의 페이지 제목은 titleToken 기능을 사용하여 Ember 라우트에서 처리됩니다. 라우트에서 이 기능이 사용될 때마다 브라우저 탭 제목의 끝에 토큰이 추가됩니다. 이것이 작동하려면 반드시 DiscourseRoute 클래스를 사용하여 라우트를 확장해야 하며, Ember의 일반 Route를 사용해서는 안 됩니다:

titleToken() {
  return i18n("admin.config.backups.title");
}

:point_right: 페이지 헤더는 3차 라우트를 지원하기 위해 /new/edit 경로에 대해 자동으로 숨겨집니다. @shouldDisplay 인수를 사용하여 오버라이드할 수 있습니다.

3. 탭

설정 또는 기능의 더 깊은 수준에 대한 액세스를 제공하는 선택적 탐색입니다. 우리는 이것을 “3차” 페이지 또는 탐색이라고도 부릅니다.

:art: 디자인

우리는 같은 컨텍스트 내에서 서로 관련이 있지만 다른 뷰를 전환하는 데 탭을 사용합니다.

사용법

  • 주 탐색에는 사용되지 않습니다.
  • 한 번에 하나만 활성 상태입니다.

:hammer_and_wrench: 구현

페이지 헤더 세부 사항을 참조하세요. 탭은 DPageHeader 컴포넌트에서 정의됩니다.

:white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square:

4. 개요/섹션 랜딩 페이지

사이드바가 접히거나 모바일 환경에서 특히 섹션의 콘텐츠를 사용자에게 표시할 수 있게 합니다.

:art: 디자인

구조
그리드 시스템을 사용하여 세 개의 동일한 열 레이아웃을 사용합니다. 작은 화면에서 이러한 열은 세로로 쌓입니다.

디자인 및 사용법

  • 브레드크럼(Admin > Community > Overview)을 통해 액세스할 수 있습니다.
  • 각 섹션에는 하나씩 있어야 하지만, 플러그인(설치된 항목을 표시)과 보고서(페이지가 하나만 있음)는 예외입니다.
  • 항목에는 다음이 있습니다:
    • 이름 - 섹션 링크와 동일
    • 설명 - 페이지가 무엇에 대한지에 대한 짧은 설명
    • 아이콘 - 사이드바에 사용되는 동일한 아이콘

:hammer_and_wrench: 구현

코드 스니펫 또는 토픽/GitHub 링크

5. 페이지 콘텐츠

설정, 구성 및 기타 콘텐츠가 표시되고 상호 작용되는 관리자 페이지의 주요 영역입니다.

:art: 디자인

구조
그리드 시스템을 사용하여 2/3 + 1/3 레이아웃을 사용합니다. 주요 섹션은 2/3를 차지하고 보조 섹션은 공간의 1/3를 차지합니다. 작은 화면에서 이러한 열은 세로로 쌓입니다.

  • 설정 영역: 페이지 콘텐츠 내에서 설정 및 구성에 전념하는 특정 섹션입니다.
  • 도움말/참조/인셋: 가이드, 문서 또는 추가적인 컨텍스트 정보를 제공하는 페이지 콘텐츠 내 영역입니다. (선택적)

디자인 및 사용법

  • 유사한 설정과 작업을 카드로 그룹화하세요.
  • 주요(2/3) 섹션은 주요 설정에, 보조(1/3) 섹션은 추가 정보나 도움이 되는 컨텍스트에 사용되도록 주요/보조 레이아웃을 구성하세요.
  • 보조 섹션이 없으면 주요 섹션의 너비를 동일하게 유지하세요.

콘텐츠

:hammer_and_wrench: 구현

코드 스니펫 또는 GitHub 링크

5.a. 서브헤드

서브헤드는 섹션 아래, 일반적으로 탭 아래에서 콘텐츠를 나누기 위해 사용되는 보조 헤딩입니다.

구조

  • 서브헤딩: 콘텐츠가 다루는 내용에 대한 서브헤딩 (선택적)
  • 주 작업: 서브헤딩의 주 작업 (선택적)
  • 보조 작업: 서브헤딩의 보조 작업 버튼 설정 (선택적)

사용법 및 콘텐츠

  • 서브헤딩: 관련 콘텐츠의 주요 주제를 설명하기 위해 헤딩 레벨 2를 사용하세요. 다음 경우에만 포함하세요:

    • 주 작업 버튼이 있거나,
    • 섹션을 설명하는 설명이 있는 경우.
  • 주 작업: btn-primary를 사용하세요. 아이콘을 포함하지 마세요.

  • 보조 작업: btn-default 버튼 설정을 사용하며, 주 작업이 존재할 때만 표시됩니다. 아이콘을 포함하지 마세요.

    :point_right: 작업 버튼은 명확해야 합니다. 예를 들어, 모호성을 줄이기 위해 단순히 “추가” 대신 "이모지 추가"와 같은 설명적인 라벨을 사용하세요.

:hammer_and_wrench: 구현

이것은 DPageHeader와 유사하며, DPageSubheader 컴포넌트가 있습니다. 주요 차이점은 actions를 위한 단일 명명된 yield만 있다는 것입니다.

  1. actions - 제목 오른쪽의 버튼을 정의하는 데 사용됩니다. Default, Primary, Danger, Wrapped 버튼을 렌더링하는 데 사용할 수 있는 actions라는 이름의 객체를 yield합니다.
<DPageSubheader @titleLabel="admin.config.backups.subheader.title">
  <:actions>
    <actions.Primary
      @action={{routeAction "showStartBackupModal"}}
      @title="admin.backups.operations.backup.title"
      @label="admin.backups.operations.backup.label"
      class="admin-backups__start"
    />
  </:actions>
</DPageSubheader>

5.b. 설정 영역

설정 영역은 카드 또는 섹션으로 구성됩니다. 카드는 관련 정보와 작업을 그룹화하는 데 유용하며, 사용자가 콘텐츠를 더 쉽게 스캔하고 우선순위를 정하는 데 도움이 됩니다.

:art: 디자인

카드

카드는 2px의 테두리 반경으로 설정되고 --secondary 배경을 사용합니다. 또한 --primary-low의 1px 솔리드 테두리와 콘텐츠 주위의 20px 패딩을 가집니다.

기본 변형

아코디언 변형

디자인 및 사용법

  • 관련 정보를 그룹화하세요.
  • 관리자와 모더레이터가 가장 중요한 사항을 먼저 볼 수 있도록 정보를 표시하세요.
  • 카드의 용도를 명확히 설명하는 헤딩을 사용하세요.
  • 필요할 경우 복잡한 카드를 여러 섹션으로 나누세요.

기본 변형

  • 카드당 하나의 주 호출 작업(CTA)에 집중하세요.
  • 다음 단계를 위해 주 호출 작업을 카드 하단에 배치하세요.

아코디언 변형

  • "모두 보기"와 같은 선택적 작업을 위해 카드의 오른쪽 위 모서리를 사용하세요.

콘텐츠

  • 모든 양식은 문서에 설명된 코어의 FormKit ember 컴포넌트를 사용해야 합니다.

  • 카드 헤더는 문장 체(senctence case)여야 합니다.

    :white_check_mark: 이렇게 하세요 :cross_mark: 이렇게 하지 마세요
    일반 설정 General Settings
    연락처 정보 CONTACT INFORMATION

:hammer_and_wrench: 구현

이 모든 카드에 사용해야 하는 AdminConfigAreaCard 컴포넌트가 있습니다. 현재 이것은 @translatedHeading@heading 인수만 가지고 있지만, 미래에는 작업을 추가하고 접을 수 있게 하는 등의 기능이 추가될 수 있습니다:

<AdminConfigAreaCard
  @heading="admin.config_areas.about.general_settings"
  class="admin-config-area-about__general-settings-section"
>
  <AdminConfigAreasAboutGeneralSettings
    @generalSettings={{this.generalSettings}}
    @setGlobalSavingStatus={{this.setSavingStatus}}
    @globalSavingStatus={{this.saving}}
  />
</AdminConfigAreaCard>

내장 사이트 설정

이 섹션은 진행 중입니다.

5.c. 도움말 인셋

이 섹션은 페이지 콘텐츠 내에서 추가적인 가이드, 문서 또는 컨텍스트를 제공합니다.

v1

:art: 디자인

디자인 및 사용법

  • 페이지 콘텐츠에 대한 관련 문서 또는 가이드를 표시하여 유용한 정보를 제공하세요.
  • 쉽게 인식할 수 있도록 헤딩에 아이콘을 포함하세요.
  • 이 섹션을 보조(1/3) 레이아웃 영역에 배치하세요.

콘텐츠

  • 헤더는 문장 체(senctence case)여야 합니다.

:hammer_and_wrench: 구현

코드 스니펫 또는 토픽/GitHub 링크

5.d. 테이블

테이블은 정보를 셀, 열, 행의 그리드로 표시하여 관리자가 항목을 빠르게 스캔하고 조치를 취할 수 있게 합니다.

:art: 디자인

사용법

  • 각 항목이 동일한 속성을 공유하는 구조화된 콘텐츠를 표시하는 데 테이블을 사용하세요.
  • 관리자가 데이터 세트를 검토하고, 활성화/비활성화하고, 편집하고, 삭제할 수 있도록 하세요.
  • 시간이 지남에 따라 계속 성장할 데이터 세트에 적합합니다.

디자인

  • 콘텐츠를 시각적으로 분리하기 위해 행 사이에 수평선을 사용하세요. 마지막 행도 포함합니다. 테이블 주위에 테두리나 프레임을 사용하여 그물처럼 보이게 하는 것을 피하세요.
  • 열 사이에 수직선을 적용하지 마세요. 수직선이 없는 테이블은 일반적으로 스캔하고 읽기가 더 쉽습니다.

추가 작업

  • 행 작업: 각 테이블 행의 가장 오른쪽 열에 추가 작업을 포함하세요.
    • 두 개 이상의 인터랙티브 요소가 있는 경우, 주 작업(예: “편집”)은 텍스트 버튼이어야 하고, "삭제"를 포함한 모든 기타 행 작업은 [...] 드롭다운에 그룹화되어야 합니다. 드롭다운 메뉴의 아이콘은 시각적으로 요소를 나누기 위해 권장됩니다.
    • 주 작업이 없고 “삭제” 작업만 있는 경우, btn-default 스타일의 인라인 “삭제” 텍스트 버튼을 사용하세요.
    • 행에 해당하는 Show/Edit 페이지로 관리자를 직접 연결하는 링크로 주요 열의 텍스트(일반적으로 d-table__cell --overview)를 감싸서 빠른 액세스를 제공해야 합니다.
  • 삭제 확인: 모든 “삭제” 버튼은 작업을 수행하기 전에 확인을 표시해야 합니다.

콘텐츠

  • 헤더: 테이블 헤더는 아래 열을 식별하는 맨 위 행입니다. 데이터가 비설명적이거나 모호한 경우 특히 명확성을 제공합니다. 헤더는 짧고, 설명적이며, 관련성이 있어야 하며, 제목 체(title case)를 사용해야 합니다. 아래 행의 콘텐츠에 비해 너무 긴 헤더를 피하세요.
  • 열: 우선순위 순서로 열을 정렬하거나 데이터로 일관된 이야기를 들려주는 방식으로 정렬하세요. 콘텐츠에 따라 열의 크기를 조정하세요. 작은 콘텐츠에는 좁은 열을, 단락에는 넓은 열을 사용하세요.
  • 행: 행은 데이터 표현을 향상시키기 위해 텍스트, 버튼, 링크, 아이콘을 지원해야 합니다.
  • 데이터 없음: 빈 목록은 AdminConfigAreaEmptyList 컴포넌트를 사용하여 CTA 버튼과 라벨을 포함하여 사용자가 새 레코드 생성으로 유도되도록 해야 합니다.

:hammer_and_wrench: 구현

테이블이 모바일과 데스크톱에서 잘 작동하도록 해야 하는 작은 CSS 클래스 컬렉션이 있습니다.

<table> 요소에는 d-table 클래스가 적용되어야 합니다.

<thead> 요소에는 d-table__header 클래스가 적용되어야 합니다.

<tr> 요소에는 d-table__row 클래스가 적용되어야 합니다.

많은 설명 텍스트를 포함하는 <td> 요소(보통 가장 왼쪽 열)에는 d-table__cell --overview 클래스를 사용해야 합니다. 기타 모든 셀에는 d-table__cell --detail을 사용해야 합니다.

d-table__cell --overview 클래스가 있는 <td> 요소는 행에 해당하는 Edit/Show 페이지로 관리자를 직접 연결하는 링크로 내부 행 콘텐츠를 감쌀 수 있습니다. 이 링크는 이 구조를 따르고 d-table__overview-link CSS 클래스가 적용되어야 합니다. 이상적으로는 LinkTo 컴포넌트를 사용해야 하지만, getURL이 함께 사용되는 한 <a>도 괜찮습니다.

여기서 이름 부분에 d-table__overview-name 클래스가 적용되어야 하지만, 설명에는 적용되지 않아야 합니다.

<td class="d-table__cell --overview">
  <LinkTo
    class="d-table__overview-link"
    @route="adminPlugins.show.explorer.details"
    @model={{query.id}}
  >
    <strong class="query-name d-table__overview-name">{{query.name}}</strong>
    {{#if query.is_default}}
      <span class="query-badge">{{i18n
          "explorer.default_query"
        }}</span>
    {{/if}}
    <div class="query-desc">{{query.description}}</div>
  </LinkTo>
</td>
<td class="d-table__cell --overview">
  <a class="d-table__overview-name admin-flag-item__name d-table__overview-link" href={{this.editUrl}}>
    {{@flag.name}}
  </a>
</td>

각 행의 버튼을 감싸는 <td> 요소에는 d-table-cell --controls CSS 클래스가 적용되어야 합니다. 이렇게 하면 버튼이 정렬됩니다. 각 버튼에는 btn-small 클래스도 적용되어야 합니다.

모바일의 경우, d-table-cell --overview를 제외한 각 <td> 요소에는 해당 열의 <th>와 동일한 I18n 라벨을 포함하는 d-table__mobile-label 클래스가 있는 <div>를 포함해야 합니다:

<td class="d-table__cell --detail">
  <div class="d-table__mobile-label">
    {{i18n "chat.incoming_webhooks.emoji"}}
  </div>
  {{replaceEmoji webhook.emoji}}
</td>

이것은 모바일에서 테이블 행을 더 읽기 쉬운 카드 기반 형식으로 표시합니다:

[...] 드롭다운 메뉴의 경우, DMenuDropdownMenu와 함께 사용해야 합니다. 다음은 예제입니다:

<DMenu
  @identifier="backup-item-menu"
  @title={{i18n "more_options"}}
  @icon="ellipsis-vertical"
  class="btn-small"
>
  <:content>
    <DropdownMenu as |dropdown|>
      <dropdown.item>
        <DButton ...[button args here] />
      </dropdown.item>
      <dropdown.item>
        <DButton ...[button args here] />
      </dropdown.item>
    </DropdownMenu>
  </:content>
</DMenu>

테이블 행의 토글은 DToggleSwitch 컴포넌트를 사용하여 처리됩니다:

<DToggleSwitch
  @state={{this.enabled}}
  class="admin-flag-item__toggle {{@flag.name_key}}"
  {{on "click" (fn this.toggleFlagEnabled @flag)}}
/>

모든 것을 합쳐서 여기는 관리자 테이블의 최소 예제입니다:

 <table class="d-table">
    <thead class="d-table__header">
      <tr>
        <th>Name</th>
        <th>Description</th>
        <th></th>
      </tr>
    </thead>
    <tbody>
      <tr class="d-table__row">
        <td class="d-table__cell --overview">
          <LinkTo @route="admin.exampleRoute" class="d-table__overview-link">
            <span class="d-table__overview-name">Example Item</span>
            <span class="d-table__overview-about">A short description</span>
          </LinkTo>
        </td>
        <td class="d-table__cell --detail">
          <span class="d-table__mobile-label">Description</span>
          Some detail content here
        </td>
        <td class="d-table__cell --controls">
          <div class="d-table__cell-actions">
            <button class="btn btn-default btn-small">Edit</button>
          </div>
        </td>
      </tr>
    </tbody>
  </table>

5.e 3차 라우트

3차 라우트는 설정 영역에서만 도달할 수 있는 라우트입니다. 이들은 플래그와 같은 편집/신규 라우트의 형태를 띠는 경우가 많습니다:

대부분의 경우 FormKit를 사용하는 양식이 여기에 배치됩니다.

이것을 위해 표준 RESTful 라우트를 사용하세요:

Action Path
New <resource>/new
Edit <resource>/:id/edit

그리고 라우트가 백엔드에서도 라우팅되도록 하세요. (신규 또는 편집 페이지를 새로 고침해도 오류가 발생하지 않아야 합니다.)

:art: 디자인

사용법

  • 주 라우트 또는 테이블 내에서 인라인 양식을 갖는 것보다 이러한 3차 라우트를 갖는 것이 좋습니다. 독립적인 편집 및 신규 라우트가 가장 좋습니다. 쉽게 링크할 수 있기 때문입니다.
  • 페이지 UI의 상단 부분(브레드크럼, 페이지 헤더 및 서브헤더)을 표시하지 마세요.
  • 대신, 관리자가 주요 설정 영역으로 돌아가도록 허용하는 단일 “X로 돌아가기” 링크를 표시하세요.
  • 페이지의 콘텐츠는 최소 하나의 AdminConfigAreaCard로 감싸야 합니다.
  • 페이지의 모든 부제목은 설정 영역 카드로 수행되어야 합니다.

:hammer_and_wrench: 구현

페이지 상단에 배치하여 뒤로 갈 수 있는 간단한 BackButton 컴포넌트가 있습니다:

<BackButton
  @route="adminConfig.flags"
  @label="admin.config_areas.flags.back"
/>

6. 필터링된 설정 구성 페이지

우리 관리자 인터페이스의 설정 페이지 중 많은 부분은 필터링된 사이트 설정의 간단한 목록입니다. 이를 통해 관리자는 /admin/config/about/와 같은 더 전문적인 설정 페이지를 만들 때까지 전체 “모든 사이트 설정” 목록에 압도되지 않고 관련 설정 그룹을 찾을 수 있습니다.

:hammer_and_wrench: 구현

이러한 라우트 중 하나를 추가하려면 몇 가지 사항이 필요합니다. 먼저, site_settings.yml의 최상위 키인 사이트 설정의 전체 category(예: branding:)를 표시하거나 설정 area를 사용할 수 있습니다.

사이트 설정은 여러 areas에 존재할 수 있으며, 같은 페이지에 하나 이상을 표시할 수 있습니다.

  1. adminConfig 아래에 관리자 라우트 맵에 라우트를 추가하세요. 예를 들어:
this.route("trustLevels", { path: "/trust-levels" }, function () {
  this.route("settings", {
    path: "/",
  });
});
  1. 새로운 라우트 .js 파일을 추가하세요. 파일은 새로운 라우트의 이름에 따라 frontend/discourse/admin/routes/admin-config/localization.js와 같은 경로와 일치해야 합니다. 이것은 AdminConfigWithSettingsRoute를 상속하고 titleToken()을 포함해야 합니다.
import { i18n } from "discourse-i18n";
import AdminConfigWithSettingsRoute from "../admin-config-with-settings-route";

export default class AdminConfigLocalizationRoute extends AdminConfigWithSettingsRoute {
  titleToken() {
    return i18n("admin.config.localization.title");
  }
}
  1. 컨트롤러를 추가하세요. 이것은 주로 설정 검색 및 필터링을 활성화하기 위한 것입니다. AdminAreaSettingsBaseController를 상속해야 합니다:
import AdminAreaSettingsBaseController from "discourse/admin/controllers/admin-area-settings-base";

export default class AdminConfigLocalizationSettingsController extends AdminAreaSettingsBaseController {}
  1. 마지막으로, .gjs 형식의 라우트 템플릿 파일을 frontend/discourse/admin/templates/admin-config/localization/settings.gjs와 같은 경로에 추가하세요. 여기에는 정상적인 DPageHeader와 브레드크럼이 포함되어야 하지만, 설정을 표시하려면 AdminAreaSettings가 필요합니다.
<div class="admin-config-page__main-area">
  <AdminAreaSettings
    @showBreadcrumb={{false}}
    @area="localization"
    @path="/admin/config/localization"
    @filter={{@controller.filter}}
    @adminSettingsFilterChangedCallback={{@controller.adminSettingsFilterChangedCallback}}
  />
</div>

여기서 변경해야 하는 중요한 사항은 @path@area(또는 대체로 @categories)입니다. 앞서 언급했듯이, 표시하려는 사이트 설정 영역 또는 카테고리로 채워 넣으세요.

7. 일반 가이드라인

  • URL 슬러그는 단어 내 공백을 나타내기 위해 언더스코어(_) 대신 하이픈(-)을 사용해야 합니다.

  • 관리자 인터페이스의 모든 텍스트는 여기에概述된 텍스트 서식 가이드라인을 따라야 합니다:

8. 플러그인

일부 플러그인은 사이트 설정의 컬렉션만 갖는 것이 아니라 플러그인에 대한 심층적인 구성 UI(예: AI, 자동화, 게이미피케이션)가 필요합니다. 예를 들어, 여기는 Discourse AI입니다:

이것을 사용하는 플러그인의 몇 가지 예시는 다음과 같습니다:

:art: 디자인

사용법

  • 독립적인 플러그인 UI를 만들 때 일반 관리자 UI 가이드라인을 따라야 합니다.

:hammer_and_wrench: 구현

Ember 라우팅

  • 모든 라우트 템플릿은
    admin/assets/javascripts/discourse/templates/admin-plugins/show/ 아래에 있어야 합니다.
  • 모든 라우트 js 파일은 admin/assets/javascripts/discourse/routes/ 아래에 있어야 하며
    admin-plugins-show- 접두사가 붙어야 합니다.
  • 관리자 라우트 맵은 admin-PLUGIN-NAME-plugin-route-map.js와 같은 파일에 있어야 합니다.
  • 라우트 맵은 다음과 같은 구조를 가져야 합니다. 중요한 부분은
    resourceadmin.adminPlugins.show를 사용한다는 것입니다.
export default {
  resource: "admin.adminPlugins.show",

  path: "/plugins",

  map() {
    this.route("discourse-ai-personas", { path: "ai-personas" }, function () {
      this.route("new");
      this.route("show", { path: "/:id" });
    });
  },
};
  • 이것이 어떻게 작동하는지에 대한 현재 예제는 Discourse AI 플러그인에서 볼 수 있으며, /admin/plugins/discourse-ai/ai-personas로 이동하면 됩니다.
  • 하위 라우트를 정의하지 않는 "상위
10개의 좋아요

And

still don’t work. I think the second one is -23 instead of -24

5개의 좋아요

So glad to finally see this up on meta. Months of work went into this, and we are going to be using it to standardize the UI and navigation of every page in the admin interface.

Should we maybe just remove that table of contents and rely on discotoc instead? I think that would be less fragile, though I do like seeing the table of contents at the top of the post.

7개의 좋아요

Thanks @Moin - all fixed!

I’ve made this change, otherwise it’s simply a duplicated table of contents.

4개의 좋아요

A post was split to a new topic: Display username in browser tab when on user admin