[Clean up source clinton@unknownlamer.org**20091208210047 Ignore-this: 14f2e925cf2f3bf457400ad39d189aee Of course, stupid me forgot to use `darcs mv' and just did the renames by hand... blech ] hunk ./beesknees.asd 12 - (:file "authentication" :depends-on ("packages")) - (:file "applications" :depends-on ("packages" "authentication")) - (:file "weblog" :depends-on ("packages")) - (:file "video-gallery" :depends-on ("packages")) - (:file "bee-page" :depends-on ("packages")) - (:file "image-manager" :depends-on ("packages")) - (:file "web-common" :depends-on ("packages" "bee-page")) - (:file "frontend-weblog" :depends-on ("packages" "weblog" "web-common")) - (:file "frontend-videos" :depends-on ("packages" "video-gallery" "web-common")) - (:file "web-frontend" :depends-on ("packages" "web-common" - "frontend-weblog" "frontend-videos")) - (:file "markdown-editor" :depends-on ("packages" "web-common")) - (:file "admin-common" :depends-on ("packages" "web-common")) - (:file "admin-videos" :depends-on ("packages" "admin-common" - "video-gallery")) - (:file "admin-weblog" :depends-on ("packages" "admin-common" - "markdown-editor" "weblog")) - (:file "web-admin" :depends-on ("packages" "admin-common" - "admin-weblog" "admin-videos" - "markdown-editor" "image-manager")) - (:file "site-control" :depends-on ("packages"))))) + (:module :core + :components ((:file "authentication") + (:file "applications" :depends-on ("authentication")) + (:file "site-control")) + :depends-on ("packages")) + (:module :video + :components ((:file "youtube")) + :depends-on ("packages")) + (:module :web + :components ((:file "bee-page") + (:file "common" :depends-on ("bee-page"))) + :depends-on ("packages")) + (:module :weblog + :components ((:file "core") + (:file "image-manager") + (:file "markdown-editor")) + :depends-on ("packages")) + (:module :admin + :components ((:file "common") + (:file "videos" :depends-on ("common")) + (:file "weblog" :depends-on ("common")) + (:file "web" :depends-on ("common" "weblog" + "videos"))) + :depends-on (:core :web :video :weblog)) + (:module :frontend + :components ((:file "weblog") + (:file "videos") + (:file "web" :depends-on ("weblog" "videos"))) + :depends-on (:core :web :video :weblog))))) adddir ./src/admin hunk ./src/admin-common.lisp 1 -(in-package :beesknees.web) - -(defcomponent bee-admin-pane (tabbed-pane) - ()) - -(defcomponent bee-admin-list (golgonooza:query-paged-view-mixin - golgonooza-db:elephant-query-view-mixin - golgonooza:query-view) - ()) - -(defmethod render ((list bee-admin-list)) - (<:ul (mapc (lambda (entry) - (<:li (golgonooza:render-query-view-result entry list))) - (golgonooza:current-items list)))) - -(defcomponent toplevel (task-component) - ((wrapped-class :initarg :wrap :accessor wrapped-class))) - -(defaction start ((c toplevel)) - (loop (call (wrapped-class c)))) - -(defclass image-selector-field (select-field) - ((path :initarg :image-directory :accessor image-directory-path)) - (:default-initargs :test-fn #'string=)) - -(defmethod ucw-forms:data-set ((field image-selector-field)) - (mapcar (lambda (p) - (format nil "~A.~A" (pathname-name p) - (pathname-type p))) - (directory (image-directory-path field)))) rmfile ./src/admin-common.lisp hunk ./src/admin-videos.lisp 1 -(in-package :beesknees.web) - -(define-html-form video-editor () - ((title (string-field :input-size 80 - :validators (make-validators 'not-empty-validator))) - (youtube-id (string-field :input-size 11 - :validators (make-validators 'not-empty-validator))) - (thumbnail (image-selector-field - :image-directory (merge-pathnames - "wwwroot/img/thumbnails/*.*" - beesknees.site-control::*bee-data-root*)))) - ((video :initarg :video :accessor edited-video :initform nil))) - -(defmethod initialize-instance :after ((editor video-editor) &rest keys) - (declare (ignore keys)) - (when-bind video (edited-video editor) - (with-slots (title youtube-id thumbnail) - editor - (setf (value title) (beesknees.videos:title video) - (value youtube-id) (beesknees.videos:youtube-id video) - (value thumbnail) (beesknees.videos:thumbnail video))))) - -(defaction process-form ((editor video-editor)) - (elephant:ensure-transaction () - (let ((video (or (edited-video editor) - (make-instance 'beesknees.videos:youtube-video)))) - (with-slots (title youtube-id thumbnail) - editor - (setf (beesknees.videos:title video) (value title) - (beesknees.videos:youtube-id video) (value youtube-id) - (beesknees.videos:thumbnail video) (value thumbnail))) - (answer video)))) - -(defcomponent video-list (bee-admin-list) - () - (:default-initargs - :index-class 'beesknees.videos:youtube-video - :index-slot 'beesknees.videos:youtube-id - :page-size 10 - :reverse t)) - -(defmethod golgonooza:render-query-view-result ((video beesknees.videos:youtube-video) - (list video-list)) - (html (bee-page) - (ensure-transaction () - (or (find-cached-markdown-output (golgonooza-db:object-hash bee-page)) - (cache-markdown-output! (golgonooza-db:object-hash bee-page) - (page-content bee-page))))) - rmfile ./src/bee-page.lisp adddir ./src/core addfile ./src/core/applications.lisp hunk ./src/core/applications.lisp 1 - +(in-package :beesknees.web) + +(defclass bee-application (standard-application + static-roots-application-mixin + tal-application-mixin + ucw::transactional-application-mixin + golgonooza-db:elephant-store-application-mixin) + + ()) + +(defclass bee-frontend-application (bee-application) + ()) + +(defclass bee-admin-application (bee-application + secure-application-mixin) + ()) + +(defmethod application-find-user ((app bee-admin-application) username) + (bee-auth:find-user username)) + +(defmethod application-check-password ((app bee-admin-application) user pass) + (bee-auth:check-password user pass)) addfile ./src/core/authentication.lisp hunk ./src/core/authentication.lisp 1 - +(in-package :beesknees.auth) + +(defpclass user () + ((username :initarg :username :accessor username :index t) + (password :initarg :password :accessor password))) + +(defmethod (setf password) (new-password (user user)) + (setf (slot-value user 'password) (md5:md5sum-sequence new-password))) + +(defun create-user (name password) + (make-instance 'user + :username name + :password (md5:md5sum-sequence password))) + +(defun find-user (name) + (get-instance-by-value 'user 'username name)) + +(defun check-password (user-or-name password) + (let ((user (typecase user-or-name + (user user-or-name) + (t (find-user user-or-name))))) + (and user (equalp (md5:md5sum-sequence password) (password user))))) addfile ./src/core/site-control.lisp hunk ./src/core/site-control.lisp 1 - +(in-package :beesknees.site-control) + +(defvar *bee-data-root* + "/home/clinton/local/var/beesknees/") + +(defclass bee-site (ucw-site elephant-store-site-mixin) + () + (:default-initargs + :data-root *bee-data-root* + :store-spec "bdb/")) + +(defmethod make-entry-points ((site bee-site)) + (defentry-point "^(index.ucw|)$" (:application (find-site-application site :frontend) + :class regexp-dispatcher) + () + (call 'bee-frontend-window)) + (defentry-point "^pages/blog/(\\d+)$" (:application (find-site-application site :frontend) + :class regexp-dispatcher) + () + (let ((window (make-instance 'beesknees.web:bee-frontend-window))) + (setf (container.current-component-key (window-body window)) + 'beesknees.web::blog) + (setf (golgonooza:page-offset (container.current-component + (window-body window))) + (- (golgonooza:page-count (container.current-component + (window-body window))) + (parse-integer (aref *dispatcher-registers* 0)))) + (call-component nil window))) + (defentry-point "^pages/blog/entry/(\\d+)$" (:application (find-site-application site :frontend) + :class regexp-dispatcher) + () + (let ((window (make-instance 'beesknees.web:bee-frontend-window))) + (setf (container.current-component-key (window-body window)) + 'beesknees.web::blog) + (setf (ucw-core::find-component (window-body window) + 'beesknees.web::blog) + (make-instance 'beesknees.web::weblog-entry-bookmark-helper + :posted (parse-integer (aref *dispatcher-registers* 0)) + :parent (window-body window))) + (call-component nil window))) + (defentry-point "^pages/videos/(\\S{11}?)$" (:application (find-site-application site :frontend) + :class regexp-dispatcher) + () + (let ((window (make-instance 'beesknees.web:bee-frontend-window))) + (setf (container.current-component-key (window-body window)) + 'beesknees.web::videos) + (setf (ucw-core::find-component (window-body window) + 'beesknees.web::videos) + (make-instance 'beesknees.web::video-bookmark-helper + :video-id (aref *dispatcher-registers* 0) + :parent (window-body window))) + (call-component nil window))) + (defentry-point "^pages/(\\w+)$" (:application (find-site-application site :frontend) + :class regexp-dispatcher) + () + (let ((page-name (aref *dispatcher-registers* 0)) + (window (make-instance 'beesknees.web:bee-frontend-window))) + (setf (container.current-component-key (window-body window)) + (intern (string-upcase page-name) :beesknees.web)) + (call-component nil window))) + + (defentry-point "^(index.ucw|)$" (:application (find-site-application site :backend) + :class regexp-dispatcher) + () + (call 'bee-admin-window))) + +(defvar *markdown-cache-size-limit* 50) +(defvar *markdown-cache-collector* nil) + +(defun markdown-cache-collector () + (let ((count (hash-table-count beesknees.pages::*markdown-output-cache*))) + (when (> count *markdown-cache-size-limit*) + (with-hash-table-iterator (next beesknees.pages::*markdown-output-cache*) + (dotimes (i (- count *markdown-cache-size-limit*)) + (multiple-value-bind (foundp key value) + (next) + (declare (ignore foundp value)) + (remhash key beesknees.pages::*markdown-output-cache*))))))) + +(defmethod start-site :before ((site bee-site)) + (setf *markdown-cache-collector* + (clon:schedule-function + #'markdown-cache-collector + (clon:make-scheduler (clon:make-typed-cron-schedule :hour '*)) + :thread t :name "markdown cache collector")) + (let* ((data-root (data-root site)) + (static-root (merge-pathnames "wwwroot/" data-root))) + (setf (applications site) + (list + (cons :frontend + (make-instance 'bee-frontend-application + :url-prefix "/" + :static-roots + (list `("static/" + . ,static-root)) + :tal-generator + (make-instance 'yaclml:file-system-generator + :cachep t + :root-directories `(,(format nil "~A~A" + data-root "tal/"))))) + (cons :backend + (make-instance 'bee-admin-application + :url-prefix "/admin/" + :static-roots + (list `("static/" + . ,static-root)))))))) + +(defmethod stop-site :after ((site bee-site)) + (when *markdown-cache-collector* + (trivial-timers:unschedule-timer *markdown-cache-collector*) + (setf *markdown-cache-collector* nil))) + +(defun start-bee-site () + (register-site 'beesknees (make-instance 'bee-site))) + +(defun stop-bee-site () + (unregister-site 'beesknees)) + +(defun restart-bee-site () + (stop-bee-site) + (start-bee-site)) adddir ./src/frontend hunk ./src/frontend-videos.lisp 1 -(in-package :beesknees.web) - -(defcomponent bee-videos-video (bee-video) - ()) - -(defmethod render :after ((vid bee-videos-video)) - ( count *markdown-cache-size-limit*) - (with-hash-table-iterator (next beesknees.pages::*markdown-output-cache*) - (dotimes (i (- count *markdown-cache-size-limit*)) - (multiple-value-bind (foundp key value) - (next) - (declare (ignore foundp value)) - (remhash key beesknees.pages::*markdown-output-cache*))))))) - -(defmethod start-site :before ((site bee-site)) - (setf *markdown-cache-collector* - (clon:schedule-function - #'markdown-cache-collector - (clon:make-scheduler (clon:make-typed-cron-schedule :hour '*)) - :thread t :name "markdown cache collector")) - (let* ((data-root (data-root site)) - (static-root (merge-pathnames "wwwroot/" data-root))) - (setf (applications site) - (list - (cons :frontend - (make-instance 'bee-frontend-application - :url-prefix "/" - :static-roots - (list `("static/" - . ,static-root)) - :tal-generator - (make-instance 'yaclml:file-system-generator - :cachep t - :root-directories `(,(format nil "~A~A" - data-root "tal/"))))) - (cons :backend - (make-instance 'bee-admin-application - :url-prefix "/admin/" - :static-roots - (list `("static/" - . ,static-root)))))))) - -(defmethod stop-site :after ((site bee-site)) - (when *markdown-cache-collector* - (trivial-timers:unschedule-timer *markdown-cache-collector*) - (setf *markdown-cache-collector* nil))) - -(defun start-bee-site () - (register-site 'beesknees (make-instance 'bee-site))) - -(defun stop-bee-site () - (unregister-site 'beesknees)) - -(defun restart-bee-site () - (stop-bee-site) - (start-bee-site)) + rmfile ./src/site-control.lisp adddir ./src/video hunk ./src/video-gallery.lisp 1 -(in-package :beesknees.videos) - -(defpclass youtube-video () - ((youtube-id :initarg :video-id :accessor youtube-id :index t) - (title :initarg :title :accessor title) - (thumbnail :initarg :thumbnail :initform nil :accessor thumbnail))) rmfile ./src/video-gallery.lisp addfile ./src/video/youtube.lisp hunk ./src/video/youtube.lisp 1 +(in-package :beesknees.videos) + +(defpclass youtube-video () + ((youtube-id :initarg :video-id :accessor youtube-id :index t) + (title :initarg :title :accessor title) + (thumbnail :initarg :thumbnail :initform nil :accessor thumbnail) + (description :initarg :description :initform nil :accessor description))) adddir ./src/web hunk ./src/web-admin.lisp 1 -(in-package :beesknees.web) - -(define-html-form page-editor (markdown-content-editor) - ((name (string-field :input-size 80 - :validators (make-validators 'not-empty-validator)))) - ((page :initarg :page :accessor edited-page :initform nil)) - (:default-initargs :field-order '(name content))) - -(defmethod initialize-instance :after ((editor page-editor) &rest keys) - (declare (ignore keys)) - (when-bind page (edited-page editor) - (with-slots (name content) - editor - (setf (value name) (symbol-name (page-name page)) - (value content) (page-content page))))) - -(defaction process-form ((editor page-editor)) - (elephant:ensure-transaction () - (let ((page (or (edited-page editor) - (make-instance 'bee-page)))) - (with-slots (name content) - editor - (setf (page-name page) (intern (string-upcase (value name)) :keyword) - (page-content page) (value content))) - (answer page)))) - -(defmethod render :after ((e page-editor)) - (html (get-instance-by-value 'bee-page - 'beesknees.pages::name - (page-name c))))) - -(defpclass bee-page-style () - ((name :initarg :name :accessor page-name :index t) - (background :initarg :background :initform nil :accessor page-background)) - (:index t)) - -(defcomponent bee-video (bee-widget) - ((video-id :initarg :video-id :accessor video-id))) - -(defmethod render ((video bee-video)) - (let ((id (ps:ps-gensym))) - (<:p :class "video-object" - :id id - (<:as-html "It would appear that you do not have flash.")) - (html (bee-page) + (ensure-transaction () + (or (find-cached-markdown-output (golgonooza-db:object-hash bee-page)) + (cache-markdown-output! (golgonooza-db:object-hash bee-page) + (page-content bee-page))))) + addfile ./src/web/common.lisp hunk ./src/web/common.lisp 1 +(in-package :beesknees.web) + +(defcomponent bee-window (standard-window-component) + () + (:default-initargs + :title "The Bee's Knees" + :stylesheet '("static/css/common.css"))) + +(defcomponent composite-container (html-block-element-mixin container) + () + (:default-initargs :css-class "ucw-composite-container")) + +(defmethod render ((container composite-container)) + (mapc (lambda (c) + (<:div :class (symbol-name (car c)) + (render (cdr c)))) + (container.contents container))) + +(defclass bee-widget (html-block-element-mixin) + () + (:documentation "Widget component that sets css-class to class-name by default")) + +(defmethod initialize-instance :after ((c bee-widget) + &rest keys) + (setf (html-element.css-class c) + (or (getf keys :css-class) + (string-downcase (symbol-name (class-name (class-of c))))))) + +(defcomponent bee-page-component (bee-widget) + ((name :initarg :name :accessor page-name) + (hash :initform nil :accessor page-hash))) + +(defmethod render ((c bee-page-component)) + (<:as-is (page->html (get-instance-by-value 'bee-page + 'beesknees.pages::name + (page-name c))))) + +(defpclass bee-page-style () + ((name :initarg :name :accessor page-name :index t) + (background :initarg :background :initform nil :accessor page-background)) + (:index t)) + +(defcomponent bee-video (bee-widget) + ((video-id :initarg :video-id :accessor video-id))) + +(defmethod render ((video bee-video)) + (let ((id (ps:ps-gensym))) + (<:p :class "video-object" + :id id + (<:as-html "It would appear that you do not have flash.")) + (