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

MarkUsProject / Markus / 12976781475

26 Jan 2025 05:20PM UTC coverage: 91.854% (-0.02%) from 91.87%
12976781475

Pull #7392

github

web-flow
Merge 4e5b55b4a into 10a758445
Pull Request #7392: Update React to v18

624 of 1361 branches covered (45.85%)

Branch coverage included in aggregate %.

0 of 16 new or added lines in 8 files covered. (0.0%)

75 existing lines in 4 files now uncovered.

41290 of 44270 relevant lines covered (93.27%)

120.23 hits per line

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

22.58
/app/javascript/Components/repo_browser.jsx
1
import React from "react";
2
import {createRoot} from "react-dom/client";
3
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
4
import {SubmissionFileManager} from "./submission_file_manager";
5

6
class RepoBrowser extends React.Component {
7
  constructor(props) {
8
    super(props);
×
9
    this.state = {
×
10
      revision_identifier: undefined,
11
      revisions: [],
12
    };
13
  }
14

15
  componentDidMount() {
16
    this.fetchRevisions();
×
17
  }
18

19
  // Update the list of revisions and set the currently-viewed revision to the most recent one.
20
  fetchRevisions = () => {
×
21
    fetch(
×
22
      Routes.revisions_course_assignment_submissions_path({
23
        course_id: this.props.course_id,
24
        assignment_id: this.props.assignment_id,
25
        grouping_id: this.props.grouping_id,
26
      }),
27
      {
28
        credentials: "same-origin",
29
        headers: {
30
          "content-type": "application/json",
31
        },
32
      }
33
    )
34
      .then(data => data.json())
×
35
      .then(data => this.setState({revisions: data, revision_identifier: data[0].id}));
×
36
  };
37

38
  selectRevision = event => {
×
39
    this.setState({revision_identifier: event.target.value});
×
40
  };
41

42
  revisionToOption = rev => {
×
43
    let text = `${rev.id_ui} `;
×
44
    if (rev.timestamp !== rev.server_timestamp) {
×
45
      text +=
×
46
        `(${I18n.t("submissions.repo_browser.client_time")} ${rev.timestamp}, ` +
47
        `${I18n.t("submissions.repo_browser.server_time")} ${rev.server_timestamp})`;
48
    } else {
49
      text += `(${rev.timestamp})`;
×
50
    }
51

52
    // Highlight the collected revision
53
    let className = "";
×
54
    if (rev.id === this.props.collected_revision_id) {
×
55
      className = "collected";
×
56
      text += ` — ${I18n.t("submissions.repo_browser.collected")}`;
×
57
    } else {
58
      className = "uncollected";
×
59
    }
60

61
    return (
×
62
      <option className={className} key={rev.id} value={rev.id}>
63
        {text}
64
      </option>
65
    );
66
  };
67

68
  isReadOnly = () => {
×
69
    if (!!this.state.revisions.length) {
×
70
      return this.state.revision_identifier !== this.state.revisions[0].id;
×
71
    } else {
72
      return false;
×
73
    }
74
  };
75

76
  render() {
77
    let className = "";
×
78
    if (this.state.revision_identifier === this.props.collected_revision_id) {
×
79
      className = "collected-checked";
×
80
    }
81
    let manualCollectionForm = "";
×
82
    if (this.props.enableCollect) {
×
83
      manualCollectionForm = (
×
84
        <ManualCollectionForm
85
          course_id={this.props.course_id}
86
          assignment_id={this.props.assignment_id}
87
          late_penalty={this.props.late_penalty}
88
          grouping_id={this.props.grouping_id}
89
          revision_identifier={this.state.revision_identifier}
90
          collected_revision_id={this.props.collected_revision_id}
91
        />
92
      );
93
    }
94
    return (
×
95
      <div>
96
        <h3>
97
          <label>{I18n.t("submissions.repo_browser.viewing_revision")}</label>
98
          <select
99
            value={this.state.revision_identifier}
100
            onChange={this.selectRevision}
101
            className={className}
102
          >
103
            {this.state.revisions.map(this.revisionToOption)}
104
          </select>
105
        </h3>
106
        {this.props.is_timed && (
×
107
          <p>
108
            <strong>{I18n.t("activerecord.attributes.assignment.start_time")}: </strong>
109
            {this.props.start_time || I18n.t("not_applicable")}
×
110
          </p>
111
        )}
112
        <p>
113
          <strong>{I18n.t("activerecord.attributes.assignment.due_date")}: </strong>
114
          {this.props.due_date}
115
        </p>
116
        <p>
117
          <strong>{I18n.t("activerecord.attributes.assignment.collection_date")}: </strong>
118
          {this.props.collection_date}
119
        </p>
120
        <SubmissionFileManager
121
          course_id={this.props.course_id}
122
          assignment_id={this.props.assignment_id}
123
          grouping_id={this.props.grouping_id}
124
          revision_identifier={this.state.revision_identifier}
125
          onChange={this.fetchRevisions}
126
          fetchOnMount={false}
127
          enableSubdirs={this.props.enableSubdirs}
128
          enableUrlSubmit={this.props.enableUrlSubmit}
129
          readOnly={this.isReadOnly()}
130
        />
131
        {manualCollectionForm}
132
      </div>
133
    );
134
  }
135
}
136

137
class ManualCollectionForm extends React.Component {
138
  static defaultProps = {
1✔
139
    revision_identifier: "", //set initial value so that the input (in render) remains controlled
140
  };
141

142
  constructor(props) {
143
    super(props);
4✔
144
    this.state = {
4✔
145
      retainExistingGrading: true,
146
    };
147
  }
148

149
  render() {
150
    const action = Routes.manually_collect_and_begin_grading_course_assignment_submissions_path(
6✔
151
      this.props.course_id,
152
      this.props.assignment_id
153
    );
154

155
    return (
6✔
156
      <fieldset>
157
        <legend>
158
          <span>{I18n.t("submissions.collect.manual_collection")}</span>
159
        </legend>
160
        <form
161
          method="POST"
162
          action={action}
163
          data-testid="form_manual_collection"
164
          onSubmit={event => {
165
            if (
2!
166
              this.props.collected_revision_id &&
7✔
167
              ((!this.state.retainExistingGrading &&
168
                !confirm(I18n.t("submissions.collect.full_overwrite_warning"))) ||
169
                (this.state.retainExistingGrading &&
170
                  !confirm(I18n.t("submissions.collect.confirm_recollect_retain_data"))))
171
            ) {
172
              event.preventDefault();
2✔
173
            }
174
          }}
175
        >
176
          <input
177
            type="hidden"
178
            name="current_revision_identifier"
179
            value={this.props.revision_identifier}
180
          />
181
          <input type="hidden" name="grouping_id" value={this.props.grouping_id} />
182
          <input type="hidden" name="authenticity_token" value={AUTH_TOKEN} />
183
          <p className="inline-labels">
184
            <input
185
              hidden={!this.props.late_penalty}
186
              type="checkbox"
187
              name="apply_late_penalty"
188
              id="apply_late_penalty"
189
            />
190
            <label hidden={!this.props.late_penalty} htmlFor="apply_late_penalty">
191
              {I18n.t("submissions.collect.apply_late_penalty")}
192
            </label>
193
          </p>
194
          <p className="inline-labels">
195
            <input
196
              type="checkbox"
197
              name="retain_existing_grading"
198
              id="retain_existing_grading"
199
              data-testid="chk_retain_existing_grading"
200
              checked={this.state.retainExistingGrading}
201
              hidden={!this.props.collected_revision_id}
202
              disabled={!this.props.collected_revision_id} // prevent from sending info on submit
203
              onChange={e => {
204
                this.setState({retainExistingGrading: e.target.checked});
1✔
205
              }}
206
            />
207
            <label
208
              data-testid="lbl_retain_existing_grading"
209
              htmlFor="retain_existing_grading"
210
              hidden={!this.props.collected_revision_id}
211
            >
212
              {I18n.t("submissions.collect.retain_existing_grading")}
213
            </label>
214
          </p>
215
          <button type="submit" name="commit">
216
            <FontAwesomeIcon icon="fa-solid fa-file-import" />
217
            {I18n.t("submissions.collect.this_revision")}
218
          </button>
219
        </form>
220
      </fieldset>
221
    );
222
  }
223
}
224

225
export function makeRepoBrowser(elem, props) {
NEW
226
  const root = createRoot(elem);
×
NEW
227
  root.render(<RepoBrowser {...props} />);
×
228
}
229

230
export {ManualCollectionForm};
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