diff --git a/README.md b/README.md index 6fe24d7..d05655b 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,12 @@ Generic Options - In addition to any specific options for fields, all fields also get a "Exists" and "! Exists" option +## External Changes && Initial State +If you want to pass in an initial state (or if you make changes to the query externally), you'll need to +set the configuration flag `needsUpdate` to `true`. Any time this flag changes to `true`, this directive +will overwrite the current state and data with whatever is now defined in your configuration object. + + ## Local Development To work on this module locally, you will need to clone it and run `gulp watch`. This will ensure that your changes get compiled properly. You will also need to make sure you run `gulp` to build the "dist" files before commit. diff --git a/dist/angular-elastic-builder.js b/dist/angular-elastic-builder.js index 0dd954d..5ee4ee8 100644 --- a/dist/angular-elastic-builder.js +++ b/dist/angular-elastic-builder.js @@ -2,7 +2,7 @@ * # angular-elastic-builder * ## Angular Module for building an Elasticsearch Query * - * @version v1.2.0 + * @version v1.3.0 * @link https://github.com/dncrews/angular-elastic-builder.git * @license MIT * @author Dan Crews @@ -78,16 +78,15 @@ }; /** - * this Watcher gets used only once on initial setting of the query and then not again + * Any time "outside forces" change the query, they should tell us so via + * `data.needsUpdate` */ - var unwatcher = scope.$watch('data.query', function(curr) { + scope.$watch('data.needsUpdate', function(curr, prev) { if (! curr) return; scope.filters = elasticQueryService.toFilters(data.query, scope.data.fields); - - /* Stop Watching */ - unwatcher(); - }, true); + scope.data.needsUpdate = false; + }); /** * Changes on the page update the Query @@ -313,6 +312,14 @@ })(window.angular); +(function(angular) {"use strict"; angular.module("angular-elastic-builder").run(["$templateCache", function($templateCache) {$templateCache.put("angular-elastic-builder/BuilderDirective.html","
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n
\n
\n\n"); +$templateCache.put("angular-elastic-builder/ChooserDirective.html","\n\n
\n\n
\n\n\n"); +$templateCache.put("angular-elastic-builder/GroupDirective.html","
\n
If\n \n of these conditions are met\n
\n
\n\n
\n \n \n \n \n \n \n
\n\n \n \n \n\n"); +$templateCache.put("angular-elastic-builder/RuleDirective.html","
\n \n\n \n\n \n \n \n\n
\n"); +$templateCache.put("angular-elastic-builder/types/Boolean.html","\n Equals\n\n \n \n \n\n"); +$templateCache.put("angular-elastic-builder/types/Multi.html","\n \n \n \n\n"); +$templateCache.put("angular-elastic-builder/types/Number.html","\n \n\n \n \n\n"); +$templateCache.put("angular-elastic-builder/types/Term.html","\n \n \n\n");}]);})(window.angular); /** * angular-elastic-builder * @@ -539,12 +546,3 @@ } })(window.angular); - -(function(angular) {"use strict"; angular.module("angular-elastic-builder").run(["$templateCache", function($templateCache) {$templateCache.put("angular-elastic-builder/BuilderDirective.html","
\n
\n
\n
\n
\n \n \n
\n
\n
\n\n"); -$templateCache.put("angular-elastic-builder/ChooserDirective.html","\n\n
\n\n
\n\n\n"); -$templateCache.put("angular-elastic-builder/GroupDirective.html","
\n
If\n \n of these conditions are met\n
\n
\n\n
\n \n \n
\n\n \n\n"); -$templateCache.put("angular-elastic-builder/RuleDirective.html","
\n \n\n \n\n \n\n
\n"); -$templateCache.put("angular-elastic-builder/types/Boolean.html","\n Equals\n\n \n \n \n\n"); -$templateCache.put("angular-elastic-builder/types/Multi.html","\n \n \n \n\n"); -$templateCache.put("angular-elastic-builder/types/Number.html","\n \n\n \n \n\n"); -$templateCache.put("angular-elastic-builder/types/Term.html","\n \n \n\n");}]);})(window.angular); \ No newline at end of file diff --git a/dist/angular-elastic-builder.min.js b/dist/angular-elastic-builder.min.js index 08dc07c..24c38e7 100644 --- a/dist/angular-elastic-builder.min.js +++ b/dist/angular-elastic-builder.min.js @@ -1 +1 @@ -!function(e){"use strict";e.module("angular-elastic-builder",["RecursionHelper"])}(window.angular),function(e){"use strict";e.module("angular-elastic-builder").directive("elasticBuilder",["elasticQueryService",function(e){return{scope:{data:"=elasticBuilder"},templateUrl:"angular-elastic-builder/BuilderDirective.html",link:function(t){var n=t.data;t.removeChild=function(e){t.filters.splice(e,1)},t.addRule=function(){t.filters.push({})},t.addGroup=function(){t.filters.push({type:"group",subType:"and",rules:[]})};var i=t.$watch("data.query",function(a){a&&(t.filters=e.toFilters(n.query,t.data.fields),i())},!0);t.$watch("filters",function(i){i&&(n.query=e.toQuery(t.filters,t.data.fields))},!0)}}}])}(window.angular),function(e){"use strict";var t=e.module("angular-elastic-builder");t.directive("elasticBuilderChooser",["RecursionHelper","groupClassHelper",function(e,t){return{scope:{elasticFields:"=",item:"=elasticBuilderChooser",onRemove:"&"},templateUrl:"angular-elastic-builder/ChooserDirective.html",compile:function(n){return e.compile(n,function(e,n,i){var a=e.depth=+i.depth,l=e.item;e.getGroupClassName=function(){var e=a;return"group"===l.type&&e++,t(e)}})}}}])}(window.angular),function(e){"use strict";var t=e.module("angular-elastic-builder");t.directive("elasticBuilderGroup",["RecursionHelper","groupClassHelper",function(e,t){return{scope:{elasticFields:"=",group:"=elasticBuilderGroup",onRemove:"&"},templateUrl:"angular-elastic-builder/GroupDirective.html",compile:function(n){return e.compile(n,function(e,n,i){var a=e.depth=+i.depth,l=e.group;e.addRule=function(){l.rules.push({})},e.addGroup=function(){l.rules.push({type:"group",subType:"and",rules:[]})},e.removeChild=function(e){l.rules.splice(e,1)},e.getGroupClassName=function(){return t(a+1)}})}}}])}(window.angular),function(e){"use strict";var t=e.module("angular-elastic-builder");t.directive("elasticBuilderRule",[function(){return{scope:{elasticFields:"=",rule:"=elasticBuilderRule",onRemove:"&"},templateUrl:"angular-elastic-builder/RuleDirective.html",link:function(e){e.getType=function(){var t=e.elasticFields,n=e.rule.field;if(t&&n)return"boolean"===t[n].subType?"boolean":t[n].type}}}}])}(window.angular),function(e){"use strict";var t=e.module("angular-elastic-builder");t.directive("elasticType",[function(){return{scope:{type:"=elasticType",rule:"=",guide:"="},template:'',link:function(e){e.getTemplateUrl=function(){var t=e.type;if(t)return t=t.charAt(0).toUpperCase()+t.slice(1),"angular-elastic-builder/types/"+t+".html"},e.booleans=["False","True"],e.booleansOrder=["True","False"],e.inputNeeded=function(){var t=["equals","notEquals","gt","gte","lt","lte"];return~t.indexOf(e.rule.subType)}}}}])}(window.angular),function(e){"use strict";e.module("angular-elastic-builder").factory("groupClassHelper",function(){return function(e){var t=["","list-group-item-info","list-group-item-success","list-group-item-warning","list-group-item-danger"];return t[e%t.length]}})}(window.angular),function(e){"use strict";function t(e,t){var n=e.map(i.bind(e,t));return n}function n(e,t){var n=e.map(a.bind(e,t)).filter(function(e){return!!e});return n}function i(e,t,n){n!==!1&&(n=!0);var a=Object.keys(t)[0],r={or:"group",and:"group",range:"number"},s=r[a]||"item",u=l(s);switch(a){case"or":case"and":u.rules=t[a].map(i.bind(t,e)),u.subType=a;break;case"missing":case"exists":u.field=t[a].field,u.subType={exists:"exists",missing:"notExists"}[a],delete u.value;break;case"term":case"terms":u.field=Object.keys(t[a])[0];var o=e[Object.keys(t[a])[0]];if("multi"===o.type){var c=t[a][u.field];"string"==typeof c&&(c=[c]),u.values=o.choices.reduce(function(e,i){return e[i]=n===t[a][u.field].indexOf(i)>-1,e},{})}else u.subType=n?"equals":"notEquals",u.value=t[a][u.field],"number"==typeof u.value&&(u.subType="boolean");break;case"range":u.field=Object.keys(t[a])[0],u.subType=Object.keys(t[a][u.field])[0],u.value=t[a][u.field][u.subType];break;case"not":u=i(e,t[a].filter,!1);break;default:u.field=Object.keys(t[a])[0]}return u}function a(e,t){var n={};if("group"===t.type)return n[t.subType]=t.rules.map(a.bind(t,e)).filter(function(e){return!!e}),n;var i=t.field,l=e[i];if(i){switch(l.type){case"term":if("boolean"===l.subType&&(t.subType="boolean"),!t.subType)return;switch(t.subType){case"equals":case"boolean":if(void 0===t.value)return;n.term={},n.term[i]=t.value;break;case"notEquals":if(void 0===t.value)return;n.not={filter:{term:{}}},n.not.filter.term[i]=t.value;break;case"exists":n.exists={field:i};break;case"notExists":n.missing={field:i};break;default:throw new Error("unexpected subtype "+t.subType)}break;case"number":n.range={},n.range[i]={},n.range[i][t.subType]=t.value;break;case"date":if("exists"===t.subType)n.exists={field:i};else{if("notExists"!==t.subType)throw new Error("unexpected subtype");n.missing={field:i}}break;case"multi":n.terms={},n.terms[i]=Object.keys(t.values||{}).reduce(function(e,n){return t.values[n]&&e.push(n),e},[]);break;default:throw new Error("unexpected type")}return n}}function l(t){var n={group:{type:"group",subType:"",rules:[]},item:{field:"",subType:"",value:""},number:{field:"",subType:"",value:null}};return e.copy(n[t])}e.module("angular-elastic-builder").factory("elasticQueryService",[function(){return{toFilters:t,toQuery:n}}])}(window.angular),function(e){"use strict";e.module("angular-elastic-builder").run(["$templateCache",function(e){e.put("angular-elastic-builder/BuilderDirective.html",'
\n
\n
\n
\n
\n \n \n
\n
\n
\n\n'),e.put("angular-elastic-builder/ChooserDirective.html",'\n\n
\n\n
\n\n\n'),e.put("angular-elastic-builder/GroupDirective.html",'
\n
If\n \n of these conditions are met\n
\n
\n\n
\n \n \n
\n\n \n\n'),e.put("angular-elastic-builder/RuleDirective.html",'
\n \n\n \n\n \n\n
\n'),e.put("angular-elastic-builder/types/Boolean.html",'\n Equals\n\n \n \n \n\n'),e.put("angular-elastic-builder/types/Multi.html",'\n \n \n \n\n'),e.put("angular-elastic-builder/types/Number.html",'\n \n\n \n \n\n'),e.put("angular-elastic-builder/types/Term.html",'\n \n \n\n')}])}(window.angular); \ No newline at end of file +!function(e){"use strict";e.module("angular-elastic-builder",["RecursionHelper"])}(window.angular),function(e){"use strict";e.module("angular-elastic-builder").directive("elasticBuilder",["elasticQueryService",function(e){return{scope:{data:"=elasticBuilder"},templateUrl:"angular-elastic-builder/BuilderDirective.html",link:function(t){var n=t.data;t.removeChild=function(e){t.filters.splice(e,1)},t.addRule=function(){t.filters.push({})},t.addGroup=function(){t.filters.push({type:"group",subType:"and",rules:[]})},t.$watch("data.needsUpdate",function(a,i){a&&(t.filters=e.toFilters(n.query,t.data.fields),t.data.needsUpdate=!1)}),t.$watch("filters",function(a){a&&(n.query=e.toQuery(t.filters,t.data.fields))},!0)}}}])}(window.angular),function(e){"use strict";var t=e.module("angular-elastic-builder");t.directive("elasticBuilderChooser",["RecursionHelper","groupClassHelper",function(e,t){return{scope:{elasticFields:"=",item:"=elasticBuilderChooser",onRemove:"&"},templateUrl:"angular-elastic-builder/ChooserDirective.html",compile:function(n){return e.compile(n,function(e,n,a){var i=e.depth=+a.depth,l=e.item;e.getGroupClassName=function(){var e=i;return"group"===l.type&&e++,t(e)}})}}}])}(window.angular),function(e){"use strict";var t=e.module("angular-elastic-builder");t.directive("elasticBuilderGroup",["RecursionHelper","groupClassHelper",function(e,t){return{scope:{elasticFields:"=",group:"=elasticBuilderGroup",onRemove:"&"},templateUrl:"angular-elastic-builder/GroupDirective.html",compile:function(n){return e.compile(n,function(e,n,a){var i=e.depth=+a.depth,l=e.group;e.addRule=function(){l.rules.push({})},e.addGroup=function(){l.rules.push({type:"group",subType:"and",rules:[]})},e.removeChild=function(e){l.rules.splice(e,1)},e.getGroupClassName=function(){return t(i+1)}})}}}])}(window.angular),function(e){"use strict";var t=e.module("angular-elastic-builder");t.directive("elasticBuilderRule",[function(){return{scope:{elasticFields:"=",rule:"=elasticBuilderRule",onRemove:"&"},templateUrl:"angular-elastic-builder/RuleDirective.html",link:function(e){e.getType=function(){var t=e.elasticFields,n=e.rule.field;if(t&&n)return"boolean"===t[n].subType?"boolean":t[n].type}}}}])}(window.angular),function(e){"use strict";var t=e.module("angular-elastic-builder");t.directive("elasticType",[function(){return{scope:{type:"=elasticType",rule:"=",guide:"="},template:'',link:function(e){e.getTemplateUrl=function(){var t=e.type;if(t)return t=t.charAt(0).toUpperCase()+t.slice(1),"angular-elastic-builder/types/"+t+".html"},e.booleans=["False","True"],e.booleansOrder=["True","False"],e.inputNeeded=function(){var t=["equals","notEquals","gt","gte","lt","lte"];return~t.indexOf(e.rule.subType)}}}}])}(window.angular),function(e){"use strict";e.module("angular-elastic-builder").run(["$templateCache",function(e){e.put("angular-elastic-builder/BuilderDirective.html",'
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n
\n
\n\n'),e.put("angular-elastic-builder/ChooserDirective.html",'\n\n
\n\n
\n\n\n'),e.put("angular-elastic-builder/GroupDirective.html",'
\n
If\n \n of these conditions are met\n
\n
\n\n
\n \n \n \n \n \n \n
\n\n \n \n \n\n'),e.put("angular-elastic-builder/RuleDirective.html",'
\n \n\n \n\n \n \n \n\n
\n'),e.put("angular-elastic-builder/types/Boolean.html",'\n Equals\n\n \n \n \n\n'),e.put("angular-elastic-builder/types/Multi.html",'\n \n \n \n\n'),e.put("angular-elastic-builder/types/Number.html",'\n \n\n \n \n\n'),e.put("angular-elastic-builder/types/Term.html",'\n \n \n\n')}])}(window.angular),function(e){"use strict";e.module("angular-elastic-builder").factory("groupClassHelper",function(){return function(e){var t=["","list-group-item-info","list-group-item-success","list-group-item-warning","list-group-item-danger"];return t[e%t.length]}})}(window.angular),function(e){"use strict";function t(e,t){var n=e.map(a.bind(e,t));return n}function n(e,t){var n=e.map(i.bind(e,t)).filter(function(e){return!!e});return n}function a(e,t,n){n!==!1&&(n=!0);var i=Object.keys(t)[0],r={or:"group",and:"group",range:"number"},s=r[i]||"item",u=l(s);switch(i){case"or":case"and":u.rules=t[i].map(a.bind(t,e)),u.subType=i;break;case"missing":case"exists":u.field=t[i].field,u.subType={exists:"exists",missing:"notExists"}[i],delete u.value;break;case"term":case"terms":u.field=Object.keys(t[i])[0];var o=e[Object.keys(t[i])[0]];if("multi"===o.type){var c=t[i][u.field];"string"==typeof c&&(c=[c]),u.values=o.choices.reduce(function(e,a){return e[a]=n===t[i][u.field].indexOf(a)>-1,e},{})}else u.subType=n?"equals":"notEquals",u.value=t[i][u.field],"number"==typeof u.value&&(u.subType="boolean");break;case"range":u.field=Object.keys(t[i])[0],u.subType=Object.keys(t[i][u.field])[0],u.value=t[i][u.field][u.subType];break;case"not":u=a(e,t[i].filter,!1);break;default:u.field=Object.keys(t[i])[0]}return u}function i(e,t){var n={};if("group"===t.type)return n[t.subType]=t.rules.map(i.bind(t,e)).filter(function(e){return!!e}),n;var a=t.field,l=e[a];if(a){switch(l.type){case"term":if("boolean"===l.subType&&(t.subType="boolean"),!t.subType)return;switch(t.subType){case"equals":case"boolean":if(void 0===t.value)return;n.term={},n.term[a]=t.value;break;case"notEquals":if(void 0===t.value)return;n.not={filter:{term:{}}},n.not.filter.term[a]=t.value;break;case"exists":n.exists={field:a};break;case"notExists":n.missing={field:a};break;default:throw new Error("unexpected subtype "+t.subType)}break;case"number":n.range={},n.range[a]={},n.range[a][t.subType]=t.value;break;case"date":if("exists"===t.subType)n.exists={field:a};else{if("notExists"!==t.subType)throw new Error("unexpected subtype");n.missing={field:a}}break;case"multi":n.terms={},n.terms[a]=Object.keys(t.values||{}).reduce(function(e,n){return t.values[n]&&e.push(n),e},[]);break;default:throw new Error("unexpected type")}return n}}function l(t){var n={group:{type:"group",subType:"",rules:[]},item:{field:"",subType:"",value:""},number:{field:"",subType:"",value:null}};return e.copy(n[t])}e.module("angular-elastic-builder").factory("elasticQueryService",[function(){return{toFilters:t,toQuery:n}}])}(window.angular); \ No newline at end of file diff --git a/examples/js/exampleApp.js b/examples/js/exampleApp.js index 12dfb76..ee4a7e8 100644 --- a/examples/js/exampleApp.js +++ b/examples/js/exampleApp.js @@ -60,6 +60,8 @@ 'test.state.multi': { type: 'multi', choices: [ 'AZ', 'CA', 'CT' ]} }; + data.needsUpdate = true; + this.showQuery = function() { var queryToShow = { size: 0, diff --git a/package.json b/package.json index d9c40f9..9144323 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-elastic-builder", - "version": "1.2.0", + "version": "1.3.0", "description": "Angular Module for building an Elasticsearch Query", "author": "Dan Crews ", "license": "MIT", diff --git a/src/directives/BuilderDirective.js b/src/directives/BuilderDirective.js index 3a453ac..7a55f14 100644 --- a/src/directives/BuilderDirective.js +++ b/src/directives/BuilderDirective.js @@ -51,16 +51,15 @@ }; /** - * this Watcher gets used only once on initial setting of the query and then not again + * Any time "outside forces" change the query, they should tell us so via + * `data.needsUpdate` */ - var unwatcher = scope.$watch('data.query', function(curr) { + scope.$watch('data.needsUpdate', function(curr, prev) { if (! curr) return; scope.filters = elasticQueryService.toFilters(data.query, scope.data.fields); - - /* Stop Watching */ - unwatcher(); - }, true); + scope.data.needsUpdate = false; + }); /** * Changes on the page update the Query diff --git a/src/tmpl/BuilderDirective.html b/src/tmpl/BuilderDirective.html index d31cef8..c0f6937 100644 --- a/src/tmpl/BuilderDirective.html +++ b/src/tmpl/BuilderDirective.html @@ -8,12 +8,12 @@ data-on-remove="removeChild($index)" data-depth="0"> diff --git a/src/tmpl/ElasticBuilderTemplates.js b/src/tmpl/ElasticBuilderTemplates.js index c766925..d0ce300 100644 --- a/src/tmpl/ElasticBuilderTemplates.js +++ b/src/tmpl/ElasticBuilderTemplates.js @@ -1,8 +1,8 @@ -(function(angular) {"use strict"; angular.module("angular-elastic-builder").run(["$templateCache", function($templateCache) {$templateCache.put("angular-elastic-builder/BuilderDirective.html","
\n
\n
\n
\n
\n \n \n
\n
\n
\n\n"); +(function(angular) {"use strict"; angular.module("angular-elastic-builder").run(["$templateCache", function($templateCache) {$templateCache.put("angular-elastic-builder/BuilderDirective.html","
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n
\n
\n\n"); $templateCache.put("angular-elastic-builder/ChooserDirective.html","\n\n
\n\n
\n\n\n"); -$templateCache.put("angular-elastic-builder/GroupDirective.html","
\n
If\n \n of these conditions are met\n
\n
\n\n
\n \n \n
\n\n \n\n"); -$templateCache.put("angular-elastic-builder/RuleDirective.html","
\n \n\n \n\n \n\n
\n"); +$templateCache.put("angular-elastic-builder/GroupDirective.html","
\n
If\n \n of these conditions are met\n
\n
\n\n
\n \n \n \n \n \n \n
\n\n \n \n \n\n"); +$templateCache.put("angular-elastic-builder/RuleDirective.html","
\n \n\n \n\n \n \n \n\n
\n"); $templateCache.put("angular-elastic-builder/types/Boolean.html","\n Equals\n\n \n \n \n\n"); -$templateCache.put("angular-elastic-builder/types/Multi.html","\n \n \n \n\n"); +$templateCache.put("angular-elastic-builder/types/Multi.html","\n \n \n \n\n"); $templateCache.put("angular-elastic-builder/types/Number.html","\n \n\n \n \n\n"); $templateCache.put("angular-elastic-builder/types/Term.html","\n \n \n\n");}]);})(window.angular); \ No newline at end of file diff --git a/src/tmpl/GroupDirective.html b/src/tmpl/GroupDirective.html index b5d759c..4f4366f 100644 --- a/src/tmpl/GroupDirective.html +++ b/src/tmpl/GroupDirective.html @@ -14,15 +14,15 @@
If data-on-remove="removeChild($index)"> - + diff --git a/src/tmpl/RuleDirective.html b/src/tmpl/RuleDirective.html index 685ebbd..9b1d2c0 100644 --- a/src/tmpl/RuleDirective.html +++ b/src/tmpl/RuleDirective.html @@ -3,8 +3,8 @@ - + diff --git a/src/tmpl/types/Multi.html b/src/tmpl/types/Multi.html index 981ce87..3c0e5a1 100644 --- a/src/tmpl/types/Multi.html +++ b/src/tmpl/types/Multi.html @@ -1,6 +1,6 @@ -