forked from learn-anything/learn-anything
-
Notifications
You must be signed in to change notification settings - Fork 0
/
default.esdl
319 lines (319 loc) · 10.4 KB
/
default.esdl
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# Short summary:
# User: user of the app. owns one wiki
# Wiki: collection of topics
# Topic: contains markdown content (user's knowledge on the topic) + notes/links
# GlobalTopic: public GlobalTopic is found on learn-anything.xyz/<GlobalTopic>
module default {
type User {
# unique email
required email: str {
constraint exclusive;
};
# uniquie UUID for user, created on signup
hankoId: str {
constraint exclusive;
};
# unique username
name: str {
constraint exclusive;
};
admin: bool;
# custom name user can choose for themselves similar to X
displayName: str;
# aws s3 or cloudflare r2 url with image
profileImage: str;
# user owns one wiki
link wiki := .<user[is Wiki];
# topics user wants to learn
multi topicsToLearn: GlobalTopic;
# topics user is learning
multi topicsLearning: GlobalTopic;
# topics user learned
multi topicsLearned: GlobalTopic;
# links user has `completed` in some way
multi completedLinks: GlobalLink;
# links user has liked
multi likedLinks: GlobalLink;
# personal links user has added
multi personalLinks: PersonalLink {
on target delete allow;
};
# links user has disliked
multi dislikedLinks: GlobalLink;
# notes user has liked
multi likedNotes: Note;
# notes user has disliked
multi dislikedNotes: Note;
# list of topics user is moderating
multi topicsModerated: GlobalTopic;
# date until user has paid membership for
memberUntil: datetime;
# month / year
stripePlan: str;
# after stripe payment works, you get back subscription object id (can be used to cancel subscription)
stripeSubscriptionObjectId: str;
# whether user has stopped subscription and won't be be charged again
subscriptionStopped: bool;
}
type Wiki {
# owner of this wiki
required link user: User;
# contains topic names + children of the topic(s)
# is used to generate sidebar in wiki
# indent is how to know which topics are children of which
# sorted alphebetically
# example:
# {
# 0: {name: 'Analytics', indent: 0},
# 1: {name: 'Grafana', indent: 1},
# }
# TODO: should in theory just be array of objects above. but how?
# TODO: perhaps there is better way to do this?
topicSidebar: json;
# used to generate local interactive graph of topics for wiki
# TODO: find out structure needed for this
topicGraph: json;
# all topics belonging to this wiki
multi link topics := .<wiki[is Topic];
}
type Topic {
# wiki this topic belongs to
required link wiki: Wiki;
# url friendly unique name of topic. i.e. 'physics' or 'linear-algebra'
# lowercase + dash separate words
# the connected .md file name of topic is also this name
required name: str {
constraint exclusive;
};
# pretty version of `name`, uppercased nicely, proper capitalisation
# i.e. Physics
required prettyName: str;
# true = anyone can see the topic. false = only user can see topic
required public: bool;
# markdown content of topic (user's knowledge/thoughts on the topic)
required content: str;
# each published topic is part of a global topic
globalTopic: GlobalTopic;
# optional path of topic: /physics/quantum-physics where each GlobalTopic name is separated by /
topicPath: str;
# all notes belonging to this topic
multi link notes := .<topic[is Note];
# all links belonging to this topic
multi link links := .<topic[is Link];
# parent topic if there is one
parentTopic: Topic;
# topics that are mentioned in this topic (computed every time topic changes)
# TODO: maybe no need to save it but have it be derived?
multi mentionedTopics: Topic;
# mentions of this topic in other topics
# TODO: maybe no need to save it but have it be derived?
multi topicBacklinks: Topic;
# users can't have two topics with same name
constraint exclusive on ((.name, .wiki));
# everything in the topic as markdown
# recomputed on every change made to the topic
topicAsMarkdown: str;
}
type Note {
# main topic this note belongs to
required topic: Topic;
# main content of the note
required content: str;
# true = anyone can see the note. false = only user can see note
required public: bool;
# topics this note can also relate more loosely to
# there is still one main topic a note belongs to as chosen by user
multi relatedTopics: Topic;
# additional content of the note
# i.e.
# - note
# - additional content in form of subnotes
# - another subnote
additionalContent: str;
# url from where the note was taken from or has reference to
url: str;
}
type Link {
# main topic this link belongs to
required topic: Topic;
# url of the link
required url: str;
# title as grabbed from the url
urlTitle: str;
# title of link as set by the user
title: str;
# true = anyone can see the link. false = only user can see link
required public: bool;
# type of the link: course/pdf/video/..
# TODO: should be a new object as Type maybe?
type: str;
# link description
description: str;
# how long it takes to `process` the link
# if its article, estimate content of article by average/user reading time
# if video, it's time length of video. i.e. `12 min`
timeEstimate: str;
# author of the link
author: str;
# TODO: should probably be int, but keeping it str for now
year: str;
# related links to this link
# could be link to `Code` or `Tweet` or some other Link
multi relatedLinks: RelatedLink;
# all links are mapped by unique URL to a global link
link globalLink: GlobalLink {
on target delete allow;
};
}
type RelatedLink {
url: str;
title: str;
}
type GlobalLink {
# nice title from url
required title: str;
# unique url of the link (without protocol)
required url: str {
constraint exclusive;
};
# http / https
required protocol: str;
# full url of the link as saved initially by user
fullUrl: str;
# true = link was verified, its valid URL, good metadata was added etc.
required verified: bool;
# true = link is available for all to see/search. false = link is private
required public: bool;
# link description
description: str;
# title as grabbed from url
urlTitle: str;
# optionally have a main topic that the link belongs to
link mainTopic: GlobalTopic;
# TODO: should probably be int, but keeping it str for now
year: str;
# related links to this link
# could be link to `Code` or `Tweet` or some other Link
multi relatedLinks: RelatedLink;
# connected topics for this link
multi link links := .<globalLink[is Link];
}
type PersonalLink {
# nice title from url
required title: str;
# unique url of the link (without protocol)
required url: str {
constraint exclusive;
};
# http / https
required protocol: str;
# link description
description: str;
year: str;
# optionally have a main topic that personal link belongs to
link mainTopic: GlobalTopic;
}
type GlobalNote {
required content: str;
url: str;
# optionally have a main topic that the note belongs to
link mainTopic: GlobalTopic;
}
type GlobalTopic {
# url friendly unique name of topic. i.e. 'physics' or 'linear-algebra'
# lowercase + dash separate words
required name: str {
constraint exclusive;
};
# pretty version of `name`, uppercased nicely, proper capitalisation i.e. Physics
required prettyName: str;
# detailed summary of the topic (in html, due to https://github.com/SaltyAom/mobius/issues/4)
required topicSummary: str;
# summary of the topic (short version)
topicSummaryShort: str;
# global guide for the topic, improved by community
# required globalTopic := .<globalTopic[is GlobalTopic];
# true = topic is available to anyone to see
# i.e. learn-anything.xyz/physics
# false = not available for all to see
# global topics are first reviewed by LA before becoming public
required public: bool;
# true = topic was verified
required verified: bool;
# optional path of topic: /physics/quantum-physics where each GlobalTopic name is separated by /
topicPath: str;
# used to generate interactive graph of topics for the global topic
# check GlobalGraph type for structure
similarTopicsGraph: json;
# related topics to this global topic
multi relatedTopics: GlobalTopic;
# all links submitted to the global topic
multi relatedLinks: GlobalLink;
# all notes submitted to the global topic
multi relatedNotes: Note;
# link globalGuide: GlobalGuide {
# on target delete allow;
# };
# past changes to global guide versioned by time
multi globalGuides: GlobalGuide;
# there is one global guide attached to each global topic
latestGlobalGuide: GlobalGuide;
description: str;
topicWebsiteLink: str;
wikipediaLink: str;
githubLink: str;
xLink: str;
redditLink: str;
aiSummary: str;
}
type GlobalGuide {
required created_at: datetime {
readonly := true;
default := datetime_of_statement();
}
# guide is split by sections
multi sections: GlobalGuideSection {
on target delete allow;
}
}
type GlobalGuideSection {
# title of section
required title: str;
# summary of the section (in html, due to https://github.com/SaltyAom/mobius/issues/4)
summary: str;
# list of links in a section
multi links: GlobalLink {
order: int16;
};
}
type UserGuide {
# global topic
required link globalTopic: GlobalTopic;
required created_at: datetime {
readonly := true;
default := datetime_of_statement();
}
# guide is split by sections
multi sections: UserGuideSection;
# owner of guide
required link user: User;
}
type UserGuideSection {
# title of section
required title: str;
# list of links in a section
multi links: GlobalLink;
}
type GlobalGraph {
# JSON graph of all topics and connections
# structure:
# [
# {
# 'topic': "physics",
# 'links': [{"topic": "quantum-physics", "weight": 1}, {"topic": "relativity", "weight": 1}"}]
# }
# ]
# gets recomputed from how users in LA draw connections between topics
required connections: json;
}
}