diff --git a/front/AGENTS.md b/front/AGENTS.md new file mode 100644 index 000000000..8ac5862da --- /dev/null +++ b/front/AGENTS.md @@ -0,0 +1,40 @@ +# Repository Guidelines + +## Project Structure & Module Organization +- `lib/` holds Phoenix contexts, controllers, and services; shared helpers sit in `test/support`. +- `assets/` hosts the Preact/TypeScript UI alongside the build scripts (`build.js`, `package.json`). +- `config/` tracks environment settings, while runtime secrets are read from sibling files in `env/`. +- `test/` mirrors `lib/` with ExUnit suites, Wallaby browser specs in `test/browser`, and fixtures under `test/fixture`. +- `priv/` serves runtime assets, and `workflow_templates/` supplies seeded YAML pipelines consumed by the UI. + +## Build, Test, and Development Commands +- First-time setup: `mix deps.get` and `npm install --prefix assets`. +- `make dev.server` (Docker) launches Phoenix with Redis, RabbitMQ, and demo data preloaded. +- `mix phx.server` runs on the host once services are already up via `docker compose up -d`. +- `mix test` runs backend suites; `make test.js` or `npm test --prefix assets` covers frontend logic. +- Keep `mix credo --strict`, `mix format`, and `npm run lint` clean before pushing. +- Bundle production assets with `mix assets.deploy`. + +## Coding Style & Naming Conventions +- Format Elixir with `mix format`; favor pipe-first flows and 2-space indentation. +- Credo (`config/.credo.exs`) runs in strict mode—fix findings instead of disabling checks. +- Modules follow `Front.Foo` naming and live in `snake_case` paths; tests are co-located as `*_test.exs`. +- TypeScript components use PascalCase filenames; reusable helpers belong under `assets/js/` and tests under `*.spec.ts`. + +## Testing Guidelines +- Keep unit tests close to their modules and name `describe` blocks after the function under test. +- Wallaby browser specs need the Docker stack running; execute with `mix test test/browser`. +- Generate coverage with `mix coveralls.html` and `npm run coverage`. +- Update fixtures in `test/fixture` when workflow, API, or UI contracts change. + +## Commit & Pull Request Guidelines +- Commits follow `type(scope): message (#issue)` (e.g., `fix(front): adjust mermaid rendering (#621)`). +- Each commit should bundle code, schema, and tests for a single concern. +- PRs summarize impact, list manual checks, link tracking items, and add UI screenshots when relevant. +- Verify CI (mix, JS lint, tests) is green before requesting review and call out any external dependencies. + +## Environment & Services +- Shared defaults live in `env/`; do not commit developer-specific overrides. +- Use Docker (via `make dev.server` or `docker compose up`) to run RabbitMQ, Redis, and API stubs before starting Phoenix. +- Validate YAML pipelines with `scripts/check-templates.sh ` prior to committing. +- Maintain security suppressions in `security-ignore-policy.rego` with a short inline rationale. diff --git a/front/assets/js/people/add_to_project.js b/front/assets/js/people/add_to_project.js index c5dce0a2e..b0fe39520 100644 --- a/front/assets/js/people/add_to_project.js +++ b/front/assets/js/people/add_to_project.js @@ -27,6 +27,7 @@ export var AddToProject = { if(addPeopleToProjectBtn){ addPeopleToProjectBtn.onclick = () => { modal.style.display = "block"; + this.setModalCopy("user") this.initProjectNonMembersFilter("user") } } @@ -34,6 +35,7 @@ export var AddToProject = { if(addGroupsToProjectBtn){ addGroupsToProjectBtn.onclick = () => { modal.style.display = "block"; + this.setModalCopy("group") this.initProjectNonMembersFilter("group") } } @@ -41,6 +43,7 @@ export var AddToProject = { if(addServiceAccountsToProjectBtn){ addServiceAccountsToProjectBtn.onclick = () => { modal.style.display = "block"; + this.setModalCopy("service_account") this.initProjectNonMembersFilter("service_account") } } @@ -59,6 +62,36 @@ export var AddToProject = { } }, + setModalCopy(type) { + const modal = document.getElementById("modal_overlay"); + const container = modal?.querySelector(".popup"); + if(!container) return; + + const suffix = type === "service_account" + ? "Service_account" + : type.charAt(0).toUpperCase() + type.slice(1); + + const title = container.dataset[`title${suffix}`]; + const subjectPlural = container.dataset[`subjectPlural${suffix}`]; + const placeholder = container.dataset[`placeholder${suffix}`]; + + const titleEl = container.querySelector("[data-modal-title]"); + if(titleEl && title){ + titleEl.textContent = title; + } + + if(subjectPlural){ + container.querySelectorAll("[data-modal-subject-plural]").forEach((el) => { + el.textContent = subjectPlural; + }); + } + + const searchInput = container.querySelector("[data-modal-search]"); + if(searchInput && placeholder){ + searchInput.placeholder = placeholder; + } + }, + initRoleSelectionListeners() { const roleDivs = document.getElementsByName("role_div") if(roleDivs){ diff --git a/front/lib/front/rbac/role_management.ex b/front/lib/front/rbac/role_management.ex index 7a4b185fe..da6d809c1 100644 --- a/front/lib/front/rbac/role_management.ex +++ b/front/lib/front/rbac/role_management.ex @@ -212,7 +212,7 @@ defmodule Front.RBAC.RoleManagement do InternalApi.RBAC.SubjectType.value(:USER) end - subject = RBAC.Subject.new(subject_id: subject_id, type: subject_type) + subject = RBAC.Subject.new(subject_id: subject_id, subject_type: subject_type) req = RBAC.AssignRoleRequest.new( diff --git a/front/lib/front_web/templates/people/add_to_project/_popup_window.html.eex b/front/lib/front_web/templates/people/add_to_project/_popup_window.html.eex index 8228c93cf..c7aa03c7a 100644 --- a/front/lib/front_web/templates/people/add_to_project/_popup_window.html.eex +++ b/front/lib/front_web/templates/people/add_to_project/_popup_window.html.eex @@ -93,17 +93,39 @@