• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mirego / accent / #825

01 Feb 2026 04:23PM UTC coverage: 76.327% (+0.2%) from 76.119%
#825

push

github

simonprev
Add document and version filtering to project dashboard

Extend correct/uncorrect all mutations to support document_id and version_id filters.
Add document and version selects to dashboard UI with lazy-loaded activities.

11 of 17 new or added lines in 5 files covered. (64.71%)

10 existing lines in 4 files now uncovered.

2344 of 3071 relevant lines covered (76.33%)

22.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.5
/lib/movement/entries_commit_processor.ex
1
defmodule Movement.EntriesCommitProcessor do
2
  @moduledoc false
3
  alias Movement.MachineTranslations
4

5
  @no_action_keys ~w(noop autocorrect)
6
  @included_slave_actions ~w(new remove renew merge_on_corrected merge_on_proposed merge_on_proposed_force merge_on_corrected_force)
7

8
  @doc """
9
  For list of translations, new data (like the content of a file upload) and a given function,
10
  returns the list of operations that will be executed. The operations will be neither persisted nor run.
11

12
  The list contains the operations for keys that exists in the current translations list. For the removal of
13
  keys, use the process_for_remove/3 function.
14
  """
15
  @spec process(Movement.Context.t()) :: Movement.Context.t()
16
  def process(%Movement.Context{entries: entries, assigns: assigns, operations: operations} = context) do
17
    grouped_translations = group_by_key(assigns[:translations])
23✔
18
    versioned_translations_by_key = assigns[:versioned_translations_by_key] || %{}
23✔
19

20
    new_operations =
23✔
21
      entries
22
      |> Enum.map(fn entry ->
23
        current_translation = fetch_current_translation(grouped_translations, entry.key)
48✔
24

25
        versioned_translation_ids =
48✔
26
          fetch_versioned_translation_ids(versioned_translations_by_key, entry.key, current_translation)
48✔
27

28
        suggested_translation = %Movement.SuggestedTranslation{
48✔
29
          text: entry.value,
48✔
30
          key: entry.key,
48✔
31
          file_comment: entry.comment,
48✔
32
          file_index: entry.index,
48✔
33
          value_type: entry.value_type,
48✔
34
          plural: entry.plural,
48✔
35
          locked: entry.locked,
48✔
36
          translation_id: current_translation && current_translation.id,
48✔
37
          revision_id: Map.get(assigns[:revision], :id),
38
          version_id: assigns[:version] && Map.get(assigns[:version], :id),
48✔
39
          placeholders: entry.placeholders,
48✔
40
          versioned_translation_ids: versioned_translation_ids
41
        }
42

43
        operation = assigns[:comparer].(current_translation, suggested_translation)
48✔
44

45
        operation =
48✔
46
          if MachineTranslations.enable_machine_translation?(
47
               operation,
48
               entry,
49
               assigns[:revision],
50
               assigns[:project],
51
               assigns[:batch_action]
52
             ) do
UNCOV
53
            %{operation | machine_translations_enabled: true}
×
54
          else
55
            operation
48✔
56
          end
57

58
        %{operation | options: assigns[:options]}
48✔
59
      end)
60
      |> filter_for_revision(assigns[:revision])
61
      |> MachineTranslations.translate(assigns[:project], assigns[:master_revision], assigns[:revision])
62

63
    %{context | operations: Enum.concat(operations, new_operations)}
23✔
64
  end
65

66
  @doc """
67
  For list of translations and new data (like the content of a file upload),
68
  returns the list of operations concerning removed keys from the content that will be exectued.
69
  """
70
  @spec process_for_remove(Movement.Context.t()) :: Movement.Context.t()
71
  def process_for_remove(%Movement.Context{entries: entries, assigns: assigns, operations: operations} = context) do
72
    grouped_entries = group_by_key(entries)
13✔
73
    grouped_entries_keys = Map.keys(grouped_entries)
13✔
74

75
    new_operations =
13✔
76
      assigns[:translations]
77
      |> Enum.filter(&(!&1.removed && &1.key not in grouped_entries_keys))
12✔
78
      |> Enum.map(fn current_translation ->
79
        suggested_translation = %{current_translation | marked_as_removed: true}
2✔
80

81
        assigns[:comparer].(suggested_translation, suggested_translation)
2✔
82
      end)
83

84
    %{context | operations: Enum.concat(operations, new_operations)}
13✔
85
  end
86

87
  defp group_by_key(list), do: Enum.group_by(list, & &1.key)
36✔
88

89
  defp fetch_current_translation(grouped_translations, key) do
90
    grouped_translations
91
    |> Map.get(key)
92
    |> case do
48✔
93
      [value | _rest] when is_map(value) -> value
19✔
94
      _ -> nil
29✔
95
    end
96
  end
97

98
  defp fetch_versioned_translation_ids(_versioned_translations_by_key, _key, current_translation)
19✔
99
       when not is_nil(current_translation),
100
       do: []
101

102
  defp fetch_versioned_translation_ids(versioned_translations_by_key, key, _current_translation) do
103
    versioned_translations_by_key
104
    |> Map.get(key, [])
105
    |> Enum.map(& &1.id)
29✔
106
  end
107

108
  defp filter_for_revision(operations, %{master: true}) do
109
    Enum.filter(
22✔
110
      operations,
111
      fn operation ->
112
        operation.action not in @no_action_keys
47✔
113
      end
114
    )
115
  end
116

117
  defp filter_for_revision(operations, _) do
118
    Enum.filter(
1✔
119
      operations,
120
      fn operation ->
121
        operation.action in @included_slave_actions and operation.action not in @no_action_keys
1✔
122
      end
123
    )
124
  end
125
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc