Upload 6 files
Browse files
script.js
CHANGED
|
@@ -116,6 +116,10 @@ async function loadData() {
|
|
| 116 |
|
| 117 |
function escapeHtml(v) { return String(v ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); }
|
| 118 |
function td(label, content) { return `<td data-label="${escapeHtml(label)}">${content}</td>`; }
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
function metric(value, label, target = "", description = "") {
|
| 120 |
const action = target ? ` role="button" tabindex="0" data-dashboard-detail="${target}"` : "";
|
| 121 |
const note = description ? `<small>${escapeHtml(description)}</small>` : "";
|
|
@@ -252,7 +256,7 @@ function renderDashboardDetail(type) {
|
|
| 252 |
.sort((a, b) => a.surveyName.localeCompare(b.surveyName, "ar"))
|
| 253 |
.map((row) => `${row.surveyName}: ${row.collectionStatus || "-"}`);
|
| 254 |
const count = new Set(group.rows.map((row) => plain(row.collectionStatus)).filter(Boolean)).size;
|
| 255 |
-
return `<tr>${td("السجل التجاري", `<button class="row-button" data-entity="${escapeHtml(group.key)}">${escapeHtml(group.commercialRegister)}</button>`)}${td("اسم المنشأة", escapeHtml(group.name))}${td("الحالات حسب المسح",
|
| 256 |
}).join("")}</tbody></table></div>`;
|
| 257 |
} else if (type === "researchers") {
|
| 258 |
const researchers = [...countBy(sharedRows, (row) => row.researcher).entries()].sort((a, b) => b[1] - a[1]).slice(0, 20);
|
|
@@ -263,7 +267,7 @@ function renderDashboardDetail(type) {
|
|
| 263 |
const title = type === "establishments" ? "المنشآت المتقاطعة" : "تفاصيل التقاطعات";
|
| 264 |
const subtitle = "السجلات التجارية التي ظهرت في أكثر من مسح.";
|
| 265 |
panel.innerHTML = `${dashboardDetailHeader(title, subtitle)}
|
| 266 |
-
<div class="table-wrap"><table><thead><tr><th>السجل التجاري</th><th>اسم المنشأة</th><th>عدد المسوح</th><th>المسوح</th><th>الباحثون</th></tr></thead><tbody>${filtered.slice(0, 50).map((group) => `<tr>${td("السجل التجاري", `<button class="row-button" data-entity="${escapeHtml(group.key)}">${escapeHtml(group.commercialRegister)}</button>`)}${td("اسم المنشأة", escapeHtml(group.name))}${td("عدد المسوح", group.surveys.length)}${td("المسوح",
|
| 267 |
}
|
| 268 |
|
| 269 |
panel.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
@@ -375,11 +379,11 @@ function renderIntersections() {
|
|
| 375 |
const three = groups.filter((group) => group.surveys.length >= 3).length;
|
| 376 |
$("intersectionMetrics").innerHTML = [metric(groups.length, "منشآت مشتركة"), metric(two, "في مسحين"), metric(three, "في 3 مسوح أو أكثر"), metric(app.byRegister.size, "سجلات قابلة للمطابقة"), metric(app.surveys.size, "إجمالي المسوح")].join("");
|
| 377 |
$("intersectionResults").className = "results";
|
| 378 |
-
$("intersectionResults").innerHTML = groups.length ? `<div class="table-wrap"><table><thead><tr><th>السجل التجاري</th><th>اسم المنشأة</th><th>عدد المسوح</th><th>المسوح</th><th>الباحثون</th></tr></thead><tbody>${groups.slice(0, 200).map((group) => `<tr>${td("السجل التجاري", `<button class="row-button" data-entity="${escapeHtml(group.key)}">${escapeHtml(group.commercialRegister)}</button>`)}${td("اسم المنشأة", escapeHtml(group.name))}${td("عدد المسوح", group.surveys.length)}${td("المسوح",
|
| 379 |
}
|
| 380 |
|
| 381 |
function renderCompactEntities(groups) {
|
| 382 |
-
return `<div class="table-wrap compact-table"><table><thead><tr><th>السجل التجاري</th><th>اسم المنشأة</th><th>المسوح</th><th>الباحثون</th></tr></thead><tbody>${groups.map((group) => `<tr>${td("السجل التجاري", `<button class="row-button" data-entity="${escapeHtml(group.key)}">${escapeHtml(group.commercialRegister || "-")}</button>`)}${td("اسم المنشأة", escapeHtml(group.name))}${td("المسوح",
|
| 383 |
}
|
| 384 |
|
| 385 |
function renderResearchers() {
|
|
|
|
| 116 |
|
| 117 |
function escapeHtml(v) { return String(v ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); }
|
| 118 |
function td(label, content) { return `<td data-label="${escapeHtml(label)}">${content}</td>`; }
|
| 119 |
+
function stackedList(items) {
|
| 120 |
+
const clean = items.map((item) => plain(item)).filter(Boolean);
|
| 121 |
+
return clean.length ? `<div class="stacked-list">${clean.map((item) => `<span>${escapeHtml(item)}</span>`).join("")}</div>` : "-";
|
| 122 |
+
}
|
| 123 |
function metric(value, label, target = "", description = "") {
|
| 124 |
const action = target ? ` role="button" tabindex="0" data-dashboard-detail="${target}"` : "";
|
| 125 |
const note = description ? `<small>${escapeHtml(description)}</small>` : "";
|
|
|
|
| 256 |
.sort((a, b) => a.surveyName.localeCompare(b.surveyName, "ar"))
|
| 257 |
.map((row) => `${row.surveyName}: ${row.collectionStatus || "-"}`);
|
| 258 |
const count = new Set(group.rows.map((row) => plain(row.collectionStatus)).filter(Boolean)).size;
|
| 259 |
+
return `<tr>${td("السجل التجاري", `<button class="row-button" data-entity="${escapeHtml(group.key)}">${escapeHtml(group.commercialRegister)}</button>`)}${td("اسم المنشأة", escapeHtml(group.name))}${td("الحالات حسب المسح", stackedList(statuses))}${td("عدد الحالات", count)}</tr>`;
|
| 260 |
}).join("")}</tbody></table></div>`;
|
| 261 |
} else if (type === "researchers") {
|
| 262 |
const researchers = [...countBy(sharedRows, (row) => row.researcher).entries()].sort((a, b) => b[1] - a[1]).slice(0, 20);
|
|
|
|
| 267 |
const title = type === "establishments" ? "المنشآت المتقاطعة" : "تفاصيل التقاطعات";
|
| 268 |
const subtitle = "السجلات التجارية التي ظهرت في أكثر من مسح.";
|
| 269 |
panel.innerHTML = `${dashboardDetailHeader(title, subtitle)}
|
| 270 |
+
<div class="table-wrap"><table><thead><tr><th>السجل التجاري</th><th>اسم المنشأة</th><th>عدد المسوح</th><th>المسوح</th><th>الباحثون</th></tr></thead><tbody>${filtered.slice(0, 50).map((group) => `<tr>${td("السجل التجاري", `<button class="row-button" data-entity="${escapeHtml(group.key)}">${escapeHtml(group.commercialRegister)}</button>`)}${td("اسم المنشأة", escapeHtml(group.name))}${td("عدد المسوح", group.surveys.length)}${td("المسوح", stackedList(group.surveys))}${td("الباحثون", stackedList(group.researchers))}</tr>`).join("")}</tbody></table></div>`;
|
| 271 |
}
|
| 272 |
|
| 273 |
panel.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
|
|
| 379 |
const three = groups.filter((group) => group.surveys.length >= 3).length;
|
| 380 |
$("intersectionMetrics").innerHTML = [metric(groups.length, "منشآت مشتركة"), metric(two, "في مسحين"), metric(three, "في 3 مسوح أو أكثر"), metric(app.byRegister.size, "سجلات قابلة للمطابقة"), metric(app.surveys.size, "إجمالي المسوح")].join("");
|
| 381 |
$("intersectionResults").className = "results";
|
| 382 |
+
$("intersectionResults").innerHTML = groups.length ? `<div class="table-wrap"><table><thead><tr><th>السجل التجاري</th><th>اسم المنشأة</th><th>عدد المسوح</th><th>المسوح</th><th>الباحثون</th></tr></thead><tbody>${groups.slice(0, 200).map((group) => `<tr>${td("السجل التجاري", `<button class="row-button" data-entity="${escapeHtml(group.key)}">${escapeHtml(group.commercialRegister)}</button>`)}${td("اسم المنشأة", escapeHtml(group.name))}${td("عدد المسوح", group.surveys.length)}${td("المسوح", stackedList(group.surveys))}${td("الباحثون", stackedList(group.researchers))}</tr>`).join("")}</tbody></table></div>` : "<div class='empty-state'>لا توجد تقاطعات قابلة للحساب.</div>";
|
| 383 |
}
|
| 384 |
|
| 385 |
function renderCompactEntities(groups) {
|
| 386 |
+
return `<div class="table-wrap compact-table"><table><thead><tr><th>السجل التجاري</th><th>اسم المنشأة</th><th>المسوح</th><th>الباحثون</th></tr></thead><tbody>${groups.map((group) => `<tr>${td("السجل التجاري", `<button class="row-button" data-entity="${escapeHtml(group.key)}">${escapeHtml(group.commercialRegister || "-")}</button>`)}${td("اسم المنشأة", escapeHtml(group.name))}${td("المسوح", stackedList(group.surveys))}${td("الباحثون", stackedList(group.researchers))}</tr>`).join("")}</tbody></table></div>`;
|
| 387 |
}
|
| 388 |
|
| 389 |
function renderResearchers() {
|
style.css
CHANGED
|
@@ -112,6 +112,9 @@ td:nth-child(1),td:nth-child(3),td:nth-child(4){white-space:nowrap}
|
|
| 112 |
td:nth-child(2),td:nth-child(5){max-width:380px;white-space:normal}
|
| 113 |
.row-button{display:block;width:100%;border:0;background:transparent;text-align:center;font:inherit;cursor:pointer;padding:0;color:var(--primary);font-weight:950;letter-spacing:.2px}
|
| 114 |
.row-button:hover{text-decoration:underline;text-underline-offset:4px;color:#145f74}
|
|
|
|
|
|
|
|
|
|
| 115 |
.batch-card textarea{width:100%;padding:15px;resize:vertical;line-height:1.7;min-height:250px}
|
| 116 |
.batch-actions{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:12px}
|
| 117 |
.batch-actions div{display:flex;gap:8px}
|
|
@@ -183,6 +186,7 @@ footer b{color:var(--primary)}
|
|
| 183 |
tr td:last-child{border-bottom:0}
|
| 184 |
td:before{content:attr(data-label);color:var(--primary);font-weight:950;text-align:right}
|
| 185 |
.row-button{text-align:right}
|
|
|
|
| 186 |
.badge{white-space:normal;text-align:center}
|
| 187 |
.occurrences{display:grid;gap:10px;padding:12px;background:#f8fbfd}
|
| 188 |
.occurrence-head{display:none}
|
|
|
|
| 112 |
td:nth-child(2),td:nth-child(5){max-width:380px;white-space:normal}
|
| 113 |
.row-button{display:block;width:100%;border:0;background:transparent;text-align:center;font:inherit;cursor:pointer;padding:0;color:var(--primary);font-weight:950;letter-spacing:.2px}
|
| 114 |
.row-button:hover{text-decoration:underline;text-underline-offset:4px;color:#145f74}
|
| 115 |
+
.stacked-list{display:grid;gap:6px;justify-items:center;text-align:center;line-height:1.65}
|
| 116 |
+
.stacked-list span{display:block;width:100%;padding-bottom:6px;border-bottom:1px solid #e7eef6}
|
| 117 |
+
.stacked-list span:last-child{padding-bottom:0;border-bottom:0}
|
| 118 |
.batch-card textarea{width:100%;padding:15px;resize:vertical;line-height:1.7;min-height:250px}
|
| 119 |
.batch-actions{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:12px}
|
| 120 |
.batch-actions div{display:flex;gap:8px}
|
|
|
|
| 186 |
tr td:last-child{border-bottom:0}
|
| 187 |
td:before{content:attr(data-label);color:var(--primary);font-weight:950;text-align:right}
|
| 188 |
.row-button{text-align:right}
|
| 189 |
+
.stacked-list{justify-items:start;text-align:right;gap:5px}
|
| 190 |
.badge{white-space:normal;text-align:center}
|
| 191 |
.occurrences{display:grid;gap:10px;padding:12px;background:#f8fbfd}
|
| 192 |
.occurrence-head{display:none}
|