Last active
December 10, 2015 13:58
-
-
Save html/4444927 to your computer and use it in GitHub Desktop.
Snippet allows to order fields in table view (columns in gridedit for example), use :fields-order view option like this :fields-order '(:id :name :group :time-created)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defclass advanced-table-view (table-view) | |
((fields-order :initarg :fields-order :initform nil))) | |
(defclass advanced-table-view-field (table-view-field) | |
()) | |
(defclass advanced-table-scaffold (table-scaffold) | |
()) | |
(defun %map-object-view-fields (proc obj view-designator | |
&key include-invisible-p (expand-mixins t) | |
custom-fields &allow-other-keys) | |
"Implement `get-object-view-fields', except for consing up the | |
result list, instead calling PROC on each resulting `field-info'." | |
(labels ((map-level-fields (proc view) | |
(let ((view (or (and view (find-view view)) | |
(return-from map-level-fields)))) | |
(map-level-fields proc (view-inherit-from view)) | |
(dolist (vfield (view-fields view)) | |
(funcall proc vfield)))) | |
(map-level (obj view mixin-container) | |
(let ((vfields (make-hash-table :test 'eq))) | |
;; prefer latest | |
(map-level-fields | |
(f_ (setf (gethash (view-field-slot-name _) vfields) _)) | |
view) | |
(let ((fields)) | |
(map-level-fields | |
(lambda (vfield) | |
;; we only use the in-order vfield as a tag into the | |
;; vfields HT, taking first-instance-only | |
(setf vfield (gethash (view-field-slot-name vfield) vfields)) | |
(when vfield | |
(push vfield fields ) | |
;; avoid duplicates | |
(remhash (view-field-slot-name vfield) vfields))) | |
view) | |
(when (and | |
(slot-exists-p (find-view view) 'fields-order) | |
(slot-boundp (find-view view) 'fields-order)) | |
(let ((fields-order (slot-value (find-view view) 'fields-order))) | |
(setf fields | |
(sort fields | |
(lambda (&rest args) | |
(let ((keywords-weight | |
(loop for i in args collect | |
(let* ((keyword (intern | |
(string-upcase | |
(view-field-slot-name i)) | |
"KEYWORD")) | |
(weight (if keyword | |
(if (find keyword fields-order) | |
(position keyword fields-order) | |
(1+ (length fields-order))) | |
0))) | |
weight)))) | |
(apply #'> keywords-weight))))))) | |
(loop for vfield in (reverse fields) do | |
(let ((vfield-info (weblocks::make-field-info | |
:field vfield :object obj | |
:parent-info mixin-container))) | |
(etypecase vfield | |
(inline-view-field | |
(when (or include-invisible-p | |
(not (let ((hide-p-value (view-field-hide-p vfield))) | |
(if (functionp hide-p-value) | |
(funcall hide-p-value obj) | |
hide-p-value)))) | |
(funcall proc vfield-info))) | |
(mixin-view-field | |
(if expand-mixins | |
(map-level | |
(and obj | |
(or (obtain-view-field-value vfield obj) | |
(aif (mixin-view-field-init-form vfield) | |
(funcall it) | |
(error "Slot for mixin field ~S has neither value nor initform!" vfield)))) | |
(mixin-view-field-view vfield) vfield-info) | |
(funcall proc vfield-info)))))) | |
)))) | |
(multiple-value-bind (wproc terminate-proc) | |
(weblocks::inserting-custom-fields obj proc custom-fields) | |
(setf proc wproc) | |
(map-level obj view-designator nil) | |
(funcall terminate-proc)))) | |
(defun map-view-fields (fn view obj &rest args) | |
"Acts like mapcar for view fields. FN should expect a structure of | |
type field-info." | |
(let ((expansion '())) | |
(apply #'%map-object-view-fields | |
(f_ (push (funcall fn _) expansion)) obj view args) | |
(nreverse expansion))) | |
(defmethod render-view-field-header :around ((field table-view-field) | |
(view advanced-table-view) | |
widget | |
(presentation hidden-presentation) value obj &rest args) | |
(declare (ignore args))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment