-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdesign.txt
More file actions
100 lines (55 loc) · 4.69 KB
/
design.txt
File metadata and controls
100 lines (55 loc) · 4.69 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
Design:
We shall build a voting system. Start minimal. A title (phrased as a question) and upvotes + downvotes. How do we ensure people vote only once?
We will attempt to ensure fair voting by using a long-running session per user (which in turn will set a cookie). Since this is a simple project we'll just default to cl-prevalence, which is extremely simple to get started with.
Structures/classes:
votable with upvotes + downvotes
This goes into models.lisp -- we like defclass* so add it to the asd file, and re-evaluate (ql:quickload "tut") at the repl.
question inherits from votable with a title
Pages:
The landing page should show all outstanding questions before the weblocks community, their upvotes + downvotes. There should be a button to add a question. Perhaps later we can have threaded comments, tickets etc.
So our files:
DONE
firstpage.lisp
DONE
Remember, when you restart weblocks/lisp for any reason (I just did it to move my development into a tmux session) you must restart weblocks.
Also, in this case we've changed what init-session does, so to see changes we'd have to reset-sessions.
So remember and use these two commands:
(weblocks:reset-sessions)
(weblocks:start-weblocks)
Well, now we actually have data to render, or rather, we'd render it if we had it.
Stop and start lisp using our standard start-tut.lisp, and at the repl (at the command prompt) go to the tut package:
(in-package 'tut)
(start-tut)
Ensure weblocks is running! That will open the tut store automatically.
Alternate instructions:
(weblocks:start-weblocks)
and start tut using a browser.
Go to the browser to ensure it's running. Then at the repl:
? (make-instance 'question :title "This is the first question")
#<QUESTION #x30004373FEBD>
? (o-save *)
#<QUESTION #x30004373FEBD>
?
* indicates "last thing printed at the repl"
Now refresh your browser. Voila!
Add a few more Qs the same way. (Since we're using rlwrap remember to use the up arrow key to save typing!).
Also note that at this point the data/transaction.xml file is created since we've saved data to the default persistence store.
Okay, now we need an interface to actually add questions thru the browser.
That means forms+views, all that good stuff. We can also do this an alternate way, by hand-coding the forms..
The earlier demo prints some errors at the repl. In later versions of weblocks, functions that are used in lieu of widgets are best wrapped in make-widget forms, and the repl errors go away.
Now we move on to actually displaying a form (next commit).
Remember to do (ql:quickload "tut") followed by (weblocks:reset-sessions) and a browser refresh to see changes!
Okay, now we have a dialog in screen. It isn't ideal. Notice what happens when you add a question and hit refresh.. the background questions list is updated. But we have no way to dismiss the dialog.
Experiment with using do-page instead of do-dialog. (reset-sessions) will come in handy!
Now we add a on-cancel directive. The fn specified by on-cancel is given a widget and calling answer with any widget returns from the continuation started by do-dialog. But the cancel button is inconvenient and only appears in form-view in the pop up dialog...
Show only the fields we need to.
Fix the earlier problem: on-cancel works fine, but if we successfully submit the data, we'd like the dialog to disappear. Note that the new data does *not* show up on the page yet, we need a refresh to see it. We will fix this next.
A simple fix to refresh the root-widget. Also: goddamnit, why didn't I separate each clause out into its own line before. duh!
We want to sort questions in order of upvotes. So first we're going to need to fix the existing data, because the upvotes field contains the string 0 aka "0" and we need a number.
Quit lisp, restart it with something like ccl --load start-tut.lisp and then (tut::start-tut) to start weblocks. Finally do (tut::fix-data) if you have existing data.
Note that sorting can be done at the store level, we're just electing to do it explicitly. Also note that we default the title to an empty string.
And upvotes-of is a convenience accessor function created for us by defclass* and it is setf-able to boot.
Even though we don't use it, ensure that if a number is entered it'll be parsed and stored as an integer.
Change the layout a bit, add upvotes and downvotes, and add an explicit refresh button. Note that if everything had been a widget we wouldn't have required the explicit refresh. We will see that next.
Tables for layout? Get out of here!
Intermediate: rejigger everything. What we should really do is have subwidgets that update the page when upvotes/downvotes happen. Also it's usually expensive to query a store, so we should move that out of render-widget-body.