dynamic_scope 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/README.md +3 -0
- data/Rakefile +4 -0
- data/app/assets/images/dynamic_scope/fieldset-remove.png +0 -0
- data/app/assets/javascripts/angular-dynamic-scope.coffee +201 -0
- data/app/assets/javascripts/angular-multiple-dynamic-scope.coffee +249 -0
- data/app/assets/javascripts/dynamic_scope.coffee +110 -0
- data/app/assets/stylesheets/dynamic_scope.sass +104 -0
- data/config/locales/dynamic_scope.de.yml +24 -0
- data/config/locales/dynamic_scope.en.yml +24 -0
- data/config/locales/dynamic_scope.fr.yml +24 -0
- data/config/locales/dynamic_scope.it.yml +24 -0
- data/dynamic_scope.gemspec +29 -0
- data/lib/dynamic_scope/acts_as_dynamically_scopable.rb +17 -0
- data/lib/dynamic_scope/class_methods.rb +71 -0
- data/lib/dynamic_scope/concerns/active_record.rb +19 -0
- data/lib/dynamic_scope/concerns.rb +2 -0
- data/lib/dynamic_scope/engine.rb +7 -0
- data/lib/dynamic_scope/processor.rb +89 -0
- data/lib/dynamic_scope/query.rb +205 -0
- data/lib/dynamic_scope/query_helpers.rb +11 -0
- data/lib/dynamic_scope/version.rb +5 -0
- data/lib/dynamic_scope/view_helpers.rb +192 -0
- data/lib/dynamic_scope.rb +14 -0
- metadata +135 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 0d425d85513eb249492e79b15ce14e476caa492b4cd7405b225815a4ab4db4cb
|
|
4
|
+
data.tar.gz: f9170279fd99494cc09101f27eed85bb820c03b26659afeee6d130e235a9a0bf
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 67556f423e7f2508c59a56de695a862c22a0f6e7300afed4ab5b2cf2b027cff9375cc3686d0d8fb045adece488a46012243024ab6e9acc16eadafd857b708871
|
|
7
|
+
data.tar.gz: 46d4aa58d0d0c5e30cafa0eaa11b3dfee3e12ff7efaa19e2dc45b355dc290e9c268f96f92c22d767a594948500a0dd82853c5e9d4b7cc74a59ad03eef49d8d01
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
|
Binary file
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#= require i18n
|
|
2
|
+
#= require i18n/translations
|
|
3
|
+
|
|
4
|
+
dynamicScope = angular.module('dynamicScope', [])
|
|
5
|
+
|
|
6
|
+
dynamicScope.directive 'dynamicScope', ['$parse', ($parse) ->
|
|
7
|
+
OPERATORS = {
|
|
8
|
+
integer: ['eq', 'not_eq', 'gteq', 'lteq'],
|
|
9
|
+
string: ['matches', 'does_not_match', 'begins_with', 'ends_with', 'eq', 'not_eq'],
|
|
10
|
+
enum: ['eq', 'not_eq', 'in', 'not_in'],
|
|
11
|
+
year: ['eq', 'gteq', 'lteq'],
|
|
12
|
+
month: ['eq', 'gteq', 'lteq'],
|
|
13
|
+
date: ['eq', 'gteq', 'lteq'],
|
|
14
|
+
datetime: ['eq', 'gteq', 'lteq'],
|
|
15
|
+
boolean: ['eq', 'not_eq']
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
IN_OPERATORS = ['in', 'not_in']
|
|
19
|
+
|
|
20
|
+
DEFAULT_VALUES = {
|
|
21
|
+
boolean: true
|
|
22
|
+
enum: undefined
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
defaultQuery = (config) ->
|
|
26
|
+
inputKey = Object.keys(config)[0]
|
|
27
|
+
inputOptions = config[inputKey]
|
|
28
|
+
[
|
|
29
|
+
{
|
|
30
|
+
key: inputKey
|
|
31
|
+
operator: (inputOptions.operators || OPERATORS[inputOptions.type])[0]
|
|
32
|
+
value: ''
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
objectQueryToArray = (objectQuery = {}) ->
|
|
37
|
+
arrayQuery = []
|
|
38
|
+
Object.keys(objectQuery).forEach (key) ->
|
|
39
|
+
arrayQuery[key] = objectQuery[key]
|
|
40
|
+
arrayQuery
|
|
41
|
+
|
|
42
|
+
arrayQueryToObject = (arrayQuery = []) ->
|
|
43
|
+
objectQuery = {}
|
|
44
|
+
arrayQuery.forEach (queryPart, index) ->
|
|
45
|
+
objectQuery[index] = queryPart
|
|
46
|
+
objectQuery
|
|
47
|
+
|
|
48
|
+
translateKey = (key) ->
|
|
49
|
+
I18n.t("dynamic_scope.key.#{key}")
|
|
50
|
+
|
|
51
|
+
translateAndSortKeys = (keys) ->
|
|
52
|
+
_.chain(keys)
|
|
53
|
+
.inject((memo, key) ->
|
|
54
|
+
memo.push([key, translateKey(key)])
|
|
55
|
+
memo
|
|
56
|
+
, [])
|
|
57
|
+
.sortBy((keyAndName) ->
|
|
58
|
+
keyAndName[1]
|
|
59
|
+
).value()
|
|
60
|
+
|
|
61
|
+
{
|
|
62
|
+
controllerAs: 'dynamicScope'
|
|
63
|
+
controller: ['$scope', '$element', '$attrs', '$transclude', ($scope, $element, $attrs, $transclude) ->
|
|
64
|
+
optionsAccessor = $parse($attrs.dynamicScope)
|
|
65
|
+
ctrl = this
|
|
66
|
+
|
|
67
|
+
@options = optionsAccessor($scope) || {}
|
|
68
|
+
@config = @options.config
|
|
69
|
+
|
|
70
|
+
if queryVarName = @options.query
|
|
71
|
+
$scope.$watch queryVarName, (newQuery) ->
|
|
72
|
+
ctrl.query = objectQueryToArray(newQuery)
|
|
73
|
+
|
|
74
|
+
@query ||= defaultQuery(@config)
|
|
75
|
+
|
|
76
|
+
@keysForNgOptions = translateAndSortKeys(_.keys(@config))
|
|
77
|
+
|
|
78
|
+
$scope.minDate = new Date()
|
|
79
|
+
|
|
80
|
+
@typeFor = (key) ->
|
|
81
|
+
ctrl.config[key].type
|
|
82
|
+
|
|
83
|
+
@operatorsFor = (key) ->
|
|
84
|
+
ctrl.config[key].operators || OPERATORS[ctrl.typeFor(key)]
|
|
85
|
+
|
|
86
|
+
@valuesFor = (key) ->
|
|
87
|
+
ctrl.config[key].values
|
|
88
|
+
|
|
89
|
+
@translateOperator = (operator) ->
|
|
90
|
+
I18n.t("dynamic_scope.operator.#{operator}")
|
|
91
|
+
|
|
92
|
+
@translateValue = (key, value, returnError) ->
|
|
93
|
+
return value if (returnError == false && I18n.t("dynamic_scope.values.#{key}.#{value}").includes("[missing", "translation]"))
|
|
94
|
+
I18n.t("dynamic_scope.values.#{key}.#{value}")
|
|
95
|
+
|
|
96
|
+
@addInput = ->
|
|
97
|
+
ctrl.query.push defaultQuery(ctrl.config)[0]
|
|
98
|
+
|
|
99
|
+
@removeInput = (input) ->
|
|
100
|
+
ctrl.query.splice(ctrl.query.indexOf(input), 1)
|
|
101
|
+
|
|
102
|
+
@submit = ->
|
|
103
|
+
ctrl.options.submit(arrayQueryToObject(ctrl.query))
|
|
104
|
+
|
|
105
|
+
@clearQuery = ->
|
|
106
|
+
ctrl.query = defaultQuery(ctrl.config)
|
|
107
|
+
|
|
108
|
+
@setInputDefaults = (queryPart) ->
|
|
109
|
+
if (defaultValue = DEFAULT_VALUES[ctrl.typeFor(queryPart.key)])?
|
|
110
|
+
queryPart.value = defaultValue
|
|
111
|
+
|
|
112
|
+
inputOperators = ctrl.operatorsFor(queryPart.key)
|
|
113
|
+
if inputOperators.indexOf(queryPart.operator) == -1
|
|
114
|
+
queryPart.operator = inputOperators[0]
|
|
115
|
+
|
|
116
|
+
@inputChanged = (type, value, queryPart) ->
|
|
117
|
+
console.log(value)
|
|
118
|
+
console.log(queryPart._value)
|
|
119
|
+
switch type
|
|
120
|
+
when 'month'
|
|
121
|
+
queryPart.value = "#{queryPart._value[0]}-#{queryPart._value[1]}"
|
|
122
|
+
|
|
123
|
+
@useMultiselect = (queryPart) ->
|
|
124
|
+
IN_OPERATORS.indexOf(queryPart.operator) >= 0
|
|
125
|
+
|
|
126
|
+
@operatorChanged = (queryPart) ->
|
|
127
|
+
type = ctrl.typeFor(queryPart.key)
|
|
128
|
+
switch type
|
|
129
|
+
when 'enum'
|
|
130
|
+
if IN_OPERATORS.indexOf(queryPart.operator) >= 0
|
|
131
|
+
queryPart.value = [queryPart.value] if typeof queryPart.value == 'string'
|
|
132
|
+
else if typeof queryPart.value == 'object'
|
|
133
|
+
queryPart.value = queryPart.value[0]
|
|
134
|
+
|
|
135
|
+
@keyChanged = (queryPart) ->
|
|
136
|
+
type = ctrl.typeFor(queryPart.key)
|
|
137
|
+
switch type
|
|
138
|
+
when 'enum'
|
|
139
|
+
queryPart.value = undefined
|
|
140
|
+
ctrl.setInputDefaults(queryPart)
|
|
141
|
+
|
|
142
|
+
return this
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
link: ($scope, $elem, $attrs) ->
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
dynamicScope.directive 'dynamicScopeFieldset', ->
|
|
150
|
+
keySelectTemplate = '<select class="key form-control" ng-model="queryPart.key" ng-options="keyAndName[0] as keyAndName[1] for keyAndName in dynamicScope.keysForNgOptions" ng-change="dynamicScope.keyChanged(queryPart)"></select>'
|
|
151
|
+
operatorSelectTemplate = '<select class="operator form-control" ng-model="queryPart.operator" ng-options="operator as dynamicScope.translateOperator(operator) for operator in dynamicScope.operatorsFor(queryPart.key)" ng-change="dynamicScope.operatorChanged(queryPart)"></select>'
|
|
152
|
+
stringInputTemplate = '<input class="value form-control type-string" type="text" ng-model="queryPart.value" ng-switch-when="string"></input>'
|
|
153
|
+
integerInputTemplate = '<input class="value form-control type-integer" type="text" ng-model="queryPart.value" ng-switch-when="integer"></input>'
|
|
154
|
+
enumSelectTemplate =
|
|
155
|
+
'<div class="value type-enum" ng-switch-when="enum">' +
|
|
156
|
+
'<ui-select multiple ng-if="dynamicScope.useMultiselect(queryPart)" ng-model="queryPart.value">' +
|
|
157
|
+
'<ui-select-match>{{$item ? dynamicScope.translateValue(queryPart.key, $item, false) : $item}}</ui-select-match>' +
|
|
158
|
+
'<ui-select-choices repeat="value in dynamicScope.valuesFor(queryPart.key)">{{dynamicScope.translateValue(queryPart.key, value, false)}}</ui-select-choices>' +
|
|
159
|
+
'</ui-select>' +
|
|
160
|
+
'<select class="form-control" ng-if="!dynamicScope.useMultiselect(queryPart)" ng-model="queryPart.value" ng-options="value as dynamicScope.translateValue(queryPart.key, value, false) for value in dynamicScope.valuesFor(queryPart.key)"></select>' +
|
|
161
|
+
'</div>'
|
|
162
|
+
yearInputTemplate = '<input type="year" class="value form-control type-year" ng-model="queryPart.value" ng-switch-when="year" placeholder="YYYY"></input>'
|
|
163
|
+
monthInputTemplate =
|
|
164
|
+
'<div class="value type-month" ng-switch-when="month">' +
|
|
165
|
+
'<input class="year form-control" type="number" min="0" max="9999" ng-model="queryPart._value[0]" placeholder="YYYY" ng-change="dynamicScope.inputChanged(\'month\', _value, queryPart)"></input>' +
|
|
166
|
+
'<select class="month form-control" ng-model="queryPart._value[1]" ng-change="dynamicScope.inputChanged(\'month\', _value, queryPart)">' +
|
|
167
|
+
'<option value="1">' + I18n.t('date.month_names.1') + '</value>' +
|
|
168
|
+
'<option value="2">' + I18n.t('date.month_names.2') + '</value>' +
|
|
169
|
+
'<option value="3">' + I18n.t('date.month_names.3') + '</value>' +
|
|
170
|
+
'<option value="4">' + I18n.t('date.month_names.4') + '</value>' +
|
|
171
|
+
'<option value="5">' + I18n.t('date.month_names.5') + '</value>' +
|
|
172
|
+
'<option value="6">' + I18n.t('date.month_names.6') + '</value>' +
|
|
173
|
+
'<option value="7">' + I18n.t('date.month_names.7') + '</value>' +
|
|
174
|
+
'<option value="8">' + I18n.t('date.month_names.8') + '</value>' +
|
|
175
|
+
'<option value="9">' + I18n.t('date.month_names.9') + '</value>' +
|
|
176
|
+
'<option value="10">' + I18n.t('date.month_names.10') + '</value>' +
|
|
177
|
+
'<option value="11">' + I18n.t('date.month_names.11') + '</value>' +
|
|
178
|
+
'<option value="12">' + I18n.t('date.month_names.12') + '</value>' +
|
|
179
|
+
'</select>' +
|
|
180
|
+
'</div>'
|
|
181
|
+
dateFutureInputTemplate = '<div class="value type-date-future" ng-switch-when="date_future"><date-input min="{{minDate | date:\'yyyy-MM-dd\'}}" ng-model="queryPart.value"></date-input></div>'
|
|
182
|
+
dateInputTemplate = '<div class="value type-date" ng-switch-when="date"><date-input ng-model="queryPart.value"></date-input></div>'
|
|
183
|
+
datetimeInputTemplate = '<div class="value type-datetime" ng-switch-when="datetime"><datetime-input ng-model="queryPart.value"></datetime-input></div>'
|
|
184
|
+
booleanSelectTemplate = '<select class="value form-control type-boolean" ng-model="queryPart.value" ng-switch-when="boolean" ng-options="value as dynamicScope.translateValue(queryPart.key, value) for value in [true, false]"></select>'
|
|
185
|
+
fieldsetRemoveTemplate = '<a class="fieldset-remove" href="javascript:;" ng-click="dynamicScope.removeInput(queryPart)" ng-show="dynamicScope.query.length > 1">' + I18n.t('dynamic_scope.remove_fieldset') + '</a>'
|
|
186
|
+
{
|
|
187
|
+
template: '<fieldset ng-repeat="queryPart in dynamicScope.query" ng-switch="dynamicScope.typeFor(queryPart.key)" class="ng-scope">' +
|
|
188
|
+
keySelectTemplate +
|
|
189
|
+
operatorSelectTemplate +
|
|
190
|
+
stringInputTemplate +
|
|
191
|
+
integerInputTemplate +
|
|
192
|
+
enumSelectTemplate +
|
|
193
|
+
yearInputTemplate +
|
|
194
|
+
monthInputTemplate +
|
|
195
|
+
dateFutureInputTemplate +
|
|
196
|
+
dateInputTemplate +
|
|
197
|
+
datetimeInputTemplate +
|
|
198
|
+
#booleanSelectTemplate +
|
|
199
|
+
fieldsetRemoveTemplate +
|
|
200
|
+
'</fieldset>'
|
|
201
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#= require i18n
|
|
2
|
+
#= require i18n/translations
|
|
3
|
+
|
|
4
|
+
multipleDynamicScope = angular.module('multipleDynamicScope', [])
|
|
5
|
+
|
|
6
|
+
multipleDynamicScope.directive 'multipleDynamicScope', ['$parse', ($parse) ->
|
|
7
|
+
OPERATORS = {
|
|
8
|
+
integer: ['eq', 'not_eq', 'gteq', 'lteq'],
|
|
9
|
+
string: ['matches', 'does_not_match', 'begins_with', 'ends_with', 'eq', 'not_eq'],
|
|
10
|
+
enum: ['eq', 'not_eq', 'in', 'not_in'],
|
|
11
|
+
year: ['eq', 'gteq', 'lteq'],
|
|
12
|
+
month: ['eq', 'gteq', 'lteq'],
|
|
13
|
+
date: ['eq', 'gteq', 'lteq'],
|
|
14
|
+
datetime: ['eq', 'gteq', 'lteq'],
|
|
15
|
+
boolean: ['eq', 'not_eq']
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
IN_OPERATORS = ['in', 'not_in']
|
|
19
|
+
|
|
20
|
+
DEFAULT_VALUES = {
|
|
21
|
+
boolean: true
|
|
22
|
+
enum: undefined
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
sectionDefaultQuery = (section, sections) ->
|
|
26
|
+
inputKey = Object.keys(sections[section])[0]
|
|
27
|
+
inputOptions = sections[section][inputKey]
|
|
28
|
+
[
|
|
29
|
+
{
|
|
30
|
+
key: inputKey
|
|
31
|
+
operator: (inputOptions.operators || OPERATORS[inputOptions.type])[0]
|
|
32
|
+
value: ''
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
defaultQuery = (sections) ->
|
|
37
|
+
query = {}
|
|
38
|
+
Object.keys(sections).forEach (section) ->
|
|
39
|
+
query[section] = sectionDefaultQuery(section, sections)
|
|
40
|
+
query
|
|
41
|
+
|
|
42
|
+
objectQueryToQuerySections = (config, default_section, objectQuery = {}) ->
|
|
43
|
+
querySections = {}
|
|
44
|
+
angular.forEach objectQuery, (value, key) ->
|
|
45
|
+
section = if config[value.key].section == undefined then default_section else config[objectQuery[key].key].section
|
|
46
|
+
querySections[section] ||= []
|
|
47
|
+
querySections[section].push(objectQuery[key])
|
|
48
|
+
querySections
|
|
49
|
+
|
|
50
|
+
querySectionsToObject = (querySections = []) ->
|
|
51
|
+
objectQuery = {}
|
|
52
|
+
index = 0
|
|
53
|
+
Object.keys(querySections).forEach (key) ->
|
|
54
|
+
querySections[key].forEach (queryPart) ->
|
|
55
|
+
objectQuery[index++] = queryPart
|
|
56
|
+
objectQuery
|
|
57
|
+
|
|
58
|
+
translateKey = (key) ->
|
|
59
|
+
I18n.t("dynamic_scope.key.#{key}")
|
|
60
|
+
|
|
61
|
+
translateAndSortKeys = (sections) ->
|
|
62
|
+
translations = {}
|
|
63
|
+
Object.keys(sections).forEach (section_name) ->
|
|
64
|
+
translations[section_name] =
|
|
65
|
+
_.chain(_.keys(sections[section_name]))
|
|
66
|
+
.inject((memo, key) ->
|
|
67
|
+
memo.push([key, translateKey(key)])
|
|
68
|
+
memo
|
|
69
|
+
, [])
|
|
70
|
+
.sortBy((keyAndName) ->
|
|
71
|
+
keyAndName[1]
|
|
72
|
+
).value()
|
|
73
|
+
translations
|
|
74
|
+
|
|
75
|
+
makeSections = (config, default_section) ->
|
|
76
|
+
sections = {}
|
|
77
|
+
if config
|
|
78
|
+
Object.keys(config).forEach (key) ->
|
|
79
|
+
section = config[key].section || default_section
|
|
80
|
+
sections[section] ||= {}
|
|
81
|
+
sections[section][key] = config[key]
|
|
82
|
+
sections
|
|
83
|
+
|
|
84
|
+
makeMapping = (sections) ->
|
|
85
|
+
mapping = {}
|
|
86
|
+
Object.keys(sections).forEach (section) ->
|
|
87
|
+
mapping[section] = Object.keys(sections[section])
|
|
88
|
+
mapping
|
|
89
|
+
|
|
90
|
+
{
|
|
91
|
+
controllerAs: 'multipleDynamicScope'
|
|
92
|
+
controller: ['$rootScope', '$scope', '$element', '$attrs', '$transclude', ($rootScope, $scope, $element, $attrs, $transclude) ->
|
|
93
|
+
optionsAccessor = $parse($attrs.multipleDynamicScope)
|
|
94
|
+
ctrl = this
|
|
95
|
+
|
|
96
|
+
@options = optionsAccessor($scope) || {}
|
|
97
|
+
@config = @options.config
|
|
98
|
+
@default_section = @options.default_section
|
|
99
|
+
@sections = makeSections(@config, @default_section)
|
|
100
|
+
@section_fields = makeMapping(@sections)
|
|
101
|
+
|
|
102
|
+
if queryVarName = @options.query
|
|
103
|
+
$scope.$watch queryVarName, (newQuery) ->
|
|
104
|
+
ctrl.query = objectQueryToQuerySections(ctrl.config, ctrl.default_section, newQuery)
|
|
105
|
+
|
|
106
|
+
@query ||= defaultQuery(@sections)
|
|
107
|
+
|
|
108
|
+
@keysForNgOptions = translateAndSortKeys(@sections)
|
|
109
|
+
|
|
110
|
+
$scope.minDate = new Date()
|
|
111
|
+
|
|
112
|
+
@queryFor = (section) ->
|
|
113
|
+
section_query = []
|
|
114
|
+
ctrl.query.forEach (row) ->
|
|
115
|
+
if ctrl.section_fields[section].includes(row.key)
|
|
116
|
+
section_query.push(row)
|
|
117
|
+
section_query
|
|
118
|
+
|
|
119
|
+
@typeFor = (key) ->
|
|
120
|
+
ctrl.config[key].type
|
|
121
|
+
|
|
122
|
+
@operatorsFor = (key) ->
|
|
123
|
+
ctrl.config[key].operators || OPERATORS[ctrl.typeFor(key)]
|
|
124
|
+
|
|
125
|
+
@valuesFor = (key) ->
|
|
126
|
+
ctrl.config[key].values
|
|
127
|
+
|
|
128
|
+
@translateOperator = (operator) ->
|
|
129
|
+
I18n.t("dynamic_scope.operator.#{operator}")
|
|
130
|
+
|
|
131
|
+
@translateValue = (key, value, returnError) ->
|
|
132
|
+
return value if (returnError == false && I18n.t("dynamic_scope.values.#{key}.#{value}").includes("[missing", "translation]"))
|
|
133
|
+
I18n.t("dynamic_scope.values.#{key}.#{value}")
|
|
134
|
+
|
|
135
|
+
@addInput = (section) ->
|
|
136
|
+
ctrl.query[section].push sectionDefaultQuery(section, ctrl.sections)[0]
|
|
137
|
+
|
|
138
|
+
@removeInput = (input, section) ->
|
|
139
|
+
if ctrl.query[section].length > 1
|
|
140
|
+
ctrl.query[section].splice(ctrl.query[section].indexOf(input), 1)
|
|
141
|
+
else
|
|
142
|
+
$rootScope.$broadcast('removeLastFieldset', section)
|
|
143
|
+
|
|
144
|
+
@submit = ->
|
|
145
|
+
ctrl.options.submit(querySectionsToObject(ctrl.query))
|
|
146
|
+
|
|
147
|
+
@clearQuery = ->
|
|
148
|
+
ctrl.query = defaultQuery(ctrl.sections)
|
|
149
|
+
|
|
150
|
+
@setInputDefaults = (queryPart) ->
|
|
151
|
+
if (defaultValue = DEFAULT_VALUES[ctrl.typeFor(queryPart.key)])?
|
|
152
|
+
queryPart.value = defaultValue
|
|
153
|
+
|
|
154
|
+
inputOperators = ctrl.operatorsFor(queryPart.key)
|
|
155
|
+
if inputOperators.indexOf(queryPart.operator) == -1
|
|
156
|
+
queryPart.operator = inputOperators[0]
|
|
157
|
+
|
|
158
|
+
@inputChanged = (type, value, queryPart) ->
|
|
159
|
+
switch type
|
|
160
|
+
when 'month'
|
|
161
|
+
queryPart.value = "#{queryPart._value[0]}-#{queryPart._value[1]}"
|
|
162
|
+
|
|
163
|
+
@useMultiselect = (queryPart) ->
|
|
164
|
+
IN_OPERATORS.indexOf(queryPart.operator) >= 0
|
|
165
|
+
|
|
166
|
+
@operatorChanged = (queryPart) ->
|
|
167
|
+
type = ctrl.typeFor(queryPart.key)
|
|
168
|
+
switch type
|
|
169
|
+
when 'enum'
|
|
170
|
+
if IN_OPERATORS.indexOf(queryPart.operator) >= 0
|
|
171
|
+
queryPart.value = [queryPart.value] if typeof queryPart.value == 'string'
|
|
172
|
+
else if typeof queryPart.value == 'object'
|
|
173
|
+
queryPart.value = queryPart.value[0]
|
|
174
|
+
|
|
175
|
+
@keyChanged = (queryPart) ->
|
|
176
|
+
type = ctrl.typeFor(queryPart.key)
|
|
177
|
+
switch type
|
|
178
|
+
when 'enum'
|
|
179
|
+
queryPart.value = undefined
|
|
180
|
+
ctrl.setInputDefaults(queryPart)
|
|
181
|
+
|
|
182
|
+
return this
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
link: ($scope, $elem, $attrs) ->
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
|
|
189
|
+
multipleDynamicScope.directive 'multipleDynamicScopeFieldset', ['$parse', ($parse) ->
|
|
190
|
+
keySelectTemplate = '<select class="key form-control" ng-model="queryPart.key" ng-options="keyAndName[0] as keyAndName[1] for keyAndName in multipleDynamicScope.keysForNgOptions[section]" ng-change="multipleDynamicScope.keyChanged(queryPart)"></select>'
|
|
191
|
+
operatorSelectTemplate = '<select class="operator form-control" ng-model="queryPart.operator" ng-options="operator as multipleDynamicScope.translateOperator(operator) for operator in multipleDynamicScope.operatorsFor(queryPart.key)" ng-change="multipleDynamicScope.operatorChanged(queryPart)"></select>'
|
|
192
|
+
stringInputTemplate = '<input class="value form-control type-string" type="text" ng-model="queryPart.value" ng-switch-when="string"></input>'
|
|
193
|
+
integerInputTemplate = '<input class="value form-control type-integer" type="text" ng-model="queryPart.value" ng-switch-when="integer"></input>'
|
|
194
|
+
enumSelectTemplate =
|
|
195
|
+
'<div class="value type-enum" ng-switch-when="enum">' +
|
|
196
|
+
'<ui-select multiple ng-if="multipleDynamicScope.useMultiselect(queryPart)" ng-model="queryPart.value">' +
|
|
197
|
+
'<ui-select-match>{{$item ? multipleDynamicScope.translateValue(queryPart.key, $item, false) : $item}}</ui-select-match>' +
|
|
198
|
+
'<ui-select-choices repeat="value in multipleDynamicScope.valuesFor(queryPart.key)">{{multipleDynamicScope.translateValue(queryPart.key, value, false)}}</ui-select-choices>' +
|
|
199
|
+
'</ui-select>' +
|
|
200
|
+
'<select class="form-control" ng-if="!multipleDynamicScope.useMultiselect(queryPart)" ng-model="queryPart.value" ng-options="value as multipleDynamicScope.translateValue(queryPart.key, value, false) for value in multipleDynamicScope.valuesFor(queryPart.key)"></select>' +
|
|
201
|
+
'</div>'
|
|
202
|
+
yearInputTemplate = '<input type="year" class="value form-control type-year" ng-model="queryPart.value" ng-switch-when="year" placeholder="YYYY"></input>'
|
|
203
|
+
monthInputTemplate =
|
|
204
|
+
'<div class="value type-month" ng-switch-when="month">' +
|
|
205
|
+
'<input class="year form-control" type="number" min="0" max="9999" ng-model="queryPart._value[0]" placeholder="YYYY" ng-change="multipleDynamicScope.inputChanged(\'month\', _value, queryPart)"></input>' +
|
|
206
|
+
'<select class="month form-control" ng-model="queryPart._value[1]" ng-change="multipleDynamicScope.inputChanged(\'month\', _value, queryPart)">' +
|
|
207
|
+
'<option value="1">' + I18n.t('date.month_names.1') + '</value>' +
|
|
208
|
+
'<option value="2">' + I18n.t('date.month_names.2') + '</value>' +
|
|
209
|
+
'<option value="3">' + I18n.t('date.month_names.3') + '</value>' +
|
|
210
|
+
'<option value="4">' + I18n.t('date.month_names.4') + '</value>' +
|
|
211
|
+
'<option value="5">' + I18n.t('date.month_names.5') + '</value>' +
|
|
212
|
+
'<option value="6">' + I18n.t('date.month_names.6') + '</value>' +
|
|
213
|
+
'<option value="7">' + I18n.t('date.month_names.7') + '</value>' +
|
|
214
|
+
'<option value="8">' + I18n.t('date.month_names.8') + '</value>' +
|
|
215
|
+
'<option value="9">' + I18n.t('date.month_names.9') + '</value>' +
|
|
216
|
+
'<option value="10">' + I18n.t('date.month_names.10') + '</value>' +
|
|
217
|
+
'<option value="11">' + I18n.t('date.month_names.11') + '</value>' +
|
|
218
|
+
'<option value="12">' + I18n.t('date.month_names.12') + '</value>' +
|
|
219
|
+
'</select>' +
|
|
220
|
+
'</div>'
|
|
221
|
+
dateFutureInputTemplate = '<div class="value type-date-future" ng-switch-when="date_future"><date-input min="{{minDate | date:\'yyyy-MM-dd\'}}" ng-model="queryPart.value"></date-input></div>'
|
|
222
|
+
dateInputTemplate = '<div class="value type-date" ng-switch-when="date"><date-input ng-model="queryPart.value"></date-input></div>'
|
|
223
|
+
datetimeInputTemplate = '<div class="value type-datetime" ng-switch-when="datetime"><datetime-input ng-model="queryPart.value"></datetime-input></div>'
|
|
224
|
+
booleanSelectTemplate = '<select class="value form-control type-boolean" ng-model="queryPart.value" ng-switch-when="boolean" ng-options="value as multipleDynamicScope.translateValue(queryPart.key, value) for value in [true, false]"></select>'
|
|
225
|
+
fieldsetRemoveTemplate = '<a class="fieldset-remove" href="javascript:;" ng-click="multipleDynamicScope.removeInput(queryPart, section)" ng-show="multipleDynamicScope.query[section].length > removeLength">' + I18n.t('dynamic_scope.remove_fieldset') + '</a>'
|
|
226
|
+
{
|
|
227
|
+
template: '<legend ng-hide="hideTitle">{{ title }}</legend>' +
|
|
228
|
+
'<fieldset ng-repeat="queryPart in multipleDynamicScope.query[section]" ng-switch="multipleDynamicScope.typeFor(queryPart.key)" class="ng-scope">' +
|
|
229
|
+
keySelectTemplate +
|
|
230
|
+
operatorSelectTemplate +
|
|
231
|
+
stringInputTemplate +
|
|
232
|
+
integerInputTemplate +
|
|
233
|
+
enumSelectTemplate +
|
|
234
|
+
yearInputTemplate +
|
|
235
|
+
monthInputTemplate +
|
|
236
|
+
dateFutureInputTemplate +
|
|
237
|
+
dateInputTemplate +
|
|
238
|
+
datetimeInputTemplate +
|
|
239
|
+
#booleanSelectTemplate +
|
|
240
|
+
fieldsetRemoveTemplate +
|
|
241
|
+
'</fieldset>'
|
|
242
|
+
scope: true
|
|
243
|
+
link: ($scope, $elem, $attrs) ->
|
|
244
|
+
$scope.section = $attrs.section
|
|
245
|
+
$scope.hideTitle = $attrs.hideTitle
|
|
246
|
+
$scope.title = I18n.t("dynamic_scope.section_title.#{$scope.section}")
|
|
247
|
+
$scope.removeLength = if $attrs.removeAllFieldsets then 0 else 1
|
|
248
|
+
}
|
|
249
|
+
]
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
$(() ->
|
|
2
|
+
$.widget('custom.dynamicScope', {
|
|
3
|
+
options: {}
|
|
4
|
+
|
|
5
|
+
_create: () ->
|
|
6
|
+
this.counter = this.element.find('.dynamic_scope_active').size()
|
|
7
|
+
if this.element.is('form')
|
|
8
|
+
this.form = this.element
|
|
9
|
+
else
|
|
10
|
+
this.form = this.element.find('form')
|
|
11
|
+
|
|
12
|
+
this.templates = this.form.prevAll('.templates:first').find('fieldset')
|
|
13
|
+
if this.counter > 1
|
|
14
|
+
this.element.find('.dynamic_scope_remove').attr('style', null)
|
|
15
|
+
|
|
16
|
+
that = this
|
|
17
|
+
|
|
18
|
+
this.fieldsets().each( ->
|
|
19
|
+
that.addTriggers($(this))
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
this.element.on('click', '.dynamic_scope_add', (event) ->
|
|
23
|
+
event.preventDefault
|
|
24
|
+
newFieldset = that.addFieldset()
|
|
25
|
+
that.addTriggers(newFieldset)
|
|
26
|
+
return false
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
this.element.on('click', '.dynamic_scope_clear', (event) ->
|
|
30
|
+
event.preventDefault
|
|
31
|
+
that.clear()
|
|
32
|
+
return false
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
fieldsets: () ->
|
|
36
|
+
this.form.find('fieldset')
|
|
37
|
+
|
|
38
|
+
columnChange: (select) ->
|
|
39
|
+
this.counter = this.counter + 1
|
|
40
|
+
new_value = select.find('option:selected').attr('value')
|
|
41
|
+
template = this.templates.filter('#dynamic_scope_template_' + new_value)
|
|
42
|
+
fieldset = select.closest('fieldset')
|
|
43
|
+
input = fieldset.find('input[type=text]')
|
|
44
|
+
|
|
45
|
+
fieldset.html(template.html().replace(/INDEX/g, this.counter))
|
|
46
|
+
fieldset.attr('id', "dynamic_scope_#{this.counter}")
|
|
47
|
+
fieldset.find('.date').datepicker()
|
|
48
|
+
fieldset.find('[class="' + input.attr('class') + '"]').val(input.val())
|
|
49
|
+
|
|
50
|
+
if this.fieldsets().length > 1
|
|
51
|
+
this.fieldsets().find('.dynamic_scope_remove').attr('style', null)
|
|
52
|
+
|
|
53
|
+
this.element.trigger('dynamicScope:change')
|
|
54
|
+
|
|
55
|
+
return fieldset
|
|
56
|
+
|
|
57
|
+
addFieldset: () ->
|
|
58
|
+
this.counter = this.counter + 1
|
|
59
|
+
newFieldset = this.templates.filter('#dynamic_scope_template_any_field').clone()
|
|
60
|
+
if newFieldset.length == 0
|
|
61
|
+
newFieldset = this.templates.filter('.dynamic_scope_template:first').clone()
|
|
62
|
+
|
|
63
|
+
newFieldset.attr('style', null)
|
|
64
|
+
newFieldset.removeClass('dynamic_scope_template')
|
|
65
|
+
newFieldset.addClass('dynamic_scope_active')
|
|
66
|
+
newFieldset.html(newFieldset.html().replace(/INDEX/g, this.counter))
|
|
67
|
+
newFieldset.attr('id', 'dynamic_scope_' + this.counter)
|
|
68
|
+
|
|
69
|
+
lastActive = this.element.find('.dynamic_scope_active:last')
|
|
70
|
+
if lastActive.length > 0
|
|
71
|
+
lastActive.after(newFieldset)
|
|
72
|
+
else
|
|
73
|
+
this.element.find('.dynamic_scope_fieldsets').prepend(newFieldset)
|
|
74
|
+
|
|
75
|
+
this.fieldsets().find('.dynamic_scope_remove').attr('style', null)
|
|
76
|
+
this.element.trigger('dynamicScope:add', { fieldset: newFieldset })
|
|
77
|
+
|
|
78
|
+
return newFieldset
|
|
79
|
+
|
|
80
|
+
remove: (fieldset) ->
|
|
81
|
+
fieldset.remove()
|
|
82
|
+
if this.fieldsets().length == 1
|
|
83
|
+
this.fieldsets().find('.dynamic_scope_remove').css('display', 'none')
|
|
84
|
+
|
|
85
|
+
this.element.trigger('dynamicScope:remove', { fieldset: fieldset })
|
|
86
|
+
|
|
87
|
+
clear: () ->
|
|
88
|
+
this.form.find('input[type=text]').each( ->
|
|
89
|
+
$(this).val('')
|
|
90
|
+
)
|
|
91
|
+
this.form.submit()
|
|
92
|
+
|
|
93
|
+
addTriggers: (fieldset) ->
|
|
94
|
+
that = this
|
|
95
|
+
fieldset.on('change', '.dynamic_scope_column', (event) ->
|
|
96
|
+
that.columnChange($(this))
|
|
97
|
+
)
|
|
98
|
+
fieldset.on('click', '.dynamic_scope_remove', (event) ->
|
|
99
|
+
that.remove(fieldset)
|
|
100
|
+
event.preventDefault()
|
|
101
|
+
return false
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
$(->
|
|
109
|
+
$('.dynamic_scope').dynamicScope()
|
|
110
|
+
)
|