fanforce-plugin-factory 2.0.0.rc23 → 2.0.0.rc24

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2fe6b37296b9772bf778a29848861e2355cddd2c
4
- data.tar.gz: 4fec90a06232c77a9ad182f226a4f4ea87b05168
3
+ metadata.gz: 6005745eca81beede74f73809cde2b98b7565f8d
4
+ data.tar.gz: b6e59a56b54d2969ad253648cc569a5e90d46694
5
5
  SHA512:
6
- metadata.gz: 61238a5308cd30ee4d53ea501531ebadc98a55bf20933f1fa7f6cf908a6c7f92fa0fc7a3977060fd36c35981c1d1297756f62ef96ec29b350467138042d2ef28
7
- data.tar.gz: 9d373b6cc0b2013988b3ec8ef6813e4a7042955785d102e50ad7cdd08221be36e5cb13d37f8eb18004eccb63e751685898cced0098dbea0c9cac65c08a01ef94
6
+ metadata.gz: 7c07856ea8ab3aadb691a0b41f27e83d1f774fcbe8ff978ddab3b15fcd8cb6e062ee2aa1cfc1aa22bd756c0b0c194f0fbb5047b89f30c48cf9ad268656fcc4b9
7
+ data.tar.gz: 9744bf1ffa9026f067a298f67cf4e6e60d4cbc366fea57d27bff55c5411036c116a60b11efe502c3f0fa36b159eb2a1a061886044e572e42886e2190d6d402b2
@@ -9,4 +9,5 @@
9
9
  @import 'plugin_factory/directives/page/page';
10
10
  @import 'plugin_factory/directives/saving-to-server/saving-to-server';
11
11
  @import 'plugin_factory/directives/start-arrow/start-arrow';
12
+ @import 'plugin_factory/directives/typeahead/typeahead';
12
13
  @import 'plugin_factory/directives/video-thumbnail/video-thumbnail';
@@ -0,0 +1,103 @@
1
+ $q = null
2
+
3
+ LAYERS = []
4
+ LAYERS_BY_ID = {}
5
+ CALLBACKS = {}
6
+ INSTANCE = {}
7
+
8
+ App.factory('Layers', ['$q',(q)->
9
+ $q = q
10
+
11
+ createId = (->
12
+ possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
13
+ _id = ''
14
+ _id += possible.charAt(Math.floor(Math.random() * possible.length)) for i in [0..20]
15
+ return _id
16
+ )
17
+
18
+ addLayer = (($element, should_fade_body)->
19
+ _id = createId()
20
+ layer = {
21
+ _id: _id,
22
+ $element: $element,
23
+ onRemove: ((callback)->
24
+ addLayerCallback(_id, callback)
25
+ return layer
26
+ )
27
+ remove: ((args...)->
28
+ removeLayer(_id, args...)
29
+ return layer
30
+ )
31
+ should_fade_body: should_fade_body
32
+ }
33
+ setTimeout(-> finishAddLayer(layer))
34
+ return layer
35
+ )
36
+
37
+ addLayerCallback = ((_id, callback)->
38
+ CALLBACKS[_id] ||= []
39
+ CALLBACKS[_id].push(callback) if callback
40
+ )
41
+
42
+ finishAddLayer = ((layer)->
43
+ LAYERS.unshift(layer)
44
+ LAYERS_BY_ID[layer._id] = layer
45
+ $('body').addClass('locked-scroll') if layer.should_fade_body
46
+ layer.$element.attr('is-active-layer', 'true')
47
+ )
48
+
49
+ removeLayer = ((_id, args...)->
50
+ layer = LAYERS_BY_ID[_id]
51
+ return if !layer
52
+ callbacks = CALLBACKS[_id] || []
53
+ callback(args...) for callback in callbacks
54
+ delete CALLBACKS[_id]
55
+ delete LAYERS_BY_ID[_id]
56
+ for layer, i in LAYERS
57
+ return if layer._id != _id
58
+ layer_i_to_remove = i
59
+ break
60
+ LAYERS.splice(layer_i_to_remove, 1)
61
+ $('body').removeClass('locked-scroll') if layer.should_fade_body
62
+ layer.$element.attr('is-active-layer', 'false')
63
+ )
64
+
65
+ removeAll = (->
66
+ removeLayer(layer._id) while layer = LAYERS.shift()
67
+ )
68
+
69
+ ######################################################################################################################
70
+
71
+ $('body').on('click', (e)->
72
+ layer = LAYERS[0]
73
+ return if !layer
74
+ return if $(e.target).hasClass('dropdown-toggle')
75
+
76
+ $target = $(e.target)
77
+ return if !$.contains(document, $target[0])
78
+
79
+ $element = $target if $target.attr('is-active-layer')
80
+ $element ||= $target.closest('[is-active-layer="true"]')
81
+ return if ($element and $element.length and $element[0] == layer.$element[0])
82
+
83
+ layer.remove()
84
+ )
85
+
86
+ $('body').on('keydown', (e)->
87
+ return if e.keyCode != 27
88
+
89
+ layer = LAYERS[0]
90
+ return if !layer
91
+
92
+ layer.remove()
93
+ )
94
+
95
+ ######################################################################################################################
96
+
97
+ INSTANCE.add = ((element, should_fade_body=false)->
98
+ return addLayer($(element), should_fade_body)
99
+ )
100
+ INSTANCE.removeAll = removeAll
101
+ return INSTANCE;
102
+ ]);
103
+
@@ -0,0 +1,278 @@
1
+ $q = null
2
+ _callbacks = {}
3
+ _allowed_types = {}
4
+ instance = {
5
+ results: []
6
+ data_by_type: {}
7
+ has_more_results: false
8
+ }
9
+
10
+ PAGES = [
11
+ {name: 'Dashboard', type: 'page', icon_class: 'fa fa-tachometer', link: '/#/dashboard', other_names: ['Overview','Home']}
12
+ {name: 'Insights Engine', type: 'page', icon_class: 'fa fa-lightbulb-o', link: '/#/insights'}
13
+ {name: 'People', type: 'page', icon_class: 'ff-people', link: '/#/people', other_names: ['Person']},
14
+ {name: 'Initiatives', type: 'page', icon_class: 'ff-initiatives', link: '/#/initiatives'},
15
+ {name: 'Campaigns', type: 'page', icon_class: 'fa fa-newspaper-o', link: '/#/campaigns'},
16
+ {name: 'Experiments', type: 'page', icon_class: 'fa fa-flask', link: '/#/experiments'},
17
+ {name: 'Platform Admin', type: 'page', icon_class: 'fa fa-cogs', link: '/#/admin'}
18
+ ]
19
+
20
+ TYPES = ['pages', 'people', 'initiatives', 'campaigns', 'experiments', 'segments']
21
+
22
+ App.factory('SearchEngine', ['$q',(q)->
23
+ $q = q
24
+
25
+ instance.allow = ((types...)->
26
+ _allowed_types = {}
27
+ _allowed_types[type] = true for type in (if types[0] == 'all' then TYPES else types)
28
+ return instance
29
+ )
30
+
31
+ instance.init = (->
32
+ instance.results = []
33
+ instance.data_by_type = {}
34
+ instance.current_results = 0
35
+ instance.total_results = 0
36
+ instance.has_more_results = false
37
+ )
38
+
39
+ instance.trigger = ((event_name, args...)->
40
+ return if !_callbacks[event_name]
41
+ callback(args...) for callback in _callbacks[event_name]
42
+ )
43
+
44
+ instance.on = ((event_name, callback)->
45
+ _callbacks[event_name] ||= []
46
+ _callbacks[event_name].push(callback)
47
+ )
48
+
49
+ instance.updateQuery = ((search_query, prev_search_query)->
50
+ search_query = search_query.trim() if search_query
51
+ prev_search_query = prev_search_query.trim() if prev_search_query
52
+ return instance.trigger('searching-finished') if prev_search_query == search_query
53
+
54
+ emptyArray(instance.results)
55
+ instance.data_by_type = {}
56
+ instance.current_results = 0
57
+ instance.total_results = 0
58
+ instance.has_more_results = false
59
+ instance.search_query = search_query
60
+ return instance.trigger('searching-finished') if !search_query or search_query.length < 2
61
+
62
+ instance.trigger('searching', instance.results)
63
+ fetchPages(search_query) || instance.trigger('results-updated', instance.results)
64
+
65
+ clearTimeout(instance.future_fetch) if instance.future_fetch
66
+ instance.future_fetch = setTimeout (->
67
+ fetchRemote(search_query)
68
+ instance.future_fetch = null
69
+ ), 500
70
+ )
71
+
72
+ instance.loadMoreResults = loadMoreResults
73
+
74
+ return instance;
75
+ ]);
76
+
77
+ emptyArray = ((a)->
78
+ a.splice(0,a.length)
79
+ )
80
+
81
+ fetchPages = ((search_query)->
82
+ return false if !_allowed_types.pages
83
+ return false if !search_query
84
+ data = {current_results:0,total_results:0, results: []}
85
+ for page in PAGES
86
+ continue if !pageIsMatchForQuery(page, search_query)
87
+ data.results.push(page)
88
+ data.current_results = data.total_results += 1
89
+ if data.current_results > 0
90
+ addResults('pages', data)
91
+ return true
92
+ else return false
93
+ )
94
+
95
+ loadMoreResults = (->
96
+ search_query = instance.search_query
97
+ search_query = null if search_query == '*'
98
+ promises = []
99
+ promises.push fetchSegments(search_query, true)
100
+ promises.push fetchPeople(search_query, true)
101
+ promises.push fetchInitiatives(search_query, true)
102
+ promises.push fetchCampaigns(search_query, true)
103
+ promises.push fetchExperiments(search_query, true)
104
+
105
+ $q.all(promises).then(-> instance.trigger('load-more-finished'))
106
+ )
107
+
108
+ fetchRemote = ((search_query) ->
109
+ search_query = null if search_query == '*'
110
+ promises = []
111
+ promises.push fetchSegments(search_query)
112
+ promises.push fetchPeople(search_query)
113
+ promises.push fetchInitiatives(search_query)
114
+ promises.push fetchCampaigns(search_query)
115
+ promises.push fetchExperiments(search_query)
116
+
117
+ $q.all(promises).then(-> instance.trigger('searching-finished'))
118
+ )
119
+
120
+ fetchPeople = ((search_query, should_load_next_page=false)->
121
+ return if !_allowed_types[type = 'people']
122
+ attrs = {query: search_query, per_page: 5}
123
+ if should_load_next_page and instance.data_by_type[type]
124
+ current_page = instance.data_by_type[type].current_results / attrs.per_page
125
+ total_pages = instance.data_by_type[type].total_results / attrs.per_page
126
+ return if current_page >= total_pages
127
+ attrs.page = current_page + 1
128
+
129
+ FF.api.get('/search/people', attrs).success((data) ->
130
+ FFCore.fillBlankPersonPhotos(data.results)
131
+ com_database_ids_to_fetch = {}
132
+ for person in data.results
133
+ for com_database_id in person.com_database_ids
134
+ com_database_ids_to_fetch[com_database_id] ||= []
135
+ com_database_ids_to_fetch[com_database_id].push(person)
136
+ FFCore.fillBlankPersonPhotos(person)
137
+ person.type = 'person'
138
+ person.link = "/#/people/#{person._id}"
139
+ addResults(type, data)
140
+ insertMissingComDatabasesIntoPeople(com_database_ids_to_fetch, ->
141
+ refreshResults()
142
+ )
143
+ )
144
+ )
145
+
146
+ fetchInitiatives = ((search_query, should_load_next_page=false)->
147
+ return if !_allowed_types[type = 'initiatives']
148
+ attrs = {query: search_query, per_page: 5}
149
+ if should_load_next_page and instance.data_by_type[type]
150
+ current_page = instance.data_by_type[type].current_results / attrs.per_page
151
+ total_pages = instance.data_by_type[type].total_results / attrs.per_page
152
+ return if current_page >= total_pages
153
+ attrs.page = current_page + 1
154
+
155
+ FF.api.get('/search/initiatives', attrs).success((data)->
156
+ for initiative in data.results
157
+ initiative.type = 'initiative'
158
+ initiative.link = "/#/initiatives/#{initiative._id}"
159
+ addResults(type, data)
160
+ )
161
+ )
162
+
163
+ fetchCampaigns = ((search_query, should_load_next_page=false)->
164
+ return if !_allowed_types[type = 'campaigns']
165
+ attrs = {query: search_query, per_page: 5}
166
+ if should_load_next_page and instance.data_by_type[type]
167
+ current_page = instance.data_by_type[type].current_results / attrs.per_page
168
+ total_pages = instance.data_by_type[type].total_results / attrs.per_page
169
+ return if current_page >= total_pages
170
+ attrs.page = current_page + 1
171
+
172
+ FF.api.get('/search/campaigns', attrs).success((data)->
173
+ for campaign in data.results
174
+ campaign.type = 'campaign'
175
+ campaign.link = "/#/campaigns/#{campaign._id}"
176
+ addResults(type, data)
177
+ )
178
+ )
179
+
180
+ fetchExperiments = ((search_query, should_load_next_page=false)->
181
+ return if !_allowed_types[type = 'experiments']
182
+ attrs = {query: search_query, per_page: 5}
183
+ if should_load_next_page and instance.data_by_type[type]
184
+ current_page = instance.data_by_type[type].current_results / attrs.per_page
185
+ total_pages = instance.data_by_type[type].total_results / attrs.per_page
186
+ return if current_page >= total_pages
187
+ attrs.page = current_page + 1
188
+
189
+ FF.api.get('/search/experiments', attrs).success((data)->
190
+ for experiment in data.results
191
+ experiment.type = 'experiment'
192
+ experiment.link = "/#/experiments/#{experiment._id}"
193
+ addResults(type, data)
194
+ )
195
+ )
196
+
197
+ fetchSegments = ((search_query, should_load_next_page=false)->
198
+ type = 'segments'
199
+ attrs = {query: search_query, per_page: 5}
200
+ if _allowed_types.person_segments
201
+ attrs.applies_to = 'people'
202
+ else if _allowed_types.initiative_segments
203
+ attrs.applies_to = 'initiatives'
204
+ else if _allowed_types.campaign_segments
205
+ attrs.applies_to = 'campaigns'
206
+ else if _allowed_types.experiment_segments
207
+ attrs.applies_to = 'experiments'
208
+ else if _allowed_types.activity_segments
209
+ attrs.applies_to = 'activities'
210
+ else if !_allowed_types[type]
211
+ return
212
+ if should_load_next_page and instance.data_by_type[type]
213
+ current_page = instance.data_by_type[type].current_results / attrs.per_page
214
+ total_pages = instance.data_by_type[type].total_results / attrs.per_page
215
+ return if current_page >= total_pages
216
+ attrs.page = current_page + 1
217
+
218
+ FF.api.get('/search/segments', attrs).success((data)->
219
+ for segment in data.results
220
+ segment.type = 'segment'
221
+ segment.icon_class='ff-people'
222
+ segment.badge_class='fa fa-filter'
223
+ segment.link = "/#/segments/#{segment._id}"
224
+ addResults(type, data)
225
+ )
226
+ )
227
+
228
+ addResults = ((type, data)->
229
+ instance.data_by_type[type] ||= {total_results: 0, current_results: 0, results: []}
230
+ for record in data.results
231
+ instance.results.push(record)
232
+ instance.data_by_type[type].results.push(record)
233
+
234
+ instance.current_results += data.current_results
235
+ instance.total_results += (data.total_results - instance.data_by_type[type].total_results)
236
+
237
+ instance.data_by_type[type].current_results += data.current_results
238
+ instance.data_by_type[type].total_results = data.total_results
239
+
240
+ instance.has_more_results = (instance.current_results < instance.total_results)
241
+ instance.trigger('results-updated', instance.results, instance.has_more_results)
242
+ )
243
+
244
+ refreshResults = ((type)->
245
+ instance.trigger('results-updated', instance.results, instance.has_more_results)
246
+ )
247
+
248
+ pageIsMatchForQuery = ((page, query)->
249
+ return true if !query
250
+ return true if page.name.toLowerCase().indexOf(query.toLowerCase()) > -1
251
+
252
+ if page.other_names then for other_name in page.other_names
253
+ return true if other_name.toLowerCase().indexOf(query.toLowerCase()) > -1
254
+ return false
255
+ )
256
+
257
+ COM_DATABASES_BY_ID = {}
258
+ insertMissingComDatabasesIntoPeople = ((com_for_updating, callback)->
259
+ com_ids_to_fetch = []
260
+
261
+ for own com_id, people of com_for_updating
262
+ if !COM_DATABASES_BY_ID[com_id]
263
+ com_ids_to_fetch.push(com_id)
264
+ continue
265
+ for person in people
266
+ person.com_databases ||= []
267
+ person.com_databases.push(COM_DATABASES_BY_ID[com_id])
268
+ return callback() if com_ids_to_fetch.length == 0
269
+
270
+ FF.api.get('/com_databases', _ids: com_ids_to_fetch, fields: 'name,public_urls').success((data) ->
271
+ for com_database in data.results
272
+ COM_DATABASES_BY_ID[com_database._id] = com_database
273
+ for person in com_for_updating[com_database._id]
274
+ person.com_databases ||= []
275
+ person.com_databases.push(COM_DATABASES_BY_ID[com_database._id])
276
+ callback()
277
+ )
278
+ )
@@ -0,0 +1,86 @@
1
+ App.directive('typeahead', ['$http','$q','$timeout','SearchEngine','Layers', ($http, $q, $timeout, SearchEngine, Layers) ->
2
+ restrict: 'E',
3
+ templateUrl: '/plugin_factory/directives/typeahead',
4
+ scope: {
5
+ button_labels: '=buttonLabels'
6
+ existing_records_by_id: '=existingRecordsById',
7
+ onAdd: '='
8
+ placeholder: '=?'
9
+ }
10
+ link: (($scope, $element, attrs, controller)->
11
+ $scope.$safeApply = Utils.$safeApply
12
+
13
+ $scope.search_for = (attrs.searchFor || 'people').split(/,\s*/)
14
+ $scope.placeholder ||= 'type name of person or segment'
15
+
16
+ $input = $element.find('> .search-bar input');
17
+ $menu = $element.find('> .menu');
18
+
19
+ $input.on('focus', ->
20
+ $scope.activate()
21
+ )
22
+
23
+ $scope.hide = true
24
+
25
+ $scope.records = []
26
+
27
+ $scope.$watch('query_str', (query_str, prev_query_str)->
28
+ SearchEngine.updateQuery(query_str, prev_query_str)
29
+ )
30
+ SearchEngine.on('searching', ->
31
+ openMenu()
32
+ $scope.is_searching = true
33
+ )
34
+ SearchEngine.on('searching-finished', ->
35
+ $scope.is_searching = false
36
+ $scope.$safeApply()
37
+ )
38
+ SearchEngine.on('results-updated', (results, has_more_results)->
39
+ $scope.results = results
40
+ $scope.has_more_results = has_more_results
41
+ $scope.selected_index ||= 0
42
+ max_index = $scope.results.length - 1
43
+ max_index = 0 if max_index < 0
44
+ $scope.selected_index = max_index if $scope.selected_index > max_index
45
+ $scope.$safeApply()
46
+ )
47
+
48
+ $scope.loadMore = (->
49
+ SearchEngine.loadMoreResults()
50
+ )
51
+
52
+ layer = null
53
+ openMenu = (->
54
+ return if $scope.menu_is_open
55
+ $scope.menu_is_open = true
56
+ layer = Layers.add($element).onRemove(->
57
+ $scope.close()
58
+ $input.blur()
59
+ $scope.menu_is_open = false
60
+ $scope.query_str = null
61
+ $scope.$safeApply()
62
+ )
63
+ )
64
+
65
+ $scope.add = ((record)->
66
+ record.is_adding = true
67
+ $q.all([$scope.onAdd(record)]).then(->
68
+ record.is_adding = false
69
+ record.is_added = true
70
+ )
71
+ )
72
+
73
+ $scope.activate = (->
74
+ return if $scope.is_active
75
+ $scope.is_active = true
76
+ SearchEngine.allow($scope.search_for...).init()
77
+ )
78
+
79
+ $scope.close = (->
80
+ $scope.is_active = false
81
+ )
82
+
83
+ setTimeout (-> $input.focus()), 1
84
+ )
85
+ ])
86
+
@@ -0,0 +1,78 @@
1
+ typeahead { //display:block; position:relative;
2
+ .search-bar { margin-right: 1px; position: relative;
3
+ i { position: absolute; top: 50%; margin-top: -12px; line-height: 24px; left: 5px; }
4
+ input[type='text'] { display: block; width: 100%; padding-left: 20px; }
5
+ }
6
+ .menu { z-index: 1; background:white; position: relative; width: 100%; padding-top: 3px; margin-top:1px; min-height: 20px; border:1px solid #cccccc; border-top: none; @include box-shadow(1px 1px 1px rgba(0,0,0,.1)); @include border-radius(0 0 3px 3px); @include box-sizing(border-box);
7
+ .menu-arrow { position:absolute; top:-9px; left: 75px; z-index:1; }
8
+ h5 { font-size:11px; color:#babdbf; width:73px; float:left; font-weight: normal; clear:left; padding:10px 5px 10px 0; margin:0 1px; text-align: right; border-top: 1px solid #dddddd; }
9
+ }
10
+ }
11
+
12
+ search-results { display: block; overflow-y: auto; margin-bottom: 1px;
13
+ loading.is-searching { margin: 0 2px; padding: 7px 10px; text-align: left;
14
+ .bar { margin-top: 0; }
15
+ }
16
+ .no-results { color: #cccccc; padding: 20px 12px; font-size: 16px; }
17
+ ul.results { @include reset-ul(); margin: -2px 2px 0;
18
+ & ~ loading.is-searching { border-top: 1px solid #eeeeee; margin-top: 2px; }
19
+ li.result { margin: 2px 0; padding-top: 2px; font-size: 12px; color: #666666; border-top: 1px solid #eeeeee; clear: both; position: relative; text-shadow: 1px 1px 0 white; text-align: left;
20
+ &.is-added { @include opacity(0.5); }
21
+ .adjuster-field { display: inline-block; }
22
+ .select2-container .select2-choice { background: #f6f6f6; @include box-shadow(inset 1px 1px 0 white); border-color: #cccccc; }
23
+ &:first-child { border-top: none; margin-top: 0; padding-top: 0; }
24
+ &:last-child { margin-bottom: 0; }
25
+ }
26
+ .record { display: block; padding: 4px 8px;
27
+ &.selected { background: #e9f4fd; }
28
+ &:hover { text-decoration: none; }
29
+ }
30
+ .details { display: inline-block; }
31
+ .name { display: inline-block; line-height: 22px; padding-top: 1px; vertical-align: middle; }
32
+ .person-source-icons, .record-source-icons { display: inline-block;
33
+ img { margin-left:5px; @include opacity(0.5);
34
+ &:hover { @include opacity(1); }
35
+ }
36
+ }
37
+ .photo-wrapper { width:22px; height:22px; vertical-align: middle; border: 1px solid rgba(0, 0, 0, 0.1); @include box-shadow(1px 1px 0 white); background-color:#eaf2fa; overflow:hidden; display: inline-block; margin-right: 5px; @include border-radius(50%);
38
+ img { width:20px; height:20px; }
39
+ }
40
+ .native-icon { position: relative; width: 21px; height: 21px; display: inline-block; background: #b0becb; border-color: #b0becb; @include box-shadow(1px 1px 0 white); margin-right: 5px; text-align: center; vertical-align: middle; @include border-radius(1px);
41
+ i { font-size: 15px; line-height: 19px; color: white; text-shadow: none; }
42
+ .badge-wrapper { width: 12px; height: 12px; position: absolute; top: -2px; right: -2px; background: #779cbf; border: 1px solid #5a83a9; @include border-radius(50%);
43
+ i { font-size: 8px; line-height: 10px; color: white; vertical-align: top;}
44
+ }
45
+ }
46
+ .icon-wrapper { width: 21px; height: 21px; display: inline-block; margin-right: 5px; text-align: center; vertical-align: middle;
47
+ img { width: 20px; height: 20px; }
48
+ }
49
+ .type { color: #b6c7d4; position: absolute; line-height: 16px; top: 50%; margin-top: -8px; right: 5px; }
50
+ .control-buttons { float:left; width: 75px; position: relative; top: 2px;
51
+ .btn { padding: 2px 5px; font-size: 12px; line-height: 1em; }
52
+ }
53
+ }
54
+ .show-more { margin: 2px 0; padding: 4px 8px 2px; font-size: 12px; border-top: 1px solid #eeeeee; clear: both; display: block; }
55
+ }
56
+
57
+ loading { display: block; text-align:center; padding:40px 0;
58
+ .bar {
59
+ vertical-align: bottom;
60
+ display: inline-block;
61
+ background-color:#e5eaee; border:1px solid #cfd7de;
62
+ margin-right:4px; margin-top:6px; width:6px; height:14px;
63
+ @include box-shadow(1px 1px 0 #ffffff);
64
+ @include animation(loadingbar 1s infinite);
65
+ }
66
+ & .bar:nth-child(1) { @include animation-delay(1.0s); }
67
+ & .bar:nth-child(2) { @include animation-delay(1.1s); }
68
+ & .bar:nth-child(3) { @include animation-delay(1.2s); }
69
+ & .bar:nth-child(4) { @include animation-delay(1.3s); }
70
+ }
71
+ /* The actual animation */
72
+ @include keyframes(loadingbar) {
73
+ 0% { border-color:#cfd7de; background-color:#e5eaee; }
74
+ 20% { border-color:#cfd7de; background-color:#e5eaee; }
75
+ 40% { border-color:#bec7d0; background-color:#ced4db; }
76
+ 60% { border-color:#aab5c1; background-color:#bac4cf; }
77
+ 100% { border-color:#9eabb9; background-color:#acb8c5; }
78
+ }
@@ -0,0 +1,37 @@
1
+ .search-bar
2
+ %i.fa.fa-search
3
+ %input(type='text' ng-model='query_str' autocomplete='off' placeholder='{{placeholder}}')
4
+
5
+ .menu(ng-show='menu_is_open')
6
+ %img.menu-arrow
7
+ %search-results
8
+ %loading.is-searching(ng-show='is_searching')
9
+ .no-results(ng-show='results.length == 0 && !is_searching')
10
+ .text No People Found
11
+ %ul.results(ng-show='results.length > 0 && !is_searching')
12
+ %li.result(ng-repeat='record in results' ng-class='{"is-added": record.is_added}')
13
+ .record
14
+ .native-icon(ng-if='record.icon_class' ng-class='{"page-icon": record.type=="page"}')
15
+ %i(ng-class='record.icon_class')
16
+ .badge-wrapper(ng-if='record.badge_class')
17
+ %i(ng-class='record.badge_class')
18
+ .photo-wrapper(ng-if='record.photo_small_url')
19
+ %img(ng-src='{{record.photo_small_url}}')
20
+ .icon-wrapper(ng-if='record.public_urls')
21
+ %img(ng-src='{{record.public_urls.icon_32}}')
22
+ .details
23
+ .name
24
+ {{record.name}}
25
+ %span(ng-if='record.adjuster') =
26
+ .adjuster-field(ng-class='{disabled: record.is_adding || record.is_added}')
27
+ %segment-adjuster(id='record.adjuster._id' value='record.adjuster_value' com-database='record.adjuster.com_database' field='record.adjuster.field' input-control='record.adjuster.input_control' placeholder='record.adjuster_placeholder')
28
+
29
+ .record-source-icons(ng-if='record.com_databases')
30
+ %img(ng-repeat='com_database in record.com_databases' ng-src='{{com_database.public_urls.icon_16}}' ng-hide='com_database._id == "unnamed-visitors"' tooltip='{{com_database.name}}')
31
+ .last-activity-at(ng-if='record.last_activity_at') Last Activity {{record.last_activity_at|fromNow}}
32
+ .control-buttons
33
+ %button.btn.btn-small.btn-default(ng-click='add(record)' ng-hide='record.is_added || record.is_adding || existing_records_by_id[record._id]') {{button_labels[0]}}
34
+ %button.btn.btn-small(ng-show='record.is_adding' disabled) {{button_labels[1]}}
35
+ %button.btn.btn-small(ng-show='record.is_added || existing_records_by_id[record._id]' disabled) {{button_labels[2]}}
36
+ .show-more(ng-if='has_more_results')
37
+ %a(ng-click='loadMore()') Load More
@@ -1,5 +1,5 @@
1
1
  class Fanforce
2
2
  class PluginFactory
3
- VERSION = '2.0.0.rc23'
3
+ VERSION = '2.0.0.rc24'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fanforce-plugin-factory
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc23
4
+ version: 2.0.0.rc24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Caleb Clark
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-20 00:00:00.000000000 Z
11
+ date: 2015-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -393,6 +393,11 @@ files:
393
393
  - lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/start-arrow/_start-arrow.coffee
394
394
  - lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/start-arrow/_start-arrow.scss
395
395
  - lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/start-arrow/arrow.png
396
+ - lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/typeahead/_layers.coffee
397
+ - lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/typeahead/_search_engine.coffee
398
+ - lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/typeahead/_typeahead.coffee
399
+ - lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/typeahead/_typeahead.scss
400
+ - lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/typeahead/arrow.png
396
401
  - lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/video-thumbnail/_video-thumbnail.scss
397
402
  - lib/fanforce/plugin_factory/asset_framework/plugin_factory/directives/video-thumbnail/icon-play.png
398
403
  - lib/fanforce/plugin_factory/asset_framework/plugin_factory/font-awesome.coffee
@@ -441,6 +446,7 @@ files:
441
446
  - lib/fanforce/plugin_factory/directive_views/campaign-footer.haml
442
447
  - lib/fanforce/plugin_factory/directive_views/initiative-added.haml
443
448
  - lib/fanforce/plugin_factory/directive_views/initiative-footer.haml
449
+ - lib/fanforce/plugin_factory/directive_views/typeahead.haml
444
450
  - lib/fanforce/plugin_factory/load.rb
445
451
  - lib/fanforce/plugin_factory/load_from_worker.rb
446
452
  - lib/fanforce/plugin_factory/load_sprockets.rb