Discourse 플러그인 개발 - 5부 - 관리자 인터페이스 추가

이전 튜토리얼: Developing Discourse Plugins - Part 4 - Setup git


때로는 사이트 설정만으로는 플러그인이 원하는 대로 작동하는 데 필요한 관리자 인터페이스가 충분하지 않을 수 있습니다. 예를 들어, discourse-akismet 플러그인을 설치하면 Discourse의 관리자 플러그인 섹션에 탐색 항목이 추가되는 것을 눈치챘을 수 있습니다:

이 튜토리얼에서는 플러그인을 위한 관리자 인터페이스를 추가하는 방법을 보여드리겠습니다. 제 플러그인 이름은 제가 가장 좋아하는 컴퓨터 게임 중 하나를 기념하여 purple-tentacle로 지었습니다. 진심으로, 그 게임을 정말로 사랑합니다!

관리자 루트 설정하기

튜토리얼 이전 파트에서 했던 것처럼 plugin.rb 파일을 추가하는 것부터 시작하겠습니다.

plugin.rb

# name: purple-tentacle
# about: A sample plugin showing how to add a plugin route
# version: 0.1
# authors: Robin Ward
# url: https://github.com/discourse/purple-tentacle

add_admin_route 'purple_tentacle.title', 'purple-tentacle'

Discourse::Application.routes.append do
  get '/admin/plugins/purple-tentacle' => 'admin/plugins#index', constraints: StaffConstraint.new
end

add_admin_route 라인은 이 플러그인이 /admin/plugins 페이지에 링크가 필요하다는 것을 Discourse에 알립니다. 그 제목은 i18n 번역 파일의 purple_tentacle.title이 될 것이며, purple-tentacle 루트로 링크됩니다.

그 아래 라인들은 플러그인을 위한 서버 측 루트 매핑을 설정합니다. Discourse가 가정하는 사항 중 하나는 프론트엔드의 거의 모든 루트에 데이터를 제공하는 서버 측 루트가 있다는 것입니다. 이 예제 플러그인의 경우 실제로 백엔드에서 데이터를 받을 필요가 없지만, 사용자가 /admin/plugins/purple-tentacle을 직접 방문할 경우 무언가를 제공하도록 Discourse에 알려야 합니다. 이 라인은 단순히 '사용자가 서버 측에서 해당 URL을 직접 방문하면 기본 플러그인 콘텐츠를 제공하세요!'라고 말합니다.

(이것이 혼란스럽다면 너무 걱정하지 마세요, 서버 측 작업을 처리하는 미래의 튜토리얼에서 다시 다룰 것입니다.)

다음으로, 사용자가 /admin/plugins/purple-tentacle 경로를 방문할 때 표시될 템플릿을 추가하겠습니다. 사용자가 버튼을 클릭하면 보라색 문어의 애니메이션 GIF가 표시되는 버튼만 포함됩니다:

assets/javascripts/discourse/templates/admin/plugins-purple-tentacle.gjs

import DButton from "discourse/components/d-button";

<template>
  {{#if @controller.tentacleVisible}}
    <div class="tentacle">
      <img src="https://eviltrout.com/images/tentacle.gif" />
    </div>
  {{/if}}

  <div class="buttons">
    <DButton
      @label="purple_tentacle.show"
      @action={{@controller.showTentacle}}
      @icon="eye"
      @id="show-tentacle"
    />
  </div>
</template>

handlebars의 기본을 배웠다면 템플릿은 이해하기 꽤 쉬울 것입니다. <DButton />은 라벨과 아이콘이 있는 버튼을 표시하기 위해 Discourse에서 사용하는 컴포넌트입니다.

새로운 템플릿을 연결하려면 루트 맵을 생성해야 합니다:

assets/javascripts/discourse/purple-tentacle-route-map.js

export default {
  resource: "admin.adminPlugins",
  path: "/plugins",
  map() {
    this.route("purple-tentacle");
  },
};

루트 맵은 플러그인이 ember 애플리케이션에 루트를 추가할 수 있도록 discourse에 추가한 것입니다. map() 내부의 문법은 Ember의 라우터와 매우 유사합니다. 이 경우 우리의 루트 맵은 매우 간단하며, /admin/plugins 아래에 purple-tentacle이라는 하나의 루트만 선언합니다.

마지막으로, 번역 문자열을 추가하겠습니다:

config/locales/client.en.yml

en:
  js:
    purple_tentacle:
      title: "Purple Tentacle"
      show: "Show Purple Tentacle"

개발 서버를 다시 시작하면 /admin/plugins를 방문하여 우리의 링크를 볼 수 있어야 합니다. 클릭하면 보라색 문어를 표시하는 버튼을 볼 수 있습니다:

불행히도, 버튼을 클릭하면 아무 일도 일어나지 않습니다 :frowning:

개발자 콘솔을 보면 이것이 왜 그런지에 대한 단서를 제공하는 오류를 볼 수 있어야 합니다:

Uncaught Error: Nothing handled the action 'showTentacle'`

아, 네, 그 이유는 템플릿에서 몇 가지 것에 의존하고 있기 때문입니다:

  1. 사용자가 버튼을 클릭할 때 컨트롤러에서 showTentacle이 호출되어야 합니다.
  2. showTentacle은 이미지가 표시되도록 tentacleVisible 속성을 true로 설정해야 합니다.

아직 Ember의 컨트롤러 가이드를 읽지 않았다면, 이제 읽는 것이 좋은时机입니다. purple-tentacle 템플릿을 위한 컨트롤러를 구현하여 이 로직을 처리할 것이기 때문입니다.

다음 파일을 생성하세요:

assets/javascripts/discourse/controllers/admin-plugins-purple-tentacle.js

import Controller from "@ember/controller";
import { action } from "@ember/object";
import { tracked } from "@glimmer/tracking";

export default class AdminPluginsPurpleTentacleController extends Controller {
  @tracked tentacleVisible = false;

  @action
  showTentacle() {
    this.tentacleVisible = true;
  }
}

이제 페이지를 새로고침하면 버튼을 클릭했을 때 애니메이션 캐릭터가 표시됩니다!

클릭했을 때 문어를 숨기는 버튼을 추가하는 것은 독자를 위한 추가 연습으로 남겨두겠습니다 :smile:

이 플러그인의 버전을 작동시키는 데 어려움을 겪고 있다면, github에 올렸습니다.


시리즈의 나머지

Part 1: Plugin Basics
Part 2: Plugin Outlets
Part 3: Site Settings
Part 4: git setup
Part 5: This topic
Part 6: Acceptance tests
Part 7: Publish your plugin


This document is version controlled - suggest changes on github.

28개의 좋아요

Hm, doesn’t seem to work on my local side… did anyone face the same problem?

What’s the problem? If you install the purple tentacle plugin does it not work?

edit: issue resolved. it works!

@eviltrout nope, it doesn’t work. I believe @ladydanger is also facing the same problem.
nothing appears in the site settings or plugins tabs.
I tried both following the instructions as well as symlink-ing your plugin (dl-ed from github).
I then tried to create server.en.yml, client.en.yml, settings.yml following the format of other plugins, but the image wouldn’t render anyhow.

probably something wrong with the ..route-map.js.es6 or config files.

interestingly enough, akismet’s plugin does work for me.


One issue that keeps on biting me is that I still need to do

rm -fr /tmp/cache

To kick away some odd caching we have in some cases.

1개의 좋아요

@eviltrout

oh now this is an interesting finding - apparently our ad plugins were interfering with the purple-tentacle plugin. or the other way round. it works now, after having removed the ad plugin files.

  • it now works with our ad plugins! possibly some minor bug yesterday. all is good!

@sam, what’s the difference between rm -rf tmp and rm -fr /tmp/cache

I usually only delete the cache directory, no need to nuke the entire tmp directory.

2개의 좋아요

Are you sure it was a plugin conflict?

I copied it into my localhost plugin folder and started up the VM without removing the temp folder and got the same results as you posted.

I was puzzled to see the route in object dot notation but ignored that.

I then started up the VM and did remove the temp folder and all was OK

1개의 좋아요

Actually, sometimes you need just cache, and sometimes you need the whole tmp directory.

Maybe we could have an initializer that checks the timestamps on the plugin folders and nukes tmp if they were updated (dev only).

3개의 좋아요

One thing I really should have warned you about is I started raising errors on ember deprecations. We are really working towards upgrading our version of Ember soon and I wanted to make sure developers caught them. It’s possible your plugin has a deprecation or two and is now raising an error with the latest version of Discourse.

If you can’t figure out how to fix the deprecation, it’s okay to temporarily disable it in the Discourse working directory you are using. Try removing these two lines.

2개의 좋아요

No clue what I’m doing wrong here, but it shows up like this:

It must be the /config/locales/en.yml not loading, but why?

I put this file structure in the root of the plugin directory. Verified it’s there, nuked the tmp, restart rails.

en:
  js:
    purple_tentacle:
      title: "Purple Tentacle"
      show: "Show Purple Tentacle"
1개의 좋아요

I was a bit surprised to see the file named “en.yml” but figured either eviltrout knew something I didn’t (which I’m sure he does … anyway) or that maybe something had changed the way things worked.

I’m guessing that what Robin meant was client,en.yml because that works for me.

the file goes in the plugins config/locales folder

4개의 좋아요

Thanks I’ll try that after I get my dev environment setup on the xeon, went through hell getting ubuntu 16.04 to work right with my hardware. Turned out it wasn’t the server mobo, but the new nvidia card.

Yea I meant I put all the directories listed hierarchically starting with the plugins folder. Was wondering if for some reason that last file went elsewhere.

Same thing.

I tried naming the file client,en.yml, client.en.yml, and creating a client folder placing en.yml inside it.

Same result

Did you stop vagrant, clear the cache
$> rm -rf tmp
and restart vagrant?

I’m not using vagrant, yes I nuked tmp, restart rails.

This is a bit too annoying, and not a big deal. I’m going to move forward, but thanks for the efforts.

I have a feeling you may have the folder structure wrong, or maybe the naming. Mine is like

/discourse
../plugins
..../{yourpluginname}
......plugin.rb
....../config
........settings.yml
......../locales
..........client.en.yml
..........server.en.yml
....../assets
......../javascripts
........../discourse
............{yourpluginname}-route-map.js.es6
............/controllers
..............admin-plugins-{yourpluginname}.js.es6
............/templates
............../admin
................plugins-{yourpluginname}.hbs
1개의 좋아요

That’s the file structure I have.

I don’t see a point in getting stuck on this, already hacked together a couple of rails sites and trying to absorb as much as possible.

Just going to leave this as some simple error on my part that I’ll come look back at later on and probably realize right away what it was.

Thanks, thou

Another mistake of mine! I’ve updated the OP, thanks.

2개의 좋아요

Is there any way I can change a global plugin setting, say, a siteSetting, from here?
I need admins to be able to use this interface to add data into a global array.