Compare commits
11 commits
ad51a226f7
...
1819a1e2d1
| Author | SHA1 | Date | |
|---|---|---|---|
| 1819a1e2d1 | |||
| 21ec86839a | |||
| efb3e1cc37 | |||
| c246ca59db | |||
| edf8b2b79e | |||
| bc75a5853a | |||
| e259c29224 | |||
| 93916a09f9 | |||
| a273b54c75 | |||
| a19026e430 | |||
| 1084f67f1f |
10 changed files with 4771 additions and 129 deletions
2502
docs/roles-and-permissions-architecture.md
Normal file
2502
docs/roles-and-permissions-architecture.md
Normal file
File diff suppressed because it is too large
Load diff
1653
docs/roles-and-permissions-implementation-plan.md
Normal file
1653
docs/roles-and-permissions-implementation-plan.md
Normal file
File diff suppressed because it is too large
Load diff
506
docs/roles-and-permissions-overview.md
Normal file
506
docs/roles-and-permissions-overview.md
Normal file
|
|
@ -0,0 +1,506 @@
|
|||
# Roles and Permissions - Architecture Overview
|
||||
|
||||
**Project:** Mila - Membership Management System
|
||||
**Feature:** Role-Based Access Control (RBAC) with Hardcoded Permission Sets
|
||||
**Version:** 2.0
|
||||
**Last Updated:** 2025-11-13
|
||||
**Status:** Architecture Design - MVP Approach
|
||||
|
||||
---
|
||||
|
||||
## Purpose of This Document
|
||||
|
||||
This document provides a high-level, conceptual overview of the Roles and Permissions architecture without code examples. It is designed for quick understanding of architectural decisions and concepts.
|
||||
|
||||
**For detailed technical implementation:** See [roles-and-permissions-architecture.md](./roles-and-permissions-architecture.md)
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Overview](#overview)
|
||||
2. [Requirements Summary](#requirements-summary)
|
||||
3. [Evaluated Approaches](#evaluated-approaches)
|
||||
4. [Selected Architecture](#selected-architecture)
|
||||
5. [Permission System Design](#permission-system-design)
|
||||
6. [User-Member Linking Strategy](#user-member-linking-strategy)
|
||||
7. [Field-Level Permissions Strategy](#field-level-permissions-strategy)
|
||||
8. [Migration Strategy](#migration-strategy)
|
||||
9. [Related Documents](#related-documents)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The Mila membership management system requires a flexible authorization system that controls:
|
||||
- **Who** can access **what** resources
|
||||
- **Which** pages users can view
|
||||
- **How** users interact with their own vs. others' data
|
||||
|
||||
### Key Design Principles
|
||||
|
||||
1. **Simplicity First:** Start with hardcoded permissions for fast MVP delivery
|
||||
2. **Performance:** No database queries for permission checks in MVP
|
||||
3. **Clear Migration Path:** Easy upgrade to database-backed permissions when needed
|
||||
4. **Security:** Explicit action-based authorization with no ambiguity
|
||||
5. **Maintainability:** Permission logic reviewable in Git, testable as pure functions
|
||||
|
||||
### Core Concepts
|
||||
|
||||
**Permission Set:** Defines a collection of permissions (e.g., "read_only", "admin")
|
||||
|
||||
**Role:** A named job function that references one Permission Set (e.g., "Vorstand" uses "read_only")
|
||||
|
||||
**User:** Each user has exactly one Role, inheriting that Role's Permission Set
|
||||
|
||||
**Scope:** Defines the breadth of access - "own" (only own data), "linked" (data connected to user), "all" (everything)
|
||||
|
||||
---
|
||||
|
||||
## Evaluated Approaches
|
||||
|
||||
During the design phase, we evaluated multiple implementation approaches to find the optimal balance between simplicity, performance, and future extensibility.
|
||||
|
||||
### Approach 1: JSONB in Roles Table
|
||||
|
||||
Store all permissions as a single JSONB column directly in the roles table.
|
||||
|
||||
**Advantages:**
|
||||
- Simplest database schema (single table)
|
||||
- Very flexible structure
|
||||
- No additional tables needed
|
||||
- Fast to implement
|
||||
|
||||
**Disadvantages:**
|
||||
- Poor queryability (can't efficiently filter by specific permissions)
|
||||
- No referential integrity
|
||||
- Difficult to validate structure
|
||||
- Hard to audit permission changes
|
||||
- Can't leverage database indexes effectively
|
||||
|
||||
**Verdict:** Rejected - Poor queryability makes it unsuitable for complex permission logic.
|
||||
|
||||
---
|
||||
|
||||
### Approach 2: Normalized Database Tables
|
||||
|
||||
Separate tables for `permission_sets`, `permission_set_resources`, `permission_set_pages` with full normalization.
|
||||
|
||||
**Advantages:**
|
||||
- Fully queryable with SQL
|
||||
- Runtime configurable permissions
|
||||
- Strong referential integrity
|
||||
- Easy to audit changes
|
||||
- Can index for performance
|
||||
|
||||
**Disadvantages:**
|
||||
- Complex database schema (4+ tables)
|
||||
- DB queries required for every permission check
|
||||
- Requires ETS cache for performance
|
||||
- Needs admin UI for permission management
|
||||
- Longer implementation time (4-5 weeks)
|
||||
- Overkill for fixed set of 4 permission sets
|
||||
|
||||
**Verdict:** Deferred to Phase 3 - Excellent for runtime configuration but too complex for MVP.
|
||||
|
||||
---
|
||||
|
||||
### Approach 3: Custom Authorizer
|
||||
|
||||
Implement a custom Ash Authorizer from scratch instead of using Ash Policies.
|
||||
|
||||
**Advantages:**
|
||||
- Complete control over authorization logic
|
||||
- Can implement any custom behavior
|
||||
- Not constrained by Ash Policy DSL
|
||||
|
||||
**Disadvantages:**
|
||||
- Significantly more code to write and maintain
|
||||
- Loses benefits of Ash's declarative policies
|
||||
- Harder to test than built-in policy system
|
||||
- Mixes declarative and imperative approaches
|
||||
- Must reimplement filter generation for queries
|
||||
- Higher bug risk
|
||||
|
||||
**Verdict:** Rejected - Too much custom code, reduces maintainability and loses Ash ecosystem benefits.
|
||||
|
||||
---
|
||||
|
||||
### Approach 4: Simple Role Enum
|
||||
|
||||
Add a simple `:role` enum field directly on User resource with hardcoded checks in each policy.
|
||||
|
||||
**Advantages:**
|
||||
- Very simple to implement (< 1 week)
|
||||
- No extra tables needed
|
||||
- Fast performance
|
||||
- Easy to understand
|
||||
|
||||
**Disadvantages:**
|
||||
- No separation between roles and permissions
|
||||
- Can't add new roles without code changes
|
||||
- No dynamic permission configuration
|
||||
- Not extensible to field-level permissions
|
||||
- Violates separation of concerns (role = job function, not permission set)
|
||||
- Difficult to maintain as requirements grow
|
||||
|
||||
**Verdict:** Rejected - Too inflexible, doesn't meet requirement for configurable permissions and role separation.
|
||||
|
||||
---
|
||||
|
||||
### Approach 5: Hardcoded Permissions with Migration Path (SELECTED for MVP)
|
||||
|
||||
Permission Sets hardcoded in Elixir module, only Roles table in database.
|
||||
|
||||
**Advantages:**
|
||||
- Fast implementation (2-3 weeks vs 4-5 weeks)
|
||||
- Maximum performance (zero DB queries, < 1 microsecond)
|
||||
- Simple to test (pure functions)
|
||||
- Code-reviewable permissions (visible in Git)
|
||||
- No migration needed for existing data
|
||||
- Clearly defined 4 permission sets as required
|
||||
- Clear migration path to database-backed solution (Phase 3)
|
||||
- Maintains separation of roles and permission sets
|
||||
|
||||
**Disadvantages:**
|
||||
- Permissions not editable at runtime (only role assignment possible)
|
||||
- New permissions require code deployment
|
||||
- Not suitable if permissions change frequently (> 1x/week)
|
||||
- Limited to the 4 predefined permission sets
|
||||
|
||||
**Why Selected:**
|
||||
- MVP requirement is for 4 fixed permission sets (not custom ones)
|
||||
- No stated requirement for runtime permission editing
|
||||
- Performance is critical for authorization checks
|
||||
- Fast time-to-market (2-3 weeks)
|
||||
- Clear upgrade path when runtime configuration becomes necessary
|
||||
|
||||
**Migration Path:**
|
||||
When runtime permission editing becomes a business requirement, migrate to Approach 2 (normalized DB tables) without changing the public API of the PermissionSets module.
|
||||
|
||||
---
|
||||
|
||||
## Requirements Summary
|
||||
|
||||
### Four Predefined Permission Sets
|
||||
|
||||
1. **own_data** - Access only to own user account and linked member profile
|
||||
2. **read_only** - Read access to all members and custom fields
|
||||
3. **normal_user** - Create/Read/Update members and full CRUD on custom fields (no member deletion for safety)
|
||||
4. **admin** - Unrestricted access to all resources including user management
|
||||
|
||||
### Example Roles
|
||||
|
||||
- **Mitglied (Member)** - Uses "own_data" permission set, default role
|
||||
- **Vorstand (Board)** - Uses "read_only" permission set
|
||||
- **Kassenwart (Treasurer)** - Uses "normal_user" permission set
|
||||
- **Buchhaltung (Accounting)** - Uses "read_only" permission set
|
||||
- **Admin** - Uses "admin" permission set
|
||||
|
||||
### Authorization Levels
|
||||
|
||||
**Resource Level (MVP):**
|
||||
- Controls create, read, update, destroy actions on resources
|
||||
- Resources: Member, User, Property, PropertyType, Role
|
||||
|
||||
**Page Level (MVP):**
|
||||
- Controls access to LiveView pages
|
||||
- Example: "/members/new" requires Member.create permission
|
||||
|
||||
**Field Level (Phase 2 - Future):**
|
||||
- Controls read/write access to specific fields
|
||||
- Example: Only Treasurer can see payment_history field
|
||||
|
||||
### Special Cases
|
||||
|
||||
1. **Own Credentials:** Users can always edit their own email and password
|
||||
2. **Linked Member Email:** Only admins can edit email of members linked to users
|
||||
3. **User-Member Linking:** Only admins can link/unlink users to members (except self-service creation)
|
||||
|
||||
---
|
||||
|
||||
## Selected Architecture
|
||||
|
||||
### Conceptual Model
|
||||
|
||||
```
|
||||
Elixir Module: PermissionSets
|
||||
↓ (defines)
|
||||
Permission Set (:own_data, :read_only, :normal_user, :admin)
|
||||
↓ (referenced by)
|
||||
Role (stored in DB: "Vorstand" → "read_only")
|
||||
↓ (assigned to)
|
||||
User (each user has one role_id)
|
||||
```
|
||||
|
||||
### Database Schema (MVP)
|
||||
|
||||
**Single Table: roles**
|
||||
|
||||
Contains:
|
||||
- id (UUID)
|
||||
- name (e.g., "Vorstand")
|
||||
- description
|
||||
- permission_set_name (String: "own_data", "read_only", "normal_user", "admin")
|
||||
- is_system_role (boolean, protects critical roles)
|
||||
|
||||
**No Permission Tables:** Permission Sets are hardcoded in Elixir module.
|
||||
|
||||
### Why This Approach?
|
||||
|
||||
**Fast Implementation:** 2-3 weeks instead of 4-5 weeks
|
||||
|
||||
**Maximum Performance:**
|
||||
- Zero database queries for permission checks
|
||||
- Pure function calls (< 1 microsecond)
|
||||
- No caching needed
|
||||
|
||||
**Code Review:**
|
||||
- Permissions visible in Git diffs
|
||||
- Easy to review changes
|
||||
- No accidental runtime modifications
|
||||
|
||||
**Clear Upgrade Path:**
|
||||
- Phase 1 (MVP): Hardcoded
|
||||
- Phase 2: Add field-level permissions
|
||||
- Phase 3: Migrate to database-backed with admin UI
|
||||
|
||||
**Meets Requirements:**
|
||||
- Four predefined permission sets ✓
|
||||
- Dynamic role creation ✓ (Roles in DB)
|
||||
- Role-to-user assignment ✓
|
||||
- No requirement for runtime permission changes stated
|
||||
|
||||
---
|
||||
|
||||
## Permission System Design
|
||||
|
||||
### Permission Structure
|
||||
|
||||
Each Permission Set contains:
|
||||
|
||||
**Resources:** List of resource permissions
|
||||
- resource: "Member", "User", "Property", etc.
|
||||
- action: :read, :create, :update, :destroy
|
||||
- scope: :own, :linked, :all
|
||||
- granted: true/false
|
||||
|
||||
**Pages:** List of accessible page paths
|
||||
- Examples: "/", "/members", "/members/:id/edit"
|
||||
- "*" for admin (all pages)
|
||||
|
||||
### Scope Definitions
|
||||
|
||||
**:own** - Only records where id == actor.id
|
||||
- Example: User can read their own User record
|
||||
|
||||
**:linked** - Only records where user_id == actor.id
|
||||
- Example: User can read Member linked to their account
|
||||
|
||||
**:all** - All records without restriction
|
||||
- Example: Admin can read all Members
|
||||
|
||||
### How Authorization Works
|
||||
|
||||
1. User attempts action on resource (e.g., read Member)
|
||||
2. System loads user's role from database
|
||||
3. Role contains permission_set_name string
|
||||
4. PermissionSets module returns permissions for that set
|
||||
5. Custom Policy Check evaluates permissions against action
|
||||
6. Access granted or denied based on scope
|
||||
|
||||
### Custom Policy Check
|
||||
|
||||
A reusable Ash Policy Check that:
|
||||
- Reads user's permission_set_name from their role
|
||||
- Calls PermissionSets.get_permissions/1
|
||||
- Matches resource + action against permissions list
|
||||
- Applies scope filters (own/linked/all)
|
||||
- Returns authorized, forbidden, or filtered query
|
||||
|
||||
---
|
||||
|
||||
## User-Member Linking Strategy
|
||||
|
||||
### Problem Statement
|
||||
|
||||
Users need to create member profiles for themselves (self-service), but only admins should be able to:
|
||||
- Link existing members to users
|
||||
- Unlink members from users
|
||||
- Create members pre-linked to arbitrary users
|
||||
|
||||
### Selected Approach: Separate Ash Actions
|
||||
|
||||
Instead of complex field-level validation, we use action-based authorization.
|
||||
|
||||
### Actions on Member Resource
|
||||
|
||||
**1. create_member_for_self** (All authenticated users)
|
||||
- Automatically sets user_id = actor.id
|
||||
- User cannot specify different user_id
|
||||
- UI: "Create My Profile" button
|
||||
|
||||
**2. create_member** (Admin only)
|
||||
- Can set user_id to any user or leave unlinked
|
||||
- Full flexibility for admin
|
||||
- UI: Admin member management form
|
||||
|
||||
**3. link_member_to_user** (Admin only)
|
||||
- Updates existing member to set user_id
|
||||
- Connects unlinked member to user account
|
||||
|
||||
**4. unlink_member_from_user** (Admin only)
|
||||
- Sets user_id to nil
|
||||
- Disconnects member from user account
|
||||
|
||||
**5. update** (Permission-based)
|
||||
- Normal updates (name, address, etc.)
|
||||
- user_id NOT in accept list (prevents manipulation)
|
||||
- Available to users with Member.update permission
|
||||
|
||||
### Why Separate Actions?
|
||||
|
||||
**Explicit Semantics:** Each action has clear, single purpose
|
||||
|
||||
**Server-Side Security:** user_id set by server, not client input
|
||||
|
||||
**Better UX:** Different UI flows for different use cases
|
||||
|
||||
**Simple Policies:** Authorization at action level, not field level
|
||||
|
||||
**Easy Testing:** Each action independently testable
|
||||
|
||||
---
|
||||
|
||||
## Field-Level Permissions Strategy
|
||||
|
||||
### Status: Phase 2 (Future Implementation)
|
||||
|
||||
Field-level permissions are NOT implemented in MVP but have a clear strategy defined.
|
||||
|
||||
### Problem Statement
|
||||
|
||||
Some scenarios require field-level control:
|
||||
- **Read restrictions:** Hide payment_history from certain roles
|
||||
- **Write restrictions:** Only treasurer can edit payment fields
|
||||
- **Complexity:** Ash Policies work at resource level, not field level
|
||||
|
||||
### Selected Strategy
|
||||
|
||||
**For Read Restrictions:**
|
||||
Use Ash Calculations or Custom Preparations
|
||||
- Calculations: Dynamically compute field based on permissions
|
||||
- Preparations: Filter select to only allowed fields
|
||||
- Field returns nil or "[Hidden]" if unauthorized
|
||||
|
||||
**For Write Restrictions:**
|
||||
Use Custom Validations
|
||||
- Validate changeset against field permissions
|
||||
- Similar to existing linked-member email validation
|
||||
- Return error if field modification not allowed
|
||||
|
||||
### Why This Strategy?
|
||||
|
||||
**Leverages Ash Features:** Uses built-in mechanisms, not custom authorizer
|
||||
|
||||
**Performance:** Calculations are lazy, Preparations run once per query
|
||||
|
||||
**Maintainable:** Clear validation logic, standard Ash patterns
|
||||
|
||||
**Extensible:** Easy to add new field restrictions
|
||||
|
||||
### Implementation Timeline
|
||||
|
||||
**Phase 1 (MVP):** No field-level permissions
|
||||
|
||||
**Phase 2:** Extend PermissionSets to include field permissions, implement Calculations/Validations
|
||||
|
||||
**Phase 3:** If migrating to database, add permission_set_fields table
|
||||
|
||||
---
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
### Phase 1: MVP with Hardcoded Permissions (2-3 weeks)
|
||||
|
||||
**What's Included:**
|
||||
- Roles table in database
|
||||
- PermissionSets Elixir module with 4 predefined sets
|
||||
- Custom Policy Check reading from module
|
||||
- UI Authorization Helpers for LiveView
|
||||
- Admin UI for role management (create, assign, delete roles)
|
||||
|
||||
**Limitations:**
|
||||
- Permissions not editable at runtime
|
||||
- New permissions require code deployment
|
||||
- Only 4 permission sets available
|
||||
|
||||
**Benefits:**
|
||||
- Fast implementation
|
||||
- Maximum performance
|
||||
- Simple testing and review
|
||||
|
||||
### Phase 2: Field-Level Permissions (Future, 2-3 weeks)
|
||||
|
||||
**When Needed:** Business requires field-level restrictions
|
||||
|
||||
**Implementation:**
|
||||
- Extend PermissionSets module with :fields key
|
||||
- Add Ash Calculations for read restrictions
|
||||
- Add custom validations for write restrictions
|
||||
- Update UI Helpers
|
||||
|
||||
**Migration:** No database changes, pure code additions
|
||||
|
||||
### Phase 3: Database-Backed Permissions (Future, 3-4 weeks)
|
||||
|
||||
**When Needed:** Runtime permission configuration required
|
||||
|
||||
**Implementation:**
|
||||
- Create permission tables in database
|
||||
- Seed script to migrate hardcoded permissions
|
||||
- Update PermissionSets module to query database
|
||||
- Add ETS cache for performance
|
||||
- Build admin UI for permission management
|
||||
|
||||
**Migration:** Seamless, no changes to existing Policies or UI code
|
||||
|
||||
### Decision Matrix: When to Migrate?
|
||||
|
||||
| Scenario | Recommended Phase |
|
||||
|----------|-------------------|
|
||||
| MVP with 4 fixed permission sets | Phase 1 |
|
||||
| Need field-level restrictions | Phase 2 |
|
||||
| Permission changes < 1x/month | Stay Phase 1 |
|
||||
| Need runtime permission config | Phase 3 |
|
||||
| Custom permission sets needed | Phase 3 |
|
||||
| Permission changes > 1x/week | Phase 3 |
|
||||
|
||||
---
|
||||
|
||||
## Related Documents
|
||||
|
||||
**This Document (Overview):** High-level concepts, no code examples
|
||||
|
||||
**[roles-and-permissions-architecture.md](./roles-and-permissions-architecture.md):** Complete technical specification with code examples
|
||||
|
||||
**[roles-and-permissions-implementation-plan.md](./roles-and-permissions-implementation-plan.md):** Detailed implementation plan with TDD approach
|
||||
|
||||
**[CODE_GUIDELINES.md](../CODE_GUIDELINES.md):** Project coding standards
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The selected architecture uses **hardcoded Permission Sets in Elixir** for the MVP, providing:
|
||||
- **Speed:** 2-3 weeks implementation vs 4-5 weeks
|
||||
- **Performance:** Zero database queries for authorization
|
||||
- **Clarity:** Permissions in Git, reviewable and testable
|
||||
- **Flexibility:** Clear migration path to database-backed system
|
||||
|
||||
**User-Member linking** uses **separate Ash Actions** for clarity and security.
|
||||
|
||||
**Field-level permissions** have a **defined strategy** (Calculations + Validations) for Phase 2 implementation.
|
||||
|
||||
The approach balances pragmatism for MVP delivery with extensibility for future requirements.
|
||||
|
||||
|
|
@ -19,9 +19,6 @@ defmodule MvWeb.CustomFieldLive.Form do
|
|||
- immutable - If true, values cannot be changed after creation (default: false)
|
||||
- required - If true, all members must have this custom field (default: false)
|
||||
|
||||
**Read-only (Edit mode only):**
|
||||
- slug - Auto-generated URL-friendly identifier (immutable)
|
||||
|
||||
## Value Type Selection
|
||||
- `:string` - Text data (unlimited length)
|
||||
- `:integer` - Numeric data
|
||||
|
|
@ -52,19 +49,6 @@ defmodule MvWeb.CustomFieldLive.Form do
|
|||
<.form for={@form} id="custom_field-form" phx-change="validate" phx-submit="save">
|
||||
<.input field={@form[:name]} type="text" label={gettext("Name")} />
|
||||
|
||||
<%!-- Show slug in edit mode (read-only) --%>
|
||||
<div :if={@custom_field} class="mb-4">
|
||||
<label class="block text-sm font-semibold leading-6 text-zinc-800">
|
||||
{gettext("Slug")}
|
||||
</label>
|
||||
<div class="mt-2 p-3 bg-zinc-50 border border-zinc-300 rounded-lg text-sm text-zinc-700">
|
||||
{@custom_field.slug}
|
||||
</div>
|
||||
<p class="mt-2 text-sm leading-6 text-zinc-600">
|
||||
{gettext("Auto-generated identifier (immutable)")}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<.input
|
||||
field={@form[:value_type]}
|
||||
type="select"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ defmodule MvWeb.CustomFieldLive.Index do
|
|||
- Delete custom fields (if no custom field values use them)
|
||||
|
||||
## Displayed Information
|
||||
- Slug: URL-friendly identifier (auto-generated from name)
|
||||
- Name: Unique identifier for the custom field
|
||||
- Value type: Data type constraint (string, integer, boolean, date, email)
|
||||
- Description: Human-readable explanation
|
||||
|
|
@ -44,8 +43,6 @@ defmodule MvWeb.CustomFieldLive.Index do
|
|||
rows={@streams.custom_fields}
|
||||
row_click={fn {_id, custom_field} -> JS.navigate(~p"/custom_fields/#{custom_field}") end}
|
||||
>
|
||||
<:col :let={{_id, custom_field}} label="Slug">{custom_field.slug}</:col>
|
||||
|
||||
<:col :let={{_id, custom_field}} label="Name">{custom_field.name}</:col>
|
||||
|
||||
<:col :let={{_id, custom_field}} label="Description">{custom_field.description}</:col>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,12 @@ defmodule MvWeb.CustomFieldLive.Show do
|
|||
<.list>
|
||||
<:item title="Id">{@custom_field.id}</:item>
|
||||
|
||||
<:item title="Slug">{@custom_field.slug}</:item>
|
||||
<:item title="Slug">
|
||||
{@custom_field.slug}
|
||||
<p class="mt-2 text-sm leading-6 text-zinc-600">
|
||||
{gettext("Auto-generated identifier (immutable)")}
|
||||
</p>
|
||||
</:item>
|
||||
|
||||
<:item title="Name">{@custom_field.name}</:item>
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ defmodule MvWeb.CustomFieldValueLive.Form do
|
|||
<.header>
|
||||
{@page_title}
|
||||
<:subtitle>
|
||||
{gettext("Use this form to manage custom_field_value records in your database.")}
|
||||
{gettext("Use this form to manage Custom Field Value records in your database.")}
|
||||
</:subtitle>
|
||||
</.header>
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ msgid "Delete"
|
|||
msgstr "Löschen"
|
||||
|
||||
#: lib/mv_web/live/member_live/index.html.heex:194
|
||||
#: lib/mv_web/live/user_live/form.ex:247
|
||||
#: lib/mv_web/live/user_live/form.ex:251
|
||||
#: lib/mv_web/live/user_live/index.html.heex:66
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Edit"
|
||||
|
|
@ -158,10 +158,10 @@ msgstr "Postleitzahl"
|
|||
msgid "Save Member"
|
||||
msgstr "Mitglied speichern"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:80
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:64
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:74
|
||||
#: lib/mv_web/live/member_live/form.ex:79
|
||||
#: lib/mv_web/live/user_live/form.ex:230
|
||||
#: lib/mv_web/live/user_live/form.ex:234
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Saving..."
|
||||
msgstr "Speichern..."
|
||||
|
|
@ -203,14 +203,14 @@ msgstr "Dies ist ein Mitglied aus deiner Datenbank."
|
|||
msgid "Yes"
|
||||
msgstr "Ja"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:124
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:108
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:233
|
||||
#: lib/mv_web/live/member_live/form.ex:138
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "create"
|
||||
msgstr "erstellt"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:125
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:109
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:234
|
||||
#: lib/mv_web/live/member_live/form.ex:139
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -252,10 +252,10 @@ msgstr "Ihre E-Mail-Adresse wurde bestätigt"
|
|||
msgid "Your password has successfully been reset"
|
||||
msgstr "Ihr Passwort wurde erfolgreich zurückgesetzt"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:83
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:67
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:77
|
||||
#: lib/mv_web/live/member_live/form.ex:82
|
||||
#: lib/mv_web/live/user_live/form.ex:233
|
||||
#: lib/mv_web/live/user_live/form.ex:237
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
|
@ -265,7 +265,7 @@ msgstr "Abbrechen"
|
|||
msgid "Choose a member"
|
||||
msgstr "Mitglied auswählen"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:76
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Description"
|
||||
msgstr "Beschreibung"
|
||||
|
|
@ -285,7 +285,7 @@ msgstr "Aktiviert"
|
|||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:77
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:61
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Immutable"
|
||||
msgstr "Unveränderlich"
|
||||
|
|
@ -313,7 +313,7 @@ msgstr "Mitglied"
|
|||
msgid "Members"
|
||||
msgstr "Mitglieder"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:53
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:50
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
|
@ -335,7 +335,7 @@ msgstr "Nicht gesetzt"
|
|||
|
||||
#: lib/mv_web/live/user_live/form.ex:107
|
||||
#: lib/mv_web/live/user_live/form.ex:115
|
||||
#: lib/mv_web/live/user_live/form.ex:209
|
||||
#: lib/mv_web/live/user_live/form.ex:210
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Note"
|
||||
msgstr "Hinweis"
|
||||
|
|
@ -356,7 +356,7 @@ msgstr "Passwort-Authentifizierung"
|
|||
msgid "Profil"
|
||||
msgstr "Profil"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:78
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:62
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Required"
|
||||
msgstr "Erforderlich"
|
||||
|
|
@ -376,7 +376,7 @@ msgstr "Mitglied auswählen"
|
|||
msgid "Settings"
|
||||
msgstr "Einstellungen"
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:231
|
||||
#: lib/mv_web/live/user_live/form.ex:235
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save User"
|
||||
msgstr "Benutzer*in speichern"
|
||||
|
|
@ -401,7 +401,7 @@ msgstr "Nicht unterstützter Wertetyp: %{type}"
|
|||
msgid "Use this form to manage user records in your database."
|
||||
msgstr "Verwenden Sie dieses Formular, um Benutzer*innen-Datensätze zu verwalten."
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:248
|
||||
#: lib/mv_web/live/user_live/form.ex:252
|
||||
#: lib/mv_web/live/user_live/show.ex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User"
|
||||
|
|
@ -412,7 +412,7 @@ msgstr "Benutzer*in"
|
|||
msgid "Value"
|
||||
msgstr "Wert"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:71
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:55
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Value type"
|
||||
msgstr "Wertetyp"
|
||||
|
|
@ -429,7 +429,7 @@ msgstr "aufsteigend"
|
|||
msgid "descending"
|
||||
msgstr "absteigend"
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:247
|
||||
#: lib/mv_web/live/user_live/form.ex:251
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "New"
|
||||
msgstr "Neue*r"
|
||||
|
|
@ -620,7 +620,7 @@ msgstr "Benutzerdefinierte Feldwerte"
|
|||
msgid "Custom field"
|
||||
msgstr "Benutzerdefiniertes Feld"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:131
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Custom field %{action} successfully"
|
||||
msgstr "Benutzerdefiniertes Feld erfolgreich %{action}"
|
||||
|
|
@ -635,7 +635,7 @@ msgstr "Benutzerdefinierter Feldwert erfolgreich %{action}"
|
|||
msgid "Please select a custom field first"
|
||||
msgstr "Bitte wähle zuerst ein Benutzerdefiniertes Feld"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:81
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:65
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save Custom field"
|
||||
msgstr "Benutzerdefiniertes Feld speichern"
|
||||
|
|
@ -645,32 +645,32 @@ msgstr "Benutzerdefiniertes Feld speichern"
|
|||
msgid "Save Custom field value"
|
||||
msgstr "Benutzerdefinierten Feldwert speichern"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:48
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:45
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this form to manage custom_field records in your database."
|
||||
msgstr "Verwende dieses Formular, um Benutzerdefinierte Felder in deiner Datenbank zu verwalten."
|
||||
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:42
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this form to manage custom_field_value records in your database."
|
||||
msgstr "Verwende dieses Formular, um Benutzerdefinierte Feldwerte in deiner Datenbank zu verwalten."
|
||||
|
||||
#: lib/mv_web/components/layouts/navbar.ex:20
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Custom Fields"
|
||||
msgstr "Benutzerdefinierte Felder"
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:209
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A member with this email already exists. To link with a different member, please change one of the email addresses first."
|
||||
msgstr "Ein Mitglied mit dieser E-Mail-Adresse existiert bereits. Um mit einem anderen Mitglied zu verknüpfen, ändern Sie bitte zuerst eine der E-Mail-Adressen."
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:42
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Use this form to manage Custom Field Value records in your database."
|
||||
msgstr "Verwende dieses Formular, um Benutzerdefinierte Feldwerte in deiner Datenbank zu verwalten."
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:64
|
||||
#: lib/mv_web/live/custom_field_live/show.ex:56
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Auto-generated identifier (immutable)"
|
||||
msgstr "Automatisch generierte Kennung (unveränderlich)"
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:184
|
||||
#: lib/mv_web/live/user_live/form.ex:210
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A member with this email already exists. To link with a different member, please change one of the email addresses first."
|
||||
msgstr "Ein Mitglied mit dieser E-Mail-Adresse existiert bereits. Um mit einem anderen Mitglied zu verknüpfen, ändern Sie bitte zuerst eine der E-Mail-Adressen."
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:185
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Available members"
|
||||
msgstr "Verfügbare Mitglieder"
|
||||
|
|
@ -680,7 +680,7 @@ msgstr "Verfügbare Mitglieder"
|
|||
msgid "Member will be unlinked when you save. Cannot select new member until saved."
|
||||
msgstr "Mitglied wird beim Speichern entverknüpft. Neues Mitglied kann erst nach dem Speichern ausgewählt werden."
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:222
|
||||
#: lib/mv_web/live/user_live/form.ex:226
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save to confirm linking."
|
||||
msgstr "Speichern, um die Verknüpfung zu bestätigen."
|
||||
|
|
@ -695,16 +695,11 @@ msgstr "Nach einem Mitglied zum Verknüpfen suchen..."
|
|||
msgid "Search for member to link"
|
||||
msgstr "Nach Mitglied zum Verknüpfen suchen"
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:219
|
||||
#: lib/mv_web/live/user_live/form.ex:223
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Selected"
|
||||
msgstr "Ausgewählt"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:58
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Slug"
|
||||
msgstr "Slug"
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:143
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unlink Member"
|
||||
|
|
@ -714,3 +709,8 @@ msgstr "Mitglied entverknüpfen"
|
|||
#, elixir-autogen, elixir-format
|
||||
msgid "Unlinking scheduled"
|
||||
msgstr "Entverknüpfung geplant"
|
||||
|
||||
#~ #: lib/mv_web/live/custom_field_live/form.ex:58
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Slug"
|
||||
#~ msgstr "Slug"
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ msgid "Delete"
|
|||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/member_live/index.html.heex:194
|
||||
#: lib/mv_web/live/user_live/form.ex:247
|
||||
#: lib/mv_web/live/user_live/form.ex:251
|
||||
#: lib/mv_web/live/user_live/index.html.heex:66
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Edit"
|
||||
|
|
@ -159,10 +159,10 @@ msgstr ""
|
|||
msgid "Save Member"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:80
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:64
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:74
|
||||
#: lib/mv_web/live/member_live/form.ex:79
|
||||
#: lib/mv_web/live/user_live/form.ex:230
|
||||
#: lib/mv_web/live/user_live/form.ex:234
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Saving..."
|
||||
msgstr ""
|
||||
|
|
@ -204,14 +204,14 @@ msgstr ""
|
|||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:124
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:108
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:233
|
||||
#: lib/mv_web/live/member_live/form.ex:138
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "create"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:125
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:109
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:234
|
||||
#: lib/mv_web/live/member_live/form.ex:139
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -253,10 +253,10 @@ msgstr ""
|
|||
msgid "Your password has successfully been reset"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:83
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:67
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:77
|
||||
#: lib/mv_web/live/member_live/form.ex:82
|
||||
#: lib/mv_web/live/user_live/form.ex:233
|
||||
#: lib/mv_web/live/user_live/form.ex:237
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
|
@ -266,7 +266,7 @@ msgstr ""
|
|||
msgid "Choose a member"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:76
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
|
@ -286,7 +286,7 @@ msgstr ""
|
|||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:77
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:61
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Immutable"
|
||||
msgstr ""
|
||||
|
|
@ -314,7 +314,7 @@ msgstr ""
|
|||
msgid "Members"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:53
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:50
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
|
@ -336,7 +336,7 @@ msgstr ""
|
|||
|
||||
#: lib/mv_web/live/user_live/form.ex:107
|
||||
#: lib/mv_web/live/user_live/form.ex:115
|
||||
#: lib/mv_web/live/user_live/form.ex:209
|
||||
#: lib/mv_web/live/user_live/form.ex:210
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Note"
|
||||
msgstr ""
|
||||
|
|
@ -357,7 +357,7 @@ msgstr ""
|
|||
msgid "Profil"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:78
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:62
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Required"
|
||||
msgstr ""
|
||||
|
|
@ -377,7 +377,7 @@ msgstr ""
|
|||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:231
|
||||
#: lib/mv_web/live/user_live/form.ex:235
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save User"
|
||||
msgstr ""
|
||||
|
|
@ -402,7 +402,7 @@ msgstr ""
|
|||
msgid "Use this form to manage user records in your database."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:248
|
||||
#: lib/mv_web/live/user_live/form.ex:252
|
||||
#: lib/mv_web/live/user_live/show.ex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User"
|
||||
|
|
@ -413,7 +413,7 @@ msgstr ""
|
|||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:71
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:55
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Value type"
|
||||
msgstr ""
|
||||
|
|
@ -430,7 +430,7 @@ msgstr ""
|
|||
msgid "descending"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:247
|
||||
#: lib/mv_web/live/user_live/form.ex:251
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "New"
|
||||
msgstr ""
|
||||
|
|
@ -621,7 +621,7 @@ msgstr ""
|
|||
msgid "Custom field"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:131
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Custom field %{action} successfully"
|
||||
msgstr ""
|
||||
|
|
@ -636,7 +636,7 @@ msgstr ""
|
|||
msgid "Please select a custom field first"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:81
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:65
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save Custom field"
|
||||
msgstr ""
|
||||
|
|
@ -646,32 +646,32 @@ msgstr ""
|
|||
msgid "Save Custom field value"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:48
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:45
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this form to manage custom_field records in your database."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:42
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this form to manage custom_field_value records in your database."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/components/layouts/navbar.ex:20
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Custom Fields"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:209
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:42
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A member with this email already exists. To link with a different member, please change one of the email addresses first."
|
||||
msgid "Use this form to manage Custom Field Value records in your database."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:64
|
||||
#: lib/mv_web/live/custom_field_live/show.ex:56
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Auto-generated identifier (immutable)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:184
|
||||
#: lib/mv_web/live/user_live/form.ex:210
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A member with this email already exists. To link with a different member, please change one of the email addresses first."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:185
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Available members"
|
||||
msgstr ""
|
||||
|
|
@ -681,7 +681,7 @@ msgstr ""
|
|||
msgid "Member will be unlinked when you save. Cannot select new member until saved."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:222
|
||||
#: lib/mv_web/live/user_live/form.ex:226
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save to confirm linking."
|
||||
msgstr ""
|
||||
|
|
@ -696,16 +696,11 @@ msgstr ""
|
|||
msgid "Search for member to link"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:219
|
||||
#: lib/mv_web/live/user_live/form.ex:223
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Selected"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:58
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Slug"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:143
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unlink Member"
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ msgid "Delete"
|
|||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/member_live/index.html.heex:194
|
||||
#: lib/mv_web/live/user_live/form.ex:247
|
||||
#: lib/mv_web/live/user_live/form.ex:251
|
||||
#: lib/mv_web/live/user_live/index.html.heex:66
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Edit"
|
||||
|
|
@ -159,10 +159,10 @@ msgstr ""
|
|||
msgid "Save Member"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:80
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:64
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:74
|
||||
#: lib/mv_web/live/member_live/form.ex:79
|
||||
#: lib/mv_web/live/user_live/form.ex:230
|
||||
#: lib/mv_web/live/user_live/form.ex:234
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Saving..."
|
||||
msgstr ""
|
||||
|
|
@ -204,14 +204,14 @@ msgstr ""
|
|||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:124
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:108
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:233
|
||||
#: lib/mv_web/live/member_live/form.ex:138
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "create"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:125
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:109
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:234
|
||||
#: lib/mv_web/live/member_live/form.ex:139
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -253,10 +253,10 @@ msgstr ""
|
|||
msgid "Your password has successfully been reset"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:83
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:67
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:77
|
||||
#: lib/mv_web/live/member_live/form.ex:82
|
||||
#: lib/mv_web/live/user_live/form.ex:233
|
||||
#: lib/mv_web/live/user_live/form.ex:237
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
|
@ -266,7 +266,7 @@ msgstr ""
|
|||
msgid "Choose a member"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:76
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
|
@ -286,7 +286,7 @@ msgstr ""
|
|||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:77
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:61
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Immutable"
|
||||
msgstr ""
|
||||
|
|
@ -314,7 +314,7 @@ msgstr ""
|
|||
msgid "Members"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:53
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:50
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
|
@ -336,7 +336,7 @@ msgstr ""
|
|||
|
||||
#: lib/mv_web/live/user_live/form.ex:107
|
||||
#: lib/mv_web/live/user_live/form.ex:115
|
||||
#: lib/mv_web/live/user_live/form.ex:209
|
||||
#: lib/mv_web/live/user_live/form.ex:210
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Note"
|
||||
msgstr ""
|
||||
|
|
@ -357,7 +357,7 @@ msgstr ""
|
|||
msgid "Profil"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:78
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:62
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Required"
|
||||
msgstr ""
|
||||
|
|
@ -377,7 +377,7 @@ msgstr ""
|
|||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:231
|
||||
#: lib/mv_web/live/user_live/form.ex:235
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Save User"
|
||||
msgstr ""
|
||||
|
|
@ -402,7 +402,7 @@ msgstr ""
|
|||
msgid "Use this form to manage user records in your database."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:248
|
||||
#: lib/mv_web/live/user_live/form.ex:252
|
||||
#: lib/mv_web/live/user_live/show.ex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User"
|
||||
|
|
@ -413,7 +413,7 @@ msgstr ""
|
|||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:71
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:55
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Value type"
|
||||
msgstr ""
|
||||
|
|
@ -430,7 +430,7 @@ msgstr ""
|
|||
msgid "descending"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:247
|
||||
#: lib/mv_web/live/user_live/form.ex:251
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "New"
|
||||
msgstr ""
|
||||
|
|
@ -621,7 +621,7 @@ msgstr ""
|
|||
msgid "Custom field"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:131
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Custom field %{action} successfully"
|
||||
msgstr ""
|
||||
|
|
@ -636,7 +636,7 @@ msgstr ""
|
|||
msgid "Please select a custom field first"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:81
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:65
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save Custom field"
|
||||
msgstr ""
|
||||
|
|
@ -646,32 +646,32 @@ msgstr ""
|
|||
msgid "Save Custom field value"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:48
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:45
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Use this form to manage custom_field records in your database."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:42
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Use this form to manage custom_field_value records in your database."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/components/layouts/navbar.ex:20
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Custom Fields"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:209
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A member with this email already exists. To link with a different member, please change one of the email addresses first."
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex:42
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Use this form to manage Custom Field Value records in your database."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:64
|
||||
#: lib/mv_web/live/custom_field_live/show.ex:56
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Auto-generated identifier (immutable)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:184
|
||||
#: lib/mv_web/live/user_live/form.ex:210
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A member with this email already exists. To link with a different member, please change one of the email addresses first."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:185
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Available members"
|
||||
msgstr ""
|
||||
|
|
@ -681,7 +681,7 @@ msgstr ""
|
|||
msgid "Member will be unlinked when you save. Cannot select new member until saved."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:222
|
||||
#: lib/mv_web/live/user_live/form.ex:226
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save to confirm linking."
|
||||
msgstr ""
|
||||
|
|
@ -696,16 +696,11 @@ msgstr ""
|
|||
msgid "Search for member to link"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:219
|
||||
#: lib/mv_web/live/user_live/form.ex:223
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Selected"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex:58
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Slug"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/user_live/form.ex:143
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unlink Member"
|
||||
|
|
@ -715,3 +710,8 @@ msgstr ""
|
|||
#, elixir-autogen, elixir-format
|
||||
msgid "Unlinking scheduled"
|
||||
msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/custom_field_live/form.ex:58
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Slug"
|
||||
#~ msgstr ""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue