From a61cd21f9d401518d779e6ad26e141b6a3ed80cc Mon Sep 17 00:00:00 2001 From: Mick Thomure Date: Fri, 4 Nov 2016 22:53:55 -0700 Subject: [PATCH 1/6] add vega-lite schema --- project.clj | 1 + src/clj/vizard/lite.clj | 6 +- src/clj/vizard/schema.clj | 612 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 617 insertions(+), 2 deletions(-) create mode 100644 src/clj/vizard/schema.clj diff --git a/project.clj b/project.clj index 3be2ba7..410d602 100644 --- a/project.clj +++ b/project.clj @@ -20,6 +20,7 @@ [sablono "0.3.6"] [org.omcljs/om "0.9.0"] [prismatic/om-tools "0.3.12"] + [prismatic/schema "1.1.3"] [com.cognitect/transit-cljs "0.8.239"] [cljsjs/vega "2.6.0-0"] [cljsjs/vega-lite "1.2.0-0"] diff --git a/src/clj/vizard/lite.clj b/src/clj/vizard/lite.clj index b97d55a..b7f18a6 100644 --- a/src/clj/vizard/lite.clj +++ b/src/clj/vizard/lite.clj @@ -1,8 +1,10 @@ (ns vizard.lite - (:require [vizard.colors :refer [brews]])) + (:require [vizard.colors :refer [brews]] + [schema.core :as s] + [vizard.schema :refer [Vega]])) (defn colors [name] (get brews name name)) (defn lite [vl-spec data-vals] - (assoc-in vl-spec [:data :values] data-vals)) + (assoc-in (s/validate Vega vl-spec) [:data :values] data-vals)) diff --git a/src/clj/vizard/schema.clj b/src/clj/vizard/schema.clj new file mode 100644 index 0000000..2100f2a --- /dev/null +++ b/src/clj/vizard/schema.clj @@ -0,0 +1,612 @@ +(ns vizard.schema + "Schema for Vega-Lite specs. Translated from the JSON schema + https://vega.github.io/vega-lite/vega-lite-schema.json" + (:use [schema.core :exclude [atom fn defn defmethod letfn defrecord]])) + +(defn ranged [& {:keys [min max]}] + (cond + (and min max) (constrained Num (fn [x] (<= min x max))) + min (constrained Num (fn [x] (<= min x))) + max (constrained Num (fn [x] (<= x max))) + :else Num)) + +(defn process-schema [schema] + (if (map? schema) + (into {} (for [[k v] schema] [(if (keyword? k) (optional-key k) k) v])) + schema)) + +(defmacro + defschema* + [name body] + (list 'defschema name (process-schema body))) + +(defschema* + Formula + {(required-key :field) Str, (required-key :expr) Str}) + +(defschema* Orient (enum "horizontal" "vertical")) + +(defschema* + NiceTime + (enum "second" "minute" "hour" "day" "week" "month" "year")) + +(defschema* + Interpolate + (enum + "linear" + "linear-closed" + "step" + "step-before" + "step-after" + "basis" + "basis-open" + "basis-closed" + "cardinal" + "cardinal-open" + "cardinal-closed" + "bundle" + "monotone")) + +(defschema* BandSize (enum "fit")) + +(defschema* + Mark + (enum + "area" + "bar" + "line" + "point" + "text" + "tick" + "rule" + "circle" + "square" + "errorBar")) + +(defschema* + AxisConfig + {:gridDash [Num], + :properties Any, + :labels Bool, + :titleFontSize Num, + :labelMaxLength (ranged :min 1), + :tickPadding Num, + :labelBaseline Str, + :gridOpacity Num, + :titleOffset Num, + :offset Num, + :tickWidth Num, + :tickLabelColor Str, + :grid Bool, + :tickSizeEnd (ranged :min 0), + :shortTimeLabels Bool, + :titleMaxLength (ranged :min 0), + :labelAngle Num, + :titleFont Str, + :tickSizeMinor (ranged :min 0), + :titleColor Str, + :tickLabelFontSize Num, + :tickSize (ranged :min 0), + :layer Str, + :gridWidth Num, + :subdivide Num, + :axisWidth Num, + :ticks (ranged :min 0), + :tickSizeMajor (ranged :min 0), + :characterWidth Num, + :labelAlign Str, + :gridColor Str, + :tickLabelFont Str, + :axisColor Str, + :titleFontWeight Str, + :tickColor Str}) + +(defschema* AxisOrient (enum "top" "right" "left" "bottom")) + +(defschema* VerticalAlign (enum "top" "middle" "bottom")) + +(defschema* FontWeight (enum "normal" "bold")) + +(defschema* HorizontalAlign (enum "left" "right" "center")) + +(defschema* + ScaleType + (enum + "linear" + "log" + "pow" + "sqrt" + "quantile" + "quantize" + "ordinal" + "time" + "utc")) + +(defschema* SortOrder (enum "ascending" "descending" "none")) + +(defschema* + TimeUnit + (enum + "year" + "month" + "day" + "date" + "hours" + "minutes" + "seconds" + "milliseconds" + "yearmonth" + "yearmonthdate" + "yearmonthdatehours" + "yearmonthdatehoursminutes" + "yearmonthdatehoursminutesseconds" + "monthdate" + "hoursminutes" + "hoursminutesseconds" + "minutesseconds" + "secondsmilliseconds" + "quarter" + "yearquarter" + "quartermonth" + "yearquartermonth")) + +(defschema* + Bin + {:min Num, + :max Num, + :base Num, + :step Num, + :steps [Num], + :minstep Num, + :div [Num], + :maxbins (ranged :min 2)}) + +(defschema* + Shape + (enum + "circle" + "square" + "cross" + "diamond" + "triangle-up" + "triangle-down")) + +(defschema* + ScaleConfig + {:useRawDomain Bool, + :fontSizeRange [Num], + :shapeRange (cond-pre [Str] Str), + :bandSize (cond-pre BandSize Num), + :tickSizeRange [Num], + :barSizeRange [Num], + :textBandWidth (ranged :min 0), + :nominalColorRange (cond-pre [Str] Str), + :round Bool, + :opacity [Num], + :padding Num, + :ruleSizeRange [Num], + :sequentialColorRange (cond-pre [Str] Str), + :pointSizeRange [Num]}) + +(defschema* FacetScaleConfig {:round Bool, :padding Num}) + +(defschema* + AggregateOp + (enum + "values" + "count" + "valid" + "missing" + "distinct" + "sum" + "mean" + "average" + "variance" + "variancep" + "stdev" + "stdevp" + "median" + "q1" + "q3" + "modeskew" + "min" + "max" + "argmin" + "argmax")) + +(defschema* + SortField + {(required-key :field) Str, + (required-key :op) AggregateOp, + :order SortOrder}) + +(defschema* Type (enum "quantitative" "ordinal" "temporal" "nominal")) + +(defschema* + FieldDef + {:field Str, + :type Type, + :value (cond-pre Str Num Bool), + :timeUnit TimeUnit, + :bin (cond-pre Bin Bool), + :aggregate AggregateOp, + :title Str}) + +(defschema* StackOffset (enum "zero" "center" "normalize" "none")) + +(defschema* FontStyle (enum "normal" "italic")) + +(defschema* + MarkConfig + {:baseline VerticalAlign, + :strokeOpacity (ranged :min 0 :max 1), + :format Str, + :align HorizontalAlign, + :stroke Str, + :applyColorToBackground Bool, + :dx Num, + :color Str, + :tension Num, + :barSize Num, + :fill Str, + :strokeDash [Num], + :dy Num, + :shortTimeLabels Bool, + :fillOpacity (ranged :min 0 :max 1), + :orient Orient, + :interpolate Interpolate, + :angle Num, + :strokeDashOffset Num, + :theta Num, + :radius Num, + :font Str, + :size Num, + :tickThickness Num, + :stacked StackOffset, + :tickSize Num, + :strokeWidth (ranged :min 0), + :opacity (ranged :min 0 :max 1), + :fontStyle FontStyle, + :fontWeight FontWeight, + :shape (cond-pre Shape Str), + :barThinSize Num, + :fontSize Num, + :ruleSize Num, + :filled Bool, + :lineSize Num, + :text Str}) + +(defschema* + CellConfig + {:strokeOpacity Num, + :stroke Str, + :clip Bool, + :fill Str, + :strokeDash [Num], + :width Num, + :fillOpacity Num, + :strokeDashOffset Num, + :strokeWidth Num, + :height Num}) + +(defschema* + LegendConfig + {:properties Any, + :symbolSize Num, + :titleFontSize Num, + :labelBaseline Str, + :gradientStrokeWidth Num, + :offset Num, + :shortTimeLabels Bool, + :labelOffset Num, + :gradientHeight Num, + :orient Str, + :gradientStrokeColor Str, + :labelColor Str, + :titleFont Str, + :symbolShape Str, + :titleColor Str, + :gradientWidth Num, + :padding Num, + :labelFont Str, + :labelAlign Str, + :labelFontSize Num, + :symbolColor Str, + :symbolStrokeWidth (ranged :min 0), + :titleFontWeight Str, + :margin Num}) + +(defschema* + DateTime + {:quarter (ranged :min 1 :max 4), + :day (cond-pre Str Num), + :date (ranged :min 1 :max 31), + :month (cond-pre Str Num), + :seconds (ranged :min 0 :max 59), + :year Num, + :hours (ranged :min 0 :max 23), + :milliseconds (ranged :min 0 :max 999), + :minutes (ranged :min 0 :max 59)}) + +(defschema* + EqualFilter + {:timeUnit TimeUnit, + (required-key :field) Str, + :equal (cond-pre DateTime (cond-pre Str Num Bool))}) + +(defschema* + OneOfFilter + {:timeUnit TimeUnit, + (required-key :field) Str, + :oneOf [(cond-pre DateTime (cond-pre Str Num Bool))]}) + +(defschema* + Axis + (maybe + {:gridDash [Num], + :properties Any, + :labels Bool, + :titleFontSize Num, + :format Str, + :labelMaxLength (ranged :min 1), + :tickPadding Num, + :labelBaseline Str, + :gridOpacity Num, + :titleOffset Num, + :offset Num, + :tickWidth Num, + :tickLabelColor Str, + :grid Bool, + :tickSizeEnd (ranged :min 0), + :shortTimeLabels Bool, + :orient AxisOrient, + :titleMaxLength (ranged :min 0), + :title Str, + :labelAngle (ranged :min 0 :max 360), + :titleFont Str, + :tickSizeMinor (ranged :min 0), + :titleColor Str, + :tickLabelFontSize Num, + :tickSize (ranged :min 0), + :layer Str, + :gridWidth Num, + :values (cond-pre [Num] [DateTime]), + :subdivide Num, + :axisWidth Num, + :ticks (ranged :min 0), + :tickSizeMajor (ranged :min 0), + :characterWidth Num, + :labelAlign Str, + :gridColor Str, + :tickLabelFont Str, + :axisColor Str, + :titleFontWeight Str, + :tickColor Str})) + +(defschema* + Scale + {:zero Bool, + :useRawDomain Bool, + :exponent Num, + :bandSize (cond-pre BandSize Num), + :type ScaleType, + :round Bool, + :padding Num, + :nice (cond-pre NiceTime Bool), + :domain (cond-pre [Str] [Num] [DateTime]), + :clamp Bool, + :range (cond-pre [Str] [Num] Str)}) + +(defschema* + PositionChannelDef + {:scale Scale, + :value (cond-pre Str Num Bool), + :field Str, + :type Type, + :title Str, + :bin (cond-pre Bin Bool), + :timeUnit TimeUnit, + :aggregate AggregateOp, + :axis Axis, + :sort (cond-pre SortOrder SortField)}) + +(defschema* Facet {:row PositionChannelDef, :column PositionChannelDef}) + +(defschema* + RangeFilter + {:timeUnit TimeUnit, + (required-key :field) Str, + :range [(cond-pre DateTime Num)]}) + +(defschema* + Transform + {:filter + (cond-pre + EqualFilter + RangeFilter + OneOfFilter + [(cond-pre EqualFilter RangeFilter OneOfFilter Str)] + Str), + :filterInvalid Bool, + :calculate [Formula]}) + +(defschema* + Legend + (maybe + {:properties Any, + :symbolSize Num, + :titleFontSize Num, + :format Str, + :labelBaseline Str, + :gradientStrokeWidth Num, + :offset Num, + :shortTimeLabels Bool, + :labelOffset Num, + :gradientHeight Num, + :orient Str, + :gradientStrokeColor Str, + :labelColor Str, + :title Str, + :titleFont Str, + :symbolShape Str, + :titleColor Str, + :gradientWidth Num, + :values (cond-pre [Str] [Num] [DateTime]), + :padding Num, + :labelFont Str, + :labelAlign Str, + :labelFontSize Num, + :symbolColor Str, + :symbolStrokeWidth (ranged :min 0), + :titleFontWeight Str, + :margin Num})) + +(defschema* + ChannelDefWithLegend + {:scale Scale, + :value (cond-pre Str Num Bool), + :legend Legend, + :field Str, + :type Type, + :title Str, + :bin (cond-pre Bin Bool), + :timeUnit TimeUnit, + :aggregate AggregateOp, + :sort (cond-pre SortOrder SortField)}) + +(defschema* AreaOverlay (enum "line" "linepoint" "none")) + +(defschema* + OverlayConfig + {:line Bool, + :area AreaOverlay, + :pointStyle MarkConfig, + :lineStyle MarkConfig}) + +(defschema* + OrderChannelDef + {:sort SortOrder, + :field Str, + :type Type, + :value (cond-pre Str Num Bool), + :timeUnit TimeUnit, + :bin (cond-pre Bin Bool), + :aggregate AggregateOp, + :title Str}) + +(defschema* + UnitEncoding + {:y PositionChannelDef, + :path (cond-pre OrderChannelDef [OrderChannelDef]), + :color ChannelDefWithLegend, + :size ChannelDefWithLegend, + :opacity ChannelDefWithLegend, + :label FieldDef, + :shape ChannelDefWithLegend, + :order (cond-pre OrderChannelDef [OrderChannelDef]), + :x PositionChannelDef, + :y2 FieldDef, + :x2 FieldDef, + :text FieldDef, + :detail (cond-pre FieldDef [FieldDef])}) + +(defschema* + Encoding + {:y PositionChannelDef, + :path (cond-pre OrderChannelDef [OrderChannelDef]), + :color ChannelDefWithLegend, + :size ChannelDefWithLegend, + :column PositionChannelDef, + :opacity ChannelDefWithLegend, + :label FieldDef, + :shape ChannelDefWithLegend, + :order (cond-pre OrderChannelDef [OrderChannelDef]), + :x PositionChannelDef, + :y2 FieldDef, + :x2 FieldDef, + :row PositionChannelDef, + :text FieldDef, + :detail (cond-pre FieldDef [FieldDef])}) + +(defschema* FacetGridConfig {:color Str, :opacity Num, :offset Num}) + +(defschema* + FacetConfig + {:scale FacetScaleConfig, + :axis AxisConfig, + :grid FacetGridConfig, + :cell CellConfig}) + +(defschema* + Config + {:scale ScaleConfig, + :mark MarkConfig, + :countTitle Str, + :facet FacetConfig, + :background Str, + :legend LegendConfig, + :numberFormat Str, + :overlay OverlayConfig, + :axis AxisConfig, + :viewport Num, + :cell CellConfig, + :timeFormat Str}) + +(defschema* DataFormatType (enum "json" "csv" "tsv" "topojson")) + +(defschema* + DataFormat + {:type DataFormatType, + :parse Any, + :property Str, + :feature Str, + :mesh Str}) + +(defschema* Data {:format DataFormat, :url Str, :values [Any]}) + +(defschema* + ExtendedUnitSpec + {:description Str, + :encoding Encoding, + :transform Transform, + :config Config, + :name Str, + :width Num, + (required-key :mark) Mark, + :height Num, + :data Data}) + +(defschema* + UnitSpec + {:description Str, + :encoding UnitEncoding, + :transform Transform, + :config Config, + :name Str, + :width Num, + (required-key :mark) Mark, + :height Num, + :data Data}) + +(defschema* + LayerSpec + {:width Num, + :height Num, + :layers [UnitSpec], + :name Str, + :description Str, + :data Data, + :transform Transform, + :config Config}) + +(defschema* + FacetSpec + {(required-key :facet) Facet, + :spec (cond-pre UnitSpec LayerSpec), + :name Str, + :description Str, + :data Data, + :transform Transform, + :config Config}) + +(defschema* Vega (cond-pre ExtendedUnitSpec FacetSpec LayerSpec)) From a7c5b4aa486802dbbdb559c9ee1cc9641c1d81d1 Mon Sep 17 00:00:00 2001 From: Mick Thomure Date: Fri, 4 Nov 2016 23:58:57 -0700 Subject: [PATCH 2/6] validate when POSTing to /vl-spec --- src/clj/vizard/server.clj | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/clj/vizard/server.clj b/src/clj/vizard/server.clj index ce504f0..2b98e53 100644 --- a/src/clj/vizard/server.clj +++ b/src/clj/vizard/server.clj @@ -14,6 +14,8 @@ [taoensso.sente.server-adapters.aleph :refer (get-sch-adapter)] [taoensso.sente.packers.transit :as sente-transit] [cheshire.core :as json] + [vizard.schema :refer [Vega]] + [schema.core :as s] [clojure.java.io :as io]) (:gen-class)) @@ -53,6 +55,15 @@ [req] (get-in req [:session :uid])) +(defn prepare-validation-error + "Translate instances of ValidationError to basic clojure data, so we can + serialize the result as JSON." + [error] + (letfn [(f [x] (if (instance? schema.utils.ValidationError x) + (schema.utils/validation-error-explain x) + x))] + (clojure.walk/postwalk f error))) + (defroutes my-routes (GET "/" req (content-type {:status 200 :session (if (session-uid req) @@ -74,11 +85,18 @@ :body (json/generate-string @last-spec)}) (POST "/vl-spec" req (debugf "POST /vl-spec got: %s" req) - (let [vl-spec (json/parse-string (slurp (:body req)))] - (reset! last-vl-spec vl-spec) - (doseq [uid (:any @connected-uids)] - (chsk-send! uid [:vizard/vl-spec vl-spec])) - {:status 200})) + (let [vl-spec (json/parse-string (slurp (:body req)) true)] + (if-let [error (s/check Vega vl-spec)] + {:status 400 + :content-type "application/json" + :body (json/generate-string + {:error "invalid vega-lite spec" + :reason (prepare-validation-error error)})} + (do + (reset! last-vl-spec vl-spec) + (doseq [uid (:any @connected-uids)] + (chsk-send! uid [:vizard/vl-spec vl-spec])) + {:status 200})))) (GET "/vl-spec" req (debugf "GET /vl-spec got: %s" req) {:status 200 From 080b167fc7e97ff0ff6657705dbb5584f64704dd Mon Sep 17 00:00:00 2001 From: Mick Thomure Date: Sat, 5 Nov 2016 00:16:40 -0700 Subject: [PATCH 3/6] fix bug with map keys being required by default --- src/clj/vizard/schema.clj | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/clj/vizard/schema.clj b/src/clj/vizard/schema.clj index 2100f2a..ff7ab42 100644 --- a/src/clj/vizard/schema.clj +++ b/src/clj/vizard/schema.clj @@ -15,10 +15,10 @@ (into {} (for [[k v] schema] [(if (keyword? k) (optional-key k) k) v])) schema)) -(defmacro - defschema* - [name body] - (list 'defschema name (process-schema body))) +(defmacro defschema* + "Like schema.core/defschema, but keyword map keys are optional by default." + [name body] + (list 'defschema name (process-schema body))) (defschema* Formula @@ -342,7 +342,6 @@ (defschema* Axis - (maybe {:gridDash [Num], :properties Any, :labels Bool, @@ -381,7 +380,7 @@ :tickLabelFont Str, :axisColor Str, :titleFontWeight Str, - :tickColor Str})) + :tickColor Str}) (defschema* Scale @@ -432,7 +431,6 @@ (defschema* Legend - (maybe {:properties Any, :symbolSize Num, :titleFontSize Num, @@ -459,7 +457,7 @@ :symbolColor Str, :symbolStrokeWidth (ranged :min 0), :titleFontWeight Str, - :margin Num})) + :margin Num}) (defschema* ChannelDefWithLegend From 983eadae12fa1fae8b9d925efdbbd2b28d507ddb Mon Sep 17 00:00:00 2001 From: Mick Thomure Date: Tue, 8 Nov 2016 15:02:52 -0800 Subject: [PATCH 4/6] remove validation from rest endpoint --- src/clj/vizard/server.clj | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/clj/vizard/server.clj b/src/clj/vizard/server.clj index 2b98e53..3552398 100644 --- a/src/clj/vizard/server.clj +++ b/src/clj/vizard/server.clj @@ -86,17 +86,10 @@ (POST "/vl-spec" req (debugf "POST /vl-spec got: %s" req) (let [vl-spec (json/parse-string (slurp (:body req)) true)] - (if-let [error (s/check Vega vl-spec)] - {:status 400 - :content-type "application/json" - :body (json/generate-string - {:error "invalid vega-lite spec" - :reason (prepare-validation-error error)})} - (do - (reset! last-vl-spec vl-spec) - (doseq [uid (:any @connected-uids)] - (chsk-send! uid [:vizard/vl-spec vl-spec])) - {:status 200})))) + (reset! last-vl-spec vl-spec) + (doseq [uid (:any @connected-uids)] + (chsk-send! uid [:vizard/vl-spec vl-spec])) + {:status 200})) (GET "/vl-spec" req (debugf "GET /vl-spec got: %s" req) {:status 200 From 8291b8c870ccd5af65670f5be7fcf88ae92a34af Mon Sep 17 00:00:00 2001 From: Mick Thomure Date: Tue, 8 Nov 2016 15:03:44 -0800 Subject: [PATCH 5/6] fallback to deprecated `either` for now --- src/clj/vizard/schema.clj | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/clj/vizard/schema.clj b/src/clj/vizard/schema.clj index ff7ab42..d78d08e 100644 --- a/src/clj/vizard/schema.clj +++ b/src/clj/vizard/schema.clj @@ -175,17 +175,17 @@ ScaleConfig {:useRawDomain Bool, :fontSizeRange [Num], - :shapeRange (cond-pre [Str] Str), + :shapeRange (either [Str] Str), :bandSize (cond-pre BandSize Num), :tickSizeRange [Num], :barSizeRange [Num], :textBandWidth (ranged :min 0), - :nominalColorRange (cond-pre [Str] Str), + :nominalColorRange (either [Str] Str), :round Bool, :opacity [Num], :padding Num, :ruleSizeRange [Num], - :sequentialColorRange (cond-pre [Str] Str), + :sequentialColorRange (either [Str] Str), :pointSizeRange [Num]}) (defschema* FacetScaleConfig {:round Bool, :padding Num}) @@ -332,13 +332,13 @@ EqualFilter {:timeUnit TimeUnit, (required-key :field) Str, - :equal (cond-pre DateTime (cond-pre Str Num Bool))}) + :equal (cond-pre DateTime Str Num Bool)}) (defschema* OneOfFilter {:timeUnit TimeUnit, (required-key :field) Str, - :oneOf [(cond-pre DateTime (cond-pre Str Num Bool))]}) + :oneOf [(cond-pre DateTime Str Num Bool)]}) (defschema* Axis @@ -369,7 +369,7 @@ :tickSize (ranged :min 0), :layer Str, :gridWidth Num, - :values (cond-pre [Num] [DateTime]), + :values (either [Num] [DateTime]), :subdivide Num, :axisWidth Num, :ticks (ranged :min 0), @@ -392,9 +392,9 @@ :round Bool, :padding Num, :nice (cond-pre NiceTime Bool), - :domain (cond-pre [Str] [Num] [DateTime]), + :domain (either [Str] [Num] [DateTime]), :clamp Bool, - :range (cond-pre [Str] [Num] Str)}) + :range (either [Str] [Num] Str)}) (defschema* PositionChannelDef @@ -420,7 +420,7 @@ (defschema* Transform {:filter - (cond-pre + (either EqualFilter RangeFilter OneOfFilter @@ -449,7 +449,7 @@ :symbolShape Str, :titleColor Str, :gradientWidth Num, - :values (cond-pre [Str] [Num] [DateTime]), + :values (either [Str] [Num] [DateTime]), :padding Num, :labelFont Str, :labelAlign Str, @@ -495,36 +495,36 @@ (defschema* UnitEncoding {:y PositionChannelDef, - :path (cond-pre OrderChannelDef [OrderChannelDef]), + :path (either OrderChannelDef [OrderChannelDef]), :color ChannelDefWithLegend, :size ChannelDefWithLegend, :opacity ChannelDefWithLegend, :label FieldDef, :shape ChannelDefWithLegend, - :order (cond-pre OrderChannelDef [OrderChannelDef]), + :order (either OrderChannelDef [OrderChannelDef]), :x PositionChannelDef, :y2 FieldDef, :x2 FieldDef, :text FieldDef, - :detail (cond-pre FieldDef [FieldDef])}) + :detail (either FieldDef [FieldDef])}) (defschema* Encoding {:y PositionChannelDef, - :path (cond-pre OrderChannelDef [OrderChannelDef]), + :path (either OrderChannelDef [OrderChannelDef]), :color ChannelDefWithLegend, :size ChannelDefWithLegend, :column PositionChannelDef, :opacity ChannelDefWithLegend, :label FieldDef, :shape ChannelDefWithLegend, - :order (cond-pre OrderChannelDef [OrderChannelDef]), + :order (either OrderChannelDef [OrderChannelDef]), :x PositionChannelDef, :y2 FieldDef, :x2 FieldDef, :row PositionChannelDef, :text FieldDef, - :detail (cond-pre FieldDef [FieldDef])}) + :detail (either FieldDef [FieldDef])}) (defschema* FacetGridConfig {:color Str, :opacity Num, :offset Num}) From 4c26e85dee9d87e33d9a03585dbac8a3cc4aa684 Mon Sep 17 00:00:00 2001 From: Mick Thomure Date: Wed, 7 Dec 2016 11:51:43 -0800 Subject: [PATCH 6/6] :knife: unused function --- src/clj/vizard/server.clj | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/clj/vizard/server.clj b/src/clj/vizard/server.clj index 3552398..ba33aed 100644 --- a/src/clj/vizard/server.clj +++ b/src/clj/vizard/server.clj @@ -55,15 +55,6 @@ [req] (get-in req [:session :uid])) -(defn prepare-validation-error - "Translate instances of ValidationError to basic clojure data, so we can - serialize the result as JSON." - [error] - (letfn [(f [x] (if (instance? schema.utils.ValidationError x) - (schema.utils/validation-error-explain x) - x))] - (clojure.walk/postwalk f error))) - (defroutes my-routes (GET "/" req (content-type {:status 200 :session (if (session-uid req)