-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patheditable-spaces.php
More file actions
157 lines (137 loc) · 5.22 KB
/
editable-spaces.php
File metadata and controls
157 lines (137 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Editable Spaces (Admin)</title>
<style>
body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial; padding: 20px; background:#f6f6f6; }
h1 { margin-top: 0; }
#status { margin-bottom: 12px; color: #444; }
table { width: 100%; border-collapse: collapse; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,0.04); }
th, td { padding: 8px 10px; border: 1px solid #e6e6e6; text-align: left; vertical-align: top; font-size: 14px; }
th { background: #fafafa; font-weight: 600; }
tr:nth-child(even) td { background: #fcfcfc; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, "Roboto Mono", "Courier New", monospace; font-size: 13px; color: #222; }
.nowrap { white-space: nowrap; }
#reload { margin-left: 8px; padding:6px 10px; }
.empty { padding: 20px; background: #fff; border: 1px solid #eee; }
</style>
</head>
<body>
<h1>Editable Spaces</h1>
<div id="status">Loading… <button id="reload">Reload</button></div>
<div id="table-wrap"></div>
<script>
const API_URL = 'http://localhost:9090/api/admin/user/spaces/can-add-event'; // change if your endpoint differs
const statusEl = document.getElementById('status');
const wrap = document.getElementById('table-wrap');
const reloadBtn = document.getElementById('reload');
reloadBtn.addEventListener('click', () => fetchAndRender());
async function fetchAndRender() {
statusEl.textContent = 'Loading…';
statusEl.appendChild(reloadBtn); // keep reload visible
wrap.innerHTML = '';
try {
const res = await fetch(API_URL, {
credentials: 'include', // send cookies/session
headers: {
'Accept': 'application/json'
},
credentials: 'include'
});
if (res.status === 401) {
statusEl.textContent = 'Unauthorized — please login.';
return;
}
if (!res.ok) {
statusEl.textContent = `Error: ${res.status} ${res.statusText}`;
return;
}
const data = await res.json();
// If the endpoint returns { "spaces": [...] } or similar, try to pull the main array
let rows = null;
if (Array.isArray(data)) {
rows = data;
} else if (data && Array.isArray(data.spaces)) {
rows = data.spaces;
} else if (data && Array.isArray(data['event-types'])) {
rows = data['event-types']; // fallback example
} else {
// try to find the first array property
for (const k of Object.keys(data || {})) {
if (Array.isArray(data[k])) { rows = data[k]; break; }
}
}
if (!rows || rows.length === 0) {
statusEl.textContent = 'No rows returned.';
wrap.innerHTML = '<div class="empty">No data to display.</div>';
return;
}
renderTable(rows);
statusEl.textContent = `Loaded ${rows.length} rows.`;
statusEl.appendChild(reloadBtn);
} catch (err) {
console.error(err);
statusEl.textContent = 'Network or parsing error — see console.';
}
}
// Utility to escape HTML
function escapeHtml(str) {
if (str == null) return '';
return String(str)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// Render table from array of objects. If objects have different keys, union them.
function renderTable(rows) {
// build keys (columns) in stable order
const colSet = new Set();
rows.forEach(r => {
if (r && typeof r === 'object' && !Array.isArray(r)) {
Object.keys(r).forEach(k => colSet.add(k));
}
});
const cols = Array.from(colSet);
// create table
const table = document.createElement('table');
const thead = document.createElement('thead');
const trh = document.createElement('tr');
cols.forEach(c => {
const th = document.createElement('th');
th.textContent = c;
trh.appendChild(th);
});
thead.appendChild(trh);
table.appendChild(thead);
const tbody = document.createElement('tbody');
rows.forEach(row => {
const tr = document.createElement('tr');
cols.forEach(col => {
const td = document.createElement('td');
const val = row[col];
if (val === null || val === undefined) {
td.textContent = '';
} else if (typeof val === 'object') {
// stringify nested objects/arrays nicely
td.innerHTML = '<pre class="mono">' + escapeHtml(JSON.stringify(val, null, 2)) + '</pre>';
} else {
td.textContent = String(val);
// small heuristic: if column name contains "id", show monospace
if (col.toLowerCase().includes('id')) td.classList.add('mono', 'nowrap');
}
tr.appendChild(td);
});
tbody.appendChild(tr);
});
table.appendChild(tbody);
wrap.innerHTML = '';
wrap.appendChild(table);
}
// initial load
fetchAndRender();
</script>
</body>
</html>