abersbail commited on
Commit
1ab72c5
·
verified ·
1 Parent(s): af42289

Deploy static HTML database

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +399 -17
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Simple 10 Database Html
3
- emoji: 🏃
4
- colorFrom: pink
5
- colorTo: indigo
6
  sdk: static
7
  pinned: false
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
  ---
2
+ title: Simple 10 Database
3
+ colorFrom: green
4
+ colorTo: blue
 
5
  sdk: static
6
  pinned: false
7
+ license: mit
8
  ---
9
 
10
+ # Simple 10 Database
11
+
12
+ A static HTML database page with 10 records, search, category filtering, add, delete, reset, and browser localStorage.
index.html CHANGED
@@ -1,19 +1,401 @@
1
  <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
  <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Simple 10 Database</title>
7
+ <style>
8
+ :root {
9
+ color-scheme: light;
10
+ --bg: #f5f7fb;
11
+ --panel: #ffffff;
12
+ --text: #172033;
13
+ --muted: #61708a;
14
+ --line: #d9e0ec;
15
+ --brand: #0f766e;
16
+ --brand-dark: #0b5f59;
17
+ --danger: #b42318;
18
+ --shadow: 0 10px 30px rgba(28, 39, 61, 0.09);
19
+ }
20
+
21
+ * {
22
+ box-sizing: border-box;
23
+ }
24
+
25
+ body {
26
+ margin: 0;
27
+ min-height: 100vh;
28
+ background: var(--bg);
29
+ color: var(--text);
30
+ font-family: Arial, Helvetica, sans-serif;
31
+ }
32
+
33
+ main {
34
+ width: min(1120px, calc(100% - 32px));
35
+ margin: 0 auto;
36
+ padding: 28px 0;
37
+ }
38
+
39
+ header {
40
+ display: flex;
41
+ justify-content: space-between;
42
+ gap: 20px;
43
+ align-items: flex-end;
44
+ margin-bottom: 20px;
45
+ }
46
+
47
+ h1 {
48
+ margin: 0 0 6px;
49
+ font-size: 32px;
50
+ line-height: 1.1;
51
+ }
52
+
53
+ p {
54
+ margin: 0;
55
+ color: var(--muted);
56
+ line-height: 1.5;
57
+ }
58
+
59
+ .stats {
60
+ display: flex;
61
+ gap: 10px;
62
+ flex-wrap: wrap;
63
+ justify-content: flex-end;
64
+ }
65
+
66
+ .stat {
67
+ min-width: 92px;
68
+ padding: 10px 12px;
69
+ background: var(--panel);
70
+ border: 1px solid var(--line);
71
+ border-radius: 8px;
72
+ box-shadow: var(--shadow);
73
+ }
74
+
75
+ .stat strong {
76
+ display: block;
77
+ font-size: 20px;
78
+ }
79
+
80
+ .stat span {
81
+ display: block;
82
+ margin-top: 2px;
83
+ color: var(--muted);
84
+ font-size: 12px;
85
+ text-transform: uppercase;
86
+ }
87
+
88
+ .panel {
89
+ background: var(--panel);
90
+ border: 1px solid var(--line);
91
+ border-radius: 8px;
92
+ box-shadow: var(--shadow);
93
+ overflow: hidden;
94
+ }
95
+
96
+ .toolbar {
97
+ display: grid;
98
+ grid-template-columns: 1fr auto auto;
99
+ gap: 12px;
100
+ padding: 16px;
101
+ border-bottom: 1px solid var(--line);
102
+ }
103
+
104
+ input,
105
+ select {
106
+ width: 100%;
107
+ height: 42px;
108
+ border: 1px solid var(--line);
109
+ border-radius: 6px;
110
+ padding: 0 12px;
111
+ color: var(--text);
112
+ background: #fff;
113
+ font: inherit;
114
+ }
115
+
116
+ button {
117
+ height: 42px;
118
+ border: 0;
119
+ border-radius: 6px;
120
+ padding: 0 14px;
121
+ color: #fff;
122
+ background: var(--brand);
123
+ cursor: pointer;
124
+ font: 700 14px Arial, Helvetica, sans-serif;
125
+ white-space: nowrap;
126
+ }
127
+
128
+ button:hover {
129
+ background: var(--brand-dark);
130
+ }
131
+
132
+ button.secondary {
133
+ color: var(--text);
134
+ background: #e8edf5;
135
+ }
136
+
137
+ button.secondary:hover {
138
+ background: #dce4ef;
139
+ }
140
+
141
+ button.danger {
142
+ background: var(--danger);
143
+ }
144
+
145
+ .form {
146
+ display: grid;
147
+ grid-template-columns: 90px 1fr 160px 2fr auto;
148
+ gap: 12px;
149
+ padding: 16px;
150
+ border-bottom: 1px solid var(--line);
151
+ }
152
+
153
+ .table-wrap {
154
+ overflow-x: auto;
155
+ }
156
+
157
+ table {
158
+ width: 100%;
159
+ border-collapse: collapse;
160
+ min-width: 760px;
161
+ }
162
+
163
+ th,
164
+ td {
165
+ padding: 13px 16px;
166
+ border-bottom: 1px solid var(--line);
167
+ text-align: left;
168
+ vertical-align: top;
169
+ }
170
+
171
+ th {
172
+ color: var(--muted);
173
+ background: #f8fafc;
174
+ font-size: 12px;
175
+ text-transform: uppercase;
176
+ }
177
+
178
+ tr:last-child td {
179
+ border-bottom: 0;
180
+ }
181
+
182
+ .badge {
183
+ display: inline-flex;
184
+ min-width: 82px;
185
+ justify-content: center;
186
+ padding: 5px 8px;
187
+ border-radius: 999px;
188
+ background: #eef6f4;
189
+ color: #0f5f59;
190
+ font-size: 12px;
191
+ font-weight: 700;
192
+ text-transform: capitalize;
193
+ }
194
+
195
+ .empty {
196
+ padding: 36px 16px;
197
+ color: var(--muted);
198
+ text-align: center;
199
+ }
200
+
201
+ @media (max-width: 800px) {
202
+ header,
203
+ .toolbar,
204
+ .form {
205
+ grid-template-columns: 1fr;
206
+ }
207
+
208
+ header {
209
+ display: block;
210
+ }
211
+
212
+ .stats {
213
+ justify-content: flex-start;
214
+ margin-top: 16px;
215
+ }
216
+ }
217
+ </style>
218
+ </head>
219
+ <body>
220
+ <main>
221
+ <header>
222
+ <div>
223
+ <h1>Simple 10 Database</h1>
224
+ <p>Browser database page using the 10 Hugging Face dataset records.</p>
225
+ </div>
226
+ <div class="stats">
227
+ <div class="stat">
228
+ <strong id="totalCount">0</strong>
229
+ <span>Total</span>
230
+ </div>
231
+ <div class="stat">
232
+ <strong id="visibleCount">0</strong>
233
+ <span>Visible</span>
234
+ </div>
235
+ </div>
236
+ </header>
237
+
238
+ <section class="panel" aria-label="Database records">
239
+ <div class="toolbar">
240
+ <input id="searchInput" type="search" placeholder="Search records">
241
+ <select id="categoryFilter" aria-label="Filter by category">
242
+ <option value="all">All categories</option>
243
+ <option value="starter">Starter</option>
244
+ <option value="standard">Standard</option>
245
+ <option value="advanced">Advanced</option>
246
+ </select>
247
+ <button class="secondary" id="resetButton" type="button">Reset Data</button>
248
+ </div>
249
+
250
+ <form class="form" id="recordForm">
251
+ <input id="recordId" type="number" min="1" placeholder="ID" required>
252
+ <input id="recordName" type="text" placeholder="Name" required>
253
+ <select id="recordCategory" required>
254
+ <option value="starter">Starter</option>
255
+ <option value="standard">Standard</option>
256
+ <option value="advanced">Advanced</option>
257
+ </select>
258
+ <input id="recordDescription" type="text" placeholder="Description" required>
259
+ <button type="submit">Add Record</button>
260
+ </form>
261
+
262
+ <div class="table-wrap">
263
+ <table>
264
+ <thead>
265
+ <tr>
266
+ <th>ID</th>
267
+ <th>Name</th>
268
+ <th>Category</th>
269
+ <th>Description</th>
270
+ <th>Action</th>
271
+ </tr>
272
+ </thead>
273
+ <tbody id="recordTable"></tbody>
274
+ </table>
275
+ <div class="empty" id="emptyState" hidden>No records found.</div>
276
+ </div>
277
+ </section>
278
+ </main>
279
+
280
+ <script>
281
+ const seedRecords = [
282
+ { id: 1, name: "Alpha", category: "starter", description: "First sample database record" },
283
+ { id: 2, name: "Beta", category: "starter", description: "Second sample database record" },
284
+ { id: 3, name: "Gamma", category: "starter", description: "Third sample database record" },
285
+ { id: 4, name: "Delta", category: "standard", description: "Fourth sample database record" },
286
+ { id: 5, name: "Epsilon", category: "standard", description: "Fifth sample database record" },
287
+ { id: 6, name: "Zeta", category: "standard", description: "Sixth sample database record" },
288
+ { id: 7, name: "Eta", category: "advanced", description: "Seventh sample database record" },
289
+ { id: 8, name: "Theta", category: "advanced", description: "Eighth sample database record" },
290
+ { id: 9, name: "Iota", category: "advanced", description: "Ninth sample database record" },
291
+ { id: 10, name: "Kappa", category: "advanced", description: "Tenth sample database record" }
292
+ ];
293
+
294
+ const storageKey = "simple-10-database-records";
295
+ const table = document.getElementById("recordTable");
296
+ const emptyState = document.getElementById("emptyState");
297
+ const totalCount = document.getElementById("totalCount");
298
+ const visibleCount = document.getElementById("visibleCount");
299
+ const searchInput = document.getElementById("searchInput");
300
+ const categoryFilter = document.getElementById("categoryFilter");
301
+ const form = document.getElementById("recordForm");
302
+
303
+ let records = loadRecords();
304
+
305
+ function loadRecords() {
306
+ const stored = localStorage.getItem(storageKey);
307
+ return stored ? JSON.parse(stored) : [...seedRecords];
308
+ }
309
+
310
+ function saveRecords() {
311
+ localStorage.setItem(storageKey, JSON.stringify(records));
312
+ }
313
+
314
+ function getFilteredRecords() {
315
+ const query = searchInput.value.trim().toLowerCase();
316
+ const category = categoryFilter.value;
317
+
318
+ return records
319
+ .filter((record) => category === "all" || record.category === category)
320
+ .filter((record) => {
321
+ const text = `${record.id} ${record.name} ${record.category} ${record.description}`.toLowerCase();
322
+ return text.includes(query);
323
+ })
324
+ .sort((a, b) => a.id - b.id);
325
+ }
326
+
327
+ function render() {
328
+ const filtered = getFilteredRecords();
329
+ table.innerHTML = "";
330
+
331
+ for (const record of filtered) {
332
+ const row = document.createElement("tr");
333
+ row.innerHTML = `
334
+ <td>${record.id}</td>
335
+ <td>${escapeHtml(record.name)}</td>
336
+ <td><span class="badge">${escapeHtml(record.category)}</span></td>
337
+ <td>${escapeHtml(record.description)}</td>
338
+ <td><button class="danger" type="button" data-id="${record.id}">Delete</button></td>
339
+ `;
340
+ table.appendChild(row);
341
+ }
342
+
343
+ totalCount.textContent = String(records.length);
344
+ visibleCount.textContent = String(filtered.length);
345
+ emptyState.hidden = filtered.length > 0;
346
+ }
347
+
348
+ function escapeHtml(value) {
349
+ return String(value)
350
+ .replaceAll("&", "&amp;")
351
+ .replaceAll("<", "&lt;")
352
+ .replaceAll(">", "&gt;")
353
+ .replaceAll('"', "&quot;")
354
+ .replaceAll("'", "&#039;");
355
+ }
356
+
357
+ form.addEventListener("submit", (event) => {
358
+ event.preventDefault();
359
+
360
+ const id = Number(document.getElementById("recordId").value);
361
+ if (records.some((record) => record.id === id)) {
362
+ alert("This ID already exists.");
363
+ return;
364
+ }
365
+
366
+ records.push({
367
+ id,
368
+ name: document.getElementById("recordName").value.trim(),
369
+ category: document.getElementById("recordCategory").value,
370
+ description: document.getElementById("recordDescription").value.trim()
371
+ });
372
+
373
+ saveRecords();
374
+ form.reset();
375
+ render();
376
+ });
377
+
378
+ table.addEventListener("click", (event) => {
379
+ const button = event.target.closest("button[data-id]");
380
+ if (!button) {
381
+ return;
382
+ }
383
+
384
+ const id = Number(button.dataset.id);
385
+ records = records.filter((record) => record.id !== id);
386
+ saveRecords();
387
+ render();
388
+ });
389
+
390
+ document.getElementById("resetButton").addEventListener("click", () => {
391
+ records = [...seedRecords];
392
+ saveRecords();
393
+ render();
394
+ });
395
+
396
+ searchInput.addEventListener("input", render);
397
+ categoryFilter.addEventListener("change", render);
398
+ render();
399
+ </script>
400
+ </body>
401
  </html>