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

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 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