source import export

1e6fdab · gmorell · 2025-08-08 22:04

7 files +74 -2

Files changed

modified apps/room_sanctum/lib/room_sanctum_web/live/cfg_source_live/index.html.heex
+74 −2
@@ -1,5 +1,22 @@
1 1 <.itb icon="fa-plus" to={Routes.source_index_path(@socket, :new)} what="Offering"></.itb>
2 −<h1 class="text-3xl font-bold text-accent mx-4 bg-secondary-300 py-2">Available Offerings <i class="fa-regular fa-circle-question fa-xs" phx-click="info"></i></h1>
2 +
3 +<div class="flex items-center justify-between mx-4">
4 + <h1 class="text-3xl font-bold text-accent bg-secondary-300 py-2">Available Offerings <i class="fa-regular fa-circle-question fa-xs" phx-click="info"></i></h1>
5 +
6 + <div class="flex items-center gap-2">
7 + <%= if MapSet.size(@selected_sources) > 0 do %>
8 + <button
9 + class="btn btn-primary"
10 + phx-click="export-sources"
11 + >
12 + <i class="fa-solid fa-download mr-2"></i>
13 + Export Selected (<%= MapSet.size(@selected_sources) %>)
14 + </button>
15 + <% end %>
16 +
17 + <.itb icon="fa-upload" to={Routes.source_index_path(@socket, :import)} what="Import"></.itb>
18 + </div>
19 +</div>
3 20
4 21 <%= if @show_info do %>
5 22 <div class="card card-compact w-full bg-base-100 shadow-xl mx-6 my-2">
@@ -22,9 +39,53 @@
22 39 />
23 40 </.modal>
24 41
42 +<.modal :if={@live_action == :import} id="import-modal" show on_cancel={JS.patch(Routes.source_index_path(@socket, :index))}>
43 + <.live_component
44 + module={RoomSanctumWeb.SourceLive.ImportComponent}
45 + id={:import}
46 + title={@page_title}
47 + current_user={@current_user}
48 + />
49 +</.modal>
50 +
51 +<.modal :if={@show_export_modal} id="export-modal" show on_cancel={JS.push("close-export-modal")}>
52 + <div class="p-4">
53 + <h3 class="text-lg font-bold mb-4">Export Sources JSON</h3>
54 + <div class="mb-4">
55 + <p class="text-sm text-gray-600 mb-2">Copy the JSON below to save or share your source configurations:</p>
56 + </div>
57 + <div class="bg-gray-100 p-4 rounded-lg max-h-96 overflow-auto">
58 + <pre class="text-sm whitespace-pre-wrap"><%= @export_json %></pre>
59 + </div>
60 + <div class="flex justify-end gap-2 mt-4">
61 + <button
62 + class="btn btn-secondary"
63 + phx-click="close-export-modal"
64 + >
65 + Close
66 + </button>
67 + <button
68 + class="btn btn-primary"
69 + onclick="navigator.clipboard.writeText(this.previousElementSibling.previousElementSibling.querySelector('pre').textContent)"
70 + >
71 + Copy to Clipboard
72 + </button>
73 + </div>
74 + </div>
75 +</.modal>
76 +
25 77 <table class="table table-compact w-full mx-6">
26 78 <thead>
27 79 <tr>
80 + <th>
81 + <input
82 + type="checkbox"
83 + class="checkbox"
84 + id="select-all"
85 + phx-click="toggle-all-selection"
86 + checked={all_selected(@streams.cfg_sources, @selected_sources)}
87 + />
88 + </th>
28 89 <th>Name</th>
29 90 <th>Type</th>
30 91 <th>Enabled</th>
@@ -40,9 +101,20 @@
40 101 <th></th>
41 102 </tr>
42 103 </thead>
43 − <tbody id="cfg_sources">
104 + <tbody id="cfg_sources" phx-update="stream">
44 105 <%= for {id, source} <- @streams.cfg_sources do %>
45 106 <tr id={"source-#{source.id}"}>
107 + <td>
108 + <input
109 + type="checkbox"
110 + class="checkbox source-checkbox checkbox-primary"
111 + phx-click="toggle-source-selection"
112 + phx-value-id={source.id}
113 + name="source_selection"
114 + value="on"
115 + checked={MapSet.member?(@selected_sources, source.id)}
116 + />
117 + </td>
46 118 <td><%= source.name %></td>
47 119 <td>
48 120 <span class="tooltip tooltip-primary" data-tip={source.type}>

Parents: 0dbe0b5