millas 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "millas",
3
- "version": "0.1.9",
3
+ "version": "0.2.0",
4
4
  "description": "A modern batteries-included backend framework for Node.js — built on Express, inspired by Laravel, Django, and FastAPI",
5
5
  "main": "src/index.js",
6
6
  "exports": {
@@ -101,25 +101,40 @@ class Admin {
101
101
  if (value === null || value === undefined) return '<span class="cell-muted">—</span>';
102
102
  switch (field.type) {
103
103
  case 'boolean':
104
- return value ? '<span class="bool-yes">✓</span>' : '<span class="bool-no">✗</span>';
104
+ return value
105
+ ? `<span class="bool-yes"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span>`
106
+ : `<span class="bool-no"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></span>`;
105
107
  case 'badge': {
106
- const colorMap = { admin:'purple', user:'blue', active:'green', inactive:'gray', pending:'yellow', published:'green', draft:'gray' };
108
+ const colorMap = {
109
+ admin:'purple', user:'blue', active:'green', inactive:'gray',
110
+ pending:'yellow', published:'green', draft:'gray', banned:'red',
111
+ true:'green', false:'gray', 1:'green', 0:'gray',
112
+ };
107
113
  const c = (field.colors && field.colors[String(value)]) || colorMap[String(value)] || 'gray';
108
114
  return `<span class="badge badge-${c}">${value}</span>`;
109
115
  }
110
116
  case 'datetime':
111
- try { return new Date(value).toLocaleString(); } catch { return String(value); }
117
+ try {
118
+ const d = new Date(value);
119
+ return `<span title="${d.toISOString()}" style="font-size:12.5px">${d.toLocaleString()}</span>`;
120
+ } catch { return String(value); }
112
121
  case 'date':
113
122
  try { return new Date(value).toLocaleDateString(); } catch { return String(value); }
114
123
  case 'password':
115
- return '<span class="cell-muted">••••••••</span>';
124
+ return '<span class="cell-muted" style="letter-spacing:2px">••••••</span>';
116
125
  case 'image':
117
- return value ? `<img src="${value}" style="width:36px;height:36px;border-radius:6px;object-fit:cover">` : '<span class="cell-muted">—</span>';
126
+ return value
127
+ ? `<img src="${value}" class="cell-image" alt="">`
128
+ : '<span class="cell-muted">—</span>';
118
129
  case 'json':
119
- return `<code style="font-size:11px;color:var(--text-muted)">${JSON.stringify(value).slice(0, 40)}…</code>`;
130
+ return `<code class="cell-mono">${JSON.stringify(value).slice(0, 40)}…</code>`;
131
+ case 'email':
132
+ return `<a href="mailto:${value}" style="color:var(--primary);text-decoration:none">${value}</a>`;
120
133
  default: {
121
134
  const str = String(value);
122
- return str.length > 60 ? str.slice(0, 60) + '…' : str;
135
+ return str.length > 60
136
+ ? `<span title="${str}">${str.slice(0, 60)}…</span>`
137
+ : str;
123
138
  }
124
139
  }
125
140
  });
@@ -377,10 +392,20 @@ class Admin {
377
392
  _error(res, err) {
378
393
  const status = err.status || 500;
379
394
  res.status(status).send(`
380
- <html><body style="font-family:system-ui;padding:40px;background:#0c0e14;color:#e2e8f0">
381
- <h2 style="color:#ef4444">Admin Error</h2>
382
- <pre style="background:#1c1f2e;padding:20px;border-radius:8px;color:#94a3b8">${err.stack || err.message}</pre>
383
- <a href="javascript:history.back()" style="color:#6366f1">← Go back</a>
395
+ <html><body style="font-family:'DM Sans',system-ui,sans-serif;padding:48px;background:#f4f5f7;color:#111827">
396
+ <div style="max-width:640px;margin:0 auto">
397
+ <div style="display:flex;align-items:center;gap:10px;margin-bottom:24px">
398
+ <div style="width:36px;height:36px;background:#fef2f2;border-radius:8px;display:flex;align-items:center;justify-content:center">
399
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#dc2626" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
400
+ </div>
401
+ <h2 style="font-size:17px;font-weight:600;color:#dc2626">Admin Error ${status}</h2>
402
+ </div>
403
+ <pre style="background:#fff;border:1px solid #e3e6ec;padding:20px;border-radius:8px;color:#374151;font-size:12.5px;overflow-x:auto;line-height:1.6">${err.stack || err.message}</pre>
404
+ <a href="javascript:history.back()" style="display:inline-flex;align-items:center;gap:6px;margin-top:16px;color:#2563eb;font-size:13px;text-decoration:none">
405
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>
406
+ Go back
407
+ </a>
408
+ </div>
384
409
  </body></html>
385
410
  `);
386
411
  }