collavre 0.22.0 → 0.24.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/README.md +1 -0
- data/app/assets/images/collavre/landing/interface-en-dark.png +0 -0
- data/app/assets/images/collavre/landing/interface-en.png +0 -0
- data/app/assets/images/collavre/landing/interface-ko-dark.png +0 -0
- data/app/assets/images/collavre/landing/interface-ko.png +0 -0
- data/app/assets/stylesheets/collavre/actiontext.css +251 -90
- data/app/assets/stylesheets/collavre/code_highlight.css +7 -201
- data/app/assets/stylesheets/collavre/comments_popup.css +158 -61
- data/app/assets/stylesheets/collavre/creatives.css +11 -2
- data/app/assets/stylesheets/collavre/landing.css +92 -0
- data/app/assets/stylesheets/collavre/modal_dialog.css +32 -0
- data/app/assets/stylesheets/collavre/popup.css +4 -2
- data/app/assets/stylesheets/collavre/tables.css +91 -0
- data/app/channels/collavre/inbox_badge_channel.rb +30 -0
- data/app/controllers/collavre/admin/settings_controller.rb +52 -67
- data/app/controllers/collavre/api/v1/agents_controller.rb +17 -188
- data/app/controllers/collavre/api/v1/base_controller.rb +9 -27
- data/app/controllers/collavre/api/v1/mobile/agent_events_controller.rb +224 -0
- data/app/controllers/collavre/api/v1/mobile/base_controller.rb +95 -0
- data/app/controllers/collavre/api/v1/mobile/devices_controller.rb +31 -0
- data/app/controllers/collavre/api/v1/mobile/voice_commands_controller.rb +25 -0
- data/app/controllers/collavre/attachments_controller.rb +13 -3
- data/app/controllers/collavre/concerns/slide_viewable.rb +8 -32
- data/app/controllers/collavre/creatives_controller.rb +47 -103
- data/app/controllers/collavre/inbox_items_controller.rb +10 -4
- data/app/controllers/collavre/landing_controller.rb +5 -2
- data/app/controllers/collavre/tasks_controller.rb +13 -4
- data/app/controllers/collavre/topics_controller.rb +54 -1
- data/app/controllers/collavre/typo_corrections_controller.rb +39 -0
- data/app/controllers/concerns/collavre/api/authenticatable.rb +40 -0
- data/app/controllers/concerns/collavre/users_controller/profile_and_settings.rb +16 -1
- data/app/controllers/concerns/collavre/users_controller/registration.rb +41 -1
- data/app/errors/collavre/api_error.rb +20 -0
- data/app/helpers/collavre/application_helper.rb +1 -0
- data/app/helpers/collavre/creatives_helper.rb +30 -8
- data/app/javascript/collavre.js +2 -0
- data/app/javascript/components/ImageResizer.jsx +9 -3
- data/app/javascript/components/InlineLexicalEditor.jsx +157 -72
- data/app/javascript/components/__tests__/creative_tree_row_parent_id.test.js +87 -0
- data/app/javascript/components/creative_tree_row.js +28 -5
- data/app/javascript/components/plugins/list_tab_indent_plugin.jsx +16 -0
- data/app/javascript/components/plugins/markdown_shortcuts_plugin.jsx +15 -4
- data/app/javascript/components/plugins/table_hover_actions_plugin.jsx +405 -0
- data/app/javascript/controllers/__tests__/inbox_badge_controller.test.js +73 -0
- data/app/javascript/controllers/__tests__/search_popup_controller.test.js +104 -0
- data/app/javascript/controllers/__tests__/topic_list_controller.test.js +82 -0
- data/app/javascript/controllers/comment_controller.js +5 -4
- data/app/javascript/controllers/comment_version_controller.js +2 -1
- data/app/javascript/controllers/comments/__tests__/form_controller_double_submit.test.js +159 -0
- data/app/javascript/controllers/comments/__tests__/presence_controller.test.js +3 -2
- data/app/javascript/controllers/comments/__tests__/topics_controller_delete.test.js +94 -0
- data/app/javascript/controllers/comments/__tests__/topics_controller_topic_list.test.js +61 -0
- data/app/javascript/controllers/comments/form_controller.js +21 -5
- data/app/javascript/controllers/comments/list_controller.js +18 -17
- data/app/javascript/controllers/comments/presence_controller.js +2 -1
- data/app/javascript/controllers/comments/topics_controller.js +61 -8
- data/app/javascript/controllers/common_popup_controller.js +2 -2
- data/app/javascript/controllers/creatives/__tests__/tree_controller.test.js +150 -0
- data/app/javascript/controllers/creatives/import_controller.js +2 -1
- data/app/javascript/controllers/creatives/select_mode_controller.js +2 -1
- data/app/javascript/controllers/creatives/tree_controller.js +142 -1
- data/app/javascript/controllers/image_lightbox_controller.js +2 -1
- data/app/javascript/controllers/inbox_badge_controller.js +33 -0
- data/app/javascript/controllers/index.js +7 -1
- data/app/javascript/controllers/search_popup_controller.js +17 -1
- data/app/javascript/controllers/share_modal_controller.js +4 -3
- data/app/javascript/controllers/topic_list_controller.js +78 -0
- data/app/javascript/controllers/topic_search_controller.js +2 -1
- data/app/javascript/creatives/drag_drop/event_handlers.js +14 -5
- data/app/javascript/creatives/topic_move_members_popup.js +156 -0
- data/app/javascript/creatives/tree_renderer.js +11 -0
- data/app/javascript/lib/__tests__/common_popup_bounds.test.js +58 -0
- data/app/javascript/lib/__tests__/turbo_confirm.test.js +81 -0
- data/app/javascript/lib/__tests__/typo_correction.test.js +192 -0
- data/app/javascript/lib/api/__tests__/api_error.test.js +96 -0
- data/app/javascript/lib/api/__tests__/queue_manager.test.js +88 -1
- data/app/javascript/lib/api/api_error.js +108 -0
- data/app/javascript/lib/api/queue_manager.js +38 -4
- data/app/javascript/lib/common_popup.js +42 -10
- data/app/javascript/lib/editor/__tests__/code_edit_view_token_parity.test.js +121 -0
- data/app/javascript/lib/editor/__tests__/code_language_roundtrip.test.js +152 -0
- data/app/javascript/lib/editor/__tests__/code_languages.test.js +93 -0
- data/app/javascript/lib/editor/code_languages.js +173 -0
- data/app/javascript/lib/editor/code_token_theme.js +41 -0
- data/app/javascript/lib/lexical/__tests__/code_block_toggle.test.js +326 -0
- data/app/javascript/lib/lexical/__tests__/code_fence_shortcut.test.js +179 -0
- data/app/javascript/lib/lexical/__tests__/image_focus.test.js +139 -0
- data/app/javascript/lib/lexical/__tests__/list_tab_indent.test.js +633 -0
- data/app/javascript/lib/lexical/__tests__/markdown_serialize.test.js +627 -0
- data/app/javascript/lib/lexical/__tests__/minimize_html.test.js +20 -1
- data/app/javascript/lib/lexical/__tests__/selection_boundary.test.js +88 -0
- data/app/javascript/lib/lexical/__tests__/table_transformer.test.js +163 -0
- data/app/javascript/lib/lexical/__tests__/trailing_paragraph.test.js +104 -0
- data/app/javascript/lib/lexical/code_block_toggle.js +130 -0
- data/app/javascript/lib/lexical/code_fence_shortcut.js +60 -0
- data/app/javascript/lib/lexical/list_tab_indent.js +210 -0
- data/app/javascript/lib/lexical/markdown_serialize.js +320 -0
- data/app/javascript/lib/lexical/selection_boundary.js +58 -0
- data/app/javascript/lib/lexical/table_transformer.js +182 -0
- data/app/javascript/lib/lexical/trailing_paragraph.js +29 -0
- data/app/javascript/lib/turbo_confirm.js +46 -0
- data/app/javascript/lib/typo_correction.js +146 -0
- data/app/javascript/lib/utils/__tests__/confirm_dialog.test.js +88 -0
- data/app/javascript/lib/utils/__tests__/dialog.test.js +92 -0
- data/app/javascript/lib/utils/__tests__/markdown.test.js +153 -0
- data/app/javascript/lib/utils/__tests__/sanitize_description.test.js +68 -0
- data/app/javascript/lib/utils/__tests__/table_download.test.js +93 -0
- data/app/javascript/lib/utils/confirm_dialog.js +10 -0
- data/app/javascript/lib/utils/dialog.js +300 -0
- data/app/javascript/lib/utils/markdown.js +154 -67
- data/app/javascript/lib/utils/sanitize_description.js +31 -0
- data/app/javascript/lib/utils/table_download.js +15 -0
- data/app/javascript/modules/__tests__/creative_inline_payload.test.js +231 -0
- data/app/javascript/modules/__tests__/creative_save_queue.test.js +228 -0
- data/app/javascript/modules/__tests__/creative_tree_dom.test.js +425 -0
- data/app/javascript/modules/__tests__/typo_corrector.test.js +365 -0
- data/app/javascript/modules/creative_inline_payload.js +86 -0
- data/app/javascript/modules/creative_row_editor.js +231 -471
- data/app/javascript/modules/creative_row_editor_helpers.js +76 -0
- data/app/javascript/modules/creative_save_queue.js +95 -0
- data/app/javascript/modules/creative_tree_dom.js +260 -0
- data/app/javascript/modules/export_to_markdown.js +2 -1
- data/app/javascript/modules/lexical_inline_editor.jsx +2 -1
- data/app/javascript/modules/slide_view.js +11 -2
- data/app/javascript/modules/typo_corrector.js +534 -0
- data/app/jobs/collavre/ai_agent_job.rb +7 -4
- data/app/jobs/collavre/compress_job.rb +6 -2
- data/app/jobs/collavre/permission_cache_job.rb +20 -2
- data/app/jobs/collavre/trigger_loop_check_job.rb +20 -3
- data/app/jobs/collavre/update_mcp_tools_job.rb +17 -0
- data/app/models/collavre/channel.rb +16 -0
- data/app/models/collavre/comment/approvable.rb +16 -0
- data/app/models/collavre/comment/broadcastable.rb +46 -7
- data/app/models/collavre/comment/notifiable.rb +15 -5
- data/app/models/collavre/comment.rb +87 -32
- data/app/models/collavre/comment_version.rb +1 -1
- data/app/models/collavre/creative/describable.rb +104 -19
- data/app/models/collavre/creative/linkable.rb +9 -0
- data/app/models/collavre/creative/permissible.rb +97 -49
- data/app/models/collavre/creative.rb +73 -5
- data/app/models/collavre/creative_share.rb +78 -26
- data/app/models/collavre/inbox_item.rb +2 -2
- data/app/models/collavre/task.rb +27 -0
- data/app/models/collavre/user.rb +90 -10
- data/app/models/concerns/collavre/indexed_json_columns.rb +58 -0
- data/app/services/collavre/agent_type_classifier.rb +23 -0
- data/app/services/collavre/ai_agent/a2a_dispatcher.rb +4 -0
- data/app/services/collavre/ai_agent/message_builder.rb +1 -1
- data/app/services/collavre/ai_agent/session_provisioner.rb +126 -0
- data/app/services/collavre/ai_agent/task_claim_service.rb +96 -0
- data/app/services/collavre/ai_client.rb +81 -12
- data/app/services/collavre/auto_theme_generator.rb +15 -11
- data/app/services/collavre/creatives/children_index.rb +86 -0
- data/app/services/collavre/creatives/comment_badge_index.rb +73 -0
- data/app/services/collavre/creatives/creative_tree_serializer.rb +122 -0
- data/app/services/collavre/creatives/effective_creative_resolution.rb +37 -0
- data/app/services/collavre/creatives/index_query.rb +85 -16
- data/app/services/collavre/creatives/permission_checker.rb +1 -1
- data/app/services/collavre/creatives/permission_filter.rb +144 -17
- data/app/services/collavre/creatives/tree_builder.rb +107 -78
- data/app/services/collavre/gemini_parent_recommender.rb +1 -1
- data/app/services/collavre/http_client.rb +119 -0
- data/app/services/collavre/inbox_reply_service.rb +5 -0
- data/app/services/collavre/link_preview_fetcher.rb +129 -38
- data/app/services/collavre/markdown_converter.rb +13 -3
- data/app/services/collavre/markdown_importer.rb +30 -6
- data/app/services/collavre/mobile/event_summarizer.rb +40 -0
- data/app/services/collavre/orchestration/agent_context_builder.rb +1 -15
- data/app/services/collavre/orchestration/agent_orchestrator.rb +34 -8
- data/app/services/collavre/orchestration/arbiter.rb +16 -0
- data/app/services/collavre/orchestration/matcher.rb +79 -4
- data/app/services/collavre/orchestration/policy_resolver.rb +4 -3
- data/app/services/collavre/orchestration/stuck_detector.rb +141 -34
- data/app/services/collavre/system_events/context_builder.rb +1 -14
- data/app/services/collavre/tools/creative_batch_service.rb +3 -2
- data/app/services/collavre/tools/creative_create_service.rb +8 -8
- data/app/services/collavre/tools/creative_update_service.rb +23 -8
- data/app/services/collavre/tools/preview_attach_service.rb +5 -7
- data/app/services/collavre/typo_corrector.rb +188 -0
- data/app/views/collavre/comments/_comment.html.erb +9 -4
- data/app/views/collavre/comments/_comments_popup.html.erb +25 -4
- data/app/views/collavre/creatives/_inline_edit_form.html.erb +10 -0
- data/app/views/collavre/creatives/_topic_move_members_modal.html.erb +42 -0
- data/app/views/collavre/creatives/index.html.erb +14 -1
- data/app/views/collavre/creatives/slide_view.html.erb +1 -1
- data/app/views/collavre/landing/show.html.erb +52 -10
- data/app/views/collavre/users/show.html.erb +3 -0
- data/app/views/collavre/users/typo_correction.html.erb +50 -0
- data/app/views/layouts/collavre/slide.html.erb +1 -0
- data/config/locales/comments.en.yml +16 -0
- data/config/locales/comments.ko.yml +16 -0
- data/config/locales/creatives.en.yml +6 -0
- data/config/locales/creatives.ko.yml +5 -0
- data/config/locales/integrations.en.yml +1 -1
- data/config/locales/integrations.ko.yml +1 -1
- data/config/locales/landing.en.yml +22 -10
- data/config/locales/landing.ko.yml +22 -10
- data/config/locales/mobile.en.yml +16 -0
- data/config/locales/mobile.ko.yml +16 -0
- data/config/locales/orchestration.en.yml +1 -0
- data/config/locales/orchestration.ko.yml +1 -0
- data/config/locales/users.en.yml +15 -0
- data/config/locales/users.ko.yml +15 -0
- data/config/routes.rb +13 -0
- data/db/migrate/20260120045354_encrypt_oauth_tokens.rb +13 -4
- data/db/migrate/20260612000000_add_topic_concurrency_defer_to_comments.rb +38 -0
- data/db/migrate/20260617090000_add_typo_correction_settings_to_users.rb +18 -0
- data/db/migrate/20260702000001_enforce_system_settings_key_not_null.rb +9 -0
- data/db/migrate/20260702000002_add_creative_index_and_fk_to_tags.rb +11 -0
- data/db/migrate/20260702000003_add_creative_type_index_to_labels.rb +10 -0
- data/db/migrate/20260702000004_add_creative_created_at_index_to_comments.rb +10 -0
- data/db/migrate/20260702000005_promote_channel_config_index_columns.rb +76 -0
- data/db/migrate/20260713000001_add_comments_count_to_creatives.rb +20 -0
- data/db/migrate/20260713000002_add_comment_versions_count_to_comments.rb +20 -0
- data/db/migrate/20260715000000_change_creatives_description_to_plain_text.rb +16 -0
- data/db/seeds.rb +51 -0
- data/lib/collavre/version.rb +1 -1
- data/lib/generators/collavre/install/install_generator.rb +1 -0
- metadata +96 -2
- data/app/services/collavre/tools/description_normalizable.rb +0 -16
|
@@ -101,6 +101,7 @@
|
|
|
101
101
|
<%= f.label :timezone, t('collavre.users.timezone') %>
|
|
102
102
|
<%= f.select :timezone, ActiveSupport::TimeZone.all.map { |tz| [tz.to_s, tz.tzinfo.name] } %>
|
|
103
103
|
</div>
|
|
104
|
+
|
|
104
105
|
<%= f.submit t('collavre.users.update_profile') %>
|
|
105
106
|
<% end %>
|
|
106
107
|
|
|
@@ -109,6 +110,8 @@
|
|
|
109
110
|
<br>
|
|
110
111
|
<%= link_to t('collavre.users.webauthn.manage'), collavre.passkeys_user_path(@user) %>
|
|
111
112
|
<br>
|
|
113
|
+
<%= link_to t('collavre.users.typo_correction.manage'), collavre.typo_correction_user_path(@user) %>
|
|
114
|
+
<br>
|
|
112
115
|
<%= link_to t('doorkeeper.my_applications'), main_app.oauth_applications_path %>
|
|
113
116
|
<% if @user.system_admin? %>
|
|
114
117
|
<br>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<h1 class="no-top-margin"><%= t('collavre.users.typo_correction.legend') %></h1>
|
|
2
|
+
|
|
3
|
+
<%= form_with model: @user, url: collavre.user_path(@user), method: :patch, local: true, html: { class: 'profile-form' } do |f| %>
|
|
4
|
+
<p class="text-muted"><%= t('collavre.users.typo_correction.description') %></p>
|
|
5
|
+
|
|
6
|
+
<div class="checkbox-field">
|
|
7
|
+
<%= f.check_box :typo_correction_enabled %>
|
|
8
|
+
<%= f.label :typo_correction_enabled, t('collavre.users.typo_correction.enabled') %>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<div>
|
|
12
|
+
<%= f.label :typo_correction_threshold, t('collavre.users.typo_correction.threshold') %>
|
|
13
|
+
<%= f.number_field :typo_correction_threshold, in: 0..100, step: 1, required: true %>
|
|
14
|
+
<small class="text-muted"><%= t('collavre.users.typo_correction.threshold_hint') %></small>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<fieldset>
|
|
18
|
+
<legend><%= t('collavre.users.typo_correction.device_legend') %></legend>
|
|
19
|
+
<div class="checkbox-field">
|
|
20
|
+
<%= f.check_box :typo_correction_on_voice %>
|
|
21
|
+
<%= f.label :typo_correction_on_voice, t('collavre.users.typo_correction.on_voice') %>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="checkbox-field">
|
|
24
|
+
<%= f.check_box :typo_correction_on_soft_keyboard %>
|
|
25
|
+
<%= f.label :typo_correction_on_soft_keyboard, t('collavre.users.typo_correction.on_soft_keyboard') %>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="checkbox-field">
|
|
28
|
+
<%= f.check_box :typo_correction_on_physical_keyboard %>
|
|
29
|
+
<%= f.label :typo_correction_on_physical_keyboard, t('collavre.users.typo_correction.on_physical_keyboard') %>
|
|
30
|
+
</div>
|
|
31
|
+
</fieldset>
|
|
32
|
+
|
|
33
|
+
<fieldset>
|
|
34
|
+
<legend><%= t('collavre.users.typo_correction.location_legend') %></legend>
|
|
35
|
+
<div class="checkbox-field">
|
|
36
|
+
<%= f.check_box :typo_correction_in_chat %>
|
|
37
|
+
<%= f.label :typo_correction_in_chat, t('collavre.users.typo_correction.in_chat') %>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="checkbox-field">
|
|
40
|
+
<%= f.check_box :typo_correction_in_editor %>
|
|
41
|
+
<%= f.label :typo_correction_in_editor, t('collavre.users.typo_correction.in_editor') %>
|
|
42
|
+
</div>
|
|
43
|
+
</fieldset>
|
|
44
|
+
|
|
45
|
+
<%= f.submit t('collavre.users.update') %>
|
|
46
|
+
<% end %>
|
|
47
|
+
|
|
48
|
+
<div style="margin-top: 1rem;">
|
|
49
|
+
<%= link_to t('collavre.users.back'), collavre.user_path(@user) %>
|
|
50
|
+
</div>
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
<%= stylesheet_link_tag "collavre/design_tokens" %>
|
|
11
11
|
<%= stylesheet_link_tag "collavre/dark_mode" %>
|
|
12
12
|
<%= stylesheet_link_tag 'collavre/slide_view', media: 'all' %>
|
|
13
|
+
<%= stylesheet_link_tag 'collavre/tables', media: 'all' %>
|
|
13
14
|
<%= javascript_include_tag 'actioncable', defer: true %>
|
|
14
15
|
<%= javascript_include_tag 'slide_view', defer: true %>
|
|
15
16
|
<%= render 'collavre/shared/custom_theme_style' %>
|
|
@@ -18,6 +18,17 @@ en:
|
|
|
18
18
|
move:
|
|
19
19
|
no_target_permission: You don't have write permission on the target creative.
|
|
20
20
|
duplicate_name: A topic named '%{name}' already exists in the target creative.
|
|
21
|
+
add_members:
|
|
22
|
+
title: Add members to the new location?
|
|
23
|
+
description: These people had access where the topic used to live, but not in "%{creative}". Add them so they keep access.
|
|
24
|
+
add: Add selected
|
|
25
|
+
skip: Not now
|
|
26
|
+
adding: Adding…
|
|
27
|
+
added:
|
|
28
|
+
one: 1 member added.
|
|
29
|
+
other: "%{count} members added."
|
|
30
|
+
partial: "%{added} added, %{failed} failed."
|
|
31
|
+
failed: Could not add members. Please try again.
|
|
21
32
|
github_auth:
|
|
22
33
|
login_first: Please sign in first.
|
|
23
34
|
connected: Github account connected successfully.
|
|
@@ -129,8 +140,12 @@ en:
|
|
|
129
140
|
batch_delete_not_found: Some selected messages could not be found.
|
|
130
141
|
topic_search_placeholder: Search topics...
|
|
131
142
|
topic_main: All Messages
|
|
143
|
+
topic_list: Topic list
|
|
132
144
|
fullscreen: Full screen
|
|
133
145
|
exit_fullscreen: Exit full screen
|
|
146
|
+
typo_keep_label: keep
|
|
147
|
+
typo_custom_label: custom
|
|
148
|
+
typo_input_label: correction
|
|
134
149
|
move_invalid_target: Select a valid creative to move messages to.
|
|
135
150
|
move_invalid_topic: Invalid topic selected.
|
|
136
151
|
move_not_allowed: You do not have permission to move these messages.
|
|
@@ -200,6 +215,7 @@ en:
|
|
|
200
215
|
delete_confirm: Are you sure you want to delete this version?
|
|
201
216
|
select: Select
|
|
202
217
|
stop_agent: Stop
|
|
218
|
+
stop_blocking_agent: Stop running task
|
|
203
219
|
read_by: Read by %{name}
|
|
204
220
|
activity_logs_summary: Activity Logs
|
|
205
221
|
table_download:
|
|
@@ -18,6 +18,17 @@ ko:
|
|
|
18
18
|
move:
|
|
19
19
|
no_target_permission: 대상 크리에이티브에 대한 쓰기 권한이 없습니다.
|
|
20
20
|
duplicate_name: "'%{name}' 토픽이 대상 크리에이티브에 이미 존재합니다."
|
|
21
|
+
add_members:
|
|
22
|
+
title: 새 위치에 멤버를 추가할까요?
|
|
23
|
+
description: 이 사람들은 토픽이 있던 곳에는 접근할 수 있었지만 "%{creative}"에는 없습니다. 계속 접근할 수 있도록 추가하세요.
|
|
24
|
+
add: 선택 추가
|
|
25
|
+
skip: 나중에
|
|
26
|
+
adding: 추가 중…
|
|
27
|
+
added:
|
|
28
|
+
one: 멤버 1명을 추가했습니다.
|
|
29
|
+
other: 멤버 %{count}명을 추가했습니다.
|
|
30
|
+
partial: "%{added}명 추가, %{failed}명 실패."
|
|
31
|
+
failed: 멤버를 추가하지 못했습니다. 다시 시도해 주세요.
|
|
21
32
|
github_auth:
|
|
22
33
|
login_first: 먼저 로그인해주세요.
|
|
23
34
|
connected: Github 계정이 연동되었습니다.
|
|
@@ -126,8 +137,12 @@ ko:
|
|
|
126
137
|
batch_delete_not_found: 일부 선택한 메시지를 찾을 수 없습니다.
|
|
127
138
|
topic_search_placeholder: 토픽 검색...
|
|
128
139
|
topic_main: 전체 메세지
|
|
140
|
+
topic_list: 토픽 목록
|
|
129
141
|
fullscreen: 전체 화면
|
|
130
142
|
exit_fullscreen: 전체 화면 종료
|
|
143
|
+
typo_keep_label: 유지
|
|
144
|
+
typo_custom_label: 직접 입력
|
|
145
|
+
typo_input_label: 교정
|
|
131
146
|
move_invalid_target: 이동할 크리에이티브를 선택해주세요.
|
|
132
147
|
move_invalid_topic: 유효하지 않은 토픽입니다.
|
|
133
148
|
move_not_allowed: 이 메시지를 이동할 권한이 없습니다.
|
|
@@ -197,6 +212,7 @@ ko:
|
|
|
197
212
|
delete_confirm: 이 버전을 삭제하시겠습니까?
|
|
198
213
|
select: 선택
|
|
199
214
|
stop_agent: 중지
|
|
215
|
+
stop_blocking_agent: 실행 중 작업 중지
|
|
200
216
|
read_by: "%{name} 님이 읽음"
|
|
201
217
|
activity_logs_summary: 활동 기록
|
|
202
218
|
table_download:
|
|
@@ -136,6 +136,10 @@ en:
|
|
|
136
136
|
metadata_save: Save
|
|
137
137
|
toggle_markdown: Markdown
|
|
138
138
|
toggle_richtext: Rich Text
|
|
139
|
+
save_status_pending: Save pending
|
|
140
|
+
save_status_saving: Saving…
|
|
141
|
+
save_status_saved: Saved
|
|
142
|
+
save_status_error: Save failed
|
|
139
143
|
markdown_to_richtext_confirm: Switching to Rich Text will discard the Markdown
|
|
140
144
|
source. Continue?
|
|
141
145
|
richtext_to_markdown_confirm: Switching to Markdown will discard the current
|
|
@@ -156,6 +160,8 @@ en:
|
|
|
156
160
|
errors:
|
|
157
161
|
no_permission: You do not have permission to perform this action.
|
|
158
162
|
metadata_must_be_object: Metadata must be an object.
|
|
163
|
+
description_read_only_source: cannot be changed directly for read-only source
|
|
164
|
+
content
|
|
159
165
|
inline_editor:
|
|
160
166
|
placeholder: Describe the creative…
|
|
161
167
|
markdown_placeholder: Write in Markdown…
|
|
@@ -124,6 +124,10 @@ ko:
|
|
|
124
124
|
metadata_save: 저장
|
|
125
125
|
toggle_markdown: 마크다운
|
|
126
126
|
toggle_richtext: 서식 편집
|
|
127
|
+
save_status_pending: 저장 대기중
|
|
128
|
+
save_status_saving: 저장중…
|
|
129
|
+
save_status_saved: 저장됨
|
|
130
|
+
save_status_error: 저장 실패
|
|
127
131
|
markdown_to_richtext_confirm: 서식 편집으로 전환하면 마크다운 원본이 삭제됩니다.
|
|
128
132
|
계속하시겠습니까?
|
|
129
133
|
richtext_to_markdown_confirm: 마크다운으로 전환하면 현재 서식 편집 내용이 삭제됩니다. 계속하시겠습니까?
|
|
@@ -142,6 +146,7 @@ ko:
|
|
|
142
146
|
errors:
|
|
143
147
|
no_permission: 이 작업을 수행할 권한이 없습니다.
|
|
144
148
|
metadata_must_be_object: 메타데이터는 객체여야 합니다.
|
|
149
|
+
description_read_only_source: 읽기 전용 소스 콘텐츠는 직접 변경할 수 없습니다
|
|
145
150
|
inline_editor:
|
|
146
151
|
placeholder: 크리에이티브를 설명해주세요…
|
|
147
152
|
markdown_placeholder: 마크다운으로 작성…
|
|
@@ -46,7 +46,7 @@ en:
|
|
|
46
46
|
firebase_service_account_json: "Paste the full JSON body of a Google Cloud service account key. Recommended path for server FCM auth — set this and you're done. Generate at Firebase Console → Project Settings → Service Accounts → Generate New Private Key. Takes precedence over WIF."
|
|
47
47
|
fcm_wif_audience: "Optional WIF override (AWS only). Used only when the JSON key above is empty. Leave blank to derive it in production from Sender ID using the default aws-pool/aws-provider. Override for non-default pools: //iam.googleapis.com/projects/{PROJECT_NUMBER}/locations/global/workloadIdentityPools/{POOL_ID}/providers/{PROVIDER_ID}."
|
|
48
48
|
fcm_wif_credential_source: "Optional WIF override: AWS credential source JSON (IMDS endpoints). Leave blank to use the default AWS IMDS endpoints. Override example: {\"environment_id\":\"aws1\",\"region_url\":\"http://169.254.169.254/latest/meta-data/placement/availability-zone\",\"url\":\"http://169.254.169.254/latest/meta-data/iam/security-credentials\",\"regional_cred_verification_url\":\"https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15\"}"
|
|
49
|
-
fcm_wif_service_account_email: "GCP service account email to impersonate via WIF (e.g. firebase-sender@PROJECT.iam.gserviceaccount.com). Used only in WIF mode.
|
|
49
|
+
fcm_wif_service_account_email: "GCP service account email to impersonate via WIF (e.g. firebase-sender@PROJECT.iam.gserviceaccount.com). Used only in WIF mode. Falls back to the FCM_WIF_SERVICE_ACCOUNT_EMAIL env var."
|
|
50
50
|
fcm_sender_id: "Web-push only: messagingSenderId for the Firebase JS SDK (project number). Required for browser push subscriptions. Find at Firebase Console → Project Settings → Cloud Messaging → Sender ID."
|
|
51
51
|
fcm_vapid_key: "Web-push only: VAPID public key for browser push subscriptions. Generate at Firebase Console → Project Settings → Cloud Messaging → Web configuration → Web Push certificates."
|
|
52
52
|
fcm_server_key: "Legacy FCM server key (deprecated by Google). Only set this if you have legacy clients using the old HTTP v0 API."
|
|
@@ -46,7 +46,7 @@ ko:
|
|
|
46
46
|
firebase_service_account_json: "Google Cloud 서비스 계정 키 JSON 본문 전체를 붙여넣으세요. 서버 FCM 인증의 권장 경로 — 이 값만 설정하면 끝납니다. Firebase Console → 프로젝트 설정 → 서비스 계정 → 새 비공개 키 생성. WIF 보다 우선합니다."
|
|
47
47
|
fcm_wif_audience: "선택적 WIF 오버라이드 (AWS 전용). 위 JSON 키가 비어있을 때만 사용됩니다. 비워두면 production 에서 Sender ID 로부터 기본 aws-pool/aws-provider 를 사용해 자동 생성됩니다. 비표준 풀 오버라이드: //iam.googleapis.com/projects/{PROJECT_NUMBER}/locations/global/workloadIdentityPools/{POOL_ID}/providers/{PROVIDER_ID}."
|
|
48
48
|
fcm_wif_credential_source: "선택적 WIF 오버라이드: AWS credential source JSON (IMDS 엔드포인트). 비워두면 기본 AWS IMDS 엔드포인트를 사용합니다. 오버라이드 예시: {\"environment_id\":\"aws1\",\"region_url\":\"http://169.254.169.254/latest/meta-data/placement/availability-zone\",\"url\":\"http://169.254.169.254/latest/meta-data/iam/security-credentials\",\"regional_cred_verification_url\":\"https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15\"}"
|
|
49
|
-
fcm_wif_service_account_email: "WIF 로 임퍼소네이션할 GCP 서비스 계정 이메일 (예: firebase-sender@PROJECT.iam.gserviceaccount.com). WIF 모드에서만 사용됩니다.
|
|
49
|
+
fcm_wif_service_account_email: "WIF 로 임퍼소네이션할 GCP 서비스 계정 이메일 (예: firebase-sender@PROJECT.iam.gserviceaccount.com). WIF 모드에서만 사용됩니다. FCM_WIF_SERVICE_ACCOUNT_EMAIL 환경변수를 폴백으로 읽습니다."
|
|
50
50
|
fcm_sender_id: "웹 푸시 전용: Firebase JS SDK 의 messagingSenderId (프로젝트 번호). 브라우저 푸시 구독에 필수. Firebase Console → 프로젝트 설정 → 클라우드 메시징 → 발신자 ID 에서 확인."
|
|
51
51
|
fcm_vapid_key: "웹 푸시 전용: 브라우저 푸시 구독용 VAPID 공개키. Firebase Console → 프로젝트 설정 → 클라우드 메시징 → 웹 구성 → 웹 푸시 인증서에서 생성."
|
|
52
52
|
fcm_server_key: "Legacy FCM 서버 키 (Google 에서 deprecated). 구버전 HTTP v0 API 를 쓰는 클라이언트가 있을 때만 설정하세요."
|
|
@@ -3,30 +3,28 @@ en:
|
|
|
3
3
|
landing:
|
|
4
4
|
meta:
|
|
5
5
|
title: "Where Teams Think Together"
|
|
6
|
-
description: "The collaborative workspace where hierarchical
|
|
6
|
+
description: "The collaborative workspace where hierarchical blocks, AI agents, and real-time chat come together. Organize, collaborate, and ship — with AI as your teammate."
|
|
7
7
|
hero:
|
|
8
8
|
headline_html: "A platform for both AI agents and people."
|
|
9
9
|
subline: "Achieve sustainable productivity gains."
|
|
10
10
|
learn_more: "Learn More"
|
|
11
|
-
demo:
|
|
12
|
-
title: "See it in action"
|
|
13
|
-
placeholder: "Product demo video goes here"
|
|
14
11
|
problem:
|
|
15
12
|
title: "Your tools are failing you"
|
|
13
|
+
subtitle: "Docs, trackers, chat — you write the same thing in all three, then spend the day moving between them to keep them in sync. Don't repeat yourself."
|
|
16
14
|
notion:
|
|
17
|
-
title: "
|
|
15
|
+
title: "Docs"
|
|
18
16
|
desc: "Docs become graveyards. Nobody edits someone else's page. Search replaces structure."
|
|
19
17
|
jira:
|
|
20
|
-
title: "
|
|
18
|
+
title: "Trackers"
|
|
21
19
|
desc: "Great for tasks, terrible for knowledge. Results never sync back to the wiki. Information overload."
|
|
22
20
|
slack:
|
|
23
|
-
title: "
|
|
21
|
+
title: "Chat"
|
|
24
22
|
desc: "Conversations vanish in the stream. Flat channel lists explode. Context is lost daily."
|
|
25
23
|
features:
|
|
26
24
|
title: "Everything in one living tree"
|
|
27
|
-
subtitle: "
|
|
25
|
+
subtitle: "Write it once. Every block is a doc, a task, and a discussion at the same time — one source of truth, self-hosted in your own database, that you inject straight into your AI agents."
|
|
28
26
|
tree:
|
|
29
|
-
title: "Hierarchical
|
|
27
|
+
title: "Hierarchical blocks"
|
|
30
28
|
desc: "Organize work as a tree. Drag, link, and reuse blocks across projects. Progress rolls up automatically."
|
|
31
29
|
ai:
|
|
32
30
|
title: "AI Agents as Teammates"
|
|
@@ -36,13 +34,27 @@ en:
|
|
|
36
34
|
desc: "Reduce cognitive load for people, and inject the knowledge and skills AI needs."
|
|
37
35
|
chat:
|
|
38
36
|
title: "Real-time Chat & Topics"
|
|
39
|
-
desc: "Every
|
|
37
|
+
desc: "Every block has a chat. Organize conversations with topics, move messages between blocks, and keep discussions focused."
|
|
40
38
|
integrations:
|
|
41
39
|
title: "Integrations"
|
|
42
40
|
desc: "GitHub PRs auto-analyzed, Slack messages synced, Google Calendar events linked, MCP tools built-in."
|
|
43
41
|
progress:
|
|
44
42
|
title: "Live Progress"
|
|
45
43
|
desc: "Track completion from leaf to root. Filter by tags, plans, or status. See your project's real health at a glance."
|
|
44
|
+
interface:
|
|
45
|
+
title: "The document is the tree"
|
|
46
|
+
subtitle: "A heading, a paragraph, a code block, a table — each one is a block, carrying its own progress on the right and its own thread inside. You do not fill in a tracker. You write the spec, and the plan is already there."
|
|
47
|
+
alt: "A refund spec in Collavre. Prose, a syntax-highlighted code block and a table sit as siblings next to work items, each with its own progress and its own discussion."
|
|
48
|
+
markdown: "Markdown-first. Flip any block between rich text and raw markdown."
|
|
49
|
+
rich: "Fenced code with syntax highlighting, tables, images — rendered in the tree, not hidden behind a detail page."
|
|
50
|
+
drag: "Drag a block and its whole subtree comes with it."
|
|
51
|
+
presence: "See who is in the document and who is editing which block."
|
|
52
|
+
demo:
|
|
53
|
+
title: "See it in action"
|
|
54
|
+
video: "https://collavre.com/public-assets/blobs/eyJfcmFpbHMiOnsiZGF0YSI6NDY2LCJwdXIiOiJibG9iX2lkIn19--724536948e4fa3474e57997958427e1850775c08/launch.mp4"
|
|
55
|
+
poster: "https://collavre.com/public-assets/blobs/eyJfcmFpbHMiOnsiZGF0YSI6NDY3LCJwdXIiOiJibG9iX2lkIn19--7713d27bd154806053991bc8e8abca60475a2ab8/launch-poster.jpg"
|
|
56
|
+
video_dark: "https://collavre.com/public-assets/blobs/eyJfcmFpbHMiOnsiZGF0YSI6NDY4LCJwdXIiOiJibG9iX2lkIn19--63349dc7270a3e6a0503c45a413d3b176f791dc2/launch-dark.mp4"
|
|
57
|
+
poster_dark: "https://collavre.com/public-assets/blobs/eyJfcmFpbHMiOnsiZGF0YSI6NDY5LCJwdXIiOiJibG9iX2lkIn19--25a756ed0d6ff5b4f40ef864b8216c7aa540449c/launch-dark-poster.jpg"
|
|
46
58
|
cta:
|
|
47
59
|
title: "Ready to collaborate smarter?"
|
|
48
60
|
subtitle: "Start organizing your work with AI-powered context."
|
|
@@ -3,30 +3,28 @@ ko:
|
|
|
3
3
|
landing:
|
|
4
4
|
meta:
|
|
5
5
|
title: "팀이 함께 생각하는 곳"
|
|
6
|
-
description: "계층형
|
|
6
|
+
description: "계층형 블록, AI 에이전트, 실시간 채팅이 하나로. 체계적으로 정리하고, 협업하고, AI와 함께 완성하세요."
|
|
7
7
|
hero:
|
|
8
8
|
headline_html: "AI 에이전트와 사람 모두의 플랫폼."
|
|
9
9
|
subline: "지속 가능한 생산성 향상을 이루세요."
|
|
10
10
|
learn_more: "알아보기"
|
|
11
|
-
demo:
|
|
12
|
-
title: "직접 확인하세요"
|
|
13
|
-
placeholder: "실제 작동 화면이 들어갈 자리입니다"
|
|
14
11
|
problem:
|
|
15
12
|
title: "기존 도구의 한계"
|
|
13
|
+
subtitle: "문서에, 트래커에, 대화에 — 같은 걸 세 군데에 쓰고, 하루 종일 그 사이를 오가며 셋을 맞춥니다. 반복하지 마세요."
|
|
16
14
|
notion:
|
|
17
|
-
title: "
|
|
15
|
+
title: "문서"
|
|
18
16
|
desc: "문서는 무덤이 됩니다. 남의 페이지를 고치기 꺼려하고, 검색이 구조를 대체합니다."
|
|
19
17
|
jira:
|
|
20
|
-
title: "
|
|
18
|
+
title: "트래커"
|
|
21
19
|
desc: "작업 관리는 좋지만 지식 관리는 안 됩니다. 결과물이 위키로 돌아오지 않습니다."
|
|
22
20
|
slack:
|
|
23
|
-
title: "
|
|
21
|
+
title: "대화"
|
|
24
22
|
desc: "대화가 흘러가 버립니다. 채널은 폭발적으로 늘어나고, 맥락은 매일 사라집니다."
|
|
25
23
|
features:
|
|
26
24
|
title: "하나의 살아있는 트리로"
|
|
27
|
-
subtitle: "
|
|
25
|
+
subtitle: "한 번만 쓰세요. 모든 블록이 문서이자 일감이자 대화입니다 — 셀프호스트로 자신의 DB에 쌓이는 하나의 SSOT를, 그대로 AI 에이전트에 주입합니다."
|
|
28
26
|
tree:
|
|
29
|
-
title: "계층형
|
|
27
|
+
title: "계층형 블록"
|
|
30
28
|
desc: "작업을 트리로 구성하세요. 드래그, 링크, 재사용이 자유롭고 진행률은 자동 계산됩니다."
|
|
31
29
|
ai:
|
|
32
30
|
title: "AI 에이전트 팀원"
|
|
@@ -36,13 +34,27 @@ ko:
|
|
|
36
34
|
desc: "사람의 인지 부하를 줄이고, AI에게 필요한 지식과 Skill을 주입합니다."
|
|
37
35
|
chat:
|
|
38
36
|
title: "실시간 채팅 & 토픽"
|
|
39
|
-
desc: "모든
|
|
37
|
+
desc: "모든 블록에 채팅이 있습니다. 토픽으로 대화를 정리하고, 메시지를 다른 블록으로 옮기세요."
|
|
40
38
|
integrations:
|
|
41
39
|
title: "외부 연동"
|
|
42
40
|
desc: "GitHub PR 자동 분석, Slack 동기화, Google Calendar 연동, MCP 도구 내장."
|
|
43
41
|
progress:
|
|
44
42
|
title: "실시간 진행률"
|
|
45
43
|
desc: "리프부터 루트까지 완료율 추적. 태그, 계획, 상태별 필터. 프로젝트 건강도를 한눈에."
|
|
44
|
+
interface:
|
|
45
|
+
title: "문서가 곧 트리입니다"
|
|
46
|
+
subtitle: "헤딩도, 문단도, 코드 블록도, 표도 각각 하나의 블록입니다. 저마다 오른쪽에 자기 진행률을 달고, 안에 자기 대화를 품습니다. 트래커를 채우는 게 아니라 스펙을 쓰면, 계획은 이미 거기 있습니다."
|
|
47
|
+
alt: "Collavre의 환불 스펙 화면. 산문과 문법 강조된 코드 블록과 표가 일감들과 나란히 놓여 있고, 각자 자기 진행률과 대화를 가지고 있습니다."
|
|
48
|
+
markdown: "마크다운이 먼저입니다. 어느 블록이든 리치 텍스트와 원본 마크다운을 오갈 수 있습니다."
|
|
49
|
+
rich: "코드 펜스 문법 강조, 표, 이미지 — 상세 페이지 뒤에 숨지 않고 트리에서 바로 보입니다."
|
|
50
|
+
drag: "블록을 끌면 그 아래 서브트리가 통째로 따라옵니다."
|
|
51
|
+
presence: "누가 문서에 들어와 있고 누가 어느 블록을 편집 중인지 보입니다."
|
|
52
|
+
demo:
|
|
53
|
+
title: "직접 확인하세요"
|
|
54
|
+
video: "https://collavre.com/public-assets/blobs/eyJfcmFpbHMiOnsiZGF0YSI6NDcwLCJwdXIiOiJibG9iX2lkIn19--d2e47d9773e9179a4f6a2a69f5740f3551c69e08/launch-ko.mp4"
|
|
55
|
+
poster: "https://collavre.com/public-assets/blobs/eyJfcmFpbHMiOnsiZGF0YSI6NDcxLCJwdXIiOiJibG9iX2lkIn19--9d63bb60ec693416eddd73ea3ff3532bc09ed71e/launch-ko-poster.jpg"
|
|
56
|
+
video_dark: "https://collavre.com/public-assets/blobs/eyJfcmFpbHMiOnsiZGF0YSI6NDcyLCJwdXIiOiJibG9iX2lkIn19--6d635234d2070b43f16c404a9e81e7642062c172/launch-ko-dark.mp4"
|
|
57
|
+
poster_dark: "https://collavre.com/public-assets/blobs/eyJfcmFpbHMiOnsiZGF0YSI6NDczLCJwdXIiOiJibG9iX2lkIn19--094d1e6e8691ea987effeca29195e5fc313bff33/launch-ko-dark-poster.jpg"
|
|
46
58
|
cta:
|
|
47
59
|
title: "더 똑똑하게 협업할 준비 되셨나요?"
|
|
48
60
|
subtitle: "AI 기반 컨텍스트로 작업을 정리하세요."
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
en:
|
|
2
|
+
collavre:
|
|
3
|
+
mobile:
|
|
4
|
+
default_task_label: "Task"
|
|
5
|
+
summary:
|
|
6
|
+
a_tool: "a tool"
|
|
7
|
+
approval: "%{label}. Approval requested: %{detail}. Approve it?"
|
|
8
|
+
reply:
|
|
9
|
+
approved: "Approved."
|
|
10
|
+
denied: "Denied."
|
|
11
|
+
already_decided: "That was already decided."
|
|
12
|
+
not_authorized: "You're not allowed to decide that one — it may need an administrator."
|
|
13
|
+
clarify_decision: "Sorry, did you want to approve or deny?"
|
|
14
|
+
empty_response: "I didn't catch a response."
|
|
15
|
+
relayed: "Sent your reply to the agent."
|
|
16
|
+
sent: "Sent."
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
ko:
|
|
2
|
+
collavre:
|
|
3
|
+
mobile:
|
|
4
|
+
default_task_label: "작업"
|
|
5
|
+
summary:
|
|
6
|
+
a_tool: "도구 실행"
|
|
7
|
+
approval: "%{label}. 승인 요청: %{detail}. 승인할까요?"
|
|
8
|
+
reply:
|
|
9
|
+
approved: "승인했습니다."
|
|
10
|
+
denied: "거절했습니다."
|
|
11
|
+
already_decided: "이미 결정된 항목입니다."
|
|
12
|
+
not_authorized: "그 항목은 결정할 권한이 없습니다. 관리자 승인이 필요할 수 있습니다."
|
|
13
|
+
clarify_decision: "승인할까요, 거절할까요?"
|
|
14
|
+
empty_response: "응답을 듣지 못했습니다."
|
|
15
|
+
relayed: "에이전트에게 답변을 전달했습니다."
|
|
16
|
+
sent: "전송했습니다."
|
|
@@ -4,6 +4,7 @@ en:
|
|
|
4
4
|
waiting_notice: "⏳ Waiting (%{reason})"
|
|
5
5
|
waiting_reasons:
|
|
6
6
|
topic_concurrency: "another task is running in this topic"
|
|
7
|
+
topic_concurrency_with_agent: "@%{agent} is running another task in this topic"
|
|
7
8
|
busy: "agent concurrency limit reached"
|
|
8
9
|
rate_limited: "rate limit reached"
|
|
9
10
|
unknown: "waiting for resources"
|
data/config/locales/users.en.yml
CHANGED
|
@@ -102,6 +102,7 @@ en:
|
|
|
102
102
|
current_avatar: Current avatar
|
|
103
103
|
new_avatar_preview: New avatar preview
|
|
104
104
|
update_profile: Update Profile
|
|
105
|
+
update: Update
|
|
105
106
|
delete: Delete
|
|
106
107
|
make_system_admin: Make system admin
|
|
107
108
|
make_normal_user: Make normal user
|
|
@@ -120,6 +121,20 @@ en:
|
|
|
120
121
|
en: English
|
|
121
122
|
ko: Korean
|
|
122
123
|
timezone: Timezone
|
|
124
|
+
typo_correction:
|
|
125
|
+
legend: Typo correction
|
|
126
|
+
manage: Typo correction settings
|
|
127
|
+
description: Automatically suggest and fix typos as you type. Suggestions run only when both the typing device and the input location below are enabled.
|
|
128
|
+
enabled: Enable typo correction
|
|
129
|
+
threshold: Auto-apply threshold
|
|
130
|
+
threshold_hint: Edits at or above this confidence (0-100) are applied automatically; lower-confidence edits are only suggested.
|
|
131
|
+
device_legend: Typing devices
|
|
132
|
+
on_voice: Voice input
|
|
133
|
+
on_soft_keyboard: On-screen (soft) keyboard
|
|
134
|
+
on_physical_keyboard: Physical keyboard (Bluetooth/wired)
|
|
135
|
+
location_legend: Input locations
|
|
136
|
+
in_chat: Chat message input
|
|
137
|
+
in_editor: Creative editor
|
|
123
138
|
profile_updated: Profile updated successfully.
|
|
124
139
|
avatar_updated: Avatar updated successfully.
|
|
125
140
|
password_updated: Password updated successfully.
|
data/config/locales/users.ko.yml
CHANGED
|
@@ -97,6 +97,7 @@ ko:
|
|
|
97
97
|
current_avatar: 현재 아바타
|
|
98
98
|
new_avatar_preview: 새 아바타 미리보기
|
|
99
99
|
update_profile: 프로파일 업데이트
|
|
100
|
+
update: 업데이트
|
|
100
101
|
delete: 삭제
|
|
101
102
|
make_system_admin: 시스템 관리자 지정
|
|
102
103
|
make_normal_user: 일반 사용자로 변경
|
|
@@ -115,6 +116,20 @@ ko:
|
|
|
115
116
|
en: 영어
|
|
116
117
|
ko: 한국어
|
|
117
118
|
timezone: 시간대
|
|
119
|
+
typo_correction:
|
|
120
|
+
legend: 오타 자동 수정
|
|
121
|
+
manage: 오타 자동 수정 설정
|
|
122
|
+
description: 입력하는 동안 오타를 자동으로 제안하고 수정합니다. 아래의 타이핑 장치와 입력 위치가 모두 켜져 있을 때만 동작합니다.
|
|
123
|
+
enabled: 오타 자동 수정 사용
|
|
124
|
+
threshold: 자동 적용 기준
|
|
125
|
+
threshold_hint: 이 신뢰도(0-100) 이상이면 자동으로 적용되고, 낮으면 후보로만 표시됩니다.
|
|
126
|
+
device_legend: 타이핑 장치
|
|
127
|
+
on_voice: 음성 입력
|
|
128
|
+
on_soft_keyboard: 화면(소프트) 키보드
|
|
129
|
+
on_physical_keyboard: 물리 키보드(블루투스/유선)
|
|
130
|
+
location_legend: 입력 위치
|
|
131
|
+
in_chat: 채팅 메시지 입력
|
|
132
|
+
in_editor: 크리에이티브 편집기
|
|
118
133
|
profile_updated: 프로파일이 업데이트되었습니다.
|
|
119
134
|
avatar_updated: 아바타가 변경되었습니다.
|
|
120
135
|
password_updated: 비밀번호가 성공적으로 변경되었습니다.
|
data/config/routes.rb
CHANGED
|
@@ -23,6 +23,7 @@ Collavre::Engine.routes.draw do
|
|
|
23
23
|
get :edit_password
|
|
24
24
|
patch :update_password
|
|
25
25
|
get :passkeys
|
|
26
|
+
get :typo_correction
|
|
26
27
|
end
|
|
27
28
|
end
|
|
28
29
|
get "/email_verification/:token", to: "email_verifications#show", as: :email_verification
|
|
@@ -51,6 +52,8 @@ Collavre::Engine.routes.draw do
|
|
|
51
52
|
end
|
|
52
53
|
end
|
|
53
54
|
|
|
55
|
+
resources :typo_corrections, only: [ :create ]
|
|
56
|
+
|
|
54
57
|
resources :creative_imports, only: [ :create ]
|
|
55
58
|
resources :tasks, only: [] do
|
|
56
59
|
member do
|
|
@@ -145,6 +148,16 @@ Collavre::Engine.routes.draw do
|
|
|
145
148
|
post "agent/reply", to: "agents#reply"
|
|
146
149
|
post "agent/notify", to: "agents#notify"
|
|
147
150
|
delete "agent/:id", to: "agents#destroy"
|
|
151
|
+
|
|
152
|
+
# Mobile voice companion (Android): poll Inbox#System messages, read aloud,
|
|
153
|
+
# reply to the origin topic; a cold mic press starts work in Inbox#Main.
|
|
154
|
+
namespace :mobile do
|
|
155
|
+
post "voice_commands", to: "voice_commands#create"
|
|
156
|
+
get "agent_events", to: "agent_events#index"
|
|
157
|
+
post "agent_events/:id/respond", to: "agent_events#respond"
|
|
158
|
+
post "agent_events/:id/read", to: "agent_events#read"
|
|
159
|
+
post "devices", to: "devices#create"
|
|
160
|
+
end
|
|
148
161
|
end
|
|
149
162
|
end
|
|
150
163
|
|
|
@@ -7,12 +7,21 @@ class EncryptOauthTokens < ActiveRecord::Migration[8.1]
|
|
|
7
7
|
encrypt_column(User, :google_refresh_token)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
# Vendor account tokens live in vendor engines. Guard each block so this
|
|
11
|
+
# core migration runs cleanly on an install where the engine is absent
|
|
12
|
+
# (the constant would otherwise raise NameError). When the engine is
|
|
13
|
+
# present on a fresh DB there are no plaintext rows yet, so the block is a
|
|
14
|
+
# no-op; encryption of new writes is handled by the model's `encrypts`.
|
|
15
|
+
if defined?(CollavreGithub::Account)
|
|
16
|
+
say_with_time "Encrypting CollavreGithub::Account tokens" do
|
|
17
|
+
encrypt_column(CollavreGithub::Account, :token)
|
|
18
|
+
end
|
|
12
19
|
end
|
|
13
20
|
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
if defined?(CollavreNotion::NotionAccount)
|
|
22
|
+
say_with_time "Encrypting CollavreNotion::NotionAccount tokens" do
|
|
23
|
+
encrypt_column(CollavreNotion::NotionAccount, :token)
|
|
24
|
+
end
|
|
16
25
|
end
|
|
17
26
|
end
|
|
18
27
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# A persisted, locale-independent marker distinguishing a topic-concurrency
|
|
4
|
+
# waiting notice (:deferred — queues a topic waiter, so its stop button can
|
|
5
|
+
# cancel the blocker) from a :delayed (busy / rate_limited) notice that reuses
|
|
6
|
+
# the same "⏳" content but is not waiting on topic capacity. Content is locale
|
|
7
|
+
# text and task_id is reserved for Task#reply_comment, so neither can carry this
|
|
8
|
+
# signal — hence a dedicated column.
|
|
9
|
+
class AddTopicConcurrencyDeferToComments < ActiveRecord::Migration[8.1]
|
|
10
|
+
def up
|
|
11
|
+
add_column :comments, :topic_concurrency_defer, :boolean, default: false, null: false
|
|
12
|
+
|
|
13
|
+
# Backfill pre-migration notices. The old gate treated every authorless "⏳"
|
|
14
|
+
# notice as a concurrency notice (prefix-only). Without this, legacy notices
|
|
15
|
+
# default to false and the new marker gates would hide their stop button and
|
|
16
|
+
# stop deleting them from abandoning their queued waiter. Mark only the ones
|
|
17
|
+
# that genuinely have a queued waiter in the same topic/creative — the same
|
|
18
|
+
# condition the runtime gate (topic_blocking_task) checks — so :delayed
|
|
19
|
+
# notices (no queued waiter) correctly stay false.
|
|
20
|
+
execute(<<~SQL.squish)
|
|
21
|
+
UPDATE comments
|
|
22
|
+
SET topic_concurrency_defer = #{quoted_true}
|
|
23
|
+
WHERE user_id IS NULL
|
|
24
|
+
AND topic_id IS NOT NULL
|
|
25
|
+
AND content LIKE '⏳%'
|
|
26
|
+
AND EXISTS (
|
|
27
|
+
SELECT 1 FROM tasks
|
|
28
|
+
WHERE tasks.topic_id = comments.topic_id
|
|
29
|
+
AND tasks.creative_id = comments.creative_id
|
|
30
|
+
AND tasks.status = 'queued'
|
|
31
|
+
)
|
|
32
|
+
SQL
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def down
|
|
36
|
+
remove_column :comments, :topic_concurrency_defer
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class AddTypoCorrectionSettingsToUsers < ActiveRecord::Migration[8.0]
|
|
2
|
+
def change
|
|
3
|
+
# Master switch + auto-apply confidence threshold (0-100).
|
|
4
|
+
add_column :users, :typo_correction_enabled, :boolean, default: true, null: false
|
|
5
|
+
add_column :users, :typo_correction_threshold, :integer, default: 80, null: false
|
|
6
|
+
|
|
7
|
+
# Typing-device gating (2D gating, dimension 1). Soft keyboard / voice default
|
|
8
|
+
# on, physical (BT/wired) keyboard default off — each independently toggleable.
|
|
9
|
+
add_column :users, :typo_correction_on_soft_keyboard, :boolean, default: true, null: false
|
|
10
|
+
add_column :users, :typo_correction_on_voice, :boolean, default: true, null: false
|
|
11
|
+
add_column :users, :typo_correction_on_physical_keyboard, :boolean, default: false, null: false
|
|
12
|
+
|
|
13
|
+
# Input-location gating (2D gating, dimension 2). Chat message input default on,
|
|
14
|
+
# inline Lexical/markdown editor default off — each independently toggleable.
|
|
15
|
+
add_column :users, :typo_correction_in_chat, :boolean, default: true, null: false
|
|
16
|
+
add_column :users, :typo_correction_in_editor, :boolean, default: false, null: false
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
class EnforceSystemSettingsKeyNotNull < ActiveRecord::Migration[8.1]
|
|
2
|
+
# `key` is the lookup identifier for every setting and the model already
|
|
3
|
+
# validates its presence; the unique index exists but the column was left
|
|
4
|
+
# nullable, allowing a NULL-keyed row to slip in outside the model. Enforce
|
|
5
|
+
# the invariant at the database level to match the existing UNIQUE index.
|
|
6
|
+
def change
|
|
7
|
+
change_column_null :system_settings, :key, false
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class AddCreativeIndexAndFkToTags < ActiveRecord::Migration[8.1]
|
|
2
|
+
# tags.creative_id is NOT NULL and queried on every tag lookup, but only
|
|
3
|
+
# label_id was indexed and there was no referential integrity to creatives.
|
|
4
|
+
# Add the missing index and foreign key.
|
|
5
|
+
def change
|
|
6
|
+
add_index :tags, :creative_id unless index_exists?(:tags, :creative_id)
|
|
7
|
+
unless foreign_key_exists?(:tags, :creatives, column: :creative_id)
|
|
8
|
+
add_foreign_key :tags, :creatives, column: :creative_id
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class AddCreativeTypeIndexToLabels < ActiveRecord::Migration[8.1]
|
|
2
|
+
# Labels are almost always fetched for a creative filtered by their kind
|
|
3
|
+
# (`type`). A composite index on [creative_id, type] serves those lookups
|
|
4
|
+
# far better than the standalone creative_id index alone.
|
|
5
|
+
def change
|
|
6
|
+
unless index_exists?(:labels, [ :creative_id, :type ])
|
|
7
|
+
add_index :labels, [ :creative_id, :type ], name: "index_labels_on_creative_id_and_type"
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class AddCreativeCreatedAtIndexToComments < ActiveRecord::Migration[8.1]
|
|
2
|
+
# Comments are rendered per creative in chronological order. A composite
|
|
3
|
+
# index on [creative_id, created_at] lets the DB satisfy both the filter and
|
|
4
|
+
# the sort from the index instead of filtering on creative_id then sorting.
|
|
5
|
+
def change
|
|
6
|
+
unless index_exists?(:comments, [ :creative_id, :created_at ])
|
|
7
|
+
add_index :comments, [ :creative_id, :created_at ], name: "index_comments_on_creative_id_and_created_at"
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|