Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce editable table for creating score distributions #5723

Draft
wants to merge 54 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
2ea4fd5
DIY first version
jorg-vr Aug 6, 2024
935ce06
Use jspreadsheet
jorg-vr Aug 6, 2024
0df802b
Disable unwanted options
jorg-vr Aug 7, 2024
afee968
Actually save updates
jorg-vr Aug 7, 2024
f6f7f81
Fix new rows
jorg-vr Aug 7, 2024
e45df51
Allow inserting in different order
jorg-vr Aug 7, 2024
94161d2
Add validation
jorg-vr Aug 7, 2024
6258c97
Delete no longer needed options
jorg-vr Aug 7, 2024
c1e43df
Fix toggle
jorg-vr Aug 7, 2024
e516a08
Introduce translations
jorg-vr Aug 8, 2024
4e8e4c9
Introduce translations
jorg-vr Aug 8, 2024
0ddc92a
Add help text
jorg-vr Aug 8, 2024
4d99358
Fix minor bugs
jorg-vr Aug 8, 2024
a52eeff
Show validation warning
jorg-vr Aug 8, 2024
2812c8d
Ask to confirm warnings
jorg-vr Aug 8, 2024
abadbe9
Improve buttons
jorg-vr Aug 8, 2024
2a0a4a8
Remove checkboxes
jorg-vr Aug 8, 2024
40d20f9
Fix row heights
jorg-vr Aug 8, 2024
99b27c8
Merge branch 'main' into feat/table-input
jorg-vr Aug 8, 2024
61ed540
Fix tests
jorg-vr Aug 8, 2024
66c5247
Remove system test
jorg-vr Aug 8, 2024
2451a67
Fix empty case
jorg-vr Aug 8, 2024
c68b4d0
Judge empty rows more kindly
jorg-vr Aug 8, 2024
ad5c0d8
Remove the export option
jorg-vr Aug 8, 2024
defc89e
Avoid type coercion
jorg-vr Aug 9, 2024
41d8fae
Remove comments
jorg-vr Aug 9, 2024
bf47ad7
Add docs
jorg-vr Aug 9, 2024
973371d
Add translations for menu
jorg-vr Aug 9, 2024
a7e363d
Fix dark mode
jorg-vr Aug 9, 2024
f1ac12c
Merge branch 'main' into feat/table-input
jorg-vr Aug 30, 2024
be2eec6
Merge branch 'main' into feat/table-input
jorg-vr Oct 25, 2024
838e3cc
Open edit table on click
jorg-vr Oct 25, 2024
88d9bb4
Align colums left as in non edit version
jorg-vr Oct 25, 2024
370b371
Remove outline of btn
jorg-vr Oct 25, 2024
cc50615
Change header text style
jorg-vr Oct 25, 2024
d443fa0
Improve number validation
jorg-vr Oct 25, 2024
5cb4711
Update warnings
jorg-vr Oct 25, 2024
56982a5
Fix paste in chrome
jorg-vr Oct 28, 2024
cc80dde
Update app/assets/javascripts/components/input_table.ts
jorg-vr Oct 28, 2024
26951de
Merge branch 'main' into feat/table-input
jorg-vr Nov 13, 2024
b26e13a
Fix clickability of max score column
jorg-vr Nov 13, 2024
8352cf2
Merge branch 'main' into feat/table-input
jorg-vr Nov 18, 2024
19706ee
Make cursor point out edditable
jorg-vr Nov 18, 2024
5b72d72
Use text button for edit
jorg-vr Nov 18, 2024
c47f7ce
Add button to empty state
jorg-vr Nov 18, 2024
0aef455
Add delete row button functionality
jorg-vr Nov 18, 2024
d5ab37c
Add title to delete button
jorg-vr Nov 18, 2024
e178e01
Fix checkboxes
jorg-vr Nov 19, 2024
ecaff9e
Remove error text on cancel
jorg-vr Nov 19, 2024
d8e26d0
Get rid of red squibles
jorg-vr Nov 19, 2024
7973375
fix spelling
jorg-vr Nov 19, 2024
c3515e3
Fix colspan
jorg-vr Nov 19, 2024
fe65e92
Update app/assets/javascripts/components/input_table.ts
jorg-vr Nov 20, 2024
19929b8
Fix checkbox allignment in chrome
jorg-vr Nov 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
304 changes: 304 additions & 0 deletions app/assets/javascripts/components/input_table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
import { customElement, property } from "lit/decorators.js";
import { html, PropertyValues, render, TemplateResult } from "lit";
import jspreadsheet, { CellValue, Column, CustomEditor, JspreadsheetInstance } from "jspreadsheet-ce";
import { createRef, ref, Ref } from "lit/directives/ref.js";
import { DodonaElement } from "components/meta/dodona_element";
import { fetch, ready } from "utilities";
import { i18n } from "i18n/i18n";
import { Tooltip } from "bootstrap";

