2022-07-14 11:56:11 -04:00
|
|
|
import { action } from "@ember/object";
|
|
|
|
import loadScript from "discourse/lib/load-script";
|
2022-08-11 14:33:34 -04:00
|
|
|
import {
|
|
|
|
arrayToTable,
|
|
|
|
findTableRegex,
|
|
|
|
tokenRange,
|
|
|
|
} from "../discourse-table-builder/lib/utilities";
|
2022-08-11 14:59:08 -04:00
|
|
|
import Component from "@glimmer/component";
|
2022-07-16 14:00:05 -04:00
|
|
|
import { ajax } from "discourse/lib/ajax";
|
|
|
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
2022-07-18 14:18:58 -04:00
|
|
|
import I18n from "I18n";
|
2022-07-19 19:33:10 -04:00
|
|
|
import { schedule } from "@ember/runloop";
|
2022-07-21 17:19:01 -04:00
|
|
|
import { tracked } from "@glimmer/tracking";
|
2022-07-28 10:33:25 -04:00
|
|
|
|
2022-08-11 14:59:08 -04:00
|
|
|
export default class SpreadsheetEditor extends Component {
|
2022-07-21 17:19:01 -04:00
|
|
|
@tracked showEditReason = false;
|
|
|
|
spreadsheet = null;
|
2022-08-10 16:50:38 -04:00
|
|
|
defaultColWidth = 150;
|
2022-08-15 11:47:33 -04:00
|
|
|
@tracked loading = null;
|
2022-07-19 19:33:10 -04:00
|
|
|
|
|
|
|
// Getters:
|
|
|
|
get isEditingTable() {
|
2022-08-09 20:14:35 -04:00
|
|
|
if (this.args.tableTokens) {
|
2022-07-19 19:33:10 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2022-07-21 17:19:01 -04:00
|
|
|
}
|
2022-07-19 19:33:10 -04:00
|
|
|
|
|
|
|
get modalAttributes() {
|
|
|
|
if (this.isEditingTable) {
|
|
|
|
return {
|
|
|
|
title: themePrefix("discourse_table_builder.edit.modal.title"),
|
|
|
|
insertTable: {
|
|
|
|
title: themePrefix("discourse_table_builder.edit.modal.create"),
|
|
|
|
icon: "pencil-alt",
|
|
|
|
},
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
return {
|
|
|
|
title: themePrefix("discourse_table_builder.modal.title"),
|
|
|
|
insertTable: {
|
|
|
|
title: themePrefix("discourse_table_builder.modal.create"),
|
|
|
|
icon: "plus",
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
2022-07-21 17:19:01 -04:00
|
|
|
}
|
2022-07-19 19:33:10 -04:00
|
|
|
|
|
|
|
// Actions:
|
2022-07-21 17:19:01 -04:00
|
|
|
@action
|
|
|
|
createSpreadsheet(spreadsheet) {
|
|
|
|
this.spreadsheet = spreadsheet;
|
|
|
|
|
|
|
|
schedule("afterRender", () => {
|
|
|
|
this.loadLibraries().then(() => {
|
|
|
|
if (this.isEditingTable) {
|
2022-08-09 19:51:17 -04:00
|
|
|
this.buildPopulatedTable(this.args.tableTokens);
|
2022-07-21 17:19:01 -04:00
|
|
|
} else {
|
|
|
|
this.buildNewTable();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-07-19 19:33:10 -04:00
|
|
|
@action
|
|
|
|
showEditReasonField() {
|
|
|
|
if (this.showEditReason) {
|
2022-07-21 17:19:01 -04:00
|
|
|
this.showEditReason = false;
|
2022-07-19 19:33:10 -04:00
|
|
|
} else {
|
2022-07-21 17:19:01 -04:00
|
|
|
this.showEditReason = true;
|
2022-07-19 19:33:10 -04:00
|
|
|
}
|
2022-07-21 17:19:01 -04:00
|
|
|
}
|
2022-07-19 19:33:10 -04:00
|
|
|
|
|
|
|
@action
|
|
|
|
cancelTableInsertion() {
|
2022-07-21 17:19:01 -04:00
|
|
|
this.args.triggerModalClose();
|
|
|
|
}
|
2022-07-19 19:33:10 -04:00
|
|
|
|
|
|
|
@action
|
|
|
|
insertTable() {
|
|
|
|
const updatedHeaders = this.spreadsheet.getHeaders().split(","); // keys
|
|
|
|
const updatedData = this.spreadsheet.getData(); // values
|
|
|
|
const markdownTable = this.buildTableMarkdown(updatedHeaders, updatedData);
|
|
|
|
|
|
|
|
if (!this.isEditingTable) {
|
2022-07-21 17:19:01 -04:00
|
|
|
this.args.toolbarEvent.addText(markdownTable);
|
|
|
|
return this.args.triggerModalClose();
|
2022-07-19 19:33:10 -04:00
|
|
|
} else {
|
|
|
|
return this.updateTable(markdownTable);
|
|
|
|
}
|
2022-07-21 17:19:01 -04:00
|
|
|
}
|
2022-07-19 19:33:10 -04:00
|
|
|
|
|
|
|
// Helper Methods:
|
2022-07-14 12:21:22 -04:00
|
|
|
loadLibraries() {
|
2022-08-15 11:47:33 -04:00
|
|
|
this.loading = true;
|
|
|
|
return loadScript(settings.theme_uploads_local.jsuites)
|
|
|
|
.then(() => {
|
|
|
|
return loadScript(settings.theme_uploads_local.jspreadsheet);
|
|
|
|
})
|
|
|
|
.finally(() => (this.loading = false));
|
2022-07-21 17:19:01 -04:00
|
|
|
}
|
2022-07-14 12:21:22 -04:00
|
|
|
|
2022-07-19 19:33:10 -04:00
|
|
|
buildNewTable() {
|
|
|
|
const data = [
|
|
|
|
["", "", ""],
|
|
|
|
["", "", ""],
|
|
|
|
["", "", ""],
|
2022-08-12 14:11:27 -04:00
|
|
|
["", "", ""],
|
|
|
|
["", "", ""],
|
|
|
|
["", "", ""],
|
2022-07-19 19:33:10 -04:00
|
|
|
];
|
|
|
|
|
|
|
|
const columns = [
|
2022-08-10 16:50:38 -04:00
|
|
|
{
|
|
|
|
title: I18n.t(
|
|
|
|
themePrefix("discourse_table_builder.default_header.col_1")
|
|
|
|
),
|
|
|
|
width: this.defaultColWidth,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: I18n.t(
|
|
|
|
themePrefix("discourse_table_builder.default_header.col_2")
|
|
|
|
),
|
|
|
|
width: this.defaultColWidth,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: I18n.t(
|
|
|
|
themePrefix("discourse_table_builder.default_header.col_3")
|
|
|
|
),
|
|
|
|
width: this.defaultColWidth,
|
|
|
|
},
|
2022-08-12 14:11:27 -04:00
|
|
|
{
|
|
|
|
title: I18n.t(
|
|
|
|
themePrefix("discourse_table_builder.default_header.col_4")
|
|
|
|
),
|
|
|
|
width: this.defaultColWidth,
|
|
|
|
},
|
2022-07-19 19:33:10 -04:00
|
|
|
];
|
|
|
|
|
|
|
|
return this.buildSpreadsheet(data, columns);
|
2022-07-21 17:19:01 -04:00
|
|
|
}
|
2022-07-19 19:33:10 -04:00
|
|
|
|
2022-08-09 19:51:17 -04:00
|
|
|
extractTableContent(data) {
|
|
|
|
return data
|
|
|
|
.flat()
|
|
|
|
.filter((t) => t.type === "inline")
|
|
|
|
.map((t) => t.content);
|
|
|
|
}
|
2022-07-16 14:00:05 -04:00
|
|
|
|
2022-08-09 19:51:17 -04:00
|
|
|
buildPopulatedTable(tableTokens) {
|
|
|
|
const contentRows = tokenRange(tableTokens, "tr_open", "tr_close");
|
|
|
|
const rows = [];
|
|
|
|
let headings;
|
|
|
|
const rowWidthFactor = 8;
|
|
|
|
|
|
|
|
contentRows.forEach((row, index) => {
|
|
|
|
if (index === 0) {
|
|
|
|
// headings
|
|
|
|
headings = this.extractTableContent(row).map((heading) => {
|
|
|
|
return {
|
|
|
|
title: heading,
|
2022-08-10 16:50:38 -04:00
|
|
|
width: Math.max(
|
|
|
|
heading.length * rowWidthFactor,
|
|
|
|
this.defaultColWidth
|
|
|
|
),
|
|
|
|
align: "left",
|
2022-08-09 19:51:17 -04:00
|
|
|
};
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// rows:
|
2022-08-10 16:50:38 -04:00
|
|
|
rows.push(this.extractTableContent(row));
|
2022-07-14 11:56:11 -04:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-08-09 19:51:17 -04:00
|
|
|
return this.buildSpreadsheet(rows, headings);
|
2022-07-21 17:19:01 -04:00
|
|
|
}
|
2022-07-19 19:33:10 -04:00
|
|
|
|
|
|
|
buildSpreadsheet(data, columns, opts = {}) {
|
2022-08-12 15:10:04 -04:00
|
|
|
const postNumber = this.args.model?.post_number;
|
|
|
|
const exportFileName = postNumber
|
|
|
|
? `post-${postNumber}-table-export`
|
|
|
|
: `post-table-export`;
|
|
|
|
|
2022-07-14 12:21:22 -04:00
|
|
|
// eslint-disable-next-line no-undef
|
2022-07-21 17:19:01 -04:00
|
|
|
this.spreadsheet = jspreadsheet(this.spreadsheet, {
|
2022-07-19 19:33:10 -04:00
|
|
|
data,
|
2022-07-14 11:56:11 -04:00
|
|
|
columns,
|
2022-08-10 16:50:38 -04:00
|
|
|
defaultColAlign: "left",
|
|
|
|
wordWrap: true,
|
2022-08-12 15:10:04 -04:00
|
|
|
csvFileName: exportFileName,
|
2022-07-19 19:33:10 -04:00
|
|
|
...opts,
|
2022-07-14 11:56:11 -04:00
|
|
|
});
|
2022-07-21 17:19:01 -04:00
|
|
|
}
|
2022-07-14 11:56:11 -04:00
|
|
|
|
2022-07-19 19:33:10 -04:00
|
|
|
buildUpdatedPost(tableId, raw, newRaw) {
|
|
|
|
const tableToEdit = raw.match(findTableRegex());
|
|
|
|
let editedTable;
|
|
|
|
|
2023-01-04 02:06:25 -05:00
|
|
|
if (tableToEdit.length) {
|
2022-07-19 19:33:10 -04:00
|
|
|
editedTable = raw.replace(tableToEdit[tableId], newRaw);
|
2022-07-16 14:00:05 -04:00
|
|
|
} else {
|
2023-01-04 02:06:25 -05:00
|
|
|
return raw;
|
2022-07-16 14:00:05 -04:00
|
|
|
}
|
|
|
|
|
2022-08-12 14:14:01 -04:00
|
|
|
// replace null characters
|
|
|
|
editedTable = editedTable.replace(/\0/g, "\ufffd");
|
2022-07-19 19:33:10 -04:00
|
|
|
return editedTable;
|
2022-07-21 17:19:01 -04:00
|
|
|
}
|
2022-07-14 11:56:11 -04:00
|
|
|
|
2022-07-19 19:33:10 -04:00
|
|
|
updateTable(markdownTable) {
|
2022-07-21 17:19:01 -04:00
|
|
|
const tableId = this.args.tableId;
|
|
|
|
const postId = this.args.model.id;
|
2022-07-16 14:00:05 -04:00
|
|
|
const newRaw = markdownTable;
|
2022-07-21 17:19:01 -04:00
|
|
|
|
2022-07-16 14:00:05 -04:00
|
|
|
const editReason =
|
2022-07-21 17:19:01 -04:00
|
|
|
this.editReason ||
|
2022-07-18 14:18:58 -04:00
|
|
|
I18n.t(themePrefix("discourse_table_builder.edit.default_edit_reason"));
|
2022-07-21 17:19:01 -04:00
|
|
|
const raw = this.args.model.raw;
|
2022-07-18 14:18:58 -04:00
|
|
|
const newPostRaw = this.buildUpdatedPost(tableId, raw, newRaw);
|
2022-07-18 14:03:57 -04:00
|
|
|
|
2022-07-19 19:33:10 -04:00
|
|
|
return this.sendTableUpdate(postId, newPostRaw, editReason);
|
2022-07-21 17:19:01 -04:00
|
|
|
}
|
2022-07-16 14:00:05 -04:00
|
|
|
|
2022-07-19 19:33:10 -04:00
|
|
|
sendTableUpdate(postId, raw, edit_reason) {
|
2022-07-16 14:00:05 -04:00
|
|
|
return ajax(`/posts/${postId}.json`, {
|
|
|
|
type: "PUT",
|
|
|
|
data: {
|
|
|
|
post: {
|
|
|
|
raw,
|
|
|
|
edit_reason,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
.catch(popupAjaxError)
|
|
|
|
.finally(() => {
|
2022-07-21 17:19:01 -04:00
|
|
|
this.args.triggerModalClose();
|
2022-07-16 14:00:05 -04:00
|
|
|
});
|
2022-07-21 17:19:01 -04:00
|
|
|
}
|
2022-07-14 20:07:05 -04:00
|
|
|
|
|
|
|
buildTableMarkdown(headers, data) {
|
|
|
|
const table = [];
|
|
|
|
data.forEach((row) => {
|
|
|
|
const result = {};
|
|
|
|
|
|
|
|
headers.forEach((key, index) => (result[key] = row[index]));
|
|
|
|
table.push(result);
|
|
|
|
});
|
|
|
|
|
|
|
|
return arrayToTable(table);
|
2022-07-21 17:19:01 -04:00
|
|
|
}
|
|
|
|
}
|