collavre 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/collavre/comment_versions.css +76 -0
- data/app/assets/stylesheets/collavre/comments_popup.css +347 -37
- data/app/assets/stylesheets/collavre/creatives.css +73 -1
- data/app/assets/stylesheets/collavre/org_chart.css +319 -0
- data/app/assets/stylesheets/collavre/popup.css +68 -1
- data/app/controllers/collavre/application_controller.rb +13 -0
- data/app/controllers/collavre/comments/versions_controller.rb +82 -0
- data/app/controllers/collavre/comments_controller.rb +14 -153
- data/app/controllers/collavre/concerns/exportable.rb +30 -0
- data/app/controllers/collavre/concerns/shareable.rb +28 -0
- data/app/controllers/collavre/concerns/slide_viewable.rb +37 -0
- data/app/controllers/collavre/concerns/tree_manageable.rb +141 -0
- data/app/controllers/collavre/creative_imports_controller.rb +6 -0
- data/app/controllers/collavre/creative_invitations_controller.rb +46 -0
- data/app/controllers/collavre/creative_plans_controller.rb +1 -1
- data/app/controllers/collavre/creative_shares_controller.rb +84 -14
- data/app/controllers/collavre/creatives_controller.rb +70 -194
- data/app/controllers/collavre/google_auth_controller.rb +3 -0
- data/app/controllers/collavre/invites_controller.rb +2 -1
- data/app/controllers/collavre/sessions_controller.rb +3 -0
- data/app/controllers/collavre/topics_controller.rb +39 -2
- data/app/controllers/collavre/users_controller.rb +5 -404
- data/app/controllers/concerns/collavre/comments/approval_actions.rb +108 -0
- data/app/controllers/concerns/collavre/comments/batch_operations.rb +55 -0
- data/app/controllers/concerns/collavre/comments/conversion.rb +46 -0
- data/app/controllers/concerns/collavre/users_controller/admin_operations.rb +74 -0
- data/app/controllers/concerns/collavre/users_controller/ai_user_management.rb +119 -0
- data/app/controllers/concerns/collavre/users_controller/contact_management.rb +166 -0
- data/app/controllers/concerns/collavre/users_controller/profile_and_settings.rb +102 -0
- data/app/controllers/concerns/collavre/users_controller/registration.rb +63 -0
- data/app/helpers/collavre/application_helper.rb +1 -0
- data/app/helpers/collavre/creatives_helper.rb +12 -9
- data/app/helpers/collavre/navigation_helper.rb +1 -1
- data/app/javascript/collavre.js +0 -1
- data/app/javascript/controllers/comment_controller.js +33 -70
- data/app/javascript/controllers/comment_version_controller.js +164 -0
- data/app/javascript/controllers/comments/__tests__/form_controller_review.test.js +305 -0
- data/app/javascript/controllers/comments/__tests__/list_controller_selection.test.js +103 -0
- data/app/javascript/controllers/comments/__tests__/review_quotes_store.test.js +113 -0
- data/app/javascript/controllers/comments/contexts_controller.js +363 -0
- data/app/javascript/controllers/comments/form_controller.js +304 -13
- data/app/javascript/controllers/comments/list_controller.js +151 -62
- data/app/javascript/controllers/comments/popup_controller.js +66 -38
- data/app/javascript/controllers/comments/presence_controller.js +2 -10
- data/app/javascript/controllers/comments/review_quotes_store.js +189 -0
- data/app/javascript/controllers/comments/topics_controller.js +34 -10
- data/app/javascript/controllers/index.js +15 -1
- data/app/javascript/controllers/org_chart_controller.js +46 -0
- data/app/javascript/controllers/share_modal_controller.js +369 -0
- data/app/javascript/controllers/topic_search_controller.js +103 -0
- data/app/javascript/creatives/drag_drop/event_handlers.js +42 -1
- data/app/javascript/lib/api/creatives.js +12 -0
- data/app/javascript/lib/api/csrf_fetch.js +35 -0
- data/app/javascript/lib/api/drag_drop.js +17 -0
- data/app/javascript/modules/command_menu.js +40 -0
- data/app/javascript/modules/creative_row_editor.js +88 -0
- data/app/javascript/modules/slide_view.js +2 -1
- data/app/jobs/collavre/ai_agent_job.rb +42 -30
- data/app/jobs/collavre/compress_job.rb +92 -0
- data/app/models/collavre/comment.rb +36 -1
- data/app/models/collavre/comment_version.rb +15 -0
- data/app/models/collavre/creative/describable.rb +1 -1
- data/app/models/collavre/creative.rb +51 -0
- data/app/models/collavre/task.rb +30 -2
- data/app/models/collavre/user.rb +20 -3
- data/app/services/collavre/ai_agent/a2a_dispatcher.rb +68 -0
- data/app/services/collavre/ai_agent/agent_lifecycle_manager.rb +89 -0
- data/app/services/collavre/ai_agent/message_builder.rb +85 -6
- data/app/services/collavre/ai_agent/response_finalizer.rb +97 -0
- data/app/services/collavre/ai_agent/response_streamer.rb +56 -0
- data/app/services/collavre/ai_agent/review_handler.rb +18 -1
- data/app/services/collavre/ai_agent_service.rb +130 -183
- data/app/services/collavre/ai_client.rb +6 -0
- data/app/services/collavre/auto_theme_generator.rb +1 -1
- data/app/services/collavre/command_menu_service.rb +19 -0
- data/app/services/collavre/comments/command_processor.rb +3 -1
- data/app/services/collavre/comments/compress_command.rb +75 -0
- data/app/services/collavre/comments/concerns/workflow_support.rb +115 -0
- data/app/services/collavre/comments/work_command.rb +161 -0
- data/app/services/collavre/comments/workflow_executor.rb +276 -0
- data/app/services/collavre/creatives/plan_tagger.rb +14 -3
- data/app/services/collavre/creatives/tree_formatter.rb +53 -13
- data/app/services/collavre/gemini_parent_recommender.rb +4 -4
- data/app/services/collavre/orchestration/agent_context_builder.rb +1 -3
- data/app/services/collavre/orchestration/agent_orchestrator.rb +15 -4
- data/app/services/collavre/orchestration/policy_resolver.rb +0 -19
- data/app/services/collavre/orchestration/scheduler.rb +3 -2
- data/app/services/collavre/orchestration/stuck_detector.rb +1 -1
- data/app/services/collavre/system_events/dispatcher.rb +9 -0
- data/app/services/collavre/tools/creative_create_service.rb +1 -8
- data/app/services/collavre/tools/creative_import_service.rb +46 -0
- data/app/services/collavre/tools/creative_retrieval_service.rb +157 -96
- data/app/services/collavre/tools/creative_update_service.rb +1 -8
- data/app/services/collavre/tools/cron_list_service.rb +1 -1
- data/app/services/collavre/tools/description_normalizable.rb +16 -0
- data/app/views/collavre/comments/_comment.html.erb +25 -8
- data/app/views/collavre/comments/_comments_popup.html.erb +32 -5
- data/app/views/collavre/creatives/_inline_edit_form.html.erb +13 -0
- data/app/views/collavre/creatives/_share_button.html.erb +4 -1
- data/app/views/collavre/creatives/_share_modal.html.erb +31 -1
- data/app/views/collavre/creatives/index.html.erb +5 -5
- data/app/views/collavre/creatives/slide_view.html.erb +1 -1
- data/app/views/collavre/users/{_contact_management.html.erb → _contact_list.html.erb} +4 -8
- data/app/views/collavre/users/_org_chart.html.erb +68 -0
- data/app/views/collavre/users/_org_chart_node.html.erb +169 -0
- data/app/views/collavre/users/new_ai.html.erb +9 -0
- data/app/views/collavre/users/show.html.erb +32 -8
- data/config/locales/comments.en.yml +57 -2
- data/config/locales/comments.ko.yml +57 -2
- data/config/locales/contacts.en.yml +31 -0
- data/config/locales/contacts.ko.yml +31 -0
- data/config/locales/contexts.en.yml +8 -0
- data/config/locales/contexts.ko.yml +8 -0
- data/config/locales/creatives.en.yml +6 -0
- data/config/locales/creatives.ko.yml +6 -0
- data/config/locales/users.en.yml +1 -0
- data/config/locales/users.ko.yml +1 -0
- data/config/routes.rb +14 -1
- data/db/migrate/20260220072200_add_workflow_fields_to_tasks.rb +12 -0
- data/db/migrate/20260223173533_add_review_type_to_comments.rb +5 -0
- data/db/migrate/20260225065200_create_comment_versions.rb +14 -0
- data/db/migrate/20260225074416_add_selected_version_id_to_comments.rb +7 -0
- data/lib/collavre/version.rb +1 -1
- metadata +47 -10
- data/app/javascript/lib/lexical/__tests__/action_text_attachment_node.test.jsx +0 -91
- data/app/javascript/lib/lexical/action_text_attachment_node.js +0 -459
- data/app/javascript/lib/lexical/dom_attachment_utils.js +0 -66
- data/app/javascript/modules/share_modal.js +0 -76
- data/app/javascript/modules/share_user_popup.js +0 -77
- data/app/services/collavre/orchestration/self_reflection_evaluator.rb +0 -231
- data/app/views/collavre/comments/_presence_avatars.html.erb +0 -8
- data/app/views/collavre/creatives/_delete_button.html.erb +0 -12
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReviewQuotesStore — Pure state management for review quote chips.
|
|
3
|
+
*
|
|
4
|
+
* Responsible for:
|
|
5
|
+
* - Adding / removing / updating quotes
|
|
6
|
+
* - Tracking the active (editing) quote
|
|
7
|
+
* - Building markdown content for submission
|
|
8
|
+
* - Backup / restore for send-failure rollback
|
|
9
|
+
*
|
|
10
|
+
* Does NOT touch the DOM — the controller handles all rendering.
|
|
11
|
+
*/
|
|
12
|
+
let _nextId = 1
|
|
13
|
+
|
|
14
|
+
export default class ReviewQuotesStore {
|
|
15
|
+
constructor() {
|
|
16
|
+
this._quotes = []
|
|
17
|
+
this._activeId = null
|
|
18
|
+
this._backup = null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// --- Accessors ---
|
|
22
|
+
|
|
23
|
+
get quotes() {
|
|
24
|
+
return this._quotes
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get activeId() {
|
|
28
|
+
return this._activeId
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
set activeId(id) {
|
|
32
|
+
this._activeId = id
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get activeQuote() {
|
|
36
|
+
if (!this._activeId) return null
|
|
37
|
+
return this._quotes.find(q => q.id === this._activeId) || null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get count() {
|
|
41
|
+
return this._quotes.length
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get isEmpty() {
|
|
45
|
+
return this._quotes.length === 0
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get hasActive() {
|
|
49
|
+
return this._activeId !== null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// --- Mutations ---
|
|
53
|
+
|
|
54
|
+
add(commentId, text) {
|
|
55
|
+
const quote = {
|
|
56
|
+
id: _nextId++,
|
|
57
|
+
commentId,
|
|
58
|
+
text,
|
|
59
|
+
type: 'review', // 'review' | 'question'
|
|
60
|
+
feedback: '',
|
|
61
|
+
}
|
|
62
|
+
this._quotes.push(quote)
|
|
63
|
+
this._activeId = quote.id
|
|
64
|
+
return quote
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
remove(quoteId) {
|
|
68
|
+
const idx = this._quotes.findIndex(q => q.id === quoteId)
|
|
69
|
+
if (idx === -1) return null
|
|
70
|
+
const [removed] = this._quotes.splice(idx, 1)
|
|
71
|
+
if (this._activeId === quoteId) {
|
|
72
|
+
this._activeId = null
|
|
73
|
+
}
|
|
74
|
+
return removed
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
setFeedback(quoteId, feedback) {
|
|
78
|
+
const quote = this._quotes.find(q => q.id === quoteId)
|
|
79
|
+
if (quote) quote.feedback = feedback.trim()
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
saveActiveFeedback(textareaValue) {
|
|
83
|
+
if (!this._activeId) return
|
|
84
|
+
const quote = this._quotes.find(q => q.id === this._activeId)
|
|
85
|
+
if (quote) quote.feedback = textareaValue.trim()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
commitActive(textareaValue) {
|
|
89
|
+
this.saveActiveFeedback(textareaValue)
|
|
90
|
+
this._activeId = null
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
toggleType(quoteId) {
|
|
94
|
+
const quote = this._quotes.find(q => q.id === quoteId)
|
|
95
|
+
if (!quote) return null
|
|
96
|
+
quote.type = quote.type === 'review' ? 'question' : 'review'
|
|
97
|
+
return quote
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
activate(quoteId) {
|
|
101
|
+
const quote = this._quotes.find(q => q.id === quoteId)
|
|
102
|
+
if (!quote) return null
|
|
103
|
+
this._activeId = quoteId
|
|
104
|
+
return quote
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
clear() {
|
|
108
|
+
this._quotes = []
|
|
109
|
+
this._activeId = null
|
|
110
|
+
this._backup = null
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// --- Backup / Restore (for send-failure rollback) ---
|
|
114
|
+
|
|
115
|
+
backup(textareaValue) {
|
|
116
|
+
this._backup = {
|
|
117
|
+
quotes: JSON.parse(JSON.stringify(this._quotes)),
|
|
118
|
+
textareaValue,
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
restore() {
|
|
123
|
+
if (!this._backup) return null
|
|
124
|
+
this._quotes = this._backup.quotes
|
|
125
|
+
const textareaValue = this._backup.textareaValue
|
|
126
|
+
this._backup = null
|
|
127
|
+
return textareaValue
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
hasBackup() {
|
|
131
|
+
return this._backup !== null
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// --- Markdown Builder ---
|
|
135
|
+
|
|
136
|
+
buildContent(summaryText) {
|
|
137
|
+
if (this._quotes.length === 0) return summaryText
|
|
138
|
+
|
|
139
|
+
const parts = []
|
|
140
|
+
|
|
141
|
+
this._quotes.forEach((q, i) => {
|
|
142
|
+
if (i > 0) parts.push('') // Blank line between quotes to prevent blockquote merging
|
|
143
|
+
const prefix = q.type === 'question' ? '> ❓ ' : '> '
|
|
144
|
+
const quoted = q.text.split('\n').map((line, j) => {
|
|
145
|
+
return j === 0 ? `${prefix}${line}` : `> ${line}`
|
|
146
|
+
}).join('\n')
|
|
147
|
+
parts.push(quoted)
|
|
148
|
+
if (q.feedback) {
|
|
149
|
+
parts.push('')
|
|
150
|
+
parts.push(q.feedback)
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
const summary = summaryText.trim()
|
|
155
|
+
if (summary) {
|
|
156
|
+
parts.push('')
|
|
157
|
+
parts.push('---')
|
|
158
|
+
parts.push(summary)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return parts.join('\n')
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
buildQuestionContent(quote) {
|
|
165
|
+
const prefix = '> ❓ '
|
|
166
|
+
const quoted = quote.text.split('\n').map((line, i) => {
|
|
167
|
+
return i === 0 ? `${prefix}${line}` : `> ${line}`
|
|
168
|
+
}).join('\n')
|
|
169
|
+
const parts = [quoted]
|
|
170
|
+
if (quote.feedback) {
|
|
171
|
+
parts.push('')
|
|
172
|
+
parts.push(quote.feedback)
|
|
173
|
+
}
|
|
174
|
+
return parts.join('\n')
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// --- Query ---
|
|
178
|
+
|
|
179
|
+
/** Button state: 'add' | 'send-review' | 'send-question' | 'normal' */
|
|
180
|
+
get buttonState() {
|
|
181
|
+
if (this._quotes.length === 0) return 'normal'
|
|
182
|
+
if (this._activeId) {
|
|
183
|
+
const active = this.activeQuote
|
|
184
|
+
if (active && active.type === 'question') return 'send-question'
|
|
185
|
+
return 'add'
|
|
186
|
+
}
|
|
187
|
+
return 'send-review'
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -7,6 +7,7 @@ export default class extends Controller {
|
|
|
7
7
|
connect() {
|
|
8
8
|
this.topics = []
|
|
9
9
|
this.canManageTopics = false
|
|
10
|
+
this.canCreateTopic = false
|
|
10
11
|
this.subscribedCreativeId = null
|
|
11
12
|
this.topicsSubscription = null
|
|
12
13
|
// Initial load if creativeId is available (e.g. from dataset if set server-side)
|
|
@@ -15,11 +16,14 @@ export default class extends Controller {
|
|
|
15
16
|
this.subscribe()
|
|
16
17
|
}
|
|
17
18
|
this.handleNewMessage = this.handleNewMessage.bind(this)
|
|
19
|
+
this.handleTopicMoved = this.handleTopicMoved.bind(this)
|
|
18
20
|
window.addEventListener('comments--topics:new-message', this.handleNewMessage)
|
|
21
|
+
window.addEventListener('collavre:topic-moved', this.handleTopicMoved)
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
disconnect() {
|
|
22
25
|
window.removeEventListener('comments--topics:new-message', this.handleNewMessage)
|
|
26
|
+
window.removeEventListener('collavre:topic-moved', this.handleTopicMoved)
|
|
23
27
|
this.unsubscribe()
|
|
24
28
|
}
|
|
25
29
|
|
|
@@ -59,9 +63,11 @@ export default class extends Controller {
|
|
|
59
63
|
const data = await response.json()
|
|
60
64
|
const topics = Array.isArray(data) ? data : data.topics
|
|
61
65
|
const canManage = Array.isArray(data) ? false : data.can_manage
|
|
66
|
+
const canCreateTopic = Array.isArray(data) ? false : (data.can_create_topic ?? canManage)
|
|
62
67
|
this.topics = topics
|
|
63
68
|
this.canManageTopics = canManage
|
|
64
|
-
this.
|
|
69
|
+
this.canCreateTopic = canCreateTopic
|
|
70
|
+
this.renderTopics(this.topics, this.canManageTopics, this.canCreateTopic)
|
|
65
71
|
this.restoreSelection()
|
|
66
72
|
}
|
|
67
73
|
} catch (e) {
|
|
@@ -85,7 +91,7 @@ export default class extends Controller {
|
|
|
85
91
|
}
|
|
86
92
|
}
|
|
87
93
|
|
|
88
|
-
renderTopics(topics, canManage = false) {
|
|
94
|
+
renderTopics(topics, canManage = false, canCreateTopic = canManage) {
|
|
89
95
|
const dragActions = canManage
|
|
90
96
|
? 'dragstart->comments--topics#handleTopicDragStart dragend->comments--topics#handleTopicDragEnd'
|
|
91
97
|
: ''
|
|
@@ -114,8 +120,8 @@ export default class extends Controller {
|
|
|
114
120
|
html += `</span>`
|
|
115
121
|
})
|
|
116
122
|
|
|
117
|
-
// Add create button container
|
|
118
|
-
if (
|
|
123
|
+
// Add create button container (write permission is sufficient for topic creation)
|
|
124
|
+
if (canCreateTopic) {
|
|
119
125
|
html += `<span class="topic-creation-container" data-comments--topics-target="creationContainer">
|
|
120
126
|
<button class="add-topic-btn" data-action="click->comments--topics#showInput">+</button>
|
|
121
127
|
</span>`
|
|
@@ -169,6 +175,11 @@ export default class extends Controller {
|
|
|
169
175
|
|
|
170
176
|
this.draggingTopicId = topicId
|
|
171
177
|
event.dataTransfer.setData('application/x-topic-id', topicId)
|
|
178
|
+
// Include topic move data so creative tree rows can accept this drop
|
|
179
|
+
event.dataTransfer.setData('application/x-topic-move', JSON.stringify({
|
|
180
|
+
topicId,
|
|
181
|
+
sourceCreativeId: this.creativeId
|
|
182
|
+
}))
|
|
172
183
|
event.dataTransfer.effectAllowed = 'move'
|
|
173
184
|
|
|
174
185
|
requestAnimationFrame(() => {
|
|
@@ -250,7 +261,7 @@ export default class extends Controller {
|
|
|
250
261
|
|
|
251
262
|
// Update local state and UI immediately
|
|
252
263
|
this.topics = topics
|
|
253
|
-
this.renderTopics(topics, this.canManageTopics)
|
|
264
|
+
this.renderTopics(topics, this.canManageTopics, this.canCreateTopic)
|
|
254
265
|
this.restoreSelection()
|
|
255
266
|
|
|
256
267
|
// Send to server
|
|
@@ -446,7 +457,7 @@ export default class extends Controller {
|
|
|
446
457
|
if (index !== -1) {
|
|
447
458
|
this.topics[index] = updatedTopic
|
|
448
459
|
}
|
|
449
|
-
this.renderTopics(this.topics, this.canManageTopics)
|
|
460
|
+
this.renderTopics(this.topics, this.canManageTopics, this.canCreateTopic)
|
|
450
461
|
this.restoreSelection()
|
|
451
462
|
} else {
|
|
452
463
|
alert("Failed to update topic")
|
|
@@ -483,6 +494,19 @@ export default class extends Controller {
|
|
|
483
494
|
}
|
|
484
495
|
}
|
|
485
496
|
|
|
497
|
+
handleTopicMoved(event) {
|
|
498
|
+
const { sourceCreativeId, topicId } = event.detail
|
|
499
|
+
// Reload topics if the moved topic belonged to the currently viewed creative
|
|
500
|
+
if (String(sourceCreativeId) === String(this.creativeId)) {
|
|
501
|
+
// If we were viewing the moved topic, switch to Main
|
|
502
|
+
if (String(this.currentTopicId) === String(topicId)) {
|
|
503
|
+
this.currentTopicId = ""
|
|
504
|
+
this.dispatch("change", { detail: { topicId: "" } })
|
|
505
|
+
}
|
|
506
|
+
this.loadTopics()
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
486
510
|
handleNewMessage(event) {
|
|
487
511
|
const topicId = event.detail.topicId
|
|
488
512
|
if (!topicId) return
|
|
@@ -601,7 +625,7 @@ export default class extends Controller {
|
|
|
601
625
|
if (exists) return
|
|
602
626
|
|
|
603
627
|
this.topics = [...topics, data.topic]
|
|
604
|
-
this.renderTopics(this.topics, this.canManageTopics)
|
|
628
|
+
this.renderTopics(this.topics, this.canManageTopics, this.canCreateTopic)
|
|
605
629
|
this.restoreSelection()
|
|
606
630
|
}
|
|
607
631
|
|
|
@@ -622,7 +646,7 @@ export default class extends Controller {
|
|
|
622
646
|
})
|
|
623
647
|
|
|
624
648
|
this.topics = reorderedTopics
|
|
625
|
-
this.renderTopics(this.topics, this.canManageTopics)
|
|
649
|
+
this.renderTopics(this.topics, this.canManageTopics, this.canCreateTopic)
|
|
626
650
|
this.restoreSelection()
|
|
627
651
|
}
|
|
628
652
|
|
|
@@ -632,7 +656,7 @@ export default class extends Controller {
|
|
|
632
656
|
if (index === -1) return
|
|
633
657
|
|
|
634
658
|
this.topics[index] = updatedTopic
|
|
635
|
-
this.renderTopics(this.topics, this.canManageTopics)
|
|
659
|
+
this.renderTopics(this.topics, this.canManageTopics, this.canCreateTopic)
|
|
636
660
|
this.restoreSelection()
|
|
637
661
|
}
|
|
638
662
|
|
|
@@ -649,7 +673,7 @@ export default class extends Controller {
|
|
|
649
673
|
this.dispatch("change", { detail: { topicId: "" } })
|
|
650
674
|
}
|
|
651
675
|
|
|
652
|
-
this.renderTopics(this.topics, this.canManageTopics)
|
|
676
|
+
this.renderTopics(this.topics, this.canManageTopics, this.canCreateTopic)
|
|
653
677
|
this.restoreSelection()
|
|
654
678
|
}
|
|
655
679
|
}
|
|
@@ -14,15 +14,20 @@ import CommentsFormController from "./comments/form_controller"
|
|
|
14
14
|
import CommentsPresenceController from "./comments/presence_controller"
|
|
15
15
|
import CommentsMentionMenuController from "./comments/mention_menu_controller"
|
|
16
16
|
import CommentsTopicsController from "./comments/topics_controller"
|
|
17
|
+
import CommentsContextsController from "./comments/contexts_controller"
|
|
17
18
|
import CommentsPopupController from "./comments/popup_controller"
|
|
18
19
|
import ClickTargetController from "./click_target_controller"
|
|
19
20
|
import TabsController from "./tabs_controller"
|
|
20
21
|
import LinkCreativeController from "./link_creative_controller"
|
|
22
|
+
import TopicSearchController from "./topic_search_controller"
|
|
21
23
|
import CommonPopupController from "./common_popup_controller"
|
|
22
24
|
import CommentController from "./comment_controller"
|
|
23
25
|
import ReactionPickerController from "./reaction_picker_controller"
|
|
24
26
|
import ShareInviteController from "./share_invite_controller"
|
|
25
27
|
import ShareUserSearchController from "./share_user_search_controller"
|
|
28
|
+
import CommentVersionController from "./comment_version_controller"
|
|
29
|
+
import OrgChartController from "./org_chart_controller"
|
|
30
|
+
import ShareModalController from "./share_modal_controller"
|
|
26
31
|
|
|
27
32
|
// Export all controllers
|
|
28
33
|
export {
|
|
@@ -44,11 +49,15 @@ export {
|
|
|
44
49
|
ClickTargetController,
|
|
45
50
|
TabsController,
|
|
46
51
|
LinkCreativeController,
|
|
52
|
+
TopicSearchController,
|
|
47
53
|
CommonPopupController,
|
|
48
54
|
CommentController,
|
|
49
55
|
ReactionPickerController,
|
|
50
56
|
ShareInviteController,
|
|
51
|
-
ShareUserSearchController
|
|
57
|
+
ShareUserSearchController,
|
|
58
|
+
CommentVersionController,
|
|
59
|
+
OrgChartController,
|
|
60
|
+
ShareModalController
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
// Registration function for use with a Stimulus application
|
|
@@ -67,13 +76,18 @@ export function registerControllers(application) {
|
|
|
67
76
|
application.register("comments--presence", CommentsPresenceController)
|
|
68
77
|
application.register("comments--mention-menu", CommentsMentionMenuController)
|
|
69
78
|
application.register("comments--topics", CommentsTopicsController)
|
|
79
|
+
application.register("comments--contexts", CommentsContextsController)
|
|
70
80
|
application.register("comments--popup", CommentsPopupController)
|
|
71
81
|
application.register("click-target", ClickTargetController)
|
|
72
82
|
application.register("tabs", TabsController)
|
|
73
83
|
application.register("link-creative", LinkCreativeController)
|
|
84
|
+
application.register("topic-search", TopicSearchController)
|
|
74
85
|
application.register("common-popup", CommonPopupController)
|
|
75
86
|
application.register("comment", CommentController)
|
|
76
87
|
application.register("reaction-picker", ReactionPickerController)
|
|
77
88
|
application.register("share-invite", ShareInviteController)
|
|
78
89
|
application.register("share-user-search", ShareUserSearchController)
|
|
90
|
+
application.register("comment-version", CommentVersionController)
|
|
91
|
+
application.register("org-chart", OrgChartController)
|
|
92
|
+
application.register("share-modal", ShareModalController)
|
|
79
93
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
export default class extends Controller {
|
|
4
|
+
static targets = [ "toggleAllBtn" ]
|
|
5
|
+
|
|
6
|
+
toggleAll() {
|
|
7
|
+
const details = this.element.querySelectorAll("details.org-chart-group")
|
|
8
|
+
const allOpen = Array.from(details).every(d => d.open)
|
|
9
|
+
|
|
10
|
+
details.forEach(d => d.open = !allOpen)
|
|
11
|
+
|
|
12
|
+
if (this.hasToggleAllBtnTarget) {
|
|
13
|
+
const btn = this.toggleAllBtnTarget
|
|
14
|
+
btn.textContent = allOpen
|
|
15
|
+
? btn.dataset.expandText || btn.textContent
|
|
16
|
+
: btn.dataset.collapseText || btn.textContent
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
updatePermission(event) {
|
|
21
|
+
const select = event.target
|
|
22
|
+
const url = select.dataset.updateUrl
|
|
23
|
+
const permission = select.value
|
|
24
|
+
const originalClass = select.className
|
|
25
|
+
|
|
26
|
+
// Update visual class immediately
|
|
27
|
+
select.className = select.className.replace(/org-chart-permission-\w+/g, "")
|
|
28
|
+
select.classList.add("org-chart-permission-select", `org-chart-permission-${permission}`)
|
|
29
|
+
|
|
30
|
+
fetch(url, {
|
|
31
|
+
method: "PATCH",
|
|
32
|
+
headers: {
|
|
33
|
+
"Content-Type": "application/json",
|
|
34
|
+
"X-CSRF-Token": document.querySelector("meta[name='csrf-token']")?.content,
|
|
35
|
+
"Accept": "application/json"
|
|
36
|
+
},
|
|
37
|
+
body: JSON.stringify({ permission })
|
|
38
|
+
}).then(response => {
|
|
39
|
+
if (!response.ok) throw new Error("Failed")
|
|
40
|
+
}).catch(() => {
|
|
41
|
+
select.className = originalClass
|
|
42
|
+
location.reload()
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
}
|