git.fiddlerwoaroof.com
Browse code

initial --- models done ? init view

fiddlerwoaroof authored on 30/01/2016 06:39:40
Showing 6 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.*.swp
0 2
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+This is the stub README.txt for the "timesheet" project.
0 2
new file mode 100644
... ...
@@ -0,0 +1,126 @@
1
+
2
+(in-package :timesheet.mvc)
3
+
4
+(defclass model () ())
5
+
6
+(defclass view () ())
7
+
8
+(defclass controller () ())
9
+
10
+(defclass event () ())
11
+
12
+(defgeneric operate (controller model event))
13
+(defgeneric model-changed (model receiver))
14
+
15
+(defclass client (model)
16
+  ((name :initarg :name)
17
+   (projects :initarg :projects :initform nil)))
18
+
19
+(defun make-client (name)
20
+  (make-instance 'client :name name))
21
+
22
+(defun normalize-name (name)
23
+  (string-capitalize name))
24
+
25
+(defparameter *clients* nil)
26
+(defun make-or-retrieve-client (name)
27
+  (let ((name (normalize-name name)))
28
+    (cdr (or (assoc name *clients* :test #'string=)
29
+             (car (push (cons name (make-client name)) *clients*))))))
30
+
31
+(defclass project-description (model)
32
+  ((client :initarg :client :type 'client)
33
+   (note :initarg :note :initform "")))
34
+
35
+(defun make-project-description (client-name note)
36
+  (make-instance 'project-description
37
+                 :client (make-or-retrieve-client client-name)
38
+                 :note note))
39
+
40
+(defclass generic-log (model)
41
+  ((entries :initarg :entries :initform nil)))
42
+
43
+(defgeneric most-recent-entry (container)
44
+  (:method ((container log-entry))
45
+   (with-slots (entries) container
46
+     (car entries))))
47
+
48
+(defclass generic-log-entry (model) ())
49
+
50
+(defun %add-entry (container entry)
51
+  (push entry (slot-value container 'entries)))
52
+
53
+(defgeneric add-entry (log entry))
54
+
55
+(defclass time-log (generic-log)
56
+  ((date :initarg :date :initform (local-time:today))))
57
+
58
+(defun make-time-log (&optional date)
59
+  (make-instance 'time-log :date (or date (local-time:today))))
60
+
61
+(defclass time-span (model)
62
+  ((start :initarg :start :initform (local-time:now))
63
+   (end :initarg :end)))
64
+
65
+(defclass time-log-entry (generic-log)
66
+  ((description :initarg :description :type 'project-description)))
67
+
68
+(defmethod add-entry ((time-log-entry time-log-entry) (entry time-span))
69
+  (%add-entry time-log-entry entry))
70
+
71
+(defmethod add-entry ((time-log time-log) (entry time-log-entry))
72
+  (%add-entry time-log entry))
73
+
74
+(defclass work-log (generic-log)
75
+  ((title :initarg :title :initform "")
76
+   (user :initarg :user :initform "")))
77
+
78
+(defmethod add-entry ((work-log work-log) (entry time-log))
79
+  (%add-entry work-log entry))
80
+
81
+(defun make-work-log (title user)
82
+  (make-instance 'work-log :title title :user user))
83
+
84
+
85
+;; VIEW
86
+
87
+(defgeneric display (model view output))
88
+
89
+(defclass log-view (view) ())
90
+
91
+(defmethod display ((model work-log) (view log-view) (output stream))
92
+  (let ((spinneret:*html* output))
93
+    (with-slots (title user entries) model
94
+      (spinneret:with-html
95
+        (:html
96
+          (:head
97
+            (:title (format nil "~a: ~a" user title)))
98
+          (:body
99
+            (:h1 title)
100
+            (:ul.work-log
101
+              (loop for time-log in entries
102
+                    do (with-slots (date entries) time-log
103
+                         (spinneret:with-html
104
+                           (:li
105
+                             (:div.date date)
106
+                             (:ul.time-entries
107
+                               (:li.time-span
108
+                                 (loop for time-entry in entries
109
+                                       do (with-slots (description entries) time-entry
110
+                                            (spinneret:with-html
111
+                                              (:div.description
112
+                                                (loop for time-entry in entries
113
+                                                      do (with-slots (start end) time-entry
114
+                                                           (:div.timespan
115
+                                                             (:span.start (format nil "~a" start))
116
+                                                             (when end
117
+                                                               (:span.end (format nil "~a" end))))))
118
+                                                (with-slots (client note) description
119
+                                                  (spinneret:with-html
120
+                                                    (:span.name (with-slots (name) client
121
+                                                                  (format nil "~a:" name)))
122
+                                                    (:span.note note))))))))))))))))))))
123
+
124
+(defmethod display (model view (output (eql nil)))
125
+  (with-output-to-string (s)
126
+    (display model view s)))
0 127
new file mode 100644
... ...
@@ -0,0 +1,8 @@
1
+;;;; package.lisp
2
+
3
+(defpackage #:timesheet
4
+  (:use #:cl))
5
+
6
+(defpackage #:timesheet.mvc
7
+  (:use #:cl #:anaphora #:alexandria #:serapeum)
8
+  (:export #:model #:view #:controller #:display #:operate #:has-changed))
0 9
new file mode 100644
... ...
@@ -0,0 +1,19 @@
1
+;;;; timesheet.asd
2
+
3
+(asdf:defsystem #:timesheet
4
+  :description "Describe timesheet here"
5
+  :author "fiddlerwoaroof"
6
+  :license "MIT"
7
+  :depends-on (#:alexandria
8
+               #:serapeum
9
+               #:anaphora
10
+               #:ningle
11
+               #:spinneret
12
+               )
13
+  :serial t
14
+  :components ((:file "package")
15
+               (:file "mvc")
16
+               (:file "timesheet")))
17
+
18
+
19
+;; vim: set ft=lisp:
0 20
new file mode 100644
... ...
@@ -0,0 +1,6 @@
1
+;;;; timesheet.lisp
2
+
3
+(in-package #:timesheet)
4
+
5
+;;; "timesheet" goes here. Hacks and glory await!
6
+