gaggle 0.2.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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +167 -0
- data/Rakefile +8 -0
- data/app/assets/config/gaggle_manifest.js +4 -0
- data/app/assets/stylesheets/application.css +1 -0
- data/app/assets/stylesheets/gaggle/tailwind.css +1740 -0
- data/app/controllers/gaggle/application_controller.rb +23 -0
- data/app/controllers/gaggle/channels/messages_controller.rb +27 -0
- data/app/controllers/gaggle/channels_controller.rb +84 -0
- data/app/controllers/gaggle/gooses/sessions_controller.rb +23 -0
- data/app/controllers/gaggle/gooses_controller.rb +47 -0
- data/app/controllers/gaggle/messages_controller.rb +7 -0
- data/app/controllers/gaggle/overviews_controller.rb +5 -0
- data/app/controllers/gaggle/sessions_controller.rb +27 -0
- data/app/helpers/gaggle/application_helper.rb +4 -0
- data/app/javascript/controllers/gaggle/application.js +9 -0
- data/app/javascript/controllers/gaggle/chat_field_form_controller.js +7 -0
- data/app/javascript/controllers/gaggle/index.js +4 -0
- data/app/javascript/controllers/gaggle/local_timestamp_controller.js +21 -0
- data/app/javascript/controllers/gaggle/text_area_auto_expand_controller.js +27 -0
- data/app/javascript/controllers/gaggle/transition_controller.js +102 -0
- data/app/javascript/gaggle/application.js +3 -0
- data/app/javascript/gaggle/el-transition.js +64 -0
- data/app/jobs/gaggle/application_job.rb +4 -0
- data/app/mailers/gaggle/application_mailer.rb +6 -0
- data/app/models/gaggle/application_record.rb +8 -0
- data/app/models/gaggle/channel.rb +45 -0
- data/app/models/gaggle/channel_goose.rb +11 -0
- data/app/models/gaggle/current.rb +5 -0
- data/app/models/gaggle/goose/personality_defaults.rb +87 -0
- data/app/models/gaggle/goose.rb +94 -0
- data/app/models/gaggle/message.rb +61 -0
- data/app/models/gaggle/notification.rb +47 -0
- data/app/models/gaggle/session.rb +138 -0
- data/app/views/gaggle/application/_logo.html.erb +125 -0
- data/app/views/gaggle/application/_mobile_header.html.erb +15 -0
- data/app/views/gaggle/application/_sidebar.html.erb +259 -0
- data/app/views/gaggle/channels/_channel.html.erb +22 -0
- data/app/views/gaggle/channels/_form.html.erb +70 -0
- data/app/views/gaggle/channels/edit.html.erb +10 -0
- data/app/views/gaggle/channels/gooses/index.html.erb +12 -0
- data/app/views/gaggle/channels/index.json.jbuilder +3 -0
- data/app/views/gaggle/channels/messages/new.html.erb +2 -0
- data/app/views/gaggle/channels/new.html.erb +8 -0
- data/app/views/gaggle/channels/show.html.erb +98 -0
- data/app/views/gaggle/channels/show.json.jbuilder +5 -0
- data/app/views/gaggle/channels/update.turbo_stream.erb +1 -0
- data/app/views/gaggle/gooses/_form.html.erb +65 -0
- data/app/views/gaggle/gooses/edit.html.erb +2 -0
- data/app/views/gaggle/gooses/index.json.jbuilder +5 -0
- data/app/views/gaggle/gooses/new.html.erb +2 -0
- data/app/views/gaggle/gooses/sessions/index.html.erb +55 -0
- data/app/views/gaggle/gooses/show.html.erb +41 -0
- data/app/views/gaggle/messages/_message.html.erb +30 -0
- data/app/views/gaggle/overviews/show.html.erb +17 -0
- data/app/views/gaggle/sessions/show.html.erb +76 -0
- data/app/views/layouts/gaggle/application.html.erb +19 -0
- data/config/importmap.rb +7 -0
- data/config/routes.rb +19 -0
- data/config/utility_classes.yml +22 -0
- data/db/gaggle_migrate/20250214180303_create_gaggle_tables.rb +53 -0
- data/db/gaggle_migrate/20250220002655_add_delivered_at_to_notification.rb +5 -0
- data/db/gaggle_migrate/20250220004428_create_join_table_gaggle_channel_gaggle_goose.rb +8 -0
- data/lib/gaggle/engine.rb +48 -0
- data/lib/gaggle/version.rb +3 -0
- data/lib/gaggle.rb +8 -0
- data/lib/generators/gaggle/install/install_generator.rb +7 -0
- data/lib/generators/gaggle/install/templates/db/gaggle_schema.rb +59 -0
- data/lib/generators/gaggle/update/update_generator.rb +16 -0
- metadata +269 -0
@@ -0,0 +1,259 @@
|
|
1
|
+
<%# locals: (channels:) %>
|
2
|
+
|
3
|
+
<!-- Static Sidebar for Desktop -->
|
4
|
+
<div class="hidden lg:fixed lg:inset-y-0 lg:flex lg:w-72 lg:flex-col bg-white dark:bg-gray-900
|
5
|
+
shadow-lg shadow-gray-200/50 dark:shadow-gray-800/20 transition-all duration-300">
|
6
|
+
<div class="flex grow flex-col gap-y-6 overflow-y-auto border-r border-gray-200 dark:border-gray-800
|
7
|
+
px-6 py-4">
|
8
|
+
<!-- Logo -->
|
9
|
+
<div class="flex h-16 shrink-0 items-center">
|
10
|
+
<%= render 'logo', classes: 'h-10 w-auto text-indigo-600 dark:text-indigo-400' %>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<!-- Navigation -->
|
14
|
+
<nav class="flex flex-1 flex-col">
|
15
|
+
<ul role="list" class="flex flex-1 flex-col gap-y-8">
|
16
|
+
<!-- Channels Section -->
|
17
|
+
<li>
|
18
|
+
<div class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide">
|
19
|
+
Channels
|
20
|
+
</div>
|
21
|
+
<ul role="list" class="-mx-2 mt-3 space-y-1" data-channel-list-sidebar>
|
22
|
+
<%= render channels %>
|
23
|
+
<%= link_to new_channel_path,
|
24
|
+
class: "new-channel group flex gap-x-3 rounded-lg p-2 text-sm font-medium text-gray-700
|
25
|
+
hover:bg-indigo-50 dark:hover:bg-indigo-900/50 hover:text-indigo-700
|
26
|
+
dark:text-gray-200 dark:hover:text-indigo-300 transition-all duration-200" do %>
|
27
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
28
|
+
stroke="currentColor" class="size-5 shrink-0 text-indigo-500 dark:text-indigo-400
|
29
|
+
group-hover:text-indigo-600 dark:group-hover:text-indigo-300">
|
30
|
+
<path stroke-linecap="round" stroke-linejoin="round"
|
31
|
+
d="M12 10.5v6m3-3H9m4.06-7.19-2.12-2.12a1.5 1.5 0 0 0-1.061-.44H4.5A2.25 2.25 0 0 0 2.25 6v12a2.25 2.25 0 0 0 2.25 2.25h15A2.25 2.25 0 0 0 21.75 18V9a2.25 2.25 0 0 0-2.25-2.25h-5.379a1.5 1.5 0 0 1-1.06-.44Z" />
|
32
|
+
</svg>
|
33
|
+
New Channel
|
34
|
+
<% end %>
|
35
|
+
</ul>
|
36
|
+
</li>
|
37
|
+
|
38
|
+
<!-- Your Gaggle Section -->
|
39
|
+
<li>
|
40
|
+
<div class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide">
|
41
|
+
Your Gaggle
|
42
|
+
</div>
|
43
|
+
<ul role="list" class="-mx-2 mt-3 space-y-2">
|
44
|
+
<% @geese.each do |goose| %>
|
45
|
+
<li>
|
46
|
+
<div class="group flex items-center gap-x-3 rounded-lg text-sm font-medium
|
47
|
+
text-gray-700 hover:bg-indigo-50 dark:hover:bg-indigo-900/50
|
48
|
+
hover:text-indigo-700 dark:text-gray-200 dark:hover:text-indigo-300
|
49
|
+
transition-all duration-200">
|
50
|
+
<!-- Link Part -->
|
51
|
+
<%= link_to goose,
|
52
|
+
class: "flex items-center gap-x-3 flex-1 p-4" do %>
|
53
|
+
<span class="flex size-5 shrink-0 items-center justify-center rounded-md
|
54
|
+
border border-indigo-200 dark:border-indigo-700/50
|
55
|
+
bg-indigo-50 dark:bg-indigo-900/30 text-[0.625rem] font-medium
|
56
|
+
text-indigo-600 dark:text-indigo-400">
|
57
|
+
<%= goose.name[0] %>
|
58
|
+
</span>
|
59
|
+
<span class="flex-1 truncate"><%= goose.name %></span>
|
60
|
+
<% end %>
|
61
|
+
|
62
|
+
<!-- Button Part -->
|
63
|
+
<% if session = goose.sessions.running.first %>
|
64
|
+
<%= button_to session, method: :delete, class: yass(btn: :danger),
|
65
|
+
data: { turbo_confirm: "Are you sure you want to stop this session?" } do %>
|
66
|
+
Stop
|
67
|
+
<% end %>
|
68
|
+
<% else %>
|
69
|
+
<%= button_to goose_sessions_path(goose), class: yass(btn: :success) do %>
|
70
|
+
Start
|
71
|
+
<% end %>
|
72
|
+
<% end %>
|
73
|
+
</div>
|
74
|
+
</li>
|
75
|
+
<% end %>
|
76
|
+
<%= link_to new_goose_path,
|
77
|
+
class: "group flex gap-x-3 rounded-lg p-2 text-sm font-medium text-gray-700
|
78
|
+
hover:bg-indigo-50 dark:hover:bg-indigo-900/50 hover:text-indigo-700
|
79
|
+
dark:text-gray-200 dark:hover:text-indigo-300 transition-all duration-200" do %>
|
80
|
+
<svg fill="currentColor" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"
|
81
|
+
viewBox="0 0 111.4 122.88" class="size-5 shrink-0 text-indigo-500 dark:text-indigo-400
|
82
|
+
group-hover:text-indigo-600 dark:group-hover:text-indigo-300">
|
83
|
+
<path d="M100.75,9.6l1,2.81a2.94,2.94,0,0,0-1.61-.14,4.13,4.13,0,0,0-2,1.11,9.48,9.48,0,0,0-2.56,5.15l-.94,5.85-.05.17-.07.28a7.49,7.49,0,0,1-3.24-.75l-3.93-1.72a34.26,34.26,0,0,0-3.43,18c.84,12.21,6,16.43,7.35,26.9a36.62,36.62,0,0,1,.3,3.76c.22,8.28-1.6,12.23-8.22,17.32-2,1.56-6.2,3.79-10.28,6.15-3.71,2.16-7.34,4.48-9.55,5.64a48.29,48.29,0,0,1-4.51,2.13h0l.64,1.58a3.61,3.61,0,0,0,.94.77,27,27,0,0,0,2.81,1.07c3.58,1.37,7.5,2.74,11.63,4.11a14.84,14.84,0,0,1-4.41,1.33,15.23,15.23,0,0,1-.39,5c-4.22-1.34-7.27-2.52-8.43-.43l-5.4-5.23c-1.26-1.29-1.33-2.3-.43-3.08l.78-.57c.47-.34,1-.54,1-1.18a1.5,1.5,0,0,0-.14-.65l-1.25-1.73h0a22.4,22.4,0,0,1-9.41,1h0a11.53,11.53,0,0,1-4.28,3.66A11,11,0,0,0,46.92,111c4.68.42,8.31,2.63,11.56,5.4L54,117.82a12.49,12.49,0,0,1-.4,5.06c-4-2.12-6.35-2.43-8-.92l-5.75-5.29a2,2,0,0,1-.8-2.06c.23-1.11,1.76-1.31,2.5-2.51l-2.12-3c-.77-1.11-.46-.83.42-2A9.28,9.28,0,0,0,41.88,103h0c-10.62-3.71-13.08-11.6-19.5-20.21q-2.89-3.88-6-7.42a8,8,0,0,0,2.2-.22A12.82,12.82,0,0,0,23,79.77a9.14,9.14,0,0,0,6,1.15,10.16,10.16,0,0,0,5.77,4.21,15.44,15.44,0,0,0,8.94-.63c11-.51,18-3.35,21.58-8.14s3.63-11.6.69-19.77a1.31,1.31,0,0,0-1.68-.79,1.3,1.3,0,0,0-.79,1.67c2.64,7.32,2.72,13.23-.33,17.33s-9.48,6.64-19.76,7.08A1.53,1.53,0,0,0,43,82a13.21,13.21,0,0,1-7.59.66,7.9,7.9,0,0,1-4.69-3.76,1.32,1.32,0,0,0-1.42-.65,6.85,6.85,0,0,1-5-.69A11.18,11.18,0,0,1,20.36,73a1.31,1.31,0,0,0-1.6-.63,5.61,5.61,0,0,1-2.88.33,5.14,5.14,0,0,1-2.42-1.19,1.34,1.34,0,0,0-1.08-.29L9.82,68.62c-5.53-3-9-8.78-9.82-17.85l3,.92a6.21,6.21,0,0,1,.55-5.22,13.54,13.54,0,0,1,8.28-.12l-1.29-2.7a30.21,30.21,0,0,0,6.69,1.4c9.54.89,20.58-2.83,30.71-3.5,8.6-.57,15.23.25,19.17,3,1.52-5.44,2.95-16.92,4.36-30.13a21,21,0,0,1,1.41-6.77,12.43,12.43,0,0,1,4.8-5.51c5.65-4,15-1.8,19.76,2.78a14.74,14.74,0,0,1,3.3,4.72Z"/>
|
84
|
+
</svg>
|
85
|
+
New Goose
|
86
|
+
<% end %>
|
87
|
+
</ul>
|
88
|
+
</li>
|
89
|
+
|
90
|
+
<!-- Settings -->
|
91
|
+
<li class="-mx-6 mt-auto">
|
92
|
+
<%= link_to '#',
|
93
|
+
class: "flex items-center gap-x-4 px-6 py-3 text-sm font-medium text-gray-700
|
94
|
+
hover:bg-indigo-50 dark:hover:bg-indigo-900/50 hover:text-indigo-700
|
95
|
+
dark:text-gray-200 dark:hover:text-indigo-300 transition-all duration-200" do %>
|
96
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
97
|
+
stroke="currentColor" class="size-5 text-indigo-500 dark:text-indigo-400">
|
98
|
+
<path stroke-linecap="round" stroke-linejoin="round"
|
99
|
+
d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
|
100
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
101
|
+
</svg>
|
102
|
+
Settings
|
103
|
+
<% end %>
|
104
|
+
</li>
|
105
|
+
</ul>
|
106
|
+
</nav>
|
107
|
+
</div>
|
108
|
+
</div>
|
109
|
+
|
110
|
+
<div data-controller="transition"
|
111
|
+
data-transition-open-value="false"
|
112
|
+
class="contents"
|
113
|
+
>
|
114
|
+
<!-- Mobile Menu -->
|
115
|
+
<div class="lg:hidden hidden"
|
116
|
+
data-transition-target="listener"
|
117
|
+
data-transition-enter="transition-opacity ease-linear duration-300"
|
118
|
+
data-transition-enter-start="opacity-0"
|
119
|
+
data-transition-enter-end="opacity-100"
|
120
|
+
data-transition-leave="transition-opacity ease-linear duration-300"
|
121
|
+
data-transition-leave-start="opacity-100"
|
122
|
+
data-transition-leave-end="opacity-0"
|
123
|
+
>
|
124
|
+
<div class="fixed inset-0 z-50 bg-gray-900/90 dark:bg-black/90 transition-opacity duration-200"
|
125
|
+
aria-hidden="true" data-mobile-menu-target="overlay" data-action="click->transition#close"></div>
|
126
|
+
|
127
|
+
<div class="fixed inset-y-0 left-0 z-50 w-72 flex"
|
128
|
+
data-transition-target="listener"
|
129
|
+
data-transition-enter="transition ease-in-out duration-300 transform"
|
130
|
+
data-transition-enter-start="-translate-x-full"
|
131
|
+
data-transition-enter-end="translate-x-0"
|
132
|
+
data-transition-leave="transition ease-in-out duration-300 transform"
|
133
|
+
data-transition-leave-start="translate-x-0"
|
134
|
+
data-transition-leave-end="-translate-x-full"
|
135
|
+
>
|
136
|
+
<div class="relative flex w-full flex-1 flex-col bg-white dark:bg-gray-900
|
137
|
+
shadow-lg shadow-gray-200/50 dark:shadow-gray-800/20"
|
138
|
+
data-transition-target="listener"
|
139
|
+
data-transition-enter="ease-in-out duration-300"
|
140
|
+
data-transition-enter-start="opacity-0"
|
141
|
+
data-transition-enter-end="opacity-100"
|
142
|
+
data-transition-leave="ease-in-out duration-300"
|
143
|
+
data-transition-leave-start="opacity-100"
|
144
|
+
data-transition-leave-end="opacity-0">
|
145
|
+
<!-- Close Button -->
|
146
|
+
<div class="absolute right-0 top-0 flex w-16 justify-center pt-5">
|
147
|
+
<button type="button" class="cursor-pointer -m-2.5 p-2.5 text-indigo-600 dark:text-indigo-400
|
148
|
+
hover:text-indigo-700 dark:hover:text-indigo-300 transition-colors duration-200"
|
149
|
+
data-action="transition#close">
|
150
|
+
<span class="sr-only">Close sidebar</span>
|
151
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
152
|
+
stroke="currentColor" class="size-6">
|
153
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
154
|
+
</svg>
|
155
|
+
</button>
|
156
|
+
</div>
|
157
|
+
|
158
|
+
<!-- Sidebar Content -->
|
159
|
+
<div class="flex grow flex-col gap-y-6 overflow-y-auto px-6 py-4">
|
160
|
+
<div class="flex h-16 shrink-0 items-center">
|
161
|
+
<%= render 'logo', classes: 'h-10 w-auto text-indigo-600 dark:text-indigo-400' %>
|
162
|
+
</div>
|
163
|
+
<nav class="flex flex-1 flex-col">
|
164
|
+
<ul role="list" class="flex flex-1 flex-col gap-y-8">
|
165
|
+
<li>
|
166
|
+
<div class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide">
|
167
|
+
Channels
|
168
|
+
</div>
|
169
|
+
<ul role="list" class="-mx-2 mt-3 space-y-1">
|
170
|
+
<%= render channels %>
|
171
|
+
<%= link_to new_channel_path,
|
172
|
+
class: "new-channel group flex gap-x-3 rounded-lg p-2 text-sm font-medium text-gray-700
|
173
|
+
hover:bg-indigo-50 dark:hover:bg-indigo-900/50 hover:text-indigo-700
|
174
|
+
dark:text-gray-200 dark:hover:text-indigo-300 transition-all duration-200" do %>
|
175
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
176
|
+
stroke="currentColor" class="size-5 shrink-0 text-indigo-500 dark:text-indigo-400
|
177
|
+
group-hover:text-indigo-600 dark:group-hover:text-indigo-300">
|
178
|
+
<path stroke-linecap="round" stroke-linejoin="round"
|
179
|
+
d="M12 10.5v6m3-3H9m4.06-7.19-2.12-2.12a1.5 1.5 0 0 0-1.061-.44H4.5A2.25 2.25 0 0 0 2.25 6v12a2.25 2.25 0 0 0 2.25 2.25h15A2.25 2.25 0 0 0 21.75 18V9a2.25 2.25 0 0 0-2.25-2.25h-5.379a1.5 1.5 0 0 1-1.06-.44Z" />
|
180
|
+
</svg>
|
181
|
+
New Channel
|
182
|
+
<% end %>
|
183
|
+
</ul>
|
184
|
+
</li>
|
185
|
+
<li>
|
186
|
+
<div class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide">
|
187
|
+
Your Gaggle
|
188
|
+
</div>
|
189
|
+
<ul role="list" class="-mx-2 mt-3 space-y-2">
|
190
|
+
<% @geese.each do |goose| %>
|
191
|
+
<li>
|
192
|
+
<div class="group flex items-center gap-x-3 rounded-lg text-sm font-medium
|
193
|
+
text-gray-700 hover:bg-indigo-50 dark:hover:bg-indigo-900/50
|
194
|
+
hover:text-indigo-700 dark:text-gray-200 dark:hover:text-indigo-300
|
195
|
+
transition-all duration-200">
|
196
|
+
<!-- Link Part -->
|
197
|
+
<%= link_to goose,
|
198
|
+
class: "flex items-center gap-x-3 flex-1 p-4" do %>
|
199
|
+
<span class="flex size-5 shrink-0 items-center justify-center rounded-md
|
200
|
+
border border-indigo-200 dark:border-indigo-700/50
|
201
|
+
bg-indigo-50 dark:bg-indigo-900/30 text-[0.625rem] font-medium
|
202
|
+
text-indigo-600 dark:text-indigo-400">
|
203
|
+
<%= goose.name[0] %>
|
204
|
+
</span>
|
205
|
+
<span class="flex-1 truncate"><%= goose.name %></span>
|
206
|
+
<% end %>
|
207
|
+
|
208
|
+
<!-- Button Part -->
|
209
|
+
<% if session = goose.sessions.running.first %>
|
210
|
+
<%= button_to session, method: :delete, class: yass(btn: :danger),
|
211
|
+
data: { turbo_confirm: "Are you sure you want to stop this session?" } do %>
|
212
|
+
Stop
|
213
|
+
<% end %>
|
214
|
+
<% else %>
|
215
|
+
<%= button_to goose_sessions_path(goose), class: yass(btn: :success) do %>
|
216
|
+
Start
|
217
|
+
<% end %>
|
218
|
+
<% end %>
|
219
|
+
</div>
|
220
|
+
</li>
|
221
|
+
<% end %>
|
222
|
+
<%= link_to new_goose_path,
|
223
|
+
class: "group flex gap-x-3 rounded-lg p-2 text-sm font-medium text-gray-700
|
224
|
+
hover:bg-indigo-50 dark:hover:bg-indigo-900/50 hover:text-indigo-700
|
225
|
+
dark:text-gray-200 dark:hover:text-indigo-300 transition-all duration-200" do %>
|
226
|
+
<svg fill="currentColor" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"
|
227
|
+
viewBox="0 0 111.4 122.88" class="size-5 shrink-0 text-indigo-500 dark:text-indigo-400
|
228
|
+
group-hover:text-indigo-600 dark:group-hover:text-indigo-300">
|
229
|
+
<path d="M100.75,9.6l1,2.81a2.94,2.94,0,0,0-1.61-.14,4.13,4.13,0,0,0-2,1.11,9.48,9.48,0,0,0-2.56,5.15l-.94,5.85-.05.17-.07.28a7.49,7.49,0,0,1-3.24-.75l-3.93-1.72a34.26,34.26,0,0,0-3.43,18c.84,12.21,6,16.43,7.35,26.9a36.62,36.62,0,0,1,.3,3.76c.22,8.28-1.6,12.23-8.22,17.32-2,1.56-6.2,3.79-10.28,6.15-3.71,2.16-7.34,4.48-9.55,5.64a48.29,48.29,0,0,1-4.51,2.13h0l.64,1.58a3.61,3.61,0,0,0,.94.77,27,27,0,0,0,2.81,1.07c3.58,1.37,7.5,2.74,11.63,4.11a14.84,14.84,0,0,1-4.41,1.33,15.23,15.23,0,0,1-.39,5c-4.22-1.34-7.27-2.52-8.43-.43l-5.4-5.23c-1.26-1.29-1.33-2.3-.43-3.08l.78-.57c.47-.34,1-.54,1-1.18a1.5,1.5,0,0,0-.14-.65l-1.25-1.73h0a22.4,22.4,0,0,1-9.41,1h0a11.53,11.53,0,0,1-4.28,3.66A11,11,0,0,0,46.92,111c4.68.42,8.31,2.63,11.56,5.4L54,117.82a12.49,12.49,0,0,1-.4,5.06c-4-2.12-6.35-2.43-8-.92l-5.75-5.29a2,2,0,0,1-.8-2.06c.23-1.11,1.76-1.31,2.5-2.51l-2.12-3c-.77-1.11-.46-.83.42-2A9.28,9.28,0,0,0,41.88,103h0c-10.62-3.71-13.08-11.6-19.5-20.21q-2.89-3.88-6-7.42a8,8,0,0,0,2.2-.22A12.82,12.82,0,0,0,23,79.77a9.14,9.14,0,0,0,6,1.15,10.16,10.16,0,0,0,5.77,4.21,15.44,15.44,0,0,0,8.94-.63c11-.51,18-3.35,21.58-8.14s3.63-11.6.69-19.77a1.31,1.31,0,0,0-1.68-.79,1.3,1.3,0,0,0-.79,1.67c2.64,7.32,2.72,13.23-.33,17.33s-9.48,6.64-19.76,7.08A1.53,1.53,0,0,0,43,82a13.21,13.21,0,0,1-7.59.66,7.9,7.9,0,0,1-4.69-3.76,1.32,1.32,0,0,0-1.42-.65,6.85,6.85,0,0,1-5-.69A11.18,11.18,0,0,1,20.36,73a1.31,1.31,0,0,0-1.6-.63,5.61,5.61,0,0,1-2.88.33,5.14,5.14,0,0,1-2.42-1.19,1.34,1.34,0,0,0-1.08-.29L9.82,68.62c-5.53-3-9-8.78-9.82-17.85l3,.92a6.21,6.21,0,0,1,.55-5.22,13.54,13.54,0,0,1,8.28-.12l-1.29-2.7a30.21,30.21,0,0,0,6.69,1.4c9.54.89,20.58-2.83,30.71-3.5,8.6-.57,15.23.25,19.17,3,1.52-5.44,2.95-16.92,4.36-30.13a21,21,0,0,1,1.41-6.77,12.43,12.43,0,0,1,4.8-5.51c5.65-4,15-1.8,19.76,2.78a14.74,14.74,0,0,1,3.3,4.72Z"/>
|
230
|
+
</svg>
|
231
|
+
New Goose
|
232
|
+
<% end %>
|
233
|
+
</ul>
|
234
|
+
</li>
|
235
|
+
<li class="-mx-6 mt-auto">
|
236
|
+
<%= link_to '#',
|
237
|
+
class: "flex items-center gap-x-4 px-6 py-3 text-sm font-medium text-gray-700
|
238
|
+
hover:bg-indigo-50 dark:hover:bg-indigo-900/50 hover:text-indigo-700
|
239
|
+
dark:text-gray-200 dark:hover:text-indigo-300 transition-all duration-200" do %>
|
240
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
241
|
+
stroke="currentColor" class="size-5 text-indigo-500 dark:text-indigo-400">
|
242
|
+
<path stroke-linecap="round" stroke-linejoin="round"
|
243
|
+
d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
|
244
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
245
|
+
</svg>
|
246
|
+
Settings
|
247
|
+
<% end %>
|
248
|
+
</li>
|
249
|
+
</ul>
|
250
|
+
</nav>
|
251
|
+
</div>
|
252
|
+
</div>
|
253
|
+
</div>
|
254
|
+
</div>
|
255
|
+
|
256
|
+
<main class="w-full h-full max-h-screen lg:pl-72 bg-gray-50 dark:bg-gray-950 overflow-y-auto">
|
257
|
+
<%= yield %>
|
258
|
+
</main>
|
259
|
+
</div>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<%# locals: (channel:) %>
|
2
|
+
|
3
|
+
<li class="<%= dom_id(channel, :sidebar) %>">
|
4
|
+
<%= link_to channel, class: "group flex gap-x-3 rounded-lg p-2 text-sm font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors" do %>
|
5
|
+
<svg
|
6
|
+
class="size-5 shrink-0 text-gray-500 dark:text-gray-400 group-hover:text-indigo-600 dark:group-hover:text-indigo-400"
|
7
|
+
fill="none"
|
8
|
+
viewBox="0 0 24 24"
|
9
|
+
stroke-width="1.5"
|
10
|
+
stroke="currentColor"
|
11
|
+
aria-hidden="true"
|
12
|
+
data-slot="icon"
|
13
|
+
>
|
14
|
+
<path
|
15
|
+
stroke-linecap="round"
|
16
|
+
stroke-linejoin="round"
|
17
|
+
d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"
|
18
|
+
/>
|
19
|
+
</svg>
|
20
|
+
<span class="<%= dom_id(channel, :title) %>"><%= channel.name %></span>
|
21
|
+
<% end %>
|
22
|
+
</li>
|
@@ -0,0 +1,70 @@
|
|
1
|
+
<%# locals: (channel:) %>
|
2
|
+
|
3
|
+
<%= form_with model: channel, class: "space-y-6 max-w-2xl mx-auto" do |form| %>
|
4
|
+
<% if @channel.errors.any? %>
|
5
|
+
<div id="error_explanation"
|
6
|
+
class="bg-red-50 dark:bg-red-900/40 border border-red-200 dark:border-red-800/50
|
7
|
+
text-red-700 dark:text-red-300 px-4 py-3 rounded-xl mb-4
|
8
|
+
shadow-sm shadow-red-200/50 dark:shadow-red-900/20 transition-all duration-200">
|
9
|
+
<h2 class="font-semibold text-sm tracking-wide"><%= pluralize(@channel.errors.count, "error") %> prevented saving:</h2>
|
10
|
+
<ul class="list-disc pl-5 mt-2 text-sm">
|
11
|
+
<% @channel.errors.full_messages.each do |msg| %>
|
12
|
+
<li><%= msg %></li>
|
13
|
+
<% end %>
|
14
|
+
</ul>
|
15
|
+
</div>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<!-- Name Field -->
|
19
|
+
<div class="space-y-2">
|
20
|
+
<%= form.label :name,
|
21
|
+
class: "block text-sm font-medium text-gray-900 dark:text-gray-100" %>
|
22
|
+
<%= form.text_field :name,
|
23
|
+
required: true,
|
24
|
+
placeholder: "Enter channel name",
|
25
|
+
class: "block w-full px-4 py-2.5 bg-white dark:bg-gray-800/50
|
26
|
+
border border-gray-300 dark:border-gray-700/50 rounded-lg
|
27
|
+
shadow-sm focus:outline-none focus:ring-2
|
28
|
+
focus:ring-indigo-500 dark:focus:ring-indigo-400
|
29
|
+
focus:border-transparent text-gray-900 dark:text-gray-100
|
30
|
+
placeholder:text-gray-400 dark:placeholder:text-gray-500
|
31
|
+
hover:border-indigo-400 dark:hover:border-indigo-600
|
32
|
+
transition-all duration-200" %>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<!-- Gaggle Members Assignment -->
|
36
|
+
<div class="space-y-3">
|
37
|
+
<h3 class="text-sm font-medium text-gray-900 dark:text-gray-100 uppercase tracking-wide">
|
38
|
+
Assign Gaggle Members
|
39
|
+
</h3>
|
40
|
+
<div class="grid gap-2 sm:grid-cols-2">
|
41
|
+
<%= form.collection_check_boxes :goose_ids, Gaggle::Goose.all, :id, :name do |b| %>
|
42
|
+
<label class="flex items-center gap-x-3 p-2 rounded-lg
|
43
|
+
bg-white dark:bg-gray-800/50 border border-gray-200 dark:border-gray-700/50
|
44
|
+
hover:bg-indigo-50 dark:hover:bg-indigo-900/50
|
45
|
+
hover:border-indigo-300 dark:hover:border-indigo-700/50
|
46
|
+
transition-all duration-200 cursor-pointer shadow-sm">
|
47
|
+
<%= b.check_box class: "h-4 w-4 text-indigo-600 dark:text-indigo-400
|
48
|
+
border-gray-300 dark:border-gray-600
|
49
|
+
rounded focus:ring-indigo-500 dark:focus:ring-indigo-400
|
50
|
+
bg-white dark:bg-gray-800" %>
|
51
|
+
<span class="text-sm text-gray-700 dark:text-gray-200"><%= b.text %></span>
|
52
|
+
</label>
|
53
|
+
<% end %>
|
54
|
+
</div>
|
55
|
+
</div>
|
56
|
+
|
57
|
+
<!-- Submit Button -->
|
58
|
+
<div class="pt-2">
|
59
|
+
<%= form.submit class: "w-full flex justify-center py-2.5 px-6
|
60
|
+
border border-transparent rounded-lg
|
61
|
+
shadow-md text-sm font-medium text-white
|
62
|
+
bg-indigo-600 hover:bg-indigo-700
|
63
|
+
dark:bg-indigo-500 dark:hover:bg-indigo-600
|
64
|
+
focus:outline-none focus:ring-2
|
65
|
+
focus:ring-offset-2 dark:focus:ring-offset-gray-900
|
66
|
+
focus:ring-indigo-500 disabled:opacity-50
|
67
|
+
disabled:cursor-not-allowed
|
68
|
+
hover:shadow-lg transition-all duration-300 cursor-pointer" %>
|
69
|
+
</div>
|
70
|
+
<% end %>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<%= render "mobile_header" %>
|
2
|
+
|
3
|
+
<div class="max-w-lg mx-auto p-6">
|
4
|
+
<div class="mb-8">
|
5
|
+
<h1 class="text-xl font-medium text-gray-900 dark:text-gray-100">Update Channel</h1>
|
6
|
+
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">Modify the channel settings and member assignments.</p>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<%= render 'form', channel: @channel %>
|
10
|
+
</div>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<div class="max-w-2xl mx-auto p-6 bg-white shadow rounded-lg">
|
2
|
+
<%= form_with url: channel_gooses_path(@channel), scope: :goose, method: :post, class: "space-y-4" do |form| %>
|
3
|
+
<div class="mb-4">
|
4
|
+
<%= form.label :id, "Select Goose", class: "block text-sm font-medium text-gray-700" %>
|
5
|
+
<%= form.select :id, options_from_collection_for_select(@missing_gooses, :id, :name), { prompt: "Choose a Goose" }, { class: "mt-1 block w-full border-gray-300 rounded-md shadow-sm" } %>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<div>
|
9
|
+
<%= form.submit "Add Goose", class: yass(btn: :blue) %>
|
10
|
+
</div>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<div class="max-w-lg mx-auto p-6">
|
2
|
+
<div class="mb-8">
|
3
|
+
<h1 class="text-xl font-medium text-gray-900 dark:text-gray-100">New Channel</h1>
|
4
|
+
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">Create a new channel and assign members.</p>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<%= render 'form', channel: @channel %>
|
8
|
+
</div>
|
@@ -0,0 +1,98 @@
|
|
1
|
+
<%= turbo_stream_from @channel %>
|
2
|
+
|
3
|
+
<div class="flex flex-col h-screen bg-white dark:bg-gray-950 transition-colors duration-200">
|
4
|
+
<!-- Header -->
|
5
|
+
<div class="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-800
|
6
|
+
bg-white dark:bg-gray-900 shadow-sm">
|
7
|
+
<%= render "mobile_header"%>
|
8
|
+
<h1 class="text-xl font-semibold text-gray-900 dark:text-gray-100 truncate flex-1">
|
9
|
+
<%= @channel.name %>
|
10
|
+
</h1>
|
11
|
+
|
12
|
+
<div class="flex space-x-1">
|
13
|
+
<%= link_to [:edit, @channel],
|
14
|
+
class: "p-2 text-gray-600 hover:text-yellow-600 dark:text-yellow-400
|
15
|
+
dark:hover:text-yellow-300 hover:bg-gray-100 dark:hover:bg-gray-800
|
16
|
+
rounded-lg transition-all duration-150",
|
17
|
+
title: "Edit channel" do %>
|
18
|
+
<svg xmlns="http://www.w3.org/2000/svg"
|
19
|
+
fill="none"
|
20
|
+
viewBox="0 0 24 24"
|
21
|
+
stroke-width="1.5"
|
22
|
+
stroke="currentColor"
|
23
|
+
class="w-5 h-5">
|
24
|
+
<path stroke-linecap="round"
|
25
|
+
stroke-linejoin="round"
|
26
|
+
d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" />
|
27
|
+
</svg>
|
28
|
+
<% end %>
|
29
|
+
|
30
|
+
<%= button_to @channel,
|
31
|
+
method: :delete,
|
32
|
+
class: "p-2 text-gray-600 hover:text-red-600 dark:text-gray-400
|
33
|
+
dark:hover:text-red-500 hover:bg-gray-100 dark:hover:bg-gray-800
|
34
|
+
rounded-lg transition-all duration-150 cursor-pointer",
|
35
|
+
data: { turbo_confirm: "Are you sure you want to delete this channel?" },
|
36
|
+
title: "Delete channel" do %>
|
37
|
+
<svg xmlns="http://www.w3.org/2000/svg"
|
38
|
+
fill="none"
|
39
|
+
viewBox="0 0 24 24"
|
40
|
+
stroke-width="1.5"
|
41
|
+
stroke="currentColor"
|
42
|
+
class="w-5 h-5">
|
43
|
+
<path stroke-linecap="round"
|
44
|
+
stroke-linejoin="round"
|
45
|
+
d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
|
46
|
+
</svg>
|
47
|
+
<% end %>
|
48
|
+
</div>
|
49
|
+
</div>
|
50
|
+
|
51
|
+
<!-- Messages -->
|
52
|
+
<div id="messages"
|
53
|
+
class="flex-1 overflow-y-auto p-6 space-y-4 bg-gray-50 dark:bg-gray-950
|
54
|
+
flex flex-col-reverse">
|
55
|
+
<%= render @channel.messages.reverse %>
|
56
|
+
</div>
|
57
|
+
|
58
|
+
<!-- Message Input -->
|
59
|
+
<div id="new-message"
|
60
|
+
class="p-4 border-t border-gray-200 dark:border-gray-800
|
61
|
+
bg-white dark:bg-gray-900 shadow-sm">
|
62
|
+
<%= form_with(model: [@channel, Gaggle::Message.new],
|
63
|
+
class: "relative") do |form| %>
|
64
|
+
<div class="relative flex items-center">
|
65
|
+
<%= form.text_area :content,
|
66
|
+
rows: 1,
|
67
|
+
autofocus: true,
|
68
|
+
placeholder: "Type your message...",
|
69
|
+
class: "w-full px-4 py-2.5 pr-20 rounded-lg border border-gray-300 dark:border-gray-700/50
|
70
|
+
bg-white dark:bg-gray-800/70 text-gray-900 dark:text-gray-100
|
71
|
+
placeholder-gray-400 dark:placeholder-gray-500
|
72
|
+
focus:outline-none focus:ring-2 focus:ring-indigo-500
|
73
|
+
dark:focus:ring-indigo-400 focus:border-transparent
|
74
|
+
resize-none min-h-[2.5rem] max-h-32 transition-all duration-200
|
75
|
+
scrollbar-thin scrollbar-thumb-gray-300 dark:scrollbar-thumb-gray-600
|
76
|
+
scrollbar-track-transparent hover:border-gray-400 dark:hover:border-gray-600 resize-y",
|
77
|
+
data: {
|
78
|
+
controller: "text-area-auto-expand chat-field-form",
|
79
|
+
text_area_auto_expand_max_rows_value: 5,
|
80
|
+
action: "keydown.enter->chat-field-form#submitForm:prevent"
|
81
|
+
} %>
|
82
|
+
<%= form.label :content,
|
83
|
+
class: "absolute right-2 px-3 py-1 bg-indigo-600 hover:bg-indigo-700
|
84
|
+
dark:bg-indigo-500 dark:hover:bg-indigo-600
|
85
|
+
text-white text-sm font-medium rounded-full
|
86
|
+
focus:outline-none focus:ring-2 focus:ring-indigo-500
|
87
|
+
dark:focus:ring-indigo-400 focus:ring-offset-2
|
88
|
+
dark:focus:ring-offset-gray-900
|
89
|
+
disabled:opacity-50 disabled:cursor-not-allowed
|
90
|
+
transition-all duration-200" do %>
|
91
|
+
<% form.submit '', class: 'hidden' %>
|
92
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
93
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M6 12 3.269 3.125A59.769 59.769 0 0 1 21.485 12 59.768 59.768 0 0 1 3.27 20.875L5.999 12Zm0 0h7.5" />
|
94
|
+
</svg>
|
95
|
+
<% end %>
|
96
|
+
</div>
|
97
|
+
<% end %>
|
98
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= turbo_stream.update ".#{dom_id(@channel, :title)}", @channel.name %>
|
@@ -0,0 +1,65 @@
|
|
1
|
+
<div class="max-w-2xl mx-auto p-6 bg-white dark:bg-gray-900 rounded-xl shadow-lg
|
2
|
+
shadow-gray-200/50 dark:shadow-gray-800/20 transition-all duration-300">
|
3
|
+
<%= form_with model: @goose, local: true, class: "space-y-6" do |f| %>
|
4
|
+
<!-- Name Field -->
|
5
|
+
<div class="space-y-2">
|
6
|
+
<%= f.label :name,
|
7
|
+
class: "block text-sm font-medium text-gray-900 dark:text-gray-100" %>
|
8
|
+
<%= f.text_field :name,
|
9
|
+
placeholder: "Enter name",
|
10
|
+
class: "block w-full px-4 py-2.5 bg-white dark:bg-gray-800/50
|
11
|
+
border border-gray-300 dark:border-gray-700/50
|
12
|
+
rounded-lg shadow-sm focus:outline-none focus:ring-2
|
13
|
+
focus:ring-indigo-500 dark:focus:ring-indigo-400
|
14
|
+
focus:border-transparent text-gray-900 dark:text-gray-100
|
15
|
+
placeholder:text-gray-400 dark:placeholder:text-gray-500
|
16
|
+
hover:border-gray-400 dark:hover:border-gray-600
|
17
|
+
transition-all duration-200" %>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<!-- Preset Prompts Dropdown -->
|
21
|
+
<div class="space-y-2">
|
22
|
+
<label for="preset_prompts"
|
23
|
+
class="block text-sm font-medium text-gray-900 dark:text-gray-100">
|
24
|
+
Preset Prompts
|
25
|
+
</label>
|
26
|
+
<%= select_tag :preset_prompts,
|
27
|
+
options_for_select(Gaggle::Goose.personalities.map { |personality| [personality[:name], personality[:prompt]] }),
|
28
|
+
prompt: 'Choose a preset prompt',
|
29
|
+
class: "block w-full px-4 py-2.5 bg-white dark:bg-gray-800/50
|
30
|
+
border border-gray-300 dark:border-gray-700/50
|
31
|
+
rounded-lg shadow-sm focus:outline-none focus:ring-2
|
32
|
+
focus:ring-indigo-500 dark:focus:ring-indigo-400
|
33
|
+
focus:border-transparent text-gray-900 dark:text-gray-100
|
34
|
+
appearance-none cursor-pointer
|
35
|
+
hover:border-gray-400 dark:hover:border-gray-600
|
36
|
+
transition-all duration-200",
|
37
|
+
onchange: "const target = document.getElementById('#{f.field_id(:prompt)}');
|
38
|
+
target.value = this.options[this.selectedIndex].value;
|
39
|
+
target.dispatchEvent(new Event('input'));" %>
|
40
|
+
</div>
|
41
|
+
|
42
|
+
<!-- Prompt Textarea -->
|
43
|
+
<div class="space-y-2">
|
44
|
+
<%= f.label :prompt,
|
45
|
+
class: "block text-sm font-medium text-gray-900 dark:text-gray-100" %>
|
46
|
+
<%= f.text_area :prompt,
|
47
|
+
rows: 10,
|
48
|
+
placeholder: "Enter your prompt here...",
|
49
|
+
class: "block w-full px-4 py-2.5 bg-white dark:bg-gray-800/50
|
50
|
+
border border-gray-300 dark:border-gray-700/50
|
51
|
+
rounded-lg shadow-sm focus:outline-none focus:ring-2
|
52
|
+
focus:ring-indigo-500 dark:focus:ring-indigo-400
|
53
|
+
focus:border-transparent text-gray-900 dark:text-gray-100
|
54
|
+
placeholder:text-gray-400 dark:placeholder:text-gray-500
|
55
|
+
resize-y hover:border-gray-400 dark:hover:border-gray-600",
|
56
|
+
data: { controller: "text-area-auto-expand" } %>
|
57
|
+
</div>
|
58
|
+
|
59
|
+
<!-- Submit Button -->
|
60
|
+
<div>
|
61
|
+
<%= f.submit "Save",
|
62
|
+
class: yass(btn: :success, add: 'w-full') %>
|
63
|
+
</div>
|
64
|
+
<% end %>
|
65
|
+
</div>
|