PageSourceSearch

https://campaigns.do/assets/controllers/compose_controller-6996c883.js

js campaigns.do collected 2026-09-24 11:32:46 UTC 3,337 bytes, 78 lines download raw bytes

1import { Controller } from '@hotwired/stimulus';
2
3// 통합 작성 컴포저 — 링크(🔗)를 켜면 "한마디"에서 "뉴스 공유"로 전환한다(§3.7 Phase 1).
4// 같은 폼의 action·필드명을 articles#create에 맞춰 바꿔 컨트롤러를 재사용한다.
5//   한마디: POST /short_posts  { body, tag_name }
6//   뉴스:   POST /articles     { article[url], comment(=본문), article[owned_tag_list][](=이슈) }
7export default class extends Controller {
8  static targets = ['url', 'urlWrap', 'body', 'tag', 'submit', 'newsField'];
9  static values = { shortPostsUrl: String, articlesUrl: String };
10
11  connect() {
12    this.newsMode = false;
13    this.apply();
14    // 외부 트리거(compose:open)가 news·tag 의도를 담아 열면 그 상태로 맞춘다.
15    // 예: "뉴스 추가" → 링크 모드, 이슈 페이지 트리거 → 그 이슈를 이슈 선택기에 프리셀렉트.
16    this._onOpen = (e) => {
17      const wantNews = !!(e.detail && e.detail.news);
18      if (wantNews !== this.newsMode) this.toggleUrl();
19
20      const tag = e.detail && e.detail.tag;
21      if (tag && this.hasTagTarget && this.tagTarget.tomselect) {
22        const ts = this.tagTarget.tomselect;
23        ts.addOption({ name: tag, label: tag });
24        ts.setValue(tag, true); // silent: change 이벤트 없이 선택
25      }
26    };
27    window.addEventListener('compose:open', this._onOpen);
28  }
29
30  disconnect() {
31    if (this._onOpen) window.removeEventListener('compose:open', this._onOpen);
32  }
33
34  toggleUrl() {
35    this.newsMode = !this.newsMode;
36    this.urlWrapTarget.classList.toggle('tw-hidden', !this.newsMode);
37    this.apply();
38    if (this.newsMode) this.urlTarget.focus();
39  }
40
41  // 다른 형식으로 승격(§3.7 Phase 2) — 입력한 글·이슈를 넘기며 해당 new 폼으로 이동한다.
42  escalate(event) {
43    event.preventDefault();
44    const path = event.currentTarget.dataset.newPath;
45    if (!path) return;
46    const body = this.bodyTarget.value.trim();
47    const tag = this.hasTagTarget ? (this.tagTarget.value || '') : '';
48
49    // 본문을 POST로 넘긴다 — 긴 의견을 GET 쿼리스트링에 담으면 nginx 414(URI Too Large)가 난다.
50    const form = document.createElement('form');
51    form.method = 'post';
52    form.action = path;
53    const token = document.querySelector('meta[name="csrf-token"]')?.content;
54    const addField = (name, value) => {
55      const input = document.createElement('input');
56      input.type = 'hidden';
57      input.name = name;
58      input.value = value;
59      form.appendChild(input);
60    };
61    if (token) addField('authenticity_token', token);
62    if (body) addField('body', body);
63    if (tag) addField('tag', tag);
64    document.body.appendChild(form);
65    form.submit();
66  }
67
68  apply() {
69    const news = this.newsMode;
70    this.element.action = news ? this.articlesUrlValue : this.shortPostsUrlValue;
71    this.bodyTarget.name = news ? 'comment' : 'body';
72    if (this.hasTagTarget) this.tagTarget.name = news ? 'article[owned_tag_list][]' : 'tag_name';
73    // 뉴스 전용 필드(url·is_recent·published_at)는 뉴스일 때만 전송한다
74    this.newsFieldTargets.forEach((f) => { f.disabled = !news; });
75    if (this.hasUrlTarget) this.urlTarget.required = news;
76    this.submitTarget.value = news ? '뉴스 공유' : '의견 남기기';
77  }
78}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.