codeapp-js 0.2.1 → 0.3.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.
Files changed (100) hide show
  1. package/codeApp/.power/schemas/appschemas/dataSourcesInfo.ts +6275 -0
  2. package/codeApp/.power/schemas/jira/jira.Schema.json +6903 -0
  3. package/codeApp/.power/schemas/keyvault/keyvault.Schema.json +1600 -0
  4. package/codeApp/.power/schemas/teams/teams.Schema.json +11112 -0
  5. package/codeApp/dist/codeapp.js +992 -4
  6. package/codeApp/dist/power-apps-data.js +145 -31
  7. package/codeApp/src/generated/index.ts +12 -0
  8. package/codeApp/src/generated/models/AzureKeyVaultModel.ts +107 -0
  9. package/codeApp/src/generated/models/JiraModel.ts +501 -0
  10. package/codeApp/src/generated/models/Office365GroupsModel.ts +363 -0
  11. package/codeApp/src/generated/models/Office365OutlookModel.ts +2046 -0
  12. package/codeApp/src/generated/models/Office365UsersModel.ts +254 -0
  13. package/codeApp/src/generated/services/AzureKeyVaultService.ts +257 -0
  14. package/codeApp/src/generated/services/JiraService.ts +1124 -0
  15. package/codeApp/src/generated/services/Office365GroupsService.ts +326 -0
  16. package/codeApp/src/generated/services/Office365OutlookService.ts +2476 -0
  17. package/codeApp/src/generated/services/Office365UsersService.ts +358 -0
  18. package/dev files/outlook.js +218 -9
  19. package/examples/combined demo/dist/codeapp.js +1098 -1098
  20. package/examples/combined demo/dist/index.js +470 -470
  21. package/examples/combined demo/dist/power-apps-data.js +3006 -3006
  22. package/examples/combined demo/power.config.json +42 -42
  23. package/examples/dataverse Demo/dist/codeapp.js +1085 -1085
  24. package/examples/dataverse Demo/dist/index.html +54 -54
  25. package/examples/dataverse Demo/dist/index.js +82 -82
  26. package/examples/dataverse Demo/dist/power-apps-data.js +2911 -2911
  27. package/examples/dataverse Demo/power.config.json +34 -34
  28. package/examples/dataverse Demo/readme.md +79 -79
  29. package/examples/groups Demo/dist/codeapp.js +1085 -1085
  30. package/examples/groups Demo/dist/index.js +113 -113
  31. package/examples/groups Demo/dist/power-apps-data.js +2911 -2911
  32. package/examples/kanban/dist/dataverse.js +94 -94
  33. package/examples/kanban/dist/environmentVar.js +55 -55
  34. package/examples/kanban/dist/office365groups.js +97 -97
  35. package/examples/kanban/dist/office365users.js +169 -169
  36. package/examples/kanban/dist/outlook.js +162 -162
  37. package/examples/kanban/dist/power-apps-data.js +2953 -2953
  38. package/examples/kanban/dist/sharepoint.js +339 -339
  39. package/examples/myProfile/dist/index.html +184 -184
  40. package/examples/myProfile/dist/index.js +141 -141
  41. package/examples/myProfile/dist/office365users.js +169 -169
  42. package/examples/myProfile/dist/power-apps-data.js +2953 -2953
  43. package/examples/myProfile/power.config.json +22 -22
  44. package/examples/myProfile/readme.md +79 -79
  45. package/examples/outlook Demo/dist/codeapp.js +1085 -1085
  46. package/examples/outlook Demo/dist/index.html +35 -35
  47. package/examples/outlook Demo/dist/index.js +170 -170
  48. package/examples/outlook Demo/dist/outlook.js +121 -121
  49. package/examples/outlook Demo/dist/power-apps-data.js +2911 -2911
  50. package/examples/outlook Demo/dist/styles.css +84 -84
  51. package/examples/outlook Demo/readme.md +82 -82
  52. package/examples/outlook Demo2/OutlookDemo_1_0_0_1.zip +0 -0
  53. package/examples/outlook Demo2/agent/decision-log.md +7 -0
  54. package/examples/{solution explorer → outlook Demo2}/dist/codeapp.js +245 -9
  55. package/examples/outlook Demo2/dist/index.html +98 -0
  56. package/examples/outlook Demo2/dist/index.js +272 -0
  57. package/examples/outlook Demo2/dist/styles.css +639 -0
  58. package/examples/outlook Demo2/power.config.json +23 -0
  59. package/examples/outlook Demo2/src/generated/index.ts +14 -0
  60. package/examples/outlook Demo2/src/generated/models/Office365GroupsModel.ts +363 -0
  61. package/examples/outlook Demo2/src/generated/models/Office365OutlookModel.ts +2046 -0
  62. package/examples/outlook Demo2/src/generated/models/Office365UsersModel.ts +254 -0
  63. package/examples/outlook Demo2/src/generated/services/Office365GroupsService.ts +326 -0
  64. package/examples/outlook Demo2/src/generated/services/Office365OutlookService.ts +2476 -0
  65. package/examples/outlook Demo2/src/generated/services/Office365UsersService.ts +358 -0
  66. package/examples/planning Poker/.vscode/settings.json +4 -4
  67. package/examples/planning Poker/additional files/customizations (tables).xml +6428 -6428
  68. package/examples/planning Poker/additional files/dataverse-tables.json +165 -165
  69. package/examples/planning Poker/additional files/readme.md +122 -122
  70. package/examples/planning Poker/dist/dataverse.js +78 -78
  71. package/examples/planning Poker/dist/index.html +198 -198
  72. package/examples/planning Poker/dist/index.js +954 -954
  73. package/examples/planning Poker/dist/power-apps-data.js +2953 -2953
  74. package/examples/planning Poker/dist/styles.css +815 -815
  75. package/examples/sharePoint Demo/agent/decision-log.md +5 -5
  76. package/examples/sharePoint Demo/dist/codeapp.js +1085 -1085
  77. package/examples/sharePoint Demo/dist/index.js +262 -262
  78. package/examples/sharePoint Demo/dist/power-apps-data.js +2911 -2911
  79. package/examples/sharePoint Demo/power.config.json +22 -22
  80. package/examples/todo/dist/dataverse.js +64 -64
  81. package/examples/todo/dist/index.html +75 -75
  82. package/examples/todo/dist/index.js +8 -8
  83. package/examples/todo/dist/power-apps-data.js +2953 -2953
  84. package/examples/todo/dist/renderer.js +375 -375
  85. package/examples/todo/dist/styles.css +691 -691
  86. package/examples/todo/power.config.json +34 -34
  87. package/package.json +1 -1
  88. package/readme.md +33 -4
  89. package/examples/solution explorer/agent/decision-log.md +0 -27
  90. package/examples/solution explorer/agent/mockup-01-swiss-grid.html +0 -452
  91. package/examples/solution explorer/agent/mockup-02-dark-glass.html +0 -496
  92. package/examples/solution explorer/agent/mockup-03-paper-console.html +0 -510
  93. package/examples/solution explorer/agent/mockup-04-neon-noir.html +0 -546
  94. package/examples/solution explorer/agent/mockup-05-zen-garden.html +0 -534
  95. package/examples/solution explorer/dist/index.html +0 -80
  96. package/examples/solution explorer/dist/index.js +0 -735
  97. package/examples/solution explorer/dist/styles.css +0 -571
  98. package/examples/solution explorer/power.config.json +0 -151
  99. /package/examples/{solution explorer → outlook Demo2}/dist/icon-512.png +0 -0
  100. /package/examples/{solution explorer → outlook Demo2}/dist/power-apps-data.js +0 -0
@@ -0,0 +1,98 @@
1
+
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Outlook Mail</title>
8
+ <link rel="stylesheet" href="styles.css" />
9
+ <script type="module" src="power-apps-data.js"></script>
10
+ <script type="module" src="codeapp.js"></script>
11
+ <script type="module" src="index.js"></script>
12
+ </head>
13
+ <body>
14
+ <div id="root">
15
+ <!-- Header -->
16
+ <header class="app-header">
17
+ <div class="app-header__brand">
18
+ <div class="app-header__icon">M</div>
19
+ <h1 class="app-header__title">Mail</h1>
20
+ </div>
21
+ <div class="app-header__actions">
22
+ <button class="btn btn--secondary" id="btnRefresh" title="Refresh inbox">
23
+ ↻ Refresh
24
+ </button>
25
+ <button class="btn btn--primary" id="btnCompose" title="Compose new email">
26
+ ✎ Compose
27
+ </button>
28
+ </div>
29
+ </header>
30
+
31
+ <!-- Body -->
32
+ <div class="app-body" id="appBody">
33
+ <!-- Inbox List -->
34
+ <aside class="inbox-panel">
35
+ <div class="inbox-panel__header">
36
+ <span class="inbox-panel__title">Inbox</span>
37
+ <span class="inbox-panel__count" id="emailCount">—</span>
38
+ </div>
39
+ <div class="inbox-panel__list" id="emailList">
40
+ <!-- Skeleton loader -->
41
+ <div class="loading-skeleton" id="loadingSkeleton">
42
+ <div class="skeleton-item"><div class="skeleton-circle"></div><div class="skeleton-lines"><div class="skeleton-line skeleton-line--short"></div><div class="skeleton-line skeleton-line--medium"></div><div class="skeleton-line"></div></div></div>
43
+ <div class="skeleton-item"><div class="skeleton-circle"></div><div class="skeleton-lines"><div class="skeleton-line skeleton-line--short"></div><div class="skeleton-line skeleton-line--medium"></div><div class="skeleton-line"></div></div></div>
44
+ <div class="skeleton-item"><div class="skeleton-circle"></div><div class="skeleton-lines"><div class="skeleton-line skeleton-line--short"></div><div class="skeleton-line skeleton-line--medium"></div><div class="skeleton-line"></div></div></div>
45
+ <div class="skeleton-item"><div class="skeleton-circle"></div><div class="skeleton-lines"><div class="skeleton-line skeleton-line--short"></div><div class="skeleton-line skeleton-line--medium"></div><div class="skeleton-line"></div></div></div>
46
+ <div class="skeleton-item"><div class="skeleton-circle"></div><div class="skeleton-lines"><div class="skeleton-line skeleton-line--short"></div><div class="skeleton-line skeleton-line--medium"></div><div class="skeleton-line"></div></div></div>
47
+ </div>
48
+ </div>
49
+ </aside>
50
+
51
+ <!-- Detail Panel -->
52
+ <main class="detail-panel" id="detailPanel">
53
+ <div class="detail-panel__empty" id="detailEmpty">
54
+ <div class="detail-panel__empty-icon">✉</div>
55
+ <div class="detail-panel__empty-text">Select an email to read</div>
56
+ </div>
57
+ <div class="detail-panel__content" id="detailContent" style="display:none;"></div>
58
+ </main>
59
+ </div>
60
+
61
+ <!-- Status Bar -->
62
+ <div class="status-bar" id="statusBar">
63
+ <div class="status-bar__dot"></div>
64
+ <span id="statusText">Ready</span>
65
+ </div>
66
+
67
+ <!-- Compose Modal -->
68
+ <div class="modal-overlay" id="composeOverlay">
69
+ <div class="compose-modal">
70
+ <div class="compose-modal__header">
71
+ <h2 class="compose-modal__title">New Message</h2>
72
+ <button class="compose-modal__close" id="btnCloseCompose">✕</button>
73
+ </div>
74
+ <div class="compose-modal__body">
75
+ <div class="form-group">
76
+ <label class="form-group__label" for="composeTo">To</label>
77
+ <input class="form-group__input" type="email" id="composeTo" placeholder="recipient@example.com" />
78
+ </div>
79
+ <div class="form-group">
80
+ <label class="form-group__label" for="composeSubject">Subject</label>
81
+ <input class="form-group__input" type="text" id="composeSubject" placeholder="What is this about?" />
82
+ </div>
83
+ <div class="form-group">
84
+ <label class="form-group__label" for="composeBody">Message</label>
85
+ <textarea class="form-group__input form-group__input--textarea" id="composeBody" placeholder="Write your message…"></textarea>
86
+ </div>
87
+ </div>
88
+ <div class="compose-modal__footer">
89
+ <button class="btn btn--ghost" id="btnDiscardCompose">Discard</button>
90
+ <button class="btn btn--primary" id="btnSendEmail">
91
+ Send ➤
92
+ </button>
93
+ </div>
94
+ </div>
95
+ </div>
96
+ </div>
97
+ </body>
98
+ </html>
@@ -0,0 +1,272 @@
1
+ import { listEmails, sendEmail } from './codeapp.js';
2
+
3
+ // ===== STATE =====
4
+ let emails = [];
5
+ let selectedEmailId = null;
6
+
7
+ // ===== DOM REFS =====
8
+ const $ = (sel) => document.querySelector(sel);
9
+ const emailListEl = () => $('#emailList');
10
+ const emailCountEl = () => $('#emailCount');
11
+ const loadingEl = () => $('#loadingSkeleton');
12
+ const detailEmpty = () => $('#detailEmpty');
13
+ const detailContent = () => $('#detailContent');
14
+ const statusBar = () => $('#statusBar');
15
+ const statusText = () => $('#statusText');
16
+ const composeOverlay = () => $('#composeOverlay');
17
+
18
+ // ===== STATUS HELPERS =====
19
+ const setStatus = (text, type = 'ok') => {
20
+ const bar = statusBar();
21
+ const txt = statusText();
22
+ if (!bar || !txt) return;
23
+ bar.className = 'status-bar' + (type === 'error' ? ' status-bar--error' : type === 'loading' ? ' status-bar--loading' : '');
24
+ txt.textContent = text;
25
+ };
26
+
27
+ // ===== FORMAT HELPERS =====
28
+ const getInitials = (name) => {
29
+ if (!name) return '?';
30
+ const parts = name.trim().split(/\s+/);
31
+ if (parts.length >= 2) return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
32
+ return name.slice(0, 2).toUpperCase();
33
+ };
34
+
35
+ const formatTime = (dateStr) => {
36
+ if (!dateStr) return '';
37
+ try {
38
+ const d = new Date(dateStr);
39
+ const now = new Date();
40
+ const diff = now - d;
41
+ const oneDay = 86400000;
42
+ if (diff < oneDay && d.getDate() === now.getDate()) {
43
+ return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
44
+ }
45
+ if (diff < 7 * oneDay) {
46
+ return d.toLocaleDateString([], { weekday: 'short' });
47
+ }
48
+ return d.toLocaleDateString([], { month: 'short', day: 'numeric' });
49
+ } catch {
50
+ return '';
51
+ }
52
+ };
53
+
54
+ const formatFullDate = (dateStr) => {
55
+ if (!dateStr) return '';
56
+ try {
57
+ return new Date(dateStr).toLocaleString([], {
58
+ weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',
59
+ hour: '2-digit', minute: '2-digit'
60
+ });
61
+ } catch {
62
+ return '';
63
+ }
64
+ };
65
+
66
+ const stripHtml = (html) => {
67
+ if (!html) return '';
68
+ const tmp = document.createElement('div');
69
+ tmp.innerHTML = html;
70
+ return tmp.textContent || tmp.innerText || '';
71
+ };
72
+
73
+ // ===== RENDER INBOX =====
74
+ const renderEmailList = () => {
75
+ const list = emailListEl();
76
+ if (!list) return;
77
+
78
+ const skeleton = loadingEl();
79
+ if (skeleton) skeleton.remove();
80
+
81
+ if (emails.length === 0) {
82
+ list.innerHTML = '<div style="padding:40px 20px;text-align:center;color:var(--ink-muted);font-size:14px;">No emails found</div>';
83
+ emailCountEl().textContent = '0';
84
+ return;
85
+ }
86
+
87
+ emailCountEl().textContent = `${emails.length}`;
88
+
89
+ list.innerHTML = emails.map((email) => {
90
+ const id = email.Id || email.id || '';
91
+ const from = email.From || email.from;
92
+ const senderName = from?.EmailAddress?.Name || from?.emailAddress?.name || from?.Name || 'Unknown';
93
+ const subject = email.Subject || email.subject || '(No subject)';
94
+ const preview = stripHtml(email.BodyPreview || email.bodyPreview || email.Body?.Content || '');
95
+ const dateStr = email.DateTimeReceived || email.receivedDateTime || email.ReceivedDateTime || '';
96
+ const isRead = email.IsRead ?? email.isRead ?? true;
97
+ const isActive = id === selectedEmailId;
98
+
99
+ return `
100
+ <div class="email-item ${!isRead ? 'email-item--unread' : ''} ${isActive ? 'email-item--active' : ''}"
101
+ data-id="${id}" role="button" tabindex="0">
102
+ <div class="email-item__avatar">${getInitials(senderName)}</div>
103
+ <div class="email-item__content">
104
+ <div class="email-item__row">
105
+ <span class="email-item__sender">${escapeHtml(senderName)}</span>
106
+ <span class="email-item__time">${formatTime(dateStr)}</span>
107
+ </div>
108
+ <div class="email-item__subject">${escapeHtml(subject)}</div>
109
+ <div class="email-item__preview">${escapeHtml(preview.slice(0, 100))}</div>
110
+ </div>
111
+ </div>
112
+ `;
113
+ }).join('');
114
+
115
+ // Attach click handlers
116
+ list.querySelectorAll('.email-item').forEach((el) => {
117
+ el.addEventListener('click', () => selectEmail(el.dataset.id));
118
+ });
119
+ };
120
+
121
+ const escapeHtml = (str) => {
122
+ const div = document.createElement('div');
123
+ div.appendChild(document.createTextNode(str || ''));
124
+ return div.innerHTML;
125
+ };
126
+
127
+ // ===== SELECT EMAIL =====
128
+ const selectEmail = (id) => {
129
+ selectedEmailId = id;
130
+ const email = emails.find((e) => (e.Id || e.id) === id);
131
+ if (!email) return;
132
+
133
+ // Re-render list to update active state
134
+ renderEmailList();
135
+
136
+ // Show detail
137
+ const empty = detailEmpty();
138
+ const content = detailContent();
139
+ if (empty) empty.style.display = 'none';
140
+ if (!content) return;
141
+ content.style.display = 'block';
142
+
143
+ const from = email.From || email.from;
144
+ const senderName = from?.EmailAddress?.Name || from?.emailAddress?.name || from?.Name || 'Unknown';
145
+ const senderEmail = from?.EmailAddress?.Address || from?.emailAddress?.address || from?.Address || '';
146
+ const subject = email.Subject || email.subject || '(No subject)';
147
+ const dateStr = email.DateTimeReceived || email.receivedDateTime || email.ReceivedDateTime || '';
148
+ const body = email.Body?.Content || email.body?.content || email.BodyPreview || email.bodyPreview || '';
149
+
150
+ content.innerHTML = `
151
+ <h2 class="detail-panel__subject">${escapeHtml(subject)}</h2>
152
+ <div class="detail-panel__meta">
153
+ <div class="detail-panel__meta-avatar">${getInitials(senderName)}</div>
154
+ <div class="detail-panel__meta-info">
155
+ <div class="detail-panel__meta-sender">${escapeHtml(senderName)}</div>
156
+ <div class="detail-panel__meta-email">${escapeHtml(senderEmail)}</div>
157
+ <div class="detail-panel__meta-date">${formatFullDate(dateStr)}</div>
158
+ </div>
159
+ </div>
160
+ <div class="detail-panel__body">${body}</div>
161
+ `;
162
+
163
+ // Mobile: show detail
164
+ const appBody = $('#appBody');
165
+ if (appBody) appBody.classList.add('app-body--detail-open');
166
+ };
167
+
168
+ // ===== FETCH INBOX =====
169
+ const fetchInbox = async () => {
170
+ setStatus('Loading inbox…', 'loading');
171
+ try {
172
+ const result = await listEmails({ folderId: 'Inbox', top: 25 });
173
+ emails = Array.isArray(result) ? result : [];
174
+ if (result && Array.isArray(result.value)) emails = result.value;
175
+ renderEmailList();
176
+ setStatus(`${emails.length} email${emails.length !== 1 ? 's' : ''} loaded`);
177
+ } catch (err) {
178
+ console.error('Failed to fetch inbox:', err);
179
+ setStatus(`Error: ${err.message}`, 'error');
180
+ const list = emailListEl();
181
+ const skeleton = loadingEl();
182
+ if (skeleton) skeleton.remove();
183
+ if (list) {
184
+ list.innerHTML = `<div style="padding:40px 20px;text-align:center;color:var(--accent);font-size:14px;">
185
+ Failed to load emails.<br><span style="color:var(--ink-muted);font-size:12px;">${escapeHtml(err.message)}</span>
186
+ </div>`;
187
+ }
188
+ }
189
+ };
190
+
191
+ // ===== SEND EMAIL =====
192
+ const doSendEmail = async () => {
193
+ const toEl = $('#composeTo');
194
+ const subjectEl = $('#composeSubject');
195
+ const bodyEl = $('#composeBody');
196
+ const sendBtn = $('#btnSendEmail');
197
+
198
+ const to = toEl?.value?.trim();
199
+ const subject = subjectEl?.value?.trim();
200
+ const body = bodyEl?.value?.trim();
201
+
202
+ if (!to) {
203
+ toEl?.focus();
204
+ return;
205
+ }
206
+
207
+ sendBtn.disabled = true;
208
+ sendBtn.textContent = 'Sending…';
209
+ setStatus('Sending email…', 'loading');
210
+
211
+ try {
212
+ await sendEmail({
213
+ to: to,
214
+ subject: subject || '(No subject)',
215
+ body: '<p>' + escapeHtml(body || '') + '</p>',
216
+ importance: 'Normal'
217
+ });
218
+
219
+ setStatus('Email sent successfully');
220
+ closeCompose();
221
+
222
+ // Clear form
223
+ if (toEl) toEl.value = '';
224
+ if (subjectEl) subjectEl.value = '';
225
+ if (bodyEl) bodyEl.value = '';
226
+ } catch (err) {
227
+ console.error('Failed to send email:', err);
228
+ setStatus(`Send failed: ${err.message}`, 'error');
229
+ } finally {
230
+ sendBtn.disabled = false;
231
+ sendBtn.textContent = 'Send ➤';
232
+ }
233
+ };
234
+
235
+ // ===== COMPOSE MODAL =====
236
+ const openCompose = () => {
237
+ const overlay = composeOverlay();
238
+ if (overlay) overlay.classList.add('modal-overlay--visible');
239
+ setTimeout(() => $('#composeTo')?.focus(), 200);
240
+ };
241
+
242
+ const closeCompose = () => {
243
+ const overlay = composeOverlay();
244
+ if (overlay) overlay.classList.remove('modal-overlay--visible');
245
+ };
246
+
247
+ // ===== EVENT BINDINGS =====
248
+ const bindEvents = () => {
249
+ $('#btnCompose')?.addEventListener('click', openCompose);
250
+ $('#btnCloseCompose')?.addEventListener('click', closeCompose);
251
+ $('#btnDiscardCompose')?.addEventListener('click', closeCompose);
252
+ $('#btnSendEmail')?.addEventListener('click', doSendEmail);
253
+ $('#btnRefresh')?.addEventListener('click', fetchInbox);
254
+
255
+ // Close modal on overlay click
256
+ composeOverlay()?.addEventListener('click', (e) => {
257
+ if (e.target === composeOverlay()) closeCompose();
258
+ });
259
+
260
+ // Escape key closes modal
261
+ document.addEventListener('keydown', (e) => {
262
+ if (e.key === 'Escape') closeCompose();
263
+ });
264
+ };
265
+
266
+ // ===== BOOT =====
267
+ async function boot() {
268
+ bindEvents();
269
+ await fetchInbox();
270
+ }
271
+
272
+ boot();