[claw-cvs] r104 - trunk/main/claw-demo/src/frontend/components

achiumenti at common-lisp.net achiumenti at common-lisp.net
Wed Oct 1 12:00:41 UTC 2008


Author: achiumenti
Date: Wed Oct  1 08:00:39 2008
New Revision: 104

Added:
   trunk/main/claw-demo/src/frontend/components/
   trunk/main/claw-demo/src/frontend/components/djconfirmation-submit.lisp
   trunk/main/claw-demo/src/frontend/components/edit-customer.lisp
   trunk/main/claw-demo/src/frontend/components/pager.lisp
   trunk/main/claw-demo/src/frontend/components/redirect.lisp
   trunk/main/claw-demo/src/frontend/components/site-template.lisp
   trunk/main/claw-demo/src/frontend/components/translator-threestate.lisp
Log:
several bugfixes and enhancements

Added: trunk/main/claw-demo/src/frontend/components/djconfirmation-submit.lisp
==============================================================================
--- (empty file)
+++ trunk/main/claw-demo/src/frontend/components/djconfirmation-submit.lisp	Wed Oct  1 08:00:39 2008
@@ -0,0 +1,66 @@
+;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*-
+;;; $Header: src/frontend/components/djconfirmation-submit.lisp $
+
+;;; Copyright (c) 2008, Andrea Chiumenti.  All rights reserved.
+
+;;; Redistribution and use in source and binary forms, with or without
+;;; modification, are permitted provided that the following conditions
+;;; are met:
+
+;;;   * Redistributions of source code must retain the above copyright
+;;;     notice, this list of conditions and the following disclaimer.
+
+;;;   * Redistributions in binary form must reproduce the above
+;;;     copyright notice, this list of conditions and the following
+;;;     disclaimer in the documentation and/or other materials
+;;;     provided with the distribution.
+
+;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
+;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+;;; ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+(in-package :claw-demo-frontend)
+
+(defclass djconfirmation-submit (wcomponent)
+  ((value :initarg :value
+          :accessor djconfirmation-submit-value)
+   (action :initarg :action
+           :accessor djconfirmation-submit-action)
+   (confirmation-message :initarg :confirmation-message
+                         :accessor djconfirmation-submit-confirmation-message)
+   (yes-label :initarg :yes
+              :accessor djconfirmation-submit-yes)
+   (no-label :initarg :no
+              :accessor djconfirmation-submit-no))
+  (:default-initargs :yes "Yes" :no "No")
+  (:metaclass metacomponent))
+
+(defmethod wcomponent-template ((obj djconfirmation-submit))
+  (let* ((dialog-id (generate-id "confirmationDiaolg"))
+         (yes-id (generate-id "yes"))
+         (value (djconfirmation-submit-value obj)))
+    (div> :class "dijit dijitReset dijitLeft dijitInline"
+     (djbutton> :static-id (htcomponent-client-id obj)
+                :on-click (ps:ps* `(.show (dijit.by-id ,dialog-id)))
+                (wcomponent-informal-parameters obj)
+                (or  (htcomponent-body obj) value))
+     (djdialog> :static-id dialog-id
+                :title "Confirm"
+                (div> (djconfirmation-submit-confirmation-message obj)
+                      (div> :class "buttonContainer"
+                            (djsubmit-button> :static-id yes-id
+                                              :value (djconfirmation-submit-value obj)
+                                              :action (djconfirmation-submit-action obj)
+                                              :on-click (ps:ps* `(.hide (dijit.by-id ,dialog-id)))
+                                              (djconfirmation-submit-yes obj))
+                            (djbutton> :id dialog-id
+                                       :on-click (ps:ps* `(.hide (dijit.by-id ,dialog-id)))
+                                       (djconfirmation-submit-no obj))))))))
\ No newline at end of file

Added: trunk/main/claw-demo/src/frontend/components/edit-customer.lisp
==============================================================================
--- (empty file)
+++ trunk/main/claw-demo/src/frontend/components/edit-customer.lisp	Wed Oct  1 08:00:39 2008
@@ -0,0 +1,319 @@
+;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*-
+;;; $Header: components/edit-customer.lisp $
+
+;;; Copyright (c) 2008, Andrea Chiumenti.  All rights reserved.
+
+;;; Redistribution and use in source and binary forms, with or without
+;;; modification, are permitted provided that the following conditions
+;;; are met:
+
+;;;   * Redistributions of source code must retain the above copyright
+;;;     notice, this list of conditions and the following disclaimer.
+
+;;;   * Redistributions in binary form must reproduce the above
+;;;     copyright notice, this list of conditions and the following
+;;;     disclaimer in the documentation and/or other materials
+;;;     provided with the distribution.
+
+;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
+;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+;;; ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+(in-package :claw-demo-frontend)
+
+(defgeneric edit-customer-save (edit-customer))
+
+(defclass edit-customer (djform)
+  ((customer :initarg :customer
+             :accessor edit-customer-customer)
+   (customer-id-parameter :initarg :customer-id-parameter
+                          :accessor edit-customer-customer-id-parameter)
+   (on-close-click :initarg :on-close-click
+                   :accessor edit-customer-on-close-click))
+  (:metaclass metacomponent)
+  (:default-initargs :on-close-click nil
+    :class "customerForm" :customer-id-parameter "customerid"))
+
+(defmethod initialize-instance :after ((obj edit-customer) &key rest)
+  (declare (ignore rest))
+  (setf (action-object obj) obj
+        (action obj) 'edit-customer-save))
+
+(defun find-or-add-address (customer address-type)
+  (let ((address (loop for item in (customer-addresses customer)
+                    when (= (customer-address-type item) address-type)
+                    return item)))
+    (unless address
+      (setf address (make-instance 'customer-address :address-type address-type))
+      (push address (customer-addresses customer)))
+    address))
+
+(defun address-nullp (address)
+  (let ((attributes (list (customer-address-address address)
+                          (customer-address-zip address)
+                          (customer-address-city address)
+                          (customer-address-state address)
+                          (customer-address-country address))))
+    (not
+     (loop for val in (mapcar #'(lambda (x)
+                                  (when (and x (string-not-equal x ""))
+                                    t))
+                              attributes)
+        when val
+        return t))))
+
+(defmethod htcomponent-class-initscripts :around ((obj edit-customer))
+  (let ((req-function (ps:ps (defun is-address-field-required (container-id)
+                               (defvar input-list (dojo.query "[widgetId]" (dojo.by-id container-id)))
+                               (defvar result false)
+                               (dojo.for-each (.map input-list (slot-value dijit 'by-node))
+                                              (lambda (input) (when (.get-value input) (setf result t))))
+                               (return result))))
+        (address-field-validation (ps:ps (progn
+                                           (defun address-field-validation-init (component-id address-container-class)
+                                             (dojo.for-each (dojo.query (+ "." address-container-class) (dojo.by-id component-id))
+                                                            (lambda (main-address-node)
+                                                              (dojo.for-each (.map (dojo.query "[widgetId]" main-address-node)  dijit.by-node)
+                                                                             (lambda (widget)
+                                                                               (setf (slot-value widget 'is-valid) (lambda (is-focused)
+                                                                                                                     (address-field-validation widget (slot-value main-address-node 'id))
+                                                                                                                     (return (.validator widget (slot-value (slot-value widget 'textbox) 'value)
+                                                                                                                                         (slot-value widget 'constraints))))))))))
+                                           (defun address-field-validation (sender container-id)
+                                             (if (is-address-field-required container-id)
+                                                 (unless (= (slot-value sender 'required) t)
+                                                   (defvar input-list (dojo.query "[widgetId]" (dojo.by-id container-id)))
+                                                   (dojo.for-each (.map input-list dijit.by-node)
+                                                                  (lambda (input-widget) (setf (slot-value input-widget 'required) t))))
+                                                 (unless (!= (slot-value sender 'required) t)
+                                                   (defvar input-list (dojo.query "[widgetId]" (dojo.by-id container-id)))
+                                                   (dojo.for-each (.map input-list dijit.by-node)
+                                                                  (lambda (input-widget) (setf (slot-value input-widget 'required) false))))))))))
+    (append (list req-function address-field-validation) (call-next-method))))
+
+(defmethod htcomponent-instance-initscript :around ((obj edit-customer))
+  (let* ((component-id (htcomponent-client-id obj))
+         (parent-script (call-next-method))
+         (script (ps:ps* `(progn
+                            (address-field-validation-init ,component-id "mainAddress")
+                            (address-field-validation-init ,component-id "billingAddress")))))
+    (if parent-script
+        (format nil "~a~%~a" parent-script script)
+        script)))
+
+(defmethod htcomponent-body ((obj edit-customer))
+  (let* ((visit-object (edit-customer-customer obj))
+         (main-address (find-or-add-address visit-object 0))
+         (billing-address (find-or-add-address visit-object 1))
+         (main-address-id (generate-id "mainAddress"))
+         (billing-address-id (generate-id "billingAddress"))
+         (address-1-id (generate-id "address"))
+         (zip-1-id (generate-id "zip"))
+         (city-1-id (generate-id "city"))
+         (state-1-id (generate-id "state"))
+         (country-1-id (generate-id "country"))
+         (address-2-id (generate-id "address"))
+         (zip-2-id (generate-id "zip"))
+         (city-2-id (generate-id "city"))
+         (state-2-id (generate-id "state"))
+         (country-2-id (generate-id "country")))
+    (list
+     (cinput> :id (edit-customer-customer-id-parameter obj)
+              :type "hidden" :visit-object visit-object
+              :translator *integer-translator*
+              :accessor 'table-id)
+     (cinput> :id "tabbleVersion"
+              :type "hidden"
+              :visit-object visit-object
+              :translator *integer-translator*
+              :accessor 'table-version)
+     (div> :class "label name1"
+           (span> "Name 1")
+           (djvalidation-text-box> :visit-object visit-object
+                                   :required "true"
+                                   :label "Name 1"
+                                   :accessor 'customer-name1))
+     (div> :class "label name2"
+           (span> "Name 2")
+           (djvalidation-text-box> :visit-object visit-object
+                                   :label "Name 2"
+                                   :accessor 'customer-name2))
+     (div> :class "label email"
+           (span> "Email")
+           (djvalidation-text-box> :visit-object visit-object
+                                   :label "Email"
+                                   :accessor 'customer-email))
+     (div> :class "label pone1"
+           (span> "Phone 1")
+           (djvalidation-text-box> :visit-object visit-object
+                                   :label "Phone 1"
+                                   :accessor 'customer-phone1))
+     (div> :class "label pone2"
+           (span> "Phone 2")
+           (djvalidation-text-box> :visit-object visit-object
+                                   :label "Phone 2"
+                                   :accessor 'customer-phone2))
+     (div> :class "label pone3"
+           (span> "Phone 3")
+           (djvalidation-text-box> :visit-object visit-object
+                                   :label "Phone 3"
+                                   :accessor 'customer-phone3))
+     (div> :class "label fax"
+           (span> "Fax")
+           (djvalidation-text-box> :visit-object visit-object
+                                   :label "Fax"
+                                   :accessor 'customer-fax))
+     (div> :class "label vat"
+           (span> "VAT")
+           (djvalidation-text-box> :visit-object visit-object
+                                   :label "VAT"
+                                   :accessor 'customer-vat))
+     (div> :class "label code1"
+           (span> "Code 1")
+           (djvalidation-text-box> :visit-object visit-object
+                                   :label "Code 1"
+                                   :accessor 'customer-code1))
+     (div> :class "label code2"
+           (span> "Code 2")
+           (djvalidation-text-box> :visit-object visit-object
+                                   :label "Code 2"
+                                   :accessor 'customer-code2))
+     (div> :class "label code3"
+           (span> "Code 3")
+           (djvalidation-text-box> :visit-object visit-object
+                                   :label "Code 3"
+                                   :accessor 'customer-code3))
+     (div> :class "label code4"
+           (span> "Code 4")
+           (djvalidation-text-box> :visit-object visit-object
+                                   :label "Code 4"
+                                   :accessor 'customer-code4))
+     (djtab-container> :id "addressTabs"
+                       :class "addressTabs"
+                       (djcontent-pane> :static-id main-address-id :class "mainAddress" :title "Main address"
+                                        (div> (div> :class "address"
+                                                    (span> :class "label" "Street")
+                                                    (djvalidation-text-box> :static-id address-1-id
+                                                                            :trim "true"
+                                                                            :visit-object main-address
+                                                                            :class "text"
+                                                                            :label "Main Address[address]"
+                                                                            :accessor 'customer-address-address))
+                                              (div> :class "zip"
+                                                    (span> :class "label" "Zip")
+                                                    (djvalidation-text-box> :static-id zip-1-id
+                                                                            :trim "true"
+                                                                            :visit-object main-address
+                                                                            :class "text"
+                                                                            :label "Main Address[zip]"
+                                                                            :accessor 'customer-address-zip))
+                                              (div> :class "city"
+                                                    (span> :class "label" "City")
+                                                    (djvalidation-text-box> :static-id city-1-id
+                                                                            :trim "true"
+                                                                            :visit-object main-address
+                                                                            :class "text"
+                                                                            :label "Main Address[city]"
+                                                                            :accessor 'customer-address-city))
+                                              (div> :class "state"
+                                                    (span> :class "label" "State")
+                                                    (djvalidation-text-box> :static-id state-1-id
+                                                                            :trim "true"
+                                                                            :visit-object main-address
+                                                                            :class "text"
+                                                                            :label "Main Address[state]"
+                                                                            :accessor 'customer-address-state))
+                                              (div> :class "country"
+                                                    (span> :class "label" "Country")
+                                                    (djvalidation-text-box> :static-id country-1-id
+                                                                            :trim "true"
+                                                                            :visit-object main-address
+                                                                            :class "text"
+                                                                            :label "Main Address[country]"
+                                                                            :accessor 'customer-address-country))))
+                       (djcontent-pane> :static-id billing-address-id :class "billingAddress" :title "Billing address"
+                                        (div> (div> :class "address"
+                                                    (span> :class "label" "Street")
+                                                    (djvalidation-text-box> :static-id address-2-id
+                                                                            :trim "true"
+                                                                            :visit-object billing-address
+                                                                            :class "text"
+                                                                            :label "Billing Address[street]"
+                                                                            :accessor 'customer-address-address))
+                                              (div> :class "zip"
+                                                    (span> :class "label" "Zip")
+                                                    (djvalidation-text-box> :static-id zip-2-id
+                                                                            :trim "true"
+                                                                            :visit-object billing-address
+                                                                            :class "text"
+                                                                            :label "Billing Address[zip]"
+                                                                            :accessor 'customer-address-zip))
+                                              (div> :class "city"
+                                                    (span> :class "label" "City")
+                                                    (djvalidation-text-box> :static-id city-2-id
+                                                                            :trim "true"
+                                                                            :visit-object billing-address
+                                                                            :class "text"
+                                                                            :label "Billing Address[city]"
+                                                                            :accessor 'customer-address-city))
+                                              (div> :class "state"
+                                                    (span> :class "label" "State")
+                                                    (djvalidation-text-box> :static-id state-2-id
+                                                                            :trim "true"
+                                                                            :visit-object billing-address
+                                                                            :class "text"
+                                                                            :label "Billing Address[state]"
+                                                                            :accessor 'customer-address-state))
+                                              (div> :class "country"
+                                                    (span> :class "label" "Country")
+                                                    (djvalidation-text-box> :static-id country-2-id
+                                                                            :trim "true"
+                                                                            :visit-object billing-address
+                                                                            :class "text"
+                                                                            :label "Billing Address[country]"
+                                                                            :accessor 'customer-address-country)))))
+     (div> :class "buttons"
+           (djsubmit-button> :value "Save")
+           (djbutton> :render-condition #'(lambda () (edit-customer-on-close-click obj))
+                      :id "Close"
+                      :on-click (edit-customer-on-close-click obj)
+                      "Close")))))
+
+
+(defmethod wcomponent-before-rewind :before ((obj edit-customer) (page page))
+  (when (string-equal (htcomponent-client-id obj) (claw-parameter *rewind-parameter*))
+    (let ((customer-id (parse-integer (claw-parameter (edit-customer-customer-id-parameter obj)))))
+      (setf (edit-customer-customer obj)
+            (find-by-id 'customer
+                        customer-id))
+      (find-or-add-address (edit-customer-customer obj) 0)
+      (find-or-add-address (edit-customer-customer obj) 1))))
+
+(defmethod edit-customer-save ((obj edit-customer))
+  (let ((id (htcomponent-client-id obj))
+        (customer (edit-customer-customer obj))
+        (main-address (find-or-add-address (edit-customer-customer obj) 0))
+        (billing-address (find-or-add-address (edit-customer-customer obj) 1))
+        (address-list ()))
+    (handler-case
+        (progn
+          (log-message :info "PHONE: ~a" (customer-phone1 customer))
+          (unless (address-nullp main-address)
+            (push main-address address-list))
+          (unless (address-nullp billing-address)
+            (push billing-address address-list))
+          (setf (customer-addresses customer) address-list)
+          (update-db-item customer))
+      (clsql-sys:sql-database-error (cond)
+        (log-message :info "Exception on edit-customer-save: ~a" cond)
+        (add-validation-error id (clsql-sys:sql-error-database-message cond))
+        nil))))
+

Added: trunk/main/claw-demo/src/frontend/components/pager.lisp
==============================================================================
--- (empty file)
+++ trunk/main/claw-demo/src/frontend/components/pager.lisp	Wed Oct  1 08:00:39 2008
@@ -0,0 +1,142 @@
+;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*-
+;;; $Header: src/frontend/components/pager.lisp $
+
+;;; Copyright (c) 2008, Andrea Chiumenti.  All rights reserved.
+
+;;; Redistribution and use in source and binary forms, with or without
+;;; modification, are permitted provided that the following conditions
+;;; are met:
+
+;;;   * Redistributions of source code must retain the above copyright
+;;;     notice, this list of conditions and the following disclaimer.
+
+;;;   * Redistributions in binary form must reproduce the above
+;;;     copyright notice, this list of conditions and the following
+;;;     disclaimer in the documentation and/or other materials
+;;;     provided with the distribution.
+
+;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
+;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+;;; ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+(in-package :claw-demo-frontend)
+
+(defgeneric pager-count-pages (pager))
+
+(defgeneric pager-current-page (pager))
+
+(defgeneric pager-page-list (pager))
+
+(defgeneric set-offset-value (pager page))
+
+(defclass pager (wcomponent)
+  ((update-component-id :initarg :update-component-id
+                        :accessor pager-update-component-id)
+   (class :initarg :class
+          :reader pager-class)
+   (page-size :initarg :page-size
+              :reader pager-page-size)
+   (visible-pages :initarg :visible-pages
+                  :accessor pager-visible-pages)
+   (total-items :initarg :total-items
+                :accessor pager-total-items)
+   (first-item-offset :initarg :first-item-offset
+                      :accessor pager-first-item-offset))
+  (:metaclass metacomponent)
+  (:default-initargs :page-size 10 :visible-pages 10 :class "pager"))
+
+(defmethod wcomponent-template ((pager pager))
+  (let ((total-items (pager-total-items pager))
+        (page-size (pager-page-size pager))
+        (page-list (pager-page-list pager))
+        (current-page (pager-current-page pager))
+        (count-pages (pager-count-pages pager))
+        (id (htcomponent-client-id pager)))
+    (when (> total-items page-size)
+      (div>
+       :static-id id
+       :class (pager-class pager)
+       (wcomponent-informal-parameters pager)
+
+       (when (> current-page 1)
+         (list (div> :class "button first"
+                     (span> :on-click (set-offset-value pager 1) "first"))
+               (div> :class "button previous"
+                     (span> :on-click (set-offset-value pager (1- current-page)) "previous"))))
+       (loop for page in page-list
+          collect (if (= page current-page)
+                      (div> :class "current page"
+                            (span> (format nil "~a" page)))
+                      (div> :class "page" (span> :on-click (set-offset-value pager page) (format nil "~a" page)))))
+       (when (< current-page count-pages)
+         (list (div> :class "button next"
+                     (span> :on-click (set-offset-value pager (1+ current-page)) "next"))
+               (div> :class "button last"
+                     (span> :on-click (set-offset-value pager count-pages) "last"))))))))
+
+(defmethod htcomponent-class-initscripts ((pager pager))
+  (let ((update-component-id (pager-update-component-id pager))
+        (page-size (pager-page-size pager)))
+    (list
+     (ps:ps* `(defun pager-go-to (page)
+                (setf (slot-value (dojo.by-id ,update-component-id) 'value) (* (1- page) ,page-size))
+                (defvar form-id (slot-value (slot-value (dojo.by-id ,update-component-id) 'form) 'id))
+                (let ((form-el (or (dijit.by-id form-id) 
+                                   (dojo.by-id form-id))))
+                  (.submit form-el)))))))
+
+(defmethod set-offset-value ((pager pager) page)
+  (ps:ps* `(pager-go-to ,page)))
+
+(defmethod pager-count-pages ((pager pager))
+  (let ((page-size (pager-page-size pager))
+        (total-items (pager-total-items pager)))
+    (count-pages page-size total-items)))
+
+(defun count-pages (page-size total-items)
+  (multiple-value-bind (pages rest)
+      (truncate total-items page-size)
+    (when (> rest 0) (incf pages))
+    pages))
+
+(defmethod pager-current-page ((pager pager))
+  (let ((page-size (pager-page-size pager))
+        (first-item-offset (pager-first-item-offset pager)))
+    (multiple-value-bind (page rest)
+        (truncate (1+ first-item-offset) page-size)
+      (when (> rest 0) (incf page))
+      page)))
+
+(defmethod pager-page-list ((pager pager))
+  (let ((current-page (pager-current-page pager))
+        (count-pages (pager-count-pages pager))
+        (visible-pages (pager-visible-pages pager))
+        (pages-before-current-page)
+        (pages-after-current-page)
+        (result))
+    (when (> current-page 1)
+      (setf pages-before-current-page
+            (reverse
+             (loop for page from (1- current-page) downto (max 1 (- current-page 
+                                                                    (truncate visible-pages 2)))
+                collect page))))
+    (when (< current-page count-pages)
+      (setf pages-after-current-page
+            (loop for page from (1+ current-page) to (min count-pages (+ (1- current-page) 
+                                                                         (- visible-pages (length pages-before-current-page))))
+               collect page)))
+    (setf result (append pages-before-current-page (list current-page) pages-after-current-page))
+    (let ((result-length (length result))
+          (first-result-page (first result)))
+      (if (< result-length visible-pages)
+          (append (reverse (loop for page from (1- first-result-page) downto (max 1 (- first-result-page (- visible-pages result-length)))
+                              collect page)) result)
+          result))))
\ No newline at end of file

Added: trunk/main/claw-demo/src/frontend/components/redirect.lisp
==============================================================================
--- (empty file)
+++ trunk/main/claw-demo/src/frontend/components/redirect.lisp	Wed Oct  1 08:00:39 2008
@@ -0,0 +1,41 @@
+;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*-
+;;; $Header: src/frontend/components/redirect.lisp $
+
+;;; Copyright (c) 2008, Andrea Chiumenti.  All rights reserved.
+
+;;; Redistribution and use in source and binary forms, with or without
+;;; modification, are permitted provided that the following conditions
+;;; are met:
+
+;;;   * Redistributions of source code must retain the above copyright
+;;;     notice, this list of conditions and the following disclaimer.
+
+;;;   * Redistributions in binary form must reproduce the above
+;;;     copyright notice, this list of conditions and the following
+;;;     disclaimer in the documentation and/or other materials
+;;;     provided with the distribution.
+
+;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
+;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+;;; ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+(in-package :claw-demo-frontend)
+
+(defclass redirect (wcomponent)
+  ((href :initarg :href
+         :reader redirect-href))
+  (:metaclass metacomponent))
+
+(defmethod htcomponent-instance-initscript ((redirect redirect))
+  (ps:ps* `(location.replace ,(redirect-href redirect))))
+
+(defmethod wcomponent-template ((redirect redirect))
+  ($> ""))

Added: trunk/main/claw-demo/src/frontend/components/site-template.lisp
==============================================================================
--- (empty file)
+++ trunk/main/claw-demo/src/frontend/components/site-template.lisp	Wed Oct  1 08:00:39 2008
@@ -0,0 +1,78 @@
+;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*-
+;;; $Header: src/frontend/components/site-template.lisp $
+
+;;; Copyright (c) 2008, Andrea Chiumenti.  All rights reserved.
+
+;;; Redistribution and use in source and binary forms, with or without
+;;; modification, are permitted provided that the following conditions
+;;; are met:
+
+;;;   * Redistributions of source code must retain the above copyright
+;;;     notice, this list of conditions and the following disclaimer.
+
+;;;   * Redistributions in binary form must reproduce the above
+;;;     copyright notice, this list of conditions and the following
+;;;     disclaimer in the documentation and/or other materials
+;;;     provided with the distribution.
+
+;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
+;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+;;; ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+(in-package :claw-demo-frontend)
+
+(defclass site-template (wcomponent)
+  ((title :initarg :title
+          :reader site-template-title)
+   (djconfig :initarg :djconfig
+             :reader site-template-djconfig))
+  (:metaclass metacomponent)
+  (:default-initargs :djconfig nil))
+
+(defmethod wcomponent-template ((site-template site-template))
+  (let ((principal (current-principal)))
+    (html>
+     (head>
+      (title> (site-template-title site-template))
+      (link> :href (format nil "~a/docroot/css/style.css" *root-path*)
+             :rel "stylesheet"
+             :type "text/css"))
+     (djbody> :is-debug "false"
+              :theme "soria"
+              :class "demo"
+              :djconfig (site-template-djconfig site-template)
+              (wcomponent-informal-parameters site-template)
+              (div> :class "topheader"
+                    (div> :class "logoDemo")
+                    (div> :class "logoClaw"))
+              (djtoolbar> :id "menuBar" :class "menuBar"
+                          (djdrop-down-button> (span> "File")
+                                               (djmenu>
+                                                (djmenu-item> :id "loginMenu"
+                                                              :render-condition #'(lambda () (null principal))
+                                                              :on-click (ps:ps* `(location.replace ,(format nil "~a/login.html" *root-path*)))
+                                                              "Login")
+                                                (djmenu-item> :id "logoutMenu"
+                                                              :render-condition #'(lambda () principal)
+                                                              :on-click (ps:ps* `(location.replace ,(format nil "~a/logout.html" *root-path*)))
+                                                              "Logout")))
+                          (djdrop-down-button> :render-condition #'(lambda () principal)
+                                               (span> "Anagraphics")
+                                               (djmenu>
+                                                (djmenu-item> :id "customersMenu"
+                                                              :on-click (ps:ps* `(location.replace ,(format nil "~a/customers.html" *root-path*)))
+                                                              "Customers")
+                                                (djmenu-item> :id "usersMenu"
+                                                              :render-condition #'(lambda () (user-in-role-p '("administrator")))
+                                                              :on-click (ps:ps* `(location.replace ,(format nil "~a/users.html" *root-path*)))
+                                                              "Users"))))
+              (div> :class "contentBody"
+                    (htcomponent-body site-template))))))
\ No newline at end of file

Added: trunk/main/claw-demo/src/frontend/components/translator-threestate.lisp
==============================================================================
--- (empty file)
+++ trunk/main/claw-demo/src/frontend/components/translator-threestate.lisp	Wed Oct  1 08:00:39 2008
@@ -0,0 +1,66 @@
+;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*-
+;;; $Header: src/frontend/components/translator-threestate.lisp $
+
+;;; Copyright (c) 2008, Andrea Chiumenti.  All rights reserved.
+
+;;; Redistribution and use in source and binary forms, with or without
+;;; modification, are permitted provided that the following conditions
+;;; are met:
+
+;;;   * Redistributions of source code must retain the above copyright
+;;;     notice, this list of conditions and the following disclaimer.
+
+;;;   * Redistributions in binary form must reproduce the above
+;;;     copyright notice, this list of conditions and the following
+;;;     disclaimer in the documentation and/or other materials
+;;;     provided with the distribution.
+
+;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
+;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+;;; ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+(in-package :claw-demo-frontend)
+
+(defclass translator-threestate (translator)
+  ((yes :initarg :yes
+              :reader translator-threestate-yes)
+   (no :initarg :no
+              :reader translator-threestate-no)
+   (any :initarg :any
+              :reader translator-threestate-any)
+   (yes-to-string :initarg :yes-to-string
+              :reader translator-threestate-yes-to-string)
+   (no-to-string :initarg :no-to-string
+              :reader translator-threestate-no-to-string)
+   (any-to-string :initarg :any-to-string
+              :reader translator-threestate-any-to-string)
+   (test :initarg :test
+         :reader translator-threestate-test))
+  (:default-initargs :yes-to-string "yes" :no-to-string "no" :any-to-string "any" :yes t :no nil :any :any :test #'equal))
+
+(defmethod translator-value-encode ((translator translator-threestate) value)
+  (let ((test (translator-threestate-test translator)))
+    (cond 
+      ((funcall test value (translator-threestate-yes translator)) (translator-threestate-yes-to-string translator))
+      ((funcall test value (translator-threestate-no translator)) (translator-threestate-no-to-string translator))
+      ((funcall test value (translator-threestate-any translator)) (translator-threestate-any-to-string translator))
+      (t (error "Unrecognized value for threestate translator: ~a (Test: ~a on ~a ~a)" value test value (translator-threestate-any translator))))))
+
+(defmethod translator-value-decode ((translator translator-threestate) value &optional client-id label)
+  (cond 
+      ((string-equal value (translator-threestate-yes-to-string translator)) (translator-threestate-yes translator))
+      ((string-equal value (translator-threestate-no-to-string translator)) (translator-threestate-no translator))
+      ((string-equal value (translator-threestate-any-to-string translator)) (translator-threestate-any translator))
+      (t (when label
+           (add-validation-error client-id (format nil (or (validation-error-control-string translator)
+                                                              "Field ~a: invalid value '~a'.") label value))))))
+
+(defvar *threestate-translator* (make-instance 'translator-threestate))
\ No newline at end of file



More information about the Claw-cvs mailing list