collavre 0.8.0 β†’ 0.8.2

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/collavre/actiontext.css +3 -3
  3. data/app/assets/stylesheets/collavre/comments_popup.css +44 -31
  4. data/app/assets/stylesheets/collavre/creatives.css +25 -16
  5. data/app/assets/stylesheets/collavre/dark_mode.css +56 -3
  6. data/app/assets/stylesheets/collavre/design_tokens.css +10 -2
  7. data/app/assets/stylesheets/collavre/mention_menu.css +2 -2
  8. data/app/assets/stylesheets/collavre/popup.css +82 -18
  9. data/app/controllers/collavre/creative_shares_controller.rb +27 -0
  10. data/app/javascript/components/creative_tree_row.js +11 -4
  11. data/app/javascript/controllers/comments/contexts_controller.js +7 -4
  12. data/app/javascript/controllers/comments/popup_controller.js +6 -0
  13. data/app/javascript/controllers/comments/topics_controller.js +9 -6
  14. data/app/javascript/controllers/creatives/expansion_controller.js +4 -4
  15. data/app/javascript/controllers/creatives/tree_controller.js +3 -1
  16. data/app/javascript/controllers/share_modal_controller.js +57 -0
  17. data/app/services/collavre/ai_agent/approval_handler.rb +7 -3
  18. data/app/services/collavre/ai_agent_service.rb +16 -3
  19. data/app/services/collavre/ai_client.rb +22 -6
  20. data/app/services/collavre/tools/creative_retrieval_service.rb +2 -2
  21. data/app/services/collavre/tools/creative_update_service.rb +1 -1
  22. data/app/views/collavre/comments/_comments_popup.html.erb +1 -1
  23. data/app/views/collavre/creatives/_mobile_actions_menu.html.erb +1 -1
  24. data/app/views/collavre/creatives/_share_modal.html.erb +71 -28
  25. data/app/views/collavre/creatives/index.html.erb +2 -2
  26. data/app/views/collavre/shared/_custom_theme_style.html.erb +21 -0
  27. data/app/views/collavre/users/new_ai.html.erb +1 -1
  28. data/app/views/layouts/collavre/slide.html.erb +1 -17
  29. data/config/locales/ai_agent.en.yml +10 -0
  30. data/config/locales/ai_agent.ko.yml +10 -0
  31. data/config/locales/creatives.en.yml +3 -1
  32. data/config/locales/creatives.ko.yml +3 -1
  33. data/lib/collavre/version.rb +1 -1
  34. metadata +2 -1
@@ -1,5 +1,5 @@
1
1
  <!-- Share Creative Modal -->
2
- <div id="share-creative-modal" style="display:none;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:10000;align-items:center;justify-content:center;" data-creative-id="<%= (@parent_creative || @creative).id %>" data-error-message="<%= t('collavre.creatives.share.network_error') %>">
2
+ <div id="share-creative-modal" style="display:none;position:fixed;top:0;left:0;right:0;bottom:0;z-index:10000;align-items:center;justify-content:center;background:rgba(0,0,0,0.3);" data-creative-id="<%= (@parent_creative || @creative).id %>" data-error-message="<%= t('collavre.creatives.share.network_error') %>">
3
3
  <div class="popup-box" style="min-width:320px;max-width:90vw;">
4
4
  <button type="button" id="close-share-modal" class="popup-close-btn">&times;</button>
5
5
  <h2><%= t('collavre.creatives.index.share_creative') %></h2>
@@ -21,7 +21,7 @@
21
21
  <select name="permission" id="share-permission">
22
22
  <option value="no_access"><%= t('collavre.creatives.index.permission_no_access') %></option>
23
23
  <option value="read"><%= t('collavre.creatives.index.permission_read') %></option>
24
- <option value="feedback"><%= t('collavre.creatives.index.permission_feedback') %></option>
24
+ <option value="feedback" selected><%= t('collavre.creatives.index.permission_feedback') %></option>
25
25
  <option value="write"><%= t('collavre.creatives.index.permission_write') %></option>
26
26
  <option value="admin"><%= t('collavre.creatives.index.permission_admin') %></option>
27
27
  </select>
@@ -29,52 +29,95 @@
29
29
  <button type="submit" class="btn btn-primary" data-share-invite-target="submit" data-share="<%= t('collavre.creatives.index.share') %>" data-invite="<%= t('collavre.creatives.index.invite') %>"><%= t('collavre.creatives.index.share') %></button>
30
30
  <button type="button" id="creative-invite-link" class="btn btn-secondary" data-creative-id="<%= (@parent_creative || @creative).id %>" data-no-access-message="<%= t('collavre.creatives.index.invite_link_no_access') %>" data-copied-template="<%= t('collavre.creatives.index.invite_link_copied_permission', permission: '__PERMISSION__') %>"><%= t('collavre.creatives.index.invite_link') %></button>
31
31
  </form>
32
- <% if @shared_list.any? %>
32
+ <% has_any_shares = @shared_list.any? || (defined?(@pending_invitations) && @pending_invitations.any?) || @inherited_shares.any? %>
33
+ <% if has_any_shares %>
33
34
  <div style="margin-top:1em;">
34
35
  <strong><%= t('collavre.creatives.index.shared_with') %>:</strong>
35
36
  <ul class="share-grid">
37
+ <%# Direct shares %>
36
38
  <% @shared_list.each do |share| %>
37
39
  <li>
38
40
  <span>
39
41
  <%= render Collavre::AvatarComponent.new(user: share.user, size: 20, classes: 'avatar share-avatar') %>
40
42
  </span>
41
43
  <span><%= share.user&.display_name || (share.user_id.nil? ? t('collavre.creatives.index.public_share') : t('collavre.creatives.index.unknown_user')) %></span>
42
- <span><%= t("collavre.creatives.index.permission_#{share.permission}") %></span>
44
+ <span>
45
+ <select class="org-chart-permission-select org-chart-permission-<%= share.permission %> share-modal-permission-select"
46
+ data-share-id="<%= share.id %>"
47
+ data-update-url="<%= collavre.creative_creative_share_path(@parent_creative || @creative, share) %>">
48
+ <% %w[admin write feedback read no_access].each do |perm| %>
49
+ <option value="<%= perm %>" <%= 'selected' if share.permission == perm %>>
50
+ <%= t("collavre.contacts.org_chart.permissions.#{perm}") %>
51
+ </option>
52
+ <% end %>
53
+ </select>
54
+ </span>
43
55
  <span>
44
56
  <%= button_to 'Γ—', collavre.creative_creative_share_path(@parent_creative || @creative, share), method: :delete, form: { data: { turbo_confirm: t('collavre.creatives.index.are_you_sure_delete_share') } }, class: 'delete-share-btn' %>
45
57
  </span>
46
58
  </li>
47
59
  <% end %>
48
- </ul>
49
- </div>
50
- <% end %>
51
- <% if defined?(@pending_invitations) && @pending_invitations.any? %>
52
- <div style="margin-top:1em;">
53
- <strong><%= t('collavre.contacts.org_chart.pending_invitations') %>:</strong>
54
- <ul class="share-grid">
55
- <% @pending_invitations.each do |invitation| %>
56
- <li>
60
+ <%# Inherited shares %>
61
+ <% @inherited_shares.each do |entry| %>
62
+ <% share = entry[:share] %>
63
+ <% source = entry[:source_creative] %>
64
+ <li class="share-inherited-item">
57
65
  <span>
58
- <div class="avatar-wrapper" style="width: 20px; height: 20px; display: inline-block;">
59
- <% if invitation.email.present? %>
60
- <%= image_tag asset_path("default_avatar.svg"),
61
- alt: '', width: 20, height: 20,
62
- class: 'avatar share-avatar',
63
- title: invitation.email,
64
- style: 'border-radius:50%;vertical-align:middle;' %>
65
- <span class="avatar-initial" style="font-size: 10px;"><%= invitation.email[0]&.upcase %></span>
66
- <% else %>
67
- <span class="avatar share-avatar" style="display:inline-block;width:20px;height:20px;border-radius:50%;background:var(--surface-3,#ddd);text-align:center;line-height:20px;font-size:10px;">πŸ”—</span>
68
- <% end %>
69
- </div>
66
+ <% if share.user %>
67
+ <%= render Collavre::AvatarComponent.new(user: share.user, size: 20, classes: 'avatar share-avatar') %>
68
+ <% else %>
69
+ <span class="avatar share-avatar" style="display:inline-block;width:20px;height:20px;border-radius:50%;background:var(--surface-3,#ddd);text-align:center;line-height:20px;font-size:10px;">🌐</span>
70
+ <% end %>
70
71
  </span>
71
- <span><%= invitation.email.presence || t('collavre.creatives.share.public_invite') %></span>
72
- <span><%= t("collavre.creatives.index.permission_#{invitation.permission}") %></span>
73
72
  <span>
74
- <%= button_to 'Γ—', collavre.creative_invitation_path(@parent_creative || @creative, invitation), method: :delete, form: { data: { turbo_confirm: t('collavre.contacts.org_chart.cancel_invite_confirm', email: invitation.email.presence || t('collavre.creatives.share.public_invite')) } }, class: 'delete-share-btn' %>
73
+ <%= share.user&.display_name || t('collavre.creatives.index.public_share') %>
74
+ <% source_name = source.creative_snippet %>
75
+ <%= link_to collavre.creative_path(source), class: 'share-inherited-link' do %>
76
+ <span class="share-inherited-short"><%= t('collavre.creatives.share.inherited_short') %></span>
77
+ <span class="share-inherited-full"><%= t('collavre.creatives.share.inherited_from', name: source_name) %></span>
78
+ <% end %>
75
79
  </span>
80
+ <span>
81
+ <select class="org-chart-permission-select org-chart-permission-<%= share.permission %> share-modal-permission-select" disabled>
82
+ <% %w[admin write feedback read no_access].each do |perm| %>
83
+ <option value="<%= perm %>" <%= 'selected' if share.permission == perm %>>
84
+ <%= t("collavre.contacts.org_chart.permissions.#{perm}") %>
85
+ </option>
86
+ <% end %>
87
+ </select>
88
+ </span>
89
+ <span></span>
76
90
  </li>
77
91
  <% end %>
92
+ <%# Pending invitations %>
93
+ <% if defined?(@pending_invitations) && @pending_invitations.any? %>
94
+ <% @pending_invitations.each do |invitation| %>
95
+ <li class="share-pending-item">
96
+ <span>
97
+ <div class="avatar-wrapper" style="width: 20px; height: 20px; display: inline-block;">
98
+ <% if invitation.email.present? %>
99
+ <%= image_tag asset_path("default_avatar.svg"),
100
+ alt: '', width: 20, height: 20,
101
+ class: 'avatar share-avatar',
102
+ title: invitation.email,
103
+ style: 'border-radius:50%;vertical-align:middle;' %>
104
+ <span class="avatar-initial" style="font-size: 10px;"><%= invitation.email[0]&.upcase %></span>
105
+ <% else %>
106
+ <span class="avatar share-avatar" style="display:inline-block;width:20px;height:20px;border-radius:50%;background:var(--surface-3,#ddd);text-align:center;line-height:20px;font-size:10px;">πŸ”—</span>
107
+ <% end %>
108
+ </div>
109
+ </span>
110
+ <span>
111
+ <%= invitation.email.presence || t('collavre.creatives.share.public_invite') %>
112
+ <span class="share-pending-badge"><%= t('collavre.contacts.org_chart.pending_status') %></span>
113
+ </span>
114
+ <span><%= t("collavre.creatives.index.permission_#{invitation.permission}") %></span>
115
+ <span>
116
+ <%= button_to 'Γ—', collavre.creative_invitation_path(@parent_creative || @creative, invitation), method: :delete, form: { data: { turbo_confirm: t('collavre.contacts.org_chart.cancel_invite_confirm', email: invitation.email.presence || t('collavre.creatives.share.public_invite')) } }, class: 'delete-share-btn' %>
117
+ </span>
118
+ </li>
119
+ <% end %>
120
+ <% end %>
78
121
  </ul>
79
122
  </div>
80
123
  <% end %>
@@ -51,11 +51,11 @@
51
51
  <% if (@parent_creative || @creative)&.has_permission?(Current.user, :admin) %>
52
52
  <button id="delete-selection-btn" class="danger-link" style="display:none;" data-confirm="<%= t('collavre.creatives.index.are_you_sure_delete_selection') %>" data-action="click->creatives--select-mode#deleteSelected" data-creatives--select-mode-target="deleteButton"><%= t('collavre.creatives.index.delete_selection') %></button>
53
53
  <% end %>
54
- <button id="expand-all-btn" class="expand-btn" style="width: 36px;" data-expand-text="<%= t('app.expand_all') %>" data-collapse-text="<%= t('app.collapse_all') %>" data-action="click->creatives--expansion#toggleAll" data-creatives--expansion-target="expand"><span aria-hidden="true">β–Ό</span></button>
54
+ <button id="expand-all-btn" class="expand-btn" style="width: 36px;" data-expand-text="<%= t('app.expand_all') %>" data-collapse-text="<%= t('app.collapse_all') %>" data-action="click->creatives--expansion#toggleAll" data-creatives--expansion-target="expand"><span class="icon-expand" aria-hidden="true"><%= svg_tag 'chevron-down.svg', width: 16, height: 16 %></span><span class="icon-collapse" aria-hidden="true" style="display:none"><%= svg_tag 'chevron-right.svg', width: 16, height: 16 %></span></button>
55
55
  <button id="toggle-edit-btn" class="edit-toggle-btn mobile-only" aria-label="<%= t('.edit') %>" title="<%= t('.edit') %>">
56
56
  <span aria-hidden="true"><%= svg_tag 'edit.svg', class: 'icon-edit', width: 16, height: 16 %></span></button>
57
57
  <% if authenticated? %>
58
- <button id="toggle-archived-btn" class="archive-toggle-btn desktop-only" title="<%= t('collavre.creatives.index.show_archived') %>" data-show-text="<%= t('collavre.creatives.index.show_archived') %>" data-hide-text="<%= t('collavre.creatives.index.hide_archived') %>"><span aria-hidden="true">πŸ“¦</span></button>
58
+ <button id="toggle-archived-btn" class="archive-toggle-btn desktop-only" title="<%= t('collavre.creatives.index.show_archived') %>" data-show-text="<%= t('collavre.creatives.index.show_archived') %>" data-hide-text="<%= t('collavre.creatives.index.hide_archived') %>"><span aria-hidden="true"><%= svg_tag 'archive.svg', width: 16, height: 16 %></span></button>
59
59
  <% end %>
60
60
  <% if authenticated? && (!params[:id] || (@parent_creative && @parent_creative.has_permission?(Current.user, :write))) %>
61
61
  <button id="import-markdown-btn" class="import-btn desktop-only" data-action="click->creatives--import#toggle" data-creatives--import-target="toggle"><%= t('.import_markdown') %></button>
@@ -0,0 +1,21 @@
1
+ <% if Current.user&.theme.present? && !%w[light dark].include?(Current.user.theme) %>
2
+ <% if (custom_theme = UserTheme.find_by(id: Current.user.theme)) %>
3
+ <style id="user-theme-styles" data-turbo-track="reload">
4
+ body {
5
+ <% custom_theme.variables.each do |key, value| %>
6
+ <%= key %>: <%= value %> !important;
7
+ <% end %>
8
+ <% legacy_alias_declarations(custom_theme.variables).each do |key, value| %>
9
+ <%= key %>: <%= value %> !important;
10
+ <% end %>
11
+ <% if custom_theme.dark? %>
12
+ --color-scheme: dark !important;
13
+ --surface-hover: rgba(255, 255, 255, 0.08) !important;
14
+ --shadow-color: 220 40% 2% !important;
15
+ --shadow-strength: 25% !important;
16
+ --hover-brightness: 110% !important;
17
+ <% end %>
18
+ }
19
+ </style>
20
+ <% end %>
21
+ <% end %>
@@ -7,7 +7,7 @@
7
7
  <% creative = Collavre::Creative.find_by(id: params[:creative_id]) %>
8
8
  <% if creative %>
9
9
  <div class="form-group">
10
- <p class="text-muted"><%= t('collavre.contacts.org_chart.add_ai_agent_to', creative: creative.plain_description) %></p>
10
+ <p class="text-muted"><%= t('collavre.contacts.org_chart.add_ai_agent_to', creative: Collavre::Creatives::TreeFormatter.plain_description(creative)) %></p>
11
11
  </div>
12
12
  <% end %>
13
13
  <% end %>
@@ -12,23 +12,7 @@
12
12
  <%= stylesheet_link_tag 'collavre/slide_view', media: 'all' %>
13
13
  <%= javascript_include_tag 'actioncable', defer: true %>
14
14
  <%= javascript_include_tag 'slide_view', defer: true %>
15
- <% if Current.user&.theme.present? && !%w[light dark].include?(Current.user.theme) %>
16
- <% if (custom_theme = UserTheme.find_by(id: Current.user.theme)) %>
17
- <style id="user-theme-styles" data-turbo-track="reload">
18
- body {
19
- <% custom_theme.variables.each do |key, value| %>
20
- <%= key %>: <%= value %> !important;
21
- <% end %>
22
- <% legacy_alias_declarations(custom_theme.variables).each do |key, value| %>
23
- <%= key %>: <%= value %> !important;
24
- <% end %>
25
- <% if custom_theme.dark? %>
26
- --color-scheme: dark !important;
27
- <% end %>
28
- }
29
- </style>
30
- <% end %>
31
- <% end %>
15
+ <%= render 'collavre/shared/custom_theme_style' %>
32
16
  </head>
33
17
  <body class="<%= body_theme_class %>">
34
18
  <%= yield %>
@@ -17,6 +17,16 @@ en:
17
17
 
18
18
  Please approve or reject this action.
19
19
  no_arguments: "(no arguments)"
20
+ summary_header: "πŸ“ **Summary:**"
21
+ summary_prompt: |
22
+ Summarize what the following tool call will do in 1-2 concise sentences for a human reviewer.
23
+ Be specific: mention key parameters, target resources, and the intended effect.
24
+
25
+ Tool: %{tool_name}
26
+ Arguments:
27
+ ```json
28
+ %{arguments}
29
+ ```
20
30
  a2a:
21
31
  request_header: "## ⚑ Agent Request"
22
32
  request_description: "This message is a request from another AI Agent (@%{sender_name}, %{sender_type})."
@@ -17,6 +17,16 @@ ko:
17
17
 
18
18
  승인 λ˜λŠ” κ±°λΆ€ν•΄ μ£Όμ„Έμš”.
19
19
  no_arguments: "(인자 μ—†μŒ)"
20
+ summary_header: "πŸ“ **μš”μ•½:**"
21
+ summary_prompt: |
22
+ λ‹€μŒ 도ꡬ 호좜이 무엇을 ν• μ§€ 1-2λ¬Έμž₯으둜 κ°„κ²°ν•˜κ²Œ μš”μ•½ν•΄ μ£Όμ„Έμš”.
23
+ μ£Όμš” νŒŒλΌλ―Έν„°, λŒ€μƒ λ¦¬μ†ŒμŠ€, μ˜λ„λœ 효과λ₯Ό ꡬ체적으둜 μ–ΈκΈ‰ν•˜μ„Έμš”.
24
+
25
+ 도ꡬ: %{tool_name}
26
+ 인자:
27
+ ```json
28
+ %{arguments}
29
+ ```
20
30
  a2a:
21
31
  request_header: "## ⚑ Agent μš”μ²­"
22
32
  request_description: "이 λ©”μ‹œμ§€λŠ” λ‹€λ₯Έ AI Agent(@%{sender_name}, %{sender_type})κ°€ 보낸 μš”μ²­μž…λ‹ˆλ‹€."
@@ -132,7 +132,9 @@ en:
132
132
  shared: Creative shared successfully.
133
133
  permission_updated: Permission updated successfully.
134
134
  network_error: A network error occurred. Please try again.
135
- public_invite: Public Invite
135
+ public_invite: Public
136
+ inherited_from: "Inherited from %{name}"
137
+ inherited_short: Inherited
136
138
  already_shared_in_parent: Creative already shared in parent creative.
137
139
  can_not_share_by_no_access_in_parent: You can not share by no access in parent
138
140
  creative.
@@ -120,7 +120,9 @@ ko:
120
120
  shared: ν¬λ¦¬μ—μ΄ν‹°λΈŒκ°€ μ„±κ³΅μ μœΌλ‘œ κ³΅μœ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
121
121
  permission_updated: κΆŒν•œμ΄ μ„±κ³΅μ μœΌλ‘œ λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
122
122
  network_error: λ„€νŠΈμ›Œν¬ 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.
123
- public_invite: 곡개 μ΄ˆλŒ€
123
+ public_invite: 곡개
124
+ inherited_from: "%{name}μ—μ„œ 상속"
125
+ inherited_short: 상속
124
126
  already_shared_in_parent: ν¬λ¦¬μ—μ΄ν‹°λΈŒκ°€ μƒμœ„ ν¬λ¦¬μ—μ΄ν‹°λΈŒμ— 이미 κ³΅μœ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
125
127
  can_not_share_by_no_access_in_parent: μƒμœ„ ν¬λ¦¬μ—μ΄ν‹°λΈŒμ— μ ‘κ·Ό κΈˆμ§€κ°€ μžˆμ–΄μ„œ κ³΅μœ ν•  수 μ—†μŠ΅λ‹ˆλ‹€.
126
128
  cannot_share_private_ai_agent: AI Agent μ†Œμœ μžλ§Œ κ³΅μœ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
@@ -1,3 +1,3 @@
1
1
  module Collavre
2
- VERSION = "0.8.0"
2
+ VERSION = "0.8.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: collavre
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Collavre
@@ -494,6 +494,7 @@ files:
494
494
  - app/views/collavre/sessions/new.html.erb
495
495
  - app/views/collavre/sessions/providers/_google.html.erb
496
496
  - app/views/collavre/sessions/providers/_passkey.html.erb
497
+ - app/views/collavre/shared/_custom_theme_style.html.erb
497
498
  - app/views/collavre/shared/_link_creative_modal.html.erb
498
499
  - app/views/collavre/shared/_navigation.html.erb
499
500
  - app/views/collavre/shared/navigation/_help_button.html.erb