;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- ;;; $Header: customers.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 customers-page-find-customers (customers-page)) (defgeneric customers-page-offset-reset (customers-page)) (defgeneric customers-page-edit-customer (customers-page)) (defgeneric customers-page-add-customer (customers-page)) (defgeneric customers-page-sorting (customers-page)) (defgeneric customers-page-delete-customers (customers-page)) (defclass customers-page (db-page) ((customers :initform nil :accessor customers-page-customers) (current-customer :initform (make-instance 'customer) :accessor customers-page-current-customer) (customer-edit-dialog-title :initform "Add new cutomer" :accessor customers-page-customer-edit-dialog-title) (customers-total-count :initform 0 :accessor customers-page-customers-total-count) (list-size :initarg :list-size :accessor customers-page-list-size) (offset :initform 0 :accessor customers-page-offset) (name1 :initform "*" :accessor customers-page-name1) (name2 :initform "" :accessor customers-page-name2) (email :initform "" :accessor customers-page-email) (vat :initform "" :accessor customers-page-vat) (phone :initform "" :accessor customers-page-phone) (sorting-column :initform "name1" :accessor customers-page-sorting-column) (sorting-order :initform "asc" :accessor customers-page-sorting-order) (delete-all :initform nil :accessor customers-page-delete-all) (delete-items :initform nil :accessor customers-page-delete-items)) (:default-initargs :list-size 20)) (defmethod wcomponent-after-rewind :after ((obj edit-customer) (page customers-page)) (setf (customers-page-current-customer page) (edit-customer-customer obj) (customers-page-customers page) (list (edit-customer-customer obj)))) (defmethod customers-page-offset-reset ((page customers-page)) 0) (defmethod customers-page-edit-customer ((page customers-page)) (let ((customer-id (parse-integer (claw-parameter "customerid"))) (current-customer)) (log-message :info "customers-page-edit-customer") (if (> customer-id 0) (progn (setf current-customer (find-by-id 'customer customer-id) (customers-page-customer-edit-dialog-title page) "Edit customer" (customers-page-customers page) (list current-customer)) (when current-customer (setf (customers-page-current-customer page) current-customer))) (customers-page-add-customer page)))) (defmethod customers-page-add-customer ((page customers-page)) (let ((current-customer (make-instance 'customer))) (log-message :info "customers-page-add-customer") (setf (customers-page-customer-edit-dialog-title page) "Add new customer" (customers-page-current-customer page) current-customer))) (defmethod customers-page-sorting ((page customers-page)) (let ((direction (if (string-equal "asc" (customers-page-sorting-order page)) :asc :desc)) (fields (if (string-equal "name1" (customers-page-sorting-column page)) (list (slot-column-name 'customer "name1") (slot-column-name 'customer "name2")) (list (slot-column-name 'customer "email") (slot-column-name 'customer "name1") (slot-column-name 'customer "name2"))))) (loop for field in fields collect (list field direction)))) (defun js-customers-check-deletion () (ps:ps* '(when (= (slot-value (.query dojo ".dijitCheckBoxChecked > [name='deleteItem']") 'length) 0) (.show-message claw "Message" "No items to delete") (return false)))) (defun js-customers-add-new-click (edit-customer-action-link-id offset-id) (remove #\newline (ps:ps* `(progn (setf (slot-value (.by-id dojo ,offset-id) 'value) 0 (slot-value (dijit.by-id ,edit-customer-action-link-id) 'parameters) (create "customerid" 0)) (.click (dijit.by-id ,edit-customer-action-link-id)))))) (defun js-customers-form-submit (spinner-id edit-customer-dialog-id) (remove #\newline (ps:ps* `(progn (.hide (dijit.by-id ,spinner-id)) (when (slot-value (dijit.by-id ,edit-customer-dialog-id) 'xhrShow) (setf (slot-value (dijit.by-id ,edit-customer-dialog-id) 'xhrShow) false) (.show (dijit.by-id ,edit-customer-dialog-id))))))) (defun js-customers-show-spinner (spinner-id) (remove #\newline (ps:ps* `(.show (dijit.by-id ,spinner-id))))) (defun js-customers-delete-all-on-change () (remove #\newline (ps:ps (.for-each dojo (.map (.query dojo ".deleteItem") dijit.by-node) (lambda (checkbox) (.attr checkbox "checked" (.attr this "checked"))) this)))) (defun js-customers-sort (sorting-column-id sorting-order-id form-id offset-id column) (remove #\newline (ps:ps* `(progn (setf (slot-value (dojo.by-id ,sorting-order-id) 'value) (if (and (== (slot-value (dojo.by-id ,sorting-column-id) 'value) ,column) (== (slot-value (dojo.by-id ,sorting-order-id) 'value) "asc")) "desc" "asc") (slot-value (dojo.by-id ,sorting-column-id) 'value) ,column (slot-value (dojo.by-id ,offset-id) 'value) 0) (.submit (dijit.by-id ,form-id)))))) (defun js-customers-edit (edit-customer-action-link-id customer) (remove #\newline (ps:ps* `(progn (setf (slot-value (dijit.by-id ,edit-customer-action-link-id) 'parameters) (create "customerid" ,(table-id customer))) (.click (dijit.by-id ,edit-customer-action-link-id)))))) (defun js-customers-action-edit (spinner-id edit-customer-dialog-id) (remove #\newline (ps:ps* `(progn (.hide (dijit.by-id ,spinner-id)) (.show (dijit.by-id ,edit-customer-dialog-id)))))) (defun js-customers-edit-customers-before-submit (spinner-id edit-customer-dialog-id) (remove #\newline (ps:ps* `(progn (.show (dijit.by-id ,spinner-id)) (dojo.add-class (slot-value (dijit.by-id ,edit-customer-dialog-id) 'container-node) "hideForm"))))) (defun js-customers-edit-customers-xhr-finish (spinner-id edit-customer-dialog-id) (remove #\newline (ps:ps* `(progn (.hide (dijit.by-id ,spinner-id)) (dojo.remove-class (slot-value (dijit.by-id ,edit-customer-dialog-id) 'container-node) "hideForm"))))) (defmethod page-content ((page customers-page)) (let ((spinner-id (generate-id "spinner")) (form-id (generate-id "customersForm")) (customers (customers-page-customers page)) (offset-id (generate-id "offset")) (result-container-id (generate-id "resultContainer")) (edit-customer-dialog-container-id (generate-id "customerDialogContainer")) (edit-customer-dialog-id (generate-id "customerDialog")) (edit-customer-form-id (generate-id "customerForm")) (sorting-column-id (generate-id "sorting-column")) (sorting-order-id (generate-id "sorting-order")) (edit-customer-action-link-id (generate-id "editCustomer")) (sort-field (customers-page-sorting-column page)) (sort-direction (customers-page-sorting-order page))) (site-template> :title "CLAW Demo anagraphics" (djfloating-content> :static-id spinner-id (img> :alt "spinner" :src "docroot/img/spinner.gif")) (djform> :static-id form-id :action 'customers-page-find-customers :update-id result-container-id :on-before-submit (js-customers-show-spinner spinner-id) :on-xhr-finish (js-customers-form-submit spinner-id edit-customer-dialog-id) (div> (div> :class "searchParameters hlist" (div> :class "item" (span> :class "name1" "Name") (djtext-box> :size 150 :label "name" :id "name1" :accessor 'customers-page-name1) (djtext-box> :size 80 :label "name" :id "name2" :accessor 'customers-page-name2)) (div> :class "item" (span> :class "email" "Email") (djtext-box> :size 100 :label "email" :id "email" :accessor 'customers-page-email)) (div> :class "item" (span> :class "vat" "VAT") (djtext-box> :size 50 :label "vat" :id "vat" :accessor 'customers-page-vat)) (div> :class "item" (span> :class "phone" "phone") (djtext-box> :size 25 :label "phone" :id "phone" :accessor 'customers-page-phone))) (cinput> :type "hidden" :static-id offset-id :translator *integer-translator* :reader 'customers-page-offset-reset :writer (attribute-value '(setf customers-page-offset))) (cinput> :type "hidden" :static-id sorting-column-id :accessor 'customers-page-sorting-column) (cinput> :type "hidden" :static-id sorting-order-id :accessor 'customers-page-sorting-order) (djsubmit-button> :id "search" :on-click (ps:ps* `(setf (slot-value (.by-id dojo ,offset-id) 'value) 0)) :value "Search") (djbutton> :id "addNew" :on-click (js-customers-add-new-click edit-customer-action-link-id offset-id) "Add new") (djconfirmation-submit> :id "delete" :value "Delete" :on-click (js-customers-check-deletion) :action 'customers-page-delete-customers :confirmation-message "Are you sure to delete these items?")) (div> :static-id result-container-id (table> :class "listTable" (tr> :class "header" (th> :class "deleteAll" (djcheck-box> :id "deleteAll" :value "all" :onchange (js-customers-delete-all-on-change))) (th> :class "name" (span> :class (if (string-equal "name1" sort-field) (if (string-equal "asc" sort-direction) "sort sortAsc" "sort sortDesc") "sort") :on-click (js-customers-sort sorting-column-id sorting-order-id form-id offset-id "name1") "Name")) (th> :class "email" (span> :class (if (string-equal "email" sort-field) (if (string-equal "asc" sort-direction) "sort sortAsc" "sort sortDesc") "sort") :on-click (js-customers-sort sorting-column-id sorting-order-id form-id offset-id "email") "Email")) (th> :class "vat" "VAT") (th> :class "phone" "Phone")) (loop for customer in customers for index = 0 then (incf index) collect (tr> :class (if (evenp index) "item even" "item odd") (th> :class "delete" (djcheck-box> :id "deleteItem" :class "deleteItem" :accessor 'customers-page-delete-items :value (table-id customer) :translator *integer-translator* :multiple t)) (td> (a> :id "edit" :href "#" :on-click (js-customers-edit edit-customer-action-link-id customer) (customer-name1 customer) " " (customer-name2 customer))) (td> (customer-email customer)) (td> (customer-vat customer)) (td> (customer-phone1 customer))))) (unless customers (djcheck-box> :id "deleteItem" :accessor 'customers-page-delete-items :value 0 :multiple t :translator *integer-translator* :style "display: none;")) (djaction-link> :static-id edit-customer-action-link-id :style "display:none" :action 'customers-page-edit-customer :update-id (attribute-value (list edit-customer-dialog-container-id result-container-id)) :on-before-submit (js-customers-show-spinner spinner-id) :on-xhr-finish (js-customers-action-edit spinner-id edit-customer-dialog-id) "invisible") (pager> :id "pager" :update-component-id offset-id :page-size (customers-page-list-size page) :total-items (customers-page-customers-total-count page) :first-item-offset (customers-page-offset page)))) (div> :static-id edit-customer-dialog-container-id (djdialog> :static-id edit-customer-dialog-id :class "customerDialog" :title (customers-page-customer-edit-dialog-title page) (edit-customer> :static-id edit-customer-form-id :on-close-click (ps:ps* `(.hide (dijit.by-id ,edit-customer-dialog-id))) :update-id (attribute-value (list edit-customer-form-id result-container-id)) :customer (customers-page-current-customer page) :on-before-submit (js-customers-edit-customers-before-submit spinner-id edit-customer-dialog-id) :on-xhr-finish (js-customers-edit-customers-xhr-finish spinner-id edit-customer-dialog-id)) (exception-monitor> :id "exceptionMonitor" :json-render-on-validation-errors-p edit-customer-form-id)))))) (defmethod customers-page-delete-customers ((page customers-page)) (let ((customer-id-list (customers-page-delete-items page)) (name1 (customers-page-name1 page)) (name2 (customers-page-name2 page)) (email (customers-page-email page)) (vat (customers-page-vat page)) (phone (customers-page-phone page))) (log-message :info "...deleting") (delete-by-id 'customer customer-id-list) (setf (customers-page-delete-items page) ()) (multiple-value-bind (customers total-size) (find-customers :offset (customers-page-offset page) :limit (customers-page-list-size page) :name1 (null-when-empty name1) :name2 (null-when-empty name2) :email (null-when-empty email) :vat (null-when-empty vat) :phone (null-when-empty phone) :sorting (customers-page-sorting page)) (setf (customers-page-customers page) customers (customers-page-customers-total-count page) total-size)))) (defmethod customers-page-find-customers ((page customers-page)) (let ((name1 (customers-page-name1 page)) (name2 (customers-page-name2 page)) (email (customers-page-email page)) (vat (customers-page-vat page)) (phone (customers-page-phone page))) (multiple-value-bind (customers total-size) (find-customers :offset (customers-page-offset page) :limit (customers-page-list-size page) :name1 (null-when-empty name1) :name2 (null-when-empty name2) :email (null-when-empty email) :vat (null-when-empty vat) :phone (null-when-empty phone) :sorting (customers-page-sorting page)) (setf (customers-page-customers page) customers (customers-page-customers-total-count page) total-size)))) (defmethod page-before-render ((page customers-page)) (unless (page-req-parameter page *rewind-parameter*) (multiple-value-bind (customers total-size) (find-customers :sorting (customers-page-sorting page) :offset 0 :limit (customers-page-list-size page)) (setf (customers-page-customers page) customers (customers-page-customers-total-count page) total-size)))) (lisplet-register-function-location *dojo-demo-lisplet* (make-page-renderer 'customers-page #'claw-post-parameters #'claw-get-parameters) "customers.html") (lisplet-protect *dojo-demo-lisplet* "customers.html" '("administrator" "user"))