Index: vue/src/assets/images/devops/DevSupport/github.png
===================================================================
diff -u -r08358eb7b241be838fa5939122436a4c7c3cf8dc -r122e106776f3cb7956a8926706fd8d0f0811b89c
--- vue/src/assets/images/devops/DevSupport/github.png (.../github.png) (revision 08358eb7b241be838fa5939122436a4c7c3cf8dc)
+++ vue/src/assets/images/devops/DevSupport/github.png (.../github.png) (revision 122e106776f3cb7956a8926706fd8d0f0811b89c)
@@ -1644,14 +1644,38 @@
#reqDataTable .reqTable th.desc:after {
background-image: url(../img/datatable/sort_desc.png);
}
+#reqDataTable .root {
+ padding-left: 25px !important;
+ text-align: left !important;
+}
-#reqDataTable .highlight {
+#reqDataTable .pivotTable {
+ min-width: 120%;
+}
+
+#reqDataTable .pivotTable .highlight {
color: #a4c6ff;
}
-#reqDataTable .col-span {
- border-right: none !important;
+#reqDataTable .pivot-toggle {
+ margin-right: 3px;
+ padding: 0 3px;
+ background-color: transparent;
}
+#reqDataTable .pivot-toggle .fa {
+ vertical-align: text-bottom;
+ font-size: 14px;
+ color: #a4c6ff;
+}
+#reqDataTable .pivot-toggle .fa-minus-square {
+ display: none;
+}
+#reqDataTable .pivot-toggle.active .fa-plus-square {
+ display: none;
+}
+#reqDataTable .pivot-toggle.active .fa-minus-square {
+ display: block;
+}
/* cost 분석 */
Index: arms/js/reqAddTable.js
===================================================================
diff -u -reb3049658a08f2a4fcaa3cd80294e11436b0057c -r122e106776f3cb7956a8926706fd8d0f0811b89c
--- arms/js/reqAddTable.js (.../reqAddTable.js) (revision eb3049658a08f2a4fcaa3cd80294e11436b0057c)
+++ arms/js/reqAddTable.js (.../reqAddTable.js) (revision 122e106776f3cb7956a8926706fd8d0f0811b89c)
@@ -1,4 +1,9 @@
-let versionList, tableData, pivotTableData, tableOptions, TableInstance;
+let versionList,
+ tableData,
+ pivotTableData,
+ tableOptions,
+ TableInstance,
+ pivotType = "normal";
const ContentType = {
normal: {
version: "Version",
@@ -22,21 +27,21 @@
manager: "TASK OWNER",
depth1: "Depth 1",
content: "기능",
- open: "Open",
- investigation: "Investigation",
- resolved: "Resoleved",
- closeStatus: "Close",
+ open: "열림",
+ investigation: "진행중",
+ resolved: "해결됨",
+ closeStatus: "닫힘",
statusTotal: "총계"
},
owner: {
manager: "TASK OWNER",
version: "Version",
depth1: "Depth 1",
content: "기능",
- open: "Open",
- investigation: "Investigation",
- resolved: "Resoleved",
- close: "Close",
+ open: "열림",
+ investigation: "진행중",
+ resolved: "해결됨",
+ closeStatus: "닫힘",
statusTotal: "총계"
}
};
@@ -200,8 +205,9 @@
...acc,
{
id: c_id,
- version: c_req_pdservice_versionset_link ? JSON.parse(c_req_pdservice_versionset_link) : "",
+ version: JSON.parse(c_req_pdservice_versionset_link) ?? "",
manager: c_req_owner,
+ _manager: c_req_owner,
open: reqStateEntity?.c_id === 10 ? 1 : "",
investigation: "",
resolved: reqStateEntity?.c_id === 11 ? 1 : "",
@@ -215,96 +221,103 @@
}, []);
};
+const rearrangement = (arr, key, root, data) =>
+ arr.reduce((acc, cur) => {
+ const result = { ...cur, ...data };
+ const index = acc?.findIndex((item) => item.some((task) => task[key] === result[key]));
+
+ if (index >= 0) {
+ acc[index].push(result);
+ } else {
+ acc?.push([{ ...result, root }]);
+ }
+
+ return acc;
+ }, []);
+
class Table {
- type = "normal";
constructor() {
this.$table = this.makeElement("table");
this.$data = this.setTableData();
}
setTableData(data) {
- if (this.type === "normal") {
+ if (pivotType === "normal") {
return tableData;
}
- if (this.type === "version") {
- return versionList.flatMap((version) => {
+ if (pivotType === "version") {
+ return versionList.map((version) => {
const filterItems = pivotTableData.filter((item) => item.version?.includes(`${version.c_id}`));
-
- return [
- {
- version: `${version.c_title} 총계`,
- id: version.c_id,
- col: 0,
- colSpan: 4,
- ...calcStatus(filterItems)
- },
- ...filterItems
- .reduce((acc, cur) => {
- const result = { ...cur, versionOrigin: version, version: version.c_title };
- const index = acc?.findIndex((item) => item.some((task) => task.manager === cur.manager));
-
- if (index >= 0) {
- acc[index].push(result);
- } else {
- acc?.push([result]);
+ const childrenItem = rearrangement(filterItems, "manager", "manager", {
+ version: version.c_title,
+ _version: version.c_id
+ }).reduce((acc, cur) => {
+ return [
+ ...acc,
+ {
+ ...cur[0],
+ children: cur.slice(1, cur.length - 1),
+ lastChild: {
+ _version: version.c_id,
+ manager: `${cur[0].manager} 총계`,
+ _manager: cur[0].manager,
+ col: 1,
+ colSpan: 3,
+ origin: version,
+ ...calcStatus(cur)
}
+ }
+ ];
+ }, []);
- return acc;
- }, [])
- .flatMap((group) => [
- ...group,
- { manager: `${group[0].manager} 총계`, id: group[0].id, col: 1, colSpan: 3, ...calcStatus(group) }
- ])
- ];
+ return {
+ version: `${version.c_title} 총계`,
+ _version: version.c_id,
+ col: 0,
+ colSpan: 4,
+ root: "version",
+ origin: version,
+ children: childrenItem,
+ ...calcStatus(filterItems)
+ };
});
}
- if (this.type === "owner") {
- return pivotTableData
- .flatMap((task) =>
- task.version.reduce((acc, cur) => {
- const versionItem = versionList.find((item) => item.c_id === Number(cur));
- return [...acc, { ...task, v_id: versionItem.c_id, version: versionItem.c_title }];
- }, [])
- )
- .sort((a, b) => a.manager.localeCompare(b.manager) || a.v_id - b.v_id)
- .reduce((acc, cur) => {
- const index = acc?.findIndex((item) => item.some((task) => task.manager === cur.manager));
-
- if (index >= 0) {
- acc[index].push(cur);
- } else {
- acc?.push([cur]);
- }
-
- return acc;
- }, [])
- .flatMap((group) => [
- { manager: `${group[0].manager} 총계`, id: group[0].id, col: 0, colSpan: 4, ...calcStatus(group) },
- ...group
- .reduce((acc, cur) => {
- const index = acc?.findIndex((item) => item.some((task) => task.version === cur.version));
-
- if (index >= 0) {
- acc[index].push(cur);
- } else {
- acc?.push([cur]);
- }
-
- return acc;
+ if (pivotType === "owner") {
+ return rearrangement(
+ pivotTableData
+ .flatMap((task) =>
+ task.version.reduce((acc, cur) => {
+ const versionItem = versionList.find((item) => item.c_id === Number(cur));
+ return [...acc, { ...task, _version: versionItem.c_id, version: versionItem.c_title }];
}, [])
- .flatMap((tasks) => [
- ...tasks,
- {
- version: `${tasks[0].version} 총계`,
- v_id: tasks[0].v_id,
+ )
+ .sort((a, b) => a.manager?.localeCompare(b.manager) || a._version - b._version)
+ ).map((group) => ({
+ manager: `${group[0].manager} 총계`,
+ _manager: group[0].manager,
+ col: 0,
+ colSpan: 4,
+ root: "manager",
+ children: rearrangement(group, "version", "version").reduce((acc, cur) => {
+ return [
+ ...acc,
+ {
+ ...cur[0],
+ children: cur.slice(1, cur.length - 1),
+ lastChild: {
+ version: `${cur[0].version} 총계`,
+ _manager: group[0].manager,
col: 1,
colSpan: 3,
- ...calcStatus(tasks)
+ ...calcStatus(cur)
}
- ])
- ]);
+ }
+ ];
+ }, []),
+ ...calcStatus(group)
+ }));
}
}
@@ -355,26 +368,99 @@
}
}
+ insertElement(root, list) {
+ list.forEach((row, index, arr) => {
+ if (index) arr[index - 1].after(row);
+ else root.after(row);
+ });
+ }
+
+ removeElment(selector) {
+ const elements = document.querySelectorAll(selector);
+
+ Array.from(elements)
+ .filter((el, index) => index)
+ .forEach((row) => row.remove());
+ }
+
+ getElement(target, tag, id) {
+ return target.tagName !== tag ? this.getElement(target.parentElement, tag) : target;
+ }
+
+ makePivotButton($tr, data) {
+ const rows = this.makePivotRow(
+ data.children.flatMap((item) => {
+ if (item.lastChild) return [item, item.lastChild];
+ return item;
+ }),
+ "td"
+ );
+ const btn = this.makeElement("button");
+ const plusIcon = this.makeElement("i");
+ const minusIcon = this.makeElement("i");
+
+ btn.className = "btn pivot-toggle";
+ plusIcon.className = "fa fa-plus-square";
+ minusIcon.className = "fa fa-minus-square";
+
+ btn.appendChild(plusIcon);
+ btn.appendChild(minusIcon);
+
+ btn.addEventListener("click", (e) => {
+ btn.classList.toggle("active");
+
+ if (btn.classList.contains("active")) {
+ this.insertElement(this.getElement(e.target, "TR"), rows);
+ } else {
+ this.removeElment(`[data-${data.root}="${data[`_${[data.root]}`]}"]`);
+ console.log("##### delete", data);
+ }
+ });
+
+ return btn;
+ }
+
makePivotRow(rows, tag) {
return rows.reduce((acc, cur) => {
const $tr = this.makeElement("tr");
- $tr.setAttribute("data-id", cur.id);
+ $tr.setAttribute("data-id", cur.id ?? "");
+ $tr.setAttribute("data-version", cur._version ?? "");
+ $tr.setAttribute("data-manager", cur._manager ?? "");
- Object.keys(ContentType[this.type]).forEach((key, index) => {
+ Object.keys(ContentType[pivotType]).forEach((key, index) => {
const $col = this.makeElement(tag);
$col.className = key;
- $col.innerHTML = !cur[key] ? "" : cur[key];
+ if (cur[key]) {
+ $col.innerHTML = cur[key];
+ cur.id &&
+ ["manager", "content"].includes(key) &&
+ ($col.innerHTML = `${cur[key]}`);
+ }
- if (index >= cur.col && index < cur.colSpan) {
- $col.classList.add("col-span");
+ if (tag === "th") {
+ $tr.appendChild($col);
+ return;
}
+ if (cur.col !== undefined && cur.col === index) {
+ $col.setAttribute("colspan", cur.colSpan);
+ }
+
+ if (index > cur.col && index < cur.col + cur.colSpan) {
+ $col.classList.add("remove");
+ }
+
if (cur.colSpan) {
$tr.classList.add("highlight");
}
- $tr.appendChild($col);
+ if (cur.root === key) {
+ $col.prepend(this.makePivotButton($tr, cur));
+ $col.classList.add("root");
+ }
+
+ !$col.classList.contains("remove") && $tr.appendChild($col);
});
return [...acc, $tr];
@@ -386,19 +472,24 @@
const $tr = this.makeElement("tr");
$tr.setAttribute("data-id", cur.id);
- Object.keys(ContentType[this.type]).forEach((key) => {
+ Object.keys(ContentType[pivotType]).forEach((key) => {
if ([`_${key}`].includes(key)) return;
const $col = this.makeElement(tag);
$col.className = key;
- if (tag === "td" && ["status", "priority", "difficulty"].includes(key)) {
- !!cur[key] &&
- ($col.innerHTML = `
+ if (tag === "td") {
+ if (cur[key]) {
+ $col.innerHTML = cur[key];
+ ["status", "priority", "difficulty"].includes(key) &&
+ ($col.innerHTML = `
${cur[key]}
`);
+
+ ["manager", "content"].includes(key) && ($col.innerHTML = `${cur[key]}`);
+ }
} else {
$col.innerHTML = cur[key];
}
@@ -442,7 +533,8 @@
$input.id = uuid;
$input.addEventListener("blur", () => {
- this.updateData(node.parentElement.dataset.id, "content", $input.value);
+ console.log("###", this.getElement(node, "TR"));
+ this.updateData(this.getElement(node, "TR").dataset.id, "content", $input.value);
node.textContent = $input.value;
});
@@ -508,7 +600,7 @@
$el.addEventListener("click", (e) => {
const { tagName, classList, parentElement } = e.target;
// input
- if (tagName === "TD" && (classList.contains("content") || classList.contains("manager"))) {
+ if (tagName === "SPAN" && classList.contains("col-input")) {
this.addInput(e.target);
}
@@ -525,7 +617,7 @@
$el.id = `req_${name}`;
$el.className = name;
- if (this.type === "normal") this.makeRow(rowData, col).forEach((r) => $el.append(r));
+ if (pivotType === "normal") this.makeRow(rowData, col).forEach((r) => $el.append(r));
else this.makePivotRow(rowData, col).forEach((r) => $el.append(r));
if ("thead" === name) this.bindHeadEvent($el);
@@ -535,8 +627,8 @@
}
makeTable() {
- this.$table.className = "reqTable";
- this.$table.appendChild(this.makeSection([ContentType[this.type]], "thead", "th"));
+ this.$table.className = `reqTable ${pivotType !== "normal" ? "pivotTable" : ""}`;
+ this.$table.appendChild(this.makeSection([ContentType[pivotType]], "thead", "th"));
this.$table.appendChild(this.makeSection(this.$data, "tbody", "td"));
return this.$table;
}
@@ -548,8 +640,7 @@
$wrapper.appendChild(this.makeTable());
}
- rerenderTable(type) {
- this.type = type;
+ rerenderTable() {
this.$data = this.setTableData();
this.$table.innerHTML = "";
@@ -572,5 +663,6 @@
};
const changeTableType = (type) => {
- TableInstance.rerenderTable(type, ContentType[type]);
+ pivotType = type;
+ TableInstance.rerenderTable();
};