-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapps-script.js
More file actions
148 lines (132 loc) Β· 4.79 KB
/
apps-script.js
File metadata and controls
148 lines (132 loc) Β· 4.79 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
function doGet() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const payload = {
updatedAt: new Date().toISOString(),
study: readSheet(ss, 'StudyLog'),
sessions: readSheet(ss, 'SessionLog'),
resources: readSheet(ss, 'Resources'),
};
return ContentService
.createTextOutput(JSON.stringify(payload))
.setMimeType(ContentService.MimeType.JSON);
}
function doPost(e) {
const body = parseRequestBody(e);
const type = String(body.type || '').trim();
// 1. Append new row (study / session)
if (type === 'study' || type === 'session') {
const row = body.row || {};
if (!Object.keys(row).length) return jsonResponse({ ok: false, error: 'Missing row payload.' });
const sheetName = type === 'study' ? 'StudyLog' : 'SessionLog';
appendObjectRow(SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName), row);
return jsonResponse({ ok: true, updatedAt: new Date().toISOString() });
}
// 2. Update a field in an existing row (e.g. actual_score)
if (type === 'update') {
const sessionId = body.session_id;
const field = body.field;
const value = body.value;
if (!sessionId || !field) return jsonResponse({ ok: false, error: 'Missing session_id or field.' });
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('SessionLog');
const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0].map(String);
const colIdx = headers.indexOf(field);
const idIdx = headers.indexOf('session_id');
if (colIdx === -1 || idIdx === -1) return jsonResponse({ ok: false, error: 'Column not found: ' + field });
const data = sheet.getDataRange().getValues();
for (let i = 1; i < data.length; i++) {
if (String(data[i][idIdx]) === String(sessionId)) {
sheet.getRange(i + 1, colIdx + 1).setValue(value);
return jsonResponse({ ok: true, updated: true, updatedAt: new Date().toISOString() });
}
}
return jsonResponse({ ok: false, error: 'Session not found: ' + sessionId });
}
return jsonResponse({ ok: false, error: 'Unsupported type: ' + type });
}
function parseRequestBody(e) {
const contents = e && e.postData && e.postData.contents
? String(e.postData.contents)
: '';
if (contents) {
try {
return JSON.parse(contents);
} catch (error) {
// Ignore and continue with form-style payloads.
}
}
const params = e && e.parameter ? e.parameter : {};
let row = params.row || {};
if (typeof row === 'string') {
try {
row = JSON.parse(row);
} catch (error) {
row = {};
}
}
return {
type: params.type || '',
row: row || {},
};
}
function readSheet(ss, sheetName) {
const sheet = ss.getSheetByName(sheetName);
if (!sheet) return [];
const values = sheet.getDataRange().getValues();
if (values.length < 2) return [];
const headers = values[0].map(String);
return values.slice(1)
.filter(row => row.some(cell => String(cell).trim() !== ''))
.map(row => {
const obj = {};
headers.forEach((header, index) => {
obj[header] = row[index];
});
return obj;
});
}
function appendObjectRow(sheet, row) {
const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0].map(String);
const values = headers.map(header => row[header] ?? '');
sheet.appendRow(values);
}
function jsonResponse(payload) {
return ContentService
.createTextOutput(JSON.stringify(payload))
.setMimeType(ContentService.MimeType.JSON);
}
// ββ Migration helpers (run once from editor) ββ
// Fix legacy subject "tznk" β "all"
function fixSubjectToAll() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('SessionLog');
const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0].map(String);
const subIdx = headers.indexOf('subject');
let updated = 0;
const data = sheet.getDataRange().getValues();
for (let i = 1; i < data.length; i++) {
const sub = String(data[i][subIdx] || '').trim().toLowerCase();
if (sub === 'tznk') {
sheet.getRange(i + 1, subIdx + 1).setValue('all');
updated++;
}
}
Logger.log('Fixed ' + updated + ' rows: tznkβall');
}
// Fix ISO dates (2026-05-07T19:38:21.501Z β 2026-05-07)
function fixIsoDates() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('SessionLog');
const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0].map(String);
const dateIdx = headers.indexOf('date');
let updated = 0;
const data = sheet.getDataRange().getValues();
for (let i = 1; i < data.length; i++) {
const d = String(data[i][dateIdx] || '');
if (d.includes('T')) {
sheet.getRange(i + 1, dateIdx + 1).setValue(d.slice(0, 10));
updated++;
}
}
Logger.log('Fixed ' + updated + ' dates');
}