feat(elixir): complete storage location integration
This commit is contained in:
@@ -140,13 +140,13 @@ The application uses a simple password-based authentication system:
|
||||
|
||||
## ✅ Recently Implemented Features
|
||||
|
||||
### Storage Location System Foundation 🚧 **PARTIALLY IMPLEMENTED**
|
||||
### Storage Location System Foundation ✅ **COMPLETED**
|
||||
- **Database Schema** ✅ Complete - Hierarchical storage locations with parent-child relationships
|
||||
- **Storage Location CRUD** ✅ Complete - Full create, read, update, delete operations via web interface
|
||||
- **QR Code Data Generation** ✅ Complete - Text-based QR codes with format `SL:{level}:{code}:{parent}`
|
||||
- **Hierarchical Organization** ✅ Complete - Unlimited nesting (shelf → drawer → box)
|
||||
- **Web Interface** ✅ Complete - Storage locations management page with navigation
|
||||
- **Component-Storage Integration** ❌ Missing - Linking components to storage locations not yet implemented correctly
|
||||
- **Component-Storage Integration** ✅ Complete - Components can now be assigned to storage locations via dropdown interface
|
||||
|
||||
### QR Code System - Still Needed 🚧 **NOT IMPLEMENTED**
|
||||
- **Visual QR Code Generation** ❌ Missing - No actual QR code images are generated
|
||||
|
||||
@@ -170,6 +170,14 @@ defmodule ComponentsElixir.Inventory do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Computes the path for a storage location (for display purposes).
|
||||
"""
|
||||
def compute_storage_location_path(nil), do: nil
|
||||
def compute_storage_location_path(%StorageLocation{} = location) do
|
||||
compute_path_for_single(location)
|
||||
end
|
||||
|
||||
# Convert string keys to atoms for consistency
|
||||
defp normalize_string_keys(attrs) when is_map(attrs) do
|
||||
Enum.reduce(attrs, %{}, fn
|
||||
|
||||
@@ -38,6 +38,7 @@ defmodule ComponentsElixir.Inventory.Component do
|
||||
|> validate_number(:count, greater_than_or_equal_to: 0)
|
||||
|> validate_url(:datasheet_url)
|
||||
|> foreign_key_constraint(:category_id)
|
||||
|> foreign_key_constraint(:storage_location_id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
||||
@@ -13,12 +13,14 @@ defmodule ComponentsElixirWeb.ComponentsLive do
|
||||
{:ok, socket |> push_navigate(to: ~p"/login")}
|
||||
else
|
||||
categories = Inventory.list_categories()
|
||||
storage_locations = Inventory.list_storage_locations()
|
||||
stats = Inventory.component_stats()
|
||||
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(:session, session)
|
||||
|> assign(:categories, categories)
|
||||
|> assign(:storage_locations, storage_locations)
|
||||
|> assign(:stats, stats)
|
||||
|> assign(:search, "")
|
||||
|> assign(:sort_criteria, "all_not_id")
|
||||
@@ -293,6 +295,13 @@ defmodule ComponentsElixirWeb.ComponentsLive do
|
||||
end)
|
||||
end
|
||||
|
||||
defp storage_location_options(storage_locations) do
|
||||
[{"No storage location", nil}] ++
|
||||
Enum.map(storage_locations, fn location ->
|
||||
{location.path, location.id}
|
||||
end)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
@@ -439,8 +448,12 @@ defmodule ComponentsElixirWeb.ComponentsLive do
|
||||
<.input field={@form[:keywords]} type="text" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Position</label>
|
||||
<.input field={@form[:position]} type="text" />
|
||||
<label class="block text-sm font-medium text-gray-700">Storage Location</label>
|
||||
<.input
|
||||
field={@form[:storage_location_id]}
|
||||
type="select"
|
||||
options={storage_location_options(@storage_locations)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -552,8 +565,12 @@ defmodule ComponentsElixirWeb.ComponentsLive do
|
||||
<.input field={@form[:keywords]} type="text" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Position</label>
|
||||
<.input field={@form[:position]} type="text" />
|
||||
<label class="block text-sm font-medium text-gray-700">Storage Location</label>
|
||||
<.input
|
||||
field={@form[:storage_location_id]}
|
||||
type="select"
|
||||
options={storage_location_options(@storage_locations)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -684,9 +701,9 @@ defmodule ComponentsElixirWeb.ComponentsLive do
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-2 flex items-center text-sm text-gray-500 sm:mt-0">
|
||||
<%= if component.position do %>
|
||||
<%= if component.storage_location do %>
|
||||
<p class="mr-6">
|
||||
<span class="font-medium">Position:</span> {component.position}
|
||||
<span class="font-medium">Location:</span> {Inventory.compute_storage_location_path(component.storage_location)}
|
||||
</p>
|
||||
<% end %>
|
||||
<p class="mr-6">
|
||||
|
||||
Reference in New Issue
Block a user