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
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
module Collavre
|
|
2
2
|
class CreativesController < ApplicationController
|
|
3
|
+
include Collavre::Concerns::SlideViewable
|
|
4
|
+
include Collavre::Concerns::Exportable
|
|
5
|
+
include Collavre::Concerns::TreeManageable
|
|
6
|
+
include Collavre::Concerns::Shareable
|
|
7
|
+
|
|
3
8
|
# TODO: for not for security reasons for this Collavre app, we don't expose to public, later it should be controlled by roles for each Creatives
|
|
4
9
|
# Removed unauthenticated access to index and show actions
|
|
5
10
|
allow_unauthenticated_access only: %i[ index children export_markdown show slide_view ]
|
|
6
11
|
before_action :enforce_creatives_login_policy, only: %i[ index children export_markdown show slide_view ]
|
|
7
|
-
before_action :set_creative, only: %i[ show edit update destroy
|
|
12
|
+
before_action :set_creative, only: %i[ show edit update destroy parent_suggestions slide_view request_permission unconvert contexts update_contexts update_metadata ]
|
|
8
13
|
|
|
9
14
|
def index
|
|
10
15
|
respond_to do |format|
|
|
@@ -138,29 +143,14 @@ module Collavre
|
|
|
138
143
|
progress_html: view_context.render_creative_progress(@creative),
|
|
139
144
|
depth: depth,
|
|
140
145
|
prompt: @creative.prompt_for(Current.user),
|
|
141
|
-
has_children: children_count > 0
|
|
146
|
+
has_children: children_count > 0,
|
|
147
|
+
data: @creative.effective_origin(Set.new).data
|
|
142
148
|
}
|
|
143
149
|
end
|
|
144
150
|
end
|
|
145
151
|
end
|
|
146
152
|
end
|
|
147
153
|
|
|
148
|
-
def slide_view
|
|
149
|
-
unless @creative.has_permission?(Current.user, :read)
|
|
150
|
-
if Current.user
|
|
151
|
-
redirect_to creatives_path, alert: t("collavre.creatives.errors.no_permission")
|
|
152
|
-
else
|
|
153
|
-
request_authentication
|
|
154
|
-
end
|
|
155
|
-
return
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
@slide_ids = []
|
|
159
|
-
@root_depth = @creative.ancestors.count
|
|
160
|
-
build_slide_ids(@creative)
|
|
161
|
-
render layout: "collavre/slide"
|
|
162
|
-
end
|
|
163
|
-
|
|
164
154
|
def new
|
|
165
155
|
@creative = Creative.new
|
|
166
156
|
if params[:parent_id].present?
|
|
@@ -244,173 +234,92 @@ module Collavre
|
|
|
244
234
|
end
|
|
245
235
|
end
|
|
246
236
|
|
|
247
|
-
def
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
creative: @creative,
|
|
254
|
-
user: Current.user,
|
|
255
|
-
delete_with_children: params[:delete_with_children].present?
|
|
256
|
-
).call
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
def request_permission
|
|
260
|
-
creative = @creative.effective_origin
|
|
261
|
-
if creative.user == Current.user || creative.has_permission?(Current.user, :read)
|
|
262
|
-
return head :unprocessable_entity
|
|
263
|
-
end
|
|
237
|
+
def contexts
|
|
238
|
+
creative = @creative.effective_origin(Set.new)
|
|
239
|
+
own_ids = creative.context_ids - [ creative.id ]
|
|
240
|
+
inherited_ids = (creative.effective_context_ids - own_ids - [ creative.id ]).uniq
|
|
241
|
+
own_creatives = Creative.where(id: own_ids).index_by(&:id)
|
|
242
|
+
inherited_creatives = Creative.where(id: inherited_ids).index_by(&:id)
|
|
264
243
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
InboxItem.create!(
|
|
268
|
-
owner: creative.user,
|
|
269
|
-
message_key: "inbox.permission_requested",
|
|
270
|
-
message_params: { user: Current.user.display_name, short_title: short_title },
|
|
271
|
-
link: creative_url(
|
|
272
|
-
creative,
|
|
273
|
-
Rails.application.config.action_mailer.default_url_options.merge(share_request: Current.user.email)
|
|
274
|
-
)
|
|
275
|
-
)
|
|
276
|
-
|
|
277
|
-
head :ok
|
|
278
|
-
end
|
|
244
|
+
disabled_ids = Array(creative.data&.dig("disabled_context_ids"))
|
|
279
245
|
|
|
246
|
+
own = own_ids.filter_map do |cid|
|
|
247
|
+
c = own_creatives[cid]
|
|
248
|
+
next unless c
|
|
280
249
|
|
|
250
|
+
{ id: c.id, description: c.creative_snippet, inherited: false, disabled: disabled_ids.include?(cid) }
|
|
251
|
+
end
|
|
281
252
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
direction = params[:direction]
|
|
253
|
+
inherited = inherited_ids.filter_map do |cid|
|
|
254
|
+
c = inherited_creatives[cid]
|
|
255
|
+
next unless c
|
|
286
256
|
|
|
287
|
-
|
|
288
|
-
reorderer.reorder_multiple(
|
|
289
|
-
dragged_ids: dragged_ids,
|
|
290
|
-
target_id: target_id,
|
|
291
|
-
direction: direction
|
|
292
|
-
)
|
|
293
|
-
else
|
|
294
|
-
reorderer.reorder(
|
|
295
|
-
dragged_id: params[:dragged_id],
|
|
296
|
-
target_id: target_id,
|
|
297
|
-
direction: direction
|
|
298
|
-
)
|
|
257
|
+
{ id: c.id, description: c.creative_snippet, inherited: true, disabled: disabled_ids.include?(cid) }
|
|
299
258
|
end
|
|
300
|
-
head :ok
|
|
301
|
-
rescue ::Creatives::Reorderer::Error
|
|
302
|
-
head :unprocessable_entity
|
|
303
|
-
end
|
|
304
|
-
|
|
305
|
-
def link_drop
|
|
306
|
-
result = reorderer.link_drop(
|
|
307
|
-
dragged_id: params[:dragged_id],
|
|
308
|
-
target_id: params[:target_id],
|
|
309
|
-
direction: params[:direction]
|
|
310
|
-
)
|
|
311
|
-
|
|
312
|
-
new_creative = result.new_creative
|
|
313
|
-
level = new_creative.ancestors.count + 1
|
|
314
|
-
nodes = build_tree(
|
|
315
|
-
[ new_creative ],
|
|
316
|
-
params: params,
|
|
317
|
-
expanded_state_map: {},
|
|
318
|
-
level: level
|
|
319
|
-
)
|
|
320
259
|
|
|
321
260
|
render json: {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
direction: result.direction
|
|
261
|
+
contexts: inherited + own,
|
|
262
|
+
can_manage: creative.has_permission?(Current.user, :admin),
|
|
263
|
+
disabled_self_context: creative.data&.dig("disabled_self_context") == true
|
|
326
264
|
}
|
|
327
|
-
rescue ::Creatives::Reorderer::Error
|
|
328
|
-
head :unprocessable_entity
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
def append_as_parent
|
|
332
|
-
@parent_creative = Creative.find_by(id: params[:parent_id]).parent
|
|
333
|
-
redirect_to new_creative_path(parent_id: @parent_creative&.id, child_id: params[:parent_id], tags: params[:tags])
|
|
334
265
|
end
|
|
335
266
|
|
|
336
|
-
def
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
def children
|
|
342
|
-
parent = Creative.find(params[:id])
|
|
343
|
-
effective = parent.effective_origin
|
|
344
|
-
# user_id for expanded_state lookup - use owner's state for anonymous users
|
|
345
|
-
state_user_id = Current.user&.id || effective.user_id
|
|
346
|
-
|
|
347
|
-
# HTTP caching disabled for children endpoint:
|
|
348
|
-
# Response depends on child updates, permission changes (CreativeSharesCache),
|
|
349
|
-
# and CreativeExpandedState. Tracking all dependencies reliably is expensive
|
|
350
|
-
# (requires descendant_ids query). Stale 304 responses could leak data after
|
|
351
|
-
# permission revocation. Re-enable when a cheap version key mechanism exists.
|
|
352
|
-
# Use private + no-store to prevent any caching (proxy or browser).
|
|
353
|
-
response.headers["Cache-Control"] = "private, no-store"
|
|
354
|
-
|
|
355
|
-
has_filters = params[:tags].present? || params[:min_progress].present? || params[:max_progress].present?
|
|
356
|
-
if has_filters
|
|
357
|
-
result = ::Creatives::IndexQuery.new(user: Current.user, params: params.merge(id: params[:id])).call
|
|
358
|
-
render_children_json(parent, state_user_id, result.allowed_creative_ids, result.progress_map)
|
|
359
|
-
else
|
|
360
|
-
render_children_json(parent, state_user_id, nil, nil)
|
|
267
|
+
def update_contexts
|
|
268
|
+
creative = @creative.effective_origin(Set.new)
|
|
269
|
+
unless creative.has_permission?(Current.user, :admin)
|
|
270
|
+
render json: { error: t("collavre.creatives.errors.no_permission") }, status: :forbidden
|
|
271
|
+
return
|
|
361
272
|
end
|
|
362
|
-
end
|
|
363
273
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
if
|
|
368
|
-
|
|
274
|
+
current_data = (creative.data || {}).dup
|
|
275
|
+
current_data["context_ids"] = Array(params[:context_ids]).map(&:to_i) if params.key?(:context_ids)
|
|
276
|
+
current_data["disabled_context_ids"] = Array(params[:disabled_context_ids]).map(&:to_i) if params.key?(:disabled_context_ids)
|
|
277
|
+
current_data.delete("disabled_context_ids") if current_data["disabled_context_ids"]&.empty?
|
|
278
|
+
if params.key?(:disabled_self_context)
|
|
279
|
+
if ActiveModel::Type::Boolean.new.cast(params[:disabled_self_context])
|
|
280
|
+
current_data["disabled_self_context"] = true
|
|
281
|
+
else
|
|
282
|
+
current_data.delete("disabled_self_context")
|
|
283
|
+
end
|
|
369
284
|
end
|
|
370
285
|
|
|
371
|
-
|
|
372
|
-
|
|
286
|
+
if creative.update(data: current_data)
|
|
287
|
+
head :ok
|
|
288
|
+
else
|
|
289
|
+
render json: { errors: creative.errors.full_messages }, status: :unprocessable_entity
|
|
373
290
|
end
|
|
291
|
+
end
|
|
374
292
|
|
|
375
|
-
|
|
376
|
-
|
|
293
|
+
def update_metadata
|
|
294
|
+
creative = @creative.effective_origin(Set.new)
|
|
295
|
+
unless creative.has_permission?(Current.user, :write)
|
|
296
|
+
render json: { error: t("collavre.creatives.errors.no_permission") }, status: :forbidden
|
|
297
|
+
return
|
|
377
298
|
end
|
|
378
299
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
base_creative.descendants.each(&:destroy!)
|
|
385
|
-
base_creative.destroy!
|
|
300
|
+
new_data = begin
|
|
301
|
+
JSON.parse(params[:data])
|
|
302
|
+
rescue JSON::ParserError => e
|
|
303
|
+
render json: { error: "Invalid JSON: #{e.message}" }, status: :unprocessable_entity
|
|
304
|
+
return
|
|
386
305
|
end
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
rescue ActiveRecord::RecordInvalid => e
|
|
390
|
-
render json: { error: e.record.errors.full_messages.to_sentence }, status: :unprocessable_entity
|
|
391
|
-
end
|
|
392
|
-
|
|
393
|
-
def export_markdown
|
|
394
|
-
creatives = if params[:parent_id]
|
|
395
|
-
parent_creative = Creative.find(params[:parent_id])
|
|
396
|
-
effective_origin = parent_creative.effective_origin
|
|
397
|
-
unless parent_creative.has_permission?(Current.user, :read) &&
|
|
398
|
-
effective_origin.has_permission?(Current.user, :read)
|
|
399
|
-
render plain: t("collavre.creatives.errors.no_permission"), status: :forbidden and return
|
|
400
|
-
end
|
|
401
|
-
[ effective_origin ]
|
|
306
|
+
if creative.update(data: new_data)
|
|
307
|
+
head :ok
|
|
402
308
|
else
|
|
403
|
-
|
|
404
|
-
creative.has_permission?(Current.user, :read)
|
|
405
|
-
end
|
|
309
|
+
render json: { errors: creative.errors.full_messages }, status: :unprocessable_entity
|
|
406
310
|
end
|
|
311
|
+
end
|
|
407
312
|
|
|
408
|
-
|
|
409
|
-
|
|
313
|
+
def destroy
|
|
314
|
+
parent = @creative.parent
|
|
315
|
+
unless @creative.has_permission?(Current.user, :admin)
|
|
316
|
+
redirect_to @creative, alert: t("collavre.creatives.errors.no_permission") and return
|
|
410
317
|
end
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
318
|
+
Creatives::DestroyService.new(
|
|
319
|
+
creative: @creative,
|
|
320
|
+
user: Current.user,
|
|
321
|
+
delete_with_children: params[:delete_with_children].present?
|
|
322
|
+
).call
|
|
414
323
|
end
|
|
415
324
|
|
|
416
325
|
private
|
|
@@ -449,18 +358,6 @@ module Collavre
|
|
|
449
358
|
params[:unassigned].present?
|
|
450
359
|
end
|
|
451
360
|
|
|
452
|
-
def build_slide_ids(node)
|
|
453
|
-
return unless node.has_permission?(Current.user, :read)
|
|
454
|
-
|
|
455
|
-
@slide_ids << node.id
|
|
456
|
-
children = node.children.order(:sequence)
|
|
457
|
-
if node.origin_id.present?
|
|
458
|
-
linked_children = node.linked_children
|
|
459
|
-
children = (children + linked_children).uniq.sort_by(&:sequence)
|
|
460
|
-
end
|
|
461
|
-
children.each { |child| build_slide_ids(child) }
|
|
462
|
-
end
|
|
463
|
-
|
|
464
361
|
def serialize_creatives(collection)
|
|
465
362
|
if params[:simple].present?
|
|
466
363
|
collection.map { |c| { id: c.id, description: c.effective_description(nil, false), progress: c.progress } }
|
|
@@ -473,27 +370,6 @@ module Collavre
|
|
|
473
370
|
@reorderer ||= ::Creatives::Reorderer.new(user: Current.user)
|
|
474
371
|
end
|
|
475
372
|
|
|
476
|
-
def render_children_json(parent, user_id, allowed_ids, progress_map)
|
|
477
|
-
expanded_state_map = CreativeExpandedState
|
|
478
|
-
.where(user_id: user_id, creative_id: parent.id)
|
|
479
|
-
.first&.expanded_status || {}
|
|
480
|
-
children = parent.children_with_permission(Current.user)
|
|
481
|
-
|
|
482
|
-
level = params[:level].to_i
|
|
483
|
-
json_level = level.zero? ? 1 : level
|
|
484
|
-
render json: {
|
|
485
|
-
creatives: build_tree(
|
|
486
|
-
children,
|
|
487
|
-
params: params,
|
|
488
|
-
expanded_state_map: expanded_state_map,
|
|
489
|
-
level: json_level,
|
|
490
|
-
select_mode: params[:select_mode] == "1",
|
|
491
|
-
allowed_creative_ids: allowed_ids,
|
|
492
|
-
progress_map: progress_map
|
|
493
|
-
)
|
|
494
|
-
}
|
|
495
|
-
end
|
|
496
|
-
|
|
497
373
|
def enforce_creatives_login_policy
|
|
498
374
|
if SystemSetting.creatives_login_required?
|
|
499
375
|
require_authentication
|
|
@@ -40,6 +40,9 @@ module Collavre
|
|
|
40
40
|
tz = request.env["omniauth.params"] && request.env["omniauth.params"]["timezone"]
|
|
41
41
|
user.update(timezone: tz) if tz.present? && user.timezone != tz
|
|
42
42
|
|
|
43
|
+
return_to = session[:return_to_after_authenticating]
|
|
44
|
+
reset_session
|
|
45
|
+
session[:return_to_after_authenticating] = return_to if return_to
|
|
43
46
|
start_new_session_for(user)
|
|
44
47
|
redirect_to after_authentication_url
|
|
45
48
|
end
|
|
@@ -8,7 +8,8 @@ module Collavre
|
|
|
8
8
|
permission = params[:permission] || :read
|
|
9
9
|
invitation = Invitation.create!(inviter: Current.user,
|
|
10
10
|
creative: creative,
|
|
11
|
-
permission: permission
|
|
11
|
+
permission: permission,
|
|
12
|
+
email: params[:email].presence)
|
|
12
13
|
render json: { url: invite_url(token: invitation.generate_token_for(:invite)) }
|
|
13
14
|
end
|
|
14
15
|
|
|
@@ -28,6 +28,9 @@ module Collavre
|
|
|
28
28
|
if user.email_verified?
|
|
29
29
|
user.reset_failed_login_attempts!
|
|
30
30
|
handle_invitation_for(user) if params[:invite_token].present?
|
|
31
|
+
return_to = session[:return_to_after_authenticating]
|
|
32
|
+
reset_session
|
|
33
|
+
session[:return_to_after_authenticating] = return_to if return_to
|
|
31
34
|
start_new_session_for user
|
|
32
35
|
tz = params[:timezone]
|
|
33
36
|
user.update(timezone: tz) if tz.present? && user.timezone != tz
|
|
@@ -3,10 +3,13 @@ module Collavre
|
|
|
3
3
|
before_action :set_creative
|
|
4
4
|
|
|
5
5
|
def index
|
|
6
|
-
|
|
6
|
+
is_owner = @creative.user == Current.user
|
|
7
|
+
can_manage = @creative.has_permission?(Current.user, :admin) || is_owner
|
|
8
|
+
can_create_topic = can_manage || @creative.has_permission?(Current.user, :write)
|
|
7
9
|
render json: {
|
|
8
10
|
topics: @creative.topics.order(:created_at),
|
|
9
|
-
can_manage: can_manage
|
|
11
|
+
can_manage: can_manage,
|
|
12
|
+
can_create_topic: can_create_topic
|
|
10
13
|
}
|
|
11
14
|
end
|
|
12
15
|
|
|
@@ -63,6 +66,40 @@ module Collavre
|
|
|
63
66
|
head :no_content
|
|
64
67
|
end
|
|
65
68
|
|
|
69
|
+
def move
|
|
70
|
+
unless @creative.has_permission?(Current.user, :admin) || @creative.user == Current.user
|
|
71
|
+
render json: { error: I18n.t("collavre.topics.no_permission") }, status: :forbidden and return
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
topic = @creative.topics.find(params[:id])
|
|
75
|
+
target_creative = Creative.find(params[:target_creative_id]).effective_origin
|
|
76
|
+
|
|
77
|
+
unless target_creative.has_permission?(Current.user, :write) || target_creative.user == Current.user
|
|
78
|
+
render json: { error: I18n.t("collavre.topics.move.no_target_permission") }, status: :forbidden and return
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Check for duplicate topic name in target creative
|
|
82
|
+
if target_creative.topics.where(name: topic.name).exists?
|
|
83
|
+
render json: { error: I18n.t("collavre.topics.move.duplicate_name", name: topic.name) }, status: :unprocessable_entity and return
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
Topic.transaction do
|
|
87
|
+
topic.comments.update_all(creative_id: target_creative.id)
|
|
88
|
+
topic.update!(creative: target_creative)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
TopicsChannel.broadcast_to(
|
|
92
|
+
@creative,
|
|
93
|
+
{ action: "deleted", topic_id: topic.id }
|
|
94
|
+
)
|
|
95
|
+
TopicsChannel.broadcast_to(
|
|
96
|
+
target_creative,
|
|
97
|
+
{ action: "created", topic: topic.slice(:id, :name) }
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
render json: { success: true, topic: topic.slice(:id, :name), target_creative_id: target_creative.id }
|
|
101
|
+
end
|
|
102
|
+
|
|
66
103
|
def reorder
|
|
67
104
|
unless @creative.has_permission?(Current.user, :admin) || @creative.user == Current.user
|
|
68
105
|
render json: { error: I18n.t("collavre.topics.no_permission") }, status: :forbidden and return
|