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

MarkUsProject / Markus / 26381691124

25 May 2026 03:31AM UTC coverage: 90.285% (+0.03%) from 90.258%
26381691124

Pull #7938

github

web-flow
Merge 34449a447 into 423827af9
Pull Request #7938: TICKET-614: Add case sensitivy to group search

996 of 2177 branches covered (45.75%)

Branch coverage included in aggregate %.

55 of 75 new or added lines in 5 files covered. (73.33%)

104 existing lines in 3 files now uncovered.

45971 of 49844 relevant lines covered (92.23%)

122.82 hits per line

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

79.17
/app/javascript/Components/annotation_usage_panel.jsx
1
import React from "react";
2
import ReactTable from "react-table";
3
import {createRoot} from "react-dom/client";
4
import ReactDOM from "react-dom";
5

6
import {caseSensitiveIncludes, caseSensitiveTextFilter} from "./Helpers/table_helpers";
7

8
class AnnotationUsagePanel extends React.Component {
9
  constructor(props) {
10
    super(props);
2✔
11
    this.state = {
2✔
12
      applications: null,
13
      details: false,
14
      columns: this.getColumns(),
15
    };
16
  }
17

18
  toggle = () => {
2✔
19
    if (this.state.applications === null) {
2!
20
      this.fetchData();
2✔
21
    } else {
22
      this.setState({details: !this.state.details});
×
23
    }
24
  };
25

26
  getColumns = () => {
2✔
27
    return [
2✔
28
      {
29
        Header: I18n.t("annotations.used_by"),
30
        accessor: row => `(${row.user_name}) ${row.first_name} ${row.last_name}`,
15✔
31
        id: "user",
32
        minWidth: 200,
33
        PivotValue: ({value}) => value,
18✔
34
      },
35
      {
36
        Header: I18n.t("activerecord.models.submission.one"),
37
        accessor: "group_name",
38
        id: "group_name",
39
        aggregate: (vals, pivots) => {
40
          const usageCount = pivots.reduce((sum, p) => sum + p._original.count, 0);
15✔
41
          return I18n.t("annotations.used_times", {count: usageCount});
15✔
42
        },
43
        sortable: false,
44
        Aggregated: row => `(${row.value})`,
18✔
45
        Filter: caseSensitiveTextFilter,
46
        filterMethod: (filter, row) => {
47
          const {filterValue, caseSensitive} = filter.value;
30✔
48
          if (!filterValue) return true;
30✔
49
          if (row._subRows === undefined) {
18✔
50
            return caseSensitiveIncludes(row[filter.id], filterValue, caseSensitive);
6✔
51
          }
52
          return row._subRows.some(sr =>
12✔
53
            caseSensitiveIncludes(sr.group_name, filterValue, caseSensitive)
12✔
54
          );
55
        },
56
        Cell: row => {
NEW
57
          const {group_name, count, result_id} = row.original;
×
NEW
58
          const suffix = count > 1 ? ` (${count})` : "";
×
NEW
59
          return (
×
60
            <a href={Routes.edit_course_result_path(this.props.course_id, result_id)}>
61
              {`${group_name}${suffix}`}
62
            </a>
63
          );
64
        },
65
      },
66
    ];
67
  };
68

69
  fetchData = () => {
2✔
70
    const url = Routes.annotation_text_uses_course_assignment_annotation_categories_path(
2✔
71
      this.props.course_id,
72
      this.props.assignment_id,
73
      {
74
        annotation_text_id: this.props.annotation_id,
75
      }
76
    );
77
    fetch(url, {
2✔
78
      headers: {
79
        Accept: "application/json",
80
      },
81
    })
82
      .then(response => {
83
        if (response.ok) {
2!
84
          return response.json();
2✔
85
        }
86
      })
87
      .then(res => {
88
        this.setState({applications: res, details: true});
2✔
89
      });
90
  };
91

92
  render() {
93
    let numUsed = <p>{I18n.t("annotations.count") + this.props.num_used}</p>;
4✔
94
    let displayToggle = (
95
      <p>
4✔
96
        <a onClick={this.toggle} className="button">
97
          {I18n.t("annotations.usage")}
98
        </a>
99
      </p>
100
    );
101
    if (this.state.details) {
4✔
102
      let annotation_table = (
103
        <ReactTable
2✔
104
          className="auto-overflow"
105
          data={this.state.applications}
106
          columns={this.state.columns}
107
          filterable
108
          pivotBy={["user"]}
109
        />
110
      );
111
      return (
2✔
112
        <fieldset>
113
          {numUsed}
114
          {displayToggle}
115
          {annotation_table}
116
        </fieldset>
117
      );
118
    } else {
119
      return (
2✔
120
        <fieldset>
121
          {numUsed}
122
          {displayToggle}
123
        </fieldset>
124
      );
125
    }
126
  }
127
}
128

129
export function makeAnnotationUsagePanel(elem, props) {
130
  const root = createRoot(elem);
×
131
  return root.render(<AnnotationUsagePanel {...props} />);
×
132
}
133

134
export {AnnotationUsagePanel};
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