제목이 미리 채워지면 편집기에 포커스

이런 형태의 URL을 가지고 있습니다:

https://forum.example.com/new-message?groupname=moderators&title=Help+me+with+some+task+please

이 링크를 제 사이트에 배치하여 사용자가 포럼으로 이동해 질문을 할 수 있도록 합니다. title 값에 다양한 내용을 넣어 사용자가 궁금해하는 주제를 제목에 미리 입력해 주는데, 에디터가 포커스되기를 원합니다.

이를 어떻게 수정할 수 있는지 알아보던 중 focusTarget 정의가 포함된 composer.js 파일을 발견했습니다. title이 전달된다면 이 동작을 지원하도록 수정하는 것은 꽤 쉬울 것 같습니다.

문제는 focusTarget이 실제로 어디서 호출되는지 찾을 수 없다는 것입니다. 저는 수년 동안 프로그래밍을 해왔지만 Ember는 처음이고, JavaScript 프로그래밍도 상대적으로 적게 해왔습니다.

이 문제를 어떻게 접근해야 할지 조언을 주시면 감사하겠습니다 (적절한 매뉴얼에 대한 포인터가 포함된 rtfm도 환영합니다).

감사합니다.

이것이 당신이 찾고 있는 것 같습니다:

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/components/composer-editor.js#L159-L164

focusTarget 값이 변경될 때마다 이 setFocus 함수가 호출됩니다.

네, 그 코드가 동작하게 만드는 부분입니다. 이 메서드가 제목을 가져오도록 하기 위해 어떤 코드를 수정해야 하는지, 그리고 그 후에 포커스를 편집기에 적절히 설정할 수 있을지 잘 모르겠습니다…

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/services/composer.js#L218-L243

이런 방식으로 할 수 있을 것 같습니다. 이렇게 하면 동작할 것입니다.

import putCursorAtEnd from "discourse/lib/put-cursor-at-end";

api.onAppEvent("composer:open", ({ model }) => {
  if (model.title !== "") {
    scheduleOnce("afterRender", () => {
      putCursorAtEnd(document.querySelector("textarea.d-editor-input"));
    });
  }
});

거의 성공할 것 같네요 – 코드가 실행될 때 scheduleOnce가 정의되지 않았다는 오류가 발생합니다. api.scheduleOnce를 시도해 보았지만, scheduleOnce가 ember 관련 것인 것 같습니다. 컴포넌트에 이 import를 추가해 보았지만, import는 최상위에서만 허용된다는 오류가 발생했습니다.
import { scheduleOnce } from "@ember/runloop";

아마도 제가 놓치고 있는 작은 부분이 있을 것 같아 계속 시도해 볼 생각이지만, 혹시 눈에 띄는 부분이 있는지 궁금했습니다.

다시 한번 감사합니다 :slight_smile:

네, 가져오기(import)는 정확합니다. 두 개의 import를 모두 파일 상단에 배치하면 정상적으로 동작할 것입니다.

이 파일들을 어디에 넣어야 하나요? 제가 하려던 일은 에서 컴포넌트로 사용하는 것이었습니다. 다음과 같이 작성했는데, “scheduling afterRender” 로그가 표시된 후 scheduleOnce가 존재하지 않는다는 오류가 발생합니다. import를 몇 가지 방식으로 시도해 보았지만 작동하지 않습니다. JavaScript 모듈에 대한 제 경험이 부족해서 문제가 생기는 것 같습니다. 컴포넌트를 통해는 할 수 없고 더 완전한 플러그인으로 구현해야 하는지 모르겠습니다. 그쪽도 확인해 보겠습니다 — 도움 주셔서 다시 한번 감사합니다 :slight_smile:

<script type="text/discourse-plugin" version="1.8.0">
    api.onAppEvent("composer:open", ({ model }) => {
      console.log("composer open happened, model is: ", model);
      if (model.title !== "") {
        console.log("scheduling afterRender");
        scheduleOnce("afterRender", () => {
          console.log("after render happening");
          api.putCursorAtEnd(document.querySelector("textarea.d-editor-input"));
        });
      }
    });
</script>

아, 그렇군요. 그 파일들에서 JS를 사용한다고 가정했네요.

관리자 UI에서는 이렇게 작성하시면 됩니다:

<script type="text/discourse-plugin" version="1.8.0">
    const putCursorAtEnd = require("discourse/lib/put-cursor-at-end").default;
    const { scheduleOnce } = require("@ember/runloop");

    api.onAppEvent("composer:open", ({ model }) => {
      if (model.title !== "") {
        scheduleOnce("afterRender", () => {
          putCursorAtEnd(document.querySelector("textarea.d-editor-input"));
        });
      }
    });
</script>

참고로, Theme CLI 사용을 강력히 권장합니다. 템플릿에서 테마 컴포넌트를 생성하고, 라이브 리프레시로 Discourse와 동기화하며, 편집기를 사용하여 변경 사항을 업데이트할 수 있습니다. UI를 사용하는 것보다 훨씬 쉽습니다!

정말 감사합니다 - 제가 놓치고 있는 부분이 있다는 걸 알아차렸어요 - 테마 CLI를 설정해서 그 방식으로 편집해볼게요 :slight_smile: :slight_smile:

다시 한번 Arkshine님께 감사드립니다. 이제 discourse_theme를 사용해 제 첫 번째 컴포넌트를 만들었습니다 :slight_smile:
이 스레드를 찾은 분들을 위해, 저는 기본적으로 몇 가지 명령어만 실행하면 되었습니다:

gem install discourse_theme
npm install -g yarn
discourse_theme new <component-name>

그리고 javascripts/discourse/api-initializers/.js 파일을 편집합니다.
그 후 GitHub에 업로드하면 설치하거나 공유할 수 있습니다.
제 컴포넌트는 여기에 있습니다.
파일을 수정할 때마다 서버의 버전이 자동으로 업데이트되는 기능이 있는 것 같습니다. 점점 더 복잡한 컴포넌트를 다루게 되면서 유용할 것 같네요.

감사합니다