diff --git a/.drone.yml b/.drone.yml index 085a860..833c9ca 100644 --- a/.drone.yml +++ b/.drone.yml @@ -81,13 +81,13 @@ environment: steps: - name: renovate - image: renovate/renovate:40.35 + image: renovate/renovate:40.34 environment: RENOVATE_CONFIG_FILE: "renovate_backend_config.js" RENOVATE_TOKEN: from_secret: RENOVATE_TOKEN - GITHUB_COM_TOKEN: - from_secret: GITHUB_COM_TOKEN + #GITHUB_COM_TOKEN: + # from_secret: GITHUB_COM_TOKEN commands: # https://github.com/renovatebot/renovate/discussions/15049 - unset GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL diff --git a/Justfile b/Justfile index 13e8a01..b3541fd 100644 --- a/Justfile +++ b/Justfile @@ -1,4 +1,4 @@ -run: install-dependencies start-database migrate-database seed-database +run: install-dependencies start-database migrate-database mix phx.server install-dependencies: @@ -10,9 +10,6 @@ migrate-database: reset-database: mix ash.reset -seed-database: - mix run priv/repo/seeds.exs - start-database: docker compose up -d @@ -39,35 +36,4 @@ build-docker-container: # This is meant for debugging the container build process only. run-docker-container: build-docker-container - docker run -e "SECRET_KEY_BASE=ahK8BeiDaibaige1ahkooS0chie9lo7the7uuzar0eeBeeCh2iereteshee2Oosu" -e='DATABASE_URL=postgres://postgres@localhost:5432/mv_dev' -e='PORT=4040' -e='PHX_HOST=localhost' --network=host mitgliederverwaltung - -# Usage: -# just regen-migrations migration_name [commit_hash] -# If commit_hash is given, rollback & delete the migrations from that commit. -# Otherwise, rollback & delete all untracked migrations. -regen-migrations migration_name commit_hash='': - #!/usr/bin/env bash - set -euo pipefail - # Pick migrations either from the given commit or untracked files - if [ -n "{{commit_hash}}" ]; then - echo "→ Rolling back migrations from commit {{commit_hash}}" - MIG_FILES=$(git show --name-only --pretty=format: "{{commit_hash}}" \ - | grep -E "^priv/repo/migrations/|^priv/resource_snapshots") - else - echo "→ Rolling back all untracked migrations" - MIG_FILES=$(git ls-files --others priv/repo/migrations) - fi - - # Roll back in Ash - COUNT=$(echo "$MIG_FILES" | wc -l) - mix ash_postgres.rollback -n "$COUNT" - - # Remove the migration files - echo removing $MIG_FILES - echo "$MIG_FILES" | xargs rm -f - - # Also clean up any untracked resource snapshots - git ls-files --others priv/resource_snapshots | xargs rm -f - - # Generate a fresh migration - mix ash.codegen --name "{{migration_name}}" + docker run -e "SECRET_KEY_BASE=ahK8BeiDaibaige1ahkooS0chie9lo7the7uuzar0eeBeeCh2iereteshee2Oosu" -e='DATABASE_URL=postgres://postgres@localhost:5432/mv_dev' -e='PORT=4040' -e='PHX_HOST=localhost' --network=host mitgliederverwaltung \ No newline at end of file diff --git a/lib/membership/email.ex b/lib/membership/email.ex deleted file mode 100644 index eacd548..0000000 --- a/lib/membership/email.ex +++ /dev/null @@ -1,34 +0,0 @@ -defmodule Mv.Membership.Email do - @constraints [ - match: ~r/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/, - trim?: true, - min_length: 5, - max_length: 254 - ] - - use Ash.Type.NewType, - subtype_of: :string, - constraints: @constraints - - @impl true - def cast_input(value, _) when is_binary(value) do - value = if @constraints[:trim?], do: String.trim(value), else: value - - cond do - @constraints[:min_length] && String.length(value) < @constraints[:min_length] -> - :error - - @constraints[:max_length] && String.length(value) > @constraints[:max_length] -> - :error - - @constraints[:match] && !Regex.match?(@constraints[:match], value) -> - :error - - true -> - {:ok, value} - end - end - - @impl true - def cast_input(_, _), do: :error -end diff --git a/lib/membership/property.ex b/lib/membership/property.ex index 0bd5eab..433fc63 100644 --- a/lib/membership/property.ex +++ b/lib/membership/property.ex @@ -16,17 +16,8 @@ defmodule Mv.Membership.Property do attributes do uuid_primary_key :id - attribute :value, :union, - constraints: [ - storage: :type_and_value, - types: [ - boolean: [type: :boolean], - date: [type: :date], - integer: [type: :integer], - string: [type: :string], - email: [type: Mv.Membership.Email] - ] - ] + attribute :value, :string, + description: "Speichert den Wert, Typ-Interpretation per property_type.typ" end relationships do @@ -34,8 +25,4 @@ defmodule Mv.Membership.Property do belongs_to :property_type, Mv.Membership.PropertyType end - - calculations do - calculate :value_to_string, :string, expr(value[:value] <> "") - end end diff --git a/lib/membership/property_type.ex b/lib/membership/property_type.ex index 8e42fa6..560f679 100644 --- a/lib/membership/property_type.ex +++ b/lib/membership/property_type.ex @@ -10,7 +10,7 @@ defmodule Mv.Membership.PropertyType do actions do defaults [:create, :read, :update, :destroy] - default_accept [:name, :value_type, :description, :immutable, :required] + default_accept [:name, :type, :description, :immutable, :required] end attributes do @@ -18,8 +18,7 @@ defmodule Mv.Membership.PropertyType do attribute :name, :string, allow_nil?: false, public?: true - attribute :value_type, :atom, - constraints: [one_of: [:string, :integer, :boolean, :date, :email]], + attribute :type, :string, allow_nil?: false, description: "Definies the datatype `Property.value` is interpreted as" diff --git a/lib/mv_web/member_live/form_component.ex b/lib/mv_web/member_live/form_component.ex index 101cf6c..b91d3c0 100644 --- a/lib/mv_web/member_live/form_component.ex +++ b/lib/mv_web/member_live/form_component.ex @@ -9,11 +9,7 @@ defmodule MvWeb.MemberLive.FormComponent do Enum.map(property_types, fn pt -> %{ "property_type_id" => pt.id, - "value" => %{ - "type" => pt.value_type, - "value" => nil, - "_union_type" => Atom.to_string(pt.value_type) - } + "value" => nil } end) @@ -38,15 +34,7 @@ defmodule MvWeb.MemberLive.FormComponent do > <.inputs_for :let={f_property} field={@form[:properties]}> <% type = Enum.find(@property_types, &(&1.id == f_property[:property_type_id].value)) %> - <.inputs_for :let={value_form} field={f_property[:value]}> - <% input_type = - cond do - type && type.value_type == :boolean -> "checkbox" - type && type.value_type == :date -> :date - true -> :text - end %> - <.input field={value_form[:value]} label={type && type.name} type={input_type} /> - + <.input field={f_property[:value]} label={type && type.name} /> - Enum.map(member.properties, fn prop -> - %{ - "property_type_id" => prop.property_type_id, - "value" => %{ - "_union_type" => Atom.to_string(prop.value.type), - "type" => prop.value.type, - "value" => prop.value.value - } - } - end) - } - form = AshPhoenix.Form.for_update( member, :update_member, api: Mv.Membership, as: "member", - params: params, forms: [auto?: true] ) diff --git a/priv/repo/migrations/20250528163901_initial_migration.exs b/priv/repo/migrations/20250514151922_initial_migration.exs similarity index 96% rename from priv/repo/migrations/20250528163901_initial_migration.exs rename to priv/repo/migrations/20250514151922_initial_migration.exs index bf36e43..64915c2 100644 --- a/priv/repo/migrations/20250528163901_initial_migration.exs +++ b/priv/repo/migrations/20250514151922_initial_migration.exs @@ -11,7 +11,7 @@ defmodule Mv.Repo.Migrations.InitialMigration do create table(:property_types, primary_key: false) do add :id, :uuid, null: false, default: fragment("gen_random_uuid()"), primary_key: true add :name, :text, null: false - add :value_type, :text, null: false + add :type, :text, null: false add :description, :text add :immutable, :boolean, null: false, default: false add :required, :boolean, null: false, default: false @@ -21,7 +21,7 @@ defmodule Mv.Repo.Migrations.InitialMigration do create table(:properties, primary_key: false) do add :id, :uuid, null: false, default: fragment("gen_random_uuid()"), primary_key: true - add :value, :map + add :value, :text add :member_id, :uuid add :property_type_id, :uuid end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 39327d0..8fca144 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -2,49 +2,38 @@ # # mix run priv/repo/seeds.exs # +# Inside the script, you can read and write to any of your +# repositories directly: +# +# Mv.Repo.insert!(%Mv.SomeSchema{}) +# +# We recommend using the bang functions (`insert!`, `update!` +# and so on) as they will fail if something goes wrong. alias Mv.Membership for attrs <- [ %{ name: "Vorname", - value_type: :string, + type: "string", description: "Vorname des Mitglieds", immutable: true, required: true }, - %{ - name: "Nachname", - value_type: :string, - description: "Nachname des Mitglieds", - immutable: true, - required: true - }, - %{ - name: "Geburtsdatum", - value_type: :date, - description: "Geburtsdatum des Mitglieds", - immutable: true, - required: true - }, - %{ - name: "Bezahlt", - value_type: :boolean, - description: "Status des Mitgliedsbeitrages des Mitglieds", - immutable: true, - required: true - }, %{ name: "Email", - value_type: :email, + type: "string", description: "Email-Adresse des Mitglieds", immutable: true, required: true } ] do - Membership.create_property_type!( - attrs, - upsert?: true, - upsert_identity: :unique_name - ) + # upsert?: true sorgt dafür, dass bei bestehendem Namen kein Fehler, + # sondern ein Update (hier effektiv No-Op) ausgeführt wird + {:ok, _} = + Membership.create_property_type( + attrs, + upsert?: true, + upsert_identity: :unique_name + ) end diff --git a/priv/resource_snapshots/repo/members/20250528163901.json b/priv/resource_snapshots/repo/members/20250514151922.json similarity index 87% rename from priv/resource_snapshots/repo/members/20250528163901.json rename to priv/resource_snapshots/repo/members/20250514151922.json index 2d08b17..df811d8 100644 --- a/priv/resource_snapshots/repo/members/20250528163901.json +++ b/priv/resource_snapshots/repo/members/20250514151922.json @@ -16,7 +16,7 @@ "custom_indexes": [], "custom_statements": [], "has_create_action": true, - "hash": "35D45214D6D344B0AF6CFCB69B8682FCB3D382D85883D3D3AAC1AEE7F54FD89A", + "hash": "A0402269CB456075B81CA4CB3A2135A2C88D8B7FD51CD7A23084AA5264FEE344", "identities": [], "multitenancy": { "attribute": null, diff --git a/priv/resource_snapshots/repo/properties/20250528163901.json b/priv/resource_snapshots/repo/properties/20250514151922.json similarity index 95% rename from priv/resource_snapshots/repo/properties/20250528163901.json rename to priv/resource_snapshots/repo/properties/20250514151922.json index daf3222..0707bcf 100644 --- a/priv/resource_snapshots/repo/properties/20250528163901.json +++ b/priv/resource_snapshots/repo/properties/20250514151922.json @@ -18,7 +18,7 @@ "references": null, "size": null, "source": "value", - "type": "map" + "type": "text" }, { "allow_nil?": true, @@ -84,7 +84,7 @@ "custom_indexes": [], "custom_statements": [], "has_create_action": true, - "hash": "8CF241CB9E8239511914EDEC96186BB7879529372BD8A4162431CCE9961F4F1B", + "hash": "F2A42A3427E0428637F465E4F357A3BE21B33231F94CF77B4843084128F6BDA5", "identities": [], "multitenancy": { "attribute": null, diff --git a/priv/resource_snapshots/repo/property_types/20250528163901.json b/priv/resource_snapshots/repo/property_types/20250514151922.json similarity index 94% rename from priv/resource_snapshots/repo/property_types/20250528163901.json rename to priv/resource_snapshots/repo/property_types/20250514151922.json index 55f066a..5da5fa8 100644 --- a/priv/resource_snapshots/repo/property_types/20250528163901.json +++ b/priv/resource_snapshots/repo/property_types/20250514151922.json @@ -27,7 +27,7 @@ "primary_key?": false, "references": null, "size": null, - "source": "value_type", + "source": "type", "type": "text" }, { @@ -66,7 +66,7 @@ "custom_indexes": [], "custom_statements": [], "has_create_action": true, - "hash": "F98A723AE0D20005FBE4205E46ABEE09A88DFF9334C85BADC1FBEEF100F3E25B", + "hash": "47210108DE1E7B2A20A67205E875B3440526941E61AB95B166976E8CD8AA0955", "identities": [ { "all_tenants?": false,