CRM: custom fields in column picker + role overview cards - #4
Merged
Merged
Conversation
ColumnConfig.available_columns/1 now reads PhoenixKit.Users.CustomFields.list_enabled_field_definitions/0 and emits "custom_<key>" entries under :custom for both the role and organizations scopes. RoleView and OrganizationsView render those columns by reading user.custom_fields[key] with type-aware formatting. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The overview page now lists each role connected to the CRM module as a clickable card showing the role name and the number of users assigned to it. Each card links to the role's CRM users page. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…atter
- Narrow custom-field rescue to UndefinedFunctionError; log other errors
via Logger.warning instead of silently swallowing them.
- Switch ColumnConfig.available_columns/1 :standard and :custom to
ordered lists of {id, meta} tuples so custom columns surface in the
position order returned by PhoenixKit.Users.CustomFields (the previous
Map.new collapsed it to alphabetical-by-key). Update column_modal,
all_column_ids/1, and get_column_metadata/2 to consume the list shape.
- Extract render_custom_cell/3 and format_custom_value/2 into a shared
PhoenixKitCRM.Web.CellFormat module; remove the duplicated formatter
ladder from RoleView and OrganizationsView.
- Pass the actual scope assign through render_cell/3 instead of relying
on the {:role, nil} shortcut that worked only because available_columns
ignored the role uuid.
- Add CellFormatTest covering all format_custom_value/2 branches and
update column_config_test for the new list-based shape.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ddon
added a commit
that referenced
this pull request
May 5, 2026
Retrospective Claude review for the merged "custom fields in column picker + role overview cards" PR. Flags the Iron-Law violation in CRMLive.mount/3 (DB queries fire twice per connect), the N+1 across count_users_with_role/1, and the per-cell available_columns/1 recomputation in the custom-cell render path. Also notes positives: ordering-preserving list-tuple shape, narrowed rescue+log fallback, shared CellFormat module, scope threading. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ddon
added a commit
that referenced
this pull request
May 5, 2026
Fixes the issues flagged in the PR #4 review. - CRMLive: move role-stat loading out of mount/3 into handle_params/3 gated on connected?/1. mount/3 fires twice per connect (HTTP + WebSocket), so the previous code ran 1 + N queries × 2 per page load. - RoleSettings: add list_enabled_with_user_counts/0 — single GROUP BY with a left join over role_assignments — replacing the N+1 loop of Roles.count_users_with_role/1 calls. Roles with zero users still surface (count = 0) thanks to the left join. - ColumnConfig: add column_metadata_map/1 returning a flat %{column_id => meta} map. RoleView and OrganizationsView now compute it once in mount + handle_params and assign as :column_meta. Threaded through render_cell/3, card_field/3, column_label/2, and CellFormat.render_custom_cell/3 — eliminating per-cell available_columns/1 rebuilds (previously O(rows × custom_cols) calls per render). ColumnModal does the same lookup once for the draggable-list item template. - ColumnConfig.custom_field_columns/0: filter for binary "key" upstream of the Enum.map so a malformed definition can't crash the page with ArgumentError on `"custom_" <> nil`. - CRMLive: switch long-form Gettext.gettext/dngettext calls to the short gettext/ngettext form already in scope via `use PhoenixKitWeb, :live_view`, matching the rest of the views. - Tests: cover render_custom_cell/3 with the new (column_meta, id, user) signature including unknown-column / nil-custom_fields branches; add column_metadata_map/1 assertions to ColumnConfigTest. - mix.lock: bump bandit, ecto, jason, leaf, phoenix, phoenix_kit, phoenix_live_view, postgrex via `mix deps.update --all`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ddon
added a commit
that referenced
this pull request
May 5, 2026
Adds a "Handoff: fixes landed on main" section to the existing review record pointing at the cherry-picked fix commit (8e089db), what's in it per issue, what tests are covered, what's left for Tim to verify manually (mix test / mix dialyzer / UI walkthrough), and how to revert if needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ddon
added a commit
that referenced
this pull request
May 5, 2026
Patch release shipping the PR #4 review fixes already on main (8e089db): CRMLive lifecycle, N+1 collapse via list_enabled_with_user_counts/0, column-metadata-map memoization in views, custom-field key guard, and gettext call-style alignment in CRMLive. - Bump @Version to 0.2.1 in mix.exs. - Add 0.2.1 CHANGELOG entry with Fixed / Added / Changed sections. - Append precommit results table (compile / format / credo / dialyzer all clean at 8e089db) and the 0.2.1 version-bump rationale to the PR #4 review record. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ColumnConfig.available_columns/1now pulls enabled definitions fromPhoenixKit.Users.CustomFields.list_enabled_field_definitions/0and emitscustom_<key>entries under:customfor both role and organizations scopes. Previously:customwas always%{}, so admin-defined custom fields never appeared in the "Customize columns" modal.RoleViewandOrganizationsViewgot arender_cell("custom_" <> _, user)clause that readsuser.custom_fields[key]and formats by type (boolean/checkbox/date/datetime/string/list).Roles.count_users_with_role/1). Cards navigate to the role's CRM users page; an empty-state card is shown when no roles are connected.All changes are confined to
lib/phoenix_kit_crm/...— no edits to PhoenixKit Core (deps/phoenix_kit/...); we only call public APIs.Test plan
user.custom_fieldsrender in both table and card views, with sensible formatting for each field type.mix test(column_config tests still expect empty:customwhen no DB / no enabled fields, which holds).