Check warning on line 8 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L1-L8

Added lines #L1 - L8 were not covered by tests

type CellData = string | number | boolean;
type ScoreItem = {
id: number | null;
name: string;
description?: string;
maximum: string;
visible: boolean;
order?: number;
}

type ColumnWithTooltip = Column & { tooltip?: string };

const toBoolean = (value: CellValue): boolean => {

Check warning on line 22 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L22

Added line #L22 was not covered by tests
return value === "true" || value === true;
};

/**
* A spreadsheet table to edit score items.
*
* @element d-score-item-input-table
*
* @fires cancel - When the cancel button is clicked.
*
* @prop {string} route - The route to send the updated score items to.
* @prop {ScoreItem[]} scoreItems - The original score items, that will be displayed in the table.
*/
@customElement("d-score-item-input-table")
export class ScoreItemInputTable extends DodonaElement {

Check warning on line 37 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L37

Added line #L37 was not covered by tests
@property({ type: String })
route: string = "";

Check warning on line 39 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L39

Added line #L39 was not covered by tests
@property({ type: Array, attribute: "score-items" })
scoreItems: ScoreItem[] = [];

Check warning on line 41 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L41

Added line #L41 was not covered by tests

tableRef: Ref<HTMLDivElement> = createRef();

Check warning on line 43 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L43

Added line #L43 was not covered by tests
table: JspreadsheetInstance;

@property({ state: true })
hasErrors: boolean = false;

Check warning on line 47 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L47

Added line #L47 was not covered by tests

get tableWidth(): number {
return this.tableRef.value.clientWidth;

Check warning on line 50 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L49-L50

Added lines #L49 - L50 were not covered by tests
}

get descriptionColWidth(): number {

Check warning on line 53 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L53

Added line #L53 was not covered by tests
if (!this.tableRef.value) {
return 200;

Check warning on line 55 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L55

Added line #L55 was not covered by tests
}

// full width - borders - name column - maximum column - visible column - index column - delete column
const variableWidth = this.tableWidth - 14 - 200 - 75 - 75 - 50 - 30;
return Math.max(200, variableWidth);

Check warning on line 60 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L59-L60

Added lines #L59 - L60 were not covered by tests
}

get data(): CellData[][] {
return [
...this.scoreItems.map(item => [

Check warning on line 65 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L63-L65

Added lines #L63 - L65 were not covered by tests
item.id,
item.name,
item.description,
item.maximum,
item.visible
]),
["", "", "", "", false]
];
}

get editedScoreItems(): ScoreItem[] {
const tableData = this.table.getData();

Check warning on line 77 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L76-L77

Added lines #L76 - L77 were not covered by tests

const scoreItems = tableData.map((row: CellData[], index: number) => {
return {

Check warning on line 80 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L79-L80

Added lines #L79 - L80 were not covered by tests
id: row[0] as number | null,
name: row[1] as string,
description: row[2] as string,
maximum: (row[3] as string).replace(",", "."), // replace comma with dot for float representation
visible: toBoolean(row[4]),
order: index,
};
});

// filter out empty rows
return scoreItems.filter(item => !(item.name === "" && item.maximum === "" && item.description === "" && item.visible === false));
}

deleteCellRow(cell: HTMLTableCellElement): void {
const row = cell.parentElement as HTMLTableRowElement;
this.table.deleteRow(row.rowIndex-1);

Check warning on line 96 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L94-L96

Added lines #L94 - L96 were not covered by tests
}

createDeleteButton(cell: HTMLTableCellElement): HTMLTableCellElement {
const button = html`<button

Check warning on line 100 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L99-L100

Added lines #L99 - L100 were not covered by tests
class="btn btn-icon d-btn-danger"
style="margin: -20px"
title="${i18n.t("js.score_items.jspreadsheet.deleteRow")}"
@click="${() => this.deleteCellRow(cell)}">

Check warning on line 104 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L104

Added line #L104 was not covered by tests
<i class="mdi mdi-18 mdi-delete"></i>
</button>`;
render(button, cell);
return cell;

Check warning on line 108 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L107-L108

Added lines #L107 - L108 were not covered by tests
}

customCheckboxEditor(): CustomEditor {
const updateCell = (cell: HTMLTableCellElement): void => {
this.table.setValue(cell, !toBoolean(this.table.getValue(cell)));

Check warning on line 113 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L111-L113

Added lines #L111 - L113 were not covered by tests
};
return {
createCell: (cell: HTMLTableCellElement) => {
const current = cell.innerHTML === "true";
const checkbox = html`<div class="form-check" contenteditable="false" style="margin: -16px 0;">

Check warning on line 118 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L115-L118

Added lines #L115 - L118 were not covered by tests
<input type="checkbox"
class="form-check-input"
?checked="${current}"
@change="${() => updateCell(cell)}">

Check warning on line 122 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L122

Added line #L122 was not covered by tests
</div>`;
cell.innerHTML = "";
render(checkbox, cell);
return cell;

Check warning on line 126 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L124-L126

Added lines #L124 - L126 were not covered by tests
},
openEditor: () => false,
closeEditor: (cell: HTMLTableCellElement) => {
return toBoolean(this.table.getValue(cell));

Check warning on line 130 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L128-L130

Added lines #L128 - L130 were not covered by tests
},
updateCell: (cell: HTMLTableCellElement, value: CellValue) => {
const checkbox = cell.querySelector("input");

Check warning on line 133 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L132-L133

Added lines #L132 - L133 were not covered by tests
if (checkbox) {
checkbox.checked = toBoolean(value);

Check warning on line 135 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L135

Added line #L135 was not covered by tests
}
return toBoolean(value);

Check warning on line 137 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L137

Added line #L137 was not covered by tests
}
};
}

get columnConfig(): ColumnWithTooltip[] {
return [

Check warning on line 143 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L142-L143

Added lines #L142 - L143 were not covered by tests
{ type: "hidden", title: "id" },
{ type: "text", title: i18n.t("js.score_items.name"), width: 200, align: "left" },
{ type: "text", title: i18n.t("js.score_items.description"), width: this.descriptionColWidth, align: "left", tooltip: i18n.t("js.score_items.description_help") },
{ type: "numeric", title: i18n.t("js.score_items.maximum"), width: 75, align: "left", tooltip: i18n.t("js.score_items.maximum_help") },
{ type: "html", title: i18n.t("js.score_items.visible"), width: 75, align: "left", tooltip: i18n.t("js.score_items.visible_help"), editor: this.customCheckboxEditor() },
{ type: "html", title: " ", width: 30, align: "center", readOnly: true, editor: {
createCell: (cell: HTMLTableCellElement) => this.createDeleteButton(cell),

Check warning on line 150 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L150

Added line #L150 was not covered by tests
} },
];
}

async initTable(): Promise<void> {

Check warning on line 155 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L155

Added line #L155 was not covered by tests
// Wait for translations to be present
await ready;

Check warning on line 157 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L157

Added line #L157 was not covered by tests

this.table = jspreadsheet(this.tableRef.value, {

Check warning on line 159 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L159

Added line #L159 was not covered by tests
root: this,
data: this.data,
columns: this.columnConfig,
text: {
copy: i18n.t("js.score_items.jspreadsheet.copy"),
deleteSelectedRows: i18n.t("js.score_items.jspreadsheet.deleteSelectedRows"),
insertANewRowAfter: i18n.t("js.score_items.jspreadsheet.insertNewRowAfter"),
insertANewRowBefore: i18n.t("js.score_items.jspreadsheet.insertNewRowBefore"),
paste: i18n.t("js.score_items.jspreadsheet.paste"),
},
about: false,
allowDeleteColumn: false,
allowDeleteRow: true,
allowInsertColumn: false,
allowInsertRow: true,
allowManualInsertColumn: false,
allowManualInsertRow: true,
allowRenameColumn: false,
columnResize: false,
columnSorting: false,
minSpareRows: 1,
parseFormulas: false,
selectionCopy: false,
wordWrap: true,
defaultRowHeight: 30,
allowExport: false,
});
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved

// init tooltips
this.columnConfig.forEach((column, index) => {
const td = this.tableRef.value.querySelector(`thead td[data-x="${index}"]`);

Check warning on line 190 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L189-L190

Added lines #L189 - L190 were not covered by tests
if (td && column.tooltip) {
td.setAttribute("title", column.tooltip);
new Tooltip(td);

Check warning on line 193 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L192-L193

Added lines #L192 - L193 were not covered by tests
}
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved
});

// mark header and menu as non-editable
this.tableRef.value.querySelector("thead").setAttribute("contenteditable", "false");
this.tableRef.value.querySelector(".jexcel_contextmenu").setAttribute("contenteditable", "false");

Check warning on line 199 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L198-L199

Added lines #L198 - L199 were not covered by tests


// update description column width when the window is resized
new ResizeObserver(() => {
this.table.setWidth(2, this.descriptionColWidth);

Check warning on line 204 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L203-L204

Added lines #L203 - L204 were not covered by tests
}).observe(this.tableRef.value);
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved
}

protected firstUpdated(_changedProperties: PropertyValues): void {
super.firstUpdated(_changedProperties);

Check warning on line 209 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L208-L209

Added lines #L208 - L209 were not covered by tests

this.initTable();

Check warning on line 211 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L211

Added line #L211 was not covered by tests
}

validate(): boolean {

Check warning on line 214 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L214

Added line #L214 was not covered by tests
// Remove all error classes
this.tableRef.value.querySelectorAll("td.error").forEach(cell => {
cell.classList.remove("error");

Check warning on line 217 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L216-L217

Added lines #L216 - L217 were not covered by tests
});

const invalidCells: string[] = [];
const data = this.editedScoreItems;
data.forEach(item => {
const row = item.order + 1;

Check warning on line 223 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L220-L223

Added lines #L220 - L223 were not covered by tests
if (item.name === "") {
invalidCells.push("B" + row);

Check warning on line 225 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L225

Added line #L225 was not covered by tests
}
// Check if maximum is a positive number < 1000
// we use a regex instead of parseFloat because parseFloat is too lenient
if (! /^\d{1,3}(\.\d*)?$/.test(item.maximum) || parseFloat(item.maximum) <= 0) {
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved
invalidCells.push("D" + row);

Check warning on line 230 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L230

Added line #L230 was not covered by tests
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved
}
});
invalidCells.forEach(cell => {
this.table.getCell(cell).classList.add("error");

Check warning on line 234 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L233-L234

Added lines #L233 - L234 were not covered by tests
});
this.hasErrors = invalidCells.length > 0;
return !this.hasErrors;

Check warning on line 237 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L236-L237

Added lines #L236 - L237 were not covered by tests
}
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved

confirmWarnings(): boolean {
const old = this.scoreItems;
const edited = this.editedScoreItems;
const removed = old.some(item => !edited.some(e => e.id === item.id));

Check warning on line 243 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L240-L243

Added lines #L240 - L243 were not covered by tests
const maxEdited = old.some(item => edited.some(e => e.id === item.id && e.maximum !== item.maximum));

let warnings = "";

Check warning on line 246 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L246

Added line #L246 was not covered by tests
if (removed) {
warnings += i18n.t("js.score_items.deleted_warning") + "\n";

Check warning on line 248 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L248

Added line #L248 was not covered by tests
}
if (maxEdited) {
warnings += i18n.t("js.score_items.modified_warning") + "\n";

Check warning on line 251 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L251

Added line #L251 was not covered by tests
}

return warnings === "" || confirm(warnings);
}

async save(): Promise<void> {

Check warning on line 257 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L257

Added line #L257 was not covered by tests
if (!this.validate()) {
return;

Check warning on line 259 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L259

Added line #L259 was not covered by tests
}

if (!this.confirmWarnings()) {
return;

Check warning on line 263 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L263

Added line #L263 was not covered by tests
}

const response = await fetch(this.route, {

Check warning on line 266 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L266

Added line #L266 was not covered by tests
method: "PATCH",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
score_items: this.editedScoreItems
})
});
if (response.ok) {
const js = await response.text();
eval(js);

Check warning on line 277 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L276-L277

Added lines #L276 - L277 were not covered by tests
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved
}
}
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved

cancel(): void {

Check warning on line 281 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L281

Added line #L281 was not covered by tests
if (this.table) {
this.table.setData(this.data);
this.hasErrors = false;

Check warning on line 284 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L283-L284

Added lines #L283 - L284 were not covered by tests
}
this.dispatchEvent(new Event("cancel"));

Check warning on line 286 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L286

Added line #L286 was not covered by tests
}


render(): TemplateResult {
return html`

Check warning on line 291 in app/assets/javascripts/components/input_table.ts

View check run for this annotation

Codecov / codecov/patch

app/assets/javascripts/components/input_table.ts#L290-L291

Added lines #L290 - L291 were not covered by tests
${this.hasErrors ? html`<div class="alert alert-danger">${i18n.t("js.score_items.validation_warning")}</div>` : ""}
<div style="width: 100%" ${ref(this.tableRef)} contenteditable="true"></div>
<div class="d-flex justify-content-end">
<button @click=${this.cancel} class="btn btn-text me-1">
${i18n.t("js.score_items.cancel")}
</button>
<button @click=${this.save} class="btn btn-filled">
${i18n.t("js.score_items.save")}
</button>
</div>
`;
}
}
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved
44 changes: 44 additions & 0 deletions app/assets/javascripts/i18n/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,28 @@
"score_item": {
"error": "Error while updating"
},
"score_items": {
"cancel": "Cancel",
"deleted_warning": "You have deleted one or more score items. This will also delete all scores for these items.",
"description": "Description",
"description_help": "A description is optional. Markdown formatting can be used. This is visible to the students.",
"jspreadsheet": {
"copy": "Copy...",
"deleteRow": "Delete row",
"deleteSelectedRows": "Delete selected rows",
"insertNewRowAfter": "Insert new row after",
"insertNewRowBefore": "Insert new row before",
"paste": "Paste..."
},
"maximum": "Maximum",
"maximum_help": "The maximum grade for this score item. The grade should be between 0 and 1000, and works in increments of 0.25.",
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved
"modified_warning": "You have changed the maximum score of one or more score items. This will mark all completed evaluations with this score item as uncompleted.",
"name": "Name",
"save": "Save",
"validation_warning": "All score items must have a name and a maximum score, and the maximum score must be between 0 and 1000.",
"visible": "Visible",
"visible_help": "Make the score item visible to students once the evaluation is released."
},
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved
"search": {
"filter": {
"course_id": "Course",
Expand Down Expand Up @@ -825,6 +847,28 @@
"score_item": {
"error": "Fout bij bijwerken"
},
"score_items": {
"cancel": "Annuleren",
"deleted_warning": "Je hebt een of meerdere scoreonderdelen verwijderd. Dit zal ook de bijhorende scores van de studenten verwijderen.",
"description": "Beschrijving",
"description_help": "Een beschrijving is optioneel en kan in Markdown geschreven worden. Dit is zichtbaar voor de studenten.",
"jspreadsheet": {
"copy": "Kopieer...",
"deleteRow": "Verwijder rij",
"deleteSelectedRows": "Verwijder geselecteerde rijen",
"insertNewRowAfter": "Voeg nieuwe rij toe na deze",
"insertNewRowBefore": "Voeg nieuwe rij toe voor deze",
"paste": "Plak..."
},
"maximum": "Maximum",
"maximum_help": "De maximumscore voor dit scoreonderdeel. Dit moet een getal zijn tussen 0 en 1000 en gaat in stappen van 0.25.",
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved
"modified_warning": "Je hebt de maximumscore van een of meerdere scoreonderdelen aangepast. Alle afgewerkte evaluaties met dit scoreonderdeel zullen terug als onafgewerkt gemarkeerd worden.",
"name": "Naam",
"save": "Opslaan",
"validation_warning": "Alle scoreonderdelen moeten een naam en een maximumscore hebben. De maximumscore moet een getal zijn tussen 0 en 1000.",
"visible": "Zichtbaar",
"visible_help": "Maak het scoreonderdeel zichtbaar voor studenten eens de evaluatie vrijgegeven is."
},
jorg-vr marked this conversation as resolved.
Show resolved Hide resolved
"search": {
"filter": {
"course_id": "Cursus",
Expand Down
Loading