forked from reviewjs/annotate
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsync-google-sheet.js
More file actions
121 lines (110 loc) · 4.07 KB
/
Copy pathsync-google-sheet.js
File metadata and controls
121 lines (110 loc) · 4.07 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
/* =============================================================================
* sync-google-sheet.js — Google Sheets sync plugin for annotate-sync.
* Load AFTER sync-engine.js. Registers via Annotate.sync.register({…}).
*
* Configure with data-google-sheet="<Apps Script URL>" on the annotate-sync.js
* script tag.
* ========================================================================== */
(function () {
if (!window.Annotate || !window.Annotate.sync || !window.Annotate._internals) return;
var I = window.Annotate._internals;
var GS_SYNCING = false;
function gsUrl(){ return I.state.sheetUrl; }
function gsHeaders() { return { "Content-Type": "text/plain" }; }
function safeJSON(v) {
if (typeof v !== "string" || !v) return v;
try { return JSON.parse(v); } catch (e) { return v; }
}
function gsFlatten(c) {
var rows = [];
rows.push({
annotateId: c.id, page: c.page, url: c.url, type: c.type,
author: c.author, text: c.text, color: c.color,
anchor: c.anchor ? JSON.stringify(c.anchor) : "",
geom: c.geom ? JSON.stringify(c.geom) : "",
resolved: c.resolved,
parentId: "",
createdAt: c.createdAt, updatedAt: c.updatedAt,
});
(c.replies || []).forEach(function (r) {
rows.push({
annotateId: r.id, page: c.page, url: "", type: "reply",
author: r.author, text: r.text, color: "",
anchor: "", geom: "", resolved: false,
parentId: c.id,
createdAt: r.createdAt, updatedAt: "",
});
});
return rows;
}
function gsRowToComment(row) {
if (!row || !row.annotateId) return null;
return {
id: row.annotateId, page: row.page || "", url: row.url || "",
type: row.type || "", author: row.author || "", text: row.text || "",
color: row.color || "", anchor: safeJSON(row.anchor),
geom: safeJSON(row.geom),
resolved: row.resolved === true || row.resolved === "TRUE" || row.resolved === "true",
parentId: row.parentId || "", replies: [],
createdAt: row.createdAt || "", updatedAt: row.updatedAt || "",
};
}
function gsNest(rows) {
var tops = [], byId = {};
rows.forEach(function (r) { byId[r.id] = r; });
rows.forEach(function (r) {
if (r.parentId && byId[r.parentId]) {
byId[r.parentId].replies.push({
id: r.id, author: r.author, text: r.text, createdAt: r.createdAt,
});
} else if (!r.parentId) { tops.push(r); }
});
return tops;
}
window.Annotate.sync.register({
id: "gsheet",
name: "Google Sheets",
icon: function () { return I.ICONS.sheets; },
enabled: function () { return !!I.state.sheetUrl; },
push: function (c) {
var rows = gsFlatten(c);
rows.forEach(function (row) {
fetch(gsUrl(), { method: "POST", headers: gsHeaders(),
body: JSON.stringify({ action: "upsert", comment: row }) })
.catch(function () {});
});
},
delete: function (ids) {
if (!Array.isArray(ids)) ids = [ids];
ids.forEach(function (id) {
fetch(gsUrl(), { method: "POST", headers: gsHeaders(),
body: JSON.stringify({ action: "delete", annotateId: id }) })
.catch(function () {});
});
},
pull: function (cb) {
GS_SYNCING = true;
var url = gsUrl() + "?page=" + encodeURIComponent(I.PAGE);
fetch(url)
.then(function (res) { return res.ok ? res.json() : Promise.reject(res); })
.then(function (data) {
var incoming = (data && data.comments || []).map(gsRowToComment).filter(Boolean);
incoming = gsNest(incoming);
GS_SYNCING = false;
cb(incoming, null);
})
.catch(function () {
GS_SYNCING = false;
cb(null, "Sheet pull failed");
});
},
renderStatus: function (el, n, canShare) {
if (!this.enabled()) return;
var row = I.el("div", { class: "an-localnote" }, [
I.el("span", { html: I.ICONS.sheets }),
I.el("span", { text: GS_SYNCING ? "Syncing\u2026" : "Synced to Google Sheets" }),
]);
el.appendChild(row);
},
});
})();