Merge lp:~stolowski/unity-scopes-api/update-push-filters into lp:unity-scopes-api/devel

Proposed by Paweł Stołowski
Status: Merged
Approved by: Marcus Tomlinson
Approved revision: 683
Merged at revision: 682
Proposed branch: lp:~stolowski/unity-scopes-api/update-push-filters
Merge into: lp:unity-scopes-api/devel
Diff against target: 503 lines (+105/-75)
18 files modified
RELEASE_NOTES.md (+5/-0)
STRUCTS (+2/-3)
debian/VERSION (+1/-1)
debian/changelog (+8/-0)
include/unity/scopes/SearchListenerBase.h (+9/-0)
include/unity/scopes/SearchReply.h (+8/-1)
include/unity/scopes/internal/SearchReplyImpl.h (+2/-1)
include/unity/scopes/testing/MockSearchReply.h (+1/-0)
include/unity/scopes/utility/internal/BufferedSearchReplyImpl.h (+1/-0)
src/scopes/SearchListenerBase.cpp (+5/-0)
src/scopes/internal/ResultReplyObject.cpp (+5/-10)
src/scopes/internal/SearchReplyImpl.cpp (+7/-14)
src/scopes/testing/InProcessBenchmark.cpp (+5/-0)
src/scopes/utility/internal/BufferedSearchReplyImpl.cpp (+5/-0)
test/gtest/scopes/Filters/Filters_test.cpp (+21/-10)
test/gtest/scopes/Filters/TestScope.h (+19/-2)
test/gtest/scopes/ResultCache/ResultCache_test.cpp (+1/-32)
test/gtest/scopes/ResultCache/no_filter_state_cache (+0/-1)
To merge this branch: bzr merge lp:~stolowski/unity-scopes-api/update-push-filters
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Marcus Tomlinson (community) Approve
unity-api-1-bot continuous-integration Needs Fixing
Review via email: mp+297348@code.launchpad.net

Commit message

Marked the push(Filters const&, FilterState const&) method of SearchReply and SearchListenerBase
as deprecated and provided push methods which take Filters argument only.

Description of the change

Marked the push(Filters const&, FilterState const&) method of SearchReply and SearchListenerBase
as deprecated and provided push methods which take Filters argument only.

To post a comment you must log in.
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote :

Looking good. Just a few inline comments, mostly grammatical.

review: Needs Fixing
682. By Paweł Stołowski

Review comments

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Paweł Stołowski (stolowski) wrote :

> Looking good. Just a few inline comments, mostly grammatical.

Ok, done. Thanks for the corrections... will I ever get this stuff right ;)...

Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote :

> > Looking good. Just a few inline comments, mostly grammatical.
>
> Ok, done. Thanks for the corrections... will I ever get this stuff right ;)...

;) It's really not that bad! Thanks Pawel. Although, now I see there are 2 conflicts with devel

review: Needs Fixing
683. By Paweł Stołowski

Merged devel

Revision history for this message
Paweł Stołowski (stolowski) wrote :

> > > Looking good. Just a few inline comments, mostly grammatical.
> >
> > Ok, done. Thanks for the corrections... will I ever get this stuff right
> ;)...
>
> ;) It's really not that bad! Thanks Pawel. Although, now I see there are 2
> conflicts with devel

Ok, fixed + bumped to 1.0.7.

Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote :

> > > > Looking good. Just a few inline comments, mostly grammatical.
> > >
> > > Ok, done. Thanks for the corrections... will I ever get this stuff right
> > ;)...
> >
> > ;) It's really not that bad! Thanks Pawel. Although, now I see there are 2
> > conflicts with devel
>
> Ok, fixed + bumped to 1.0.7.

Thanks +1

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'RELEASE_NOTES.md'
2--- RELEASE_NOTES.md 2016-05-23 07:55:39 +0000
3+++ RELEASE_NOTES.md 2016-06-28 08:18:23 +0000
4@@ -1,6 +1,11 @@
5 Release notes
6 =============
7
8+Changes in version 1.0.7
9+========================
10+ - Marked the push(Filters const&, FilterState const&) method of SearchReply and SearchListenerBase
11+ as deprecated and provided push methods which take the Filters argument only.
12+
13 Changes in version 1.0.6
14 ========================
15 - Got rid of category header background, as per design (Bug #1446216).
16
17=== modified file 'STRUCTS'
18--- STRUCTS 2016-02-25 16:26:09 +0000
19+++ STRUCTS 2016-06-28 08:18:23 +0000
20@@ -142,10 +142,9 @@
21 'central_label' : string
22 'filter_group' : string, optional
23
24-Filters + FilterState
25-=====================
26+Filters
27+=======
28 'filter' : array of filters (implementations of FilterBase)
29- 'filter_state' : FilterState
30
31 PreviewResult (returned by serialize())
32 =======================================
33
34=== modified file 'debian/VERSION'
35--- debian/VERSION 2016-05-23 07:56:41 +0000
36+++ debian/VERSION 2016-06-28 08:18:23 +0000
37@@ -1,1 +1,1 @@
38-1.0.6
39+1.0.7
40
41=== modified file 'debian/changelog'
42--- debian/changelog 2016-06-17 07:27:25 +0000
43+++ debian/changelog 2016-06-28 08:18:23 +0000
44@@ -1,3 +1,11 @@
45+unity-scopes-api (1.0.7-0ubuntu1) UNRELEASED; urgency=medium
46+
47+ * Marked the push(Filters const&, FilterState const&) method of SearchReply
48+ and SearchListenerBase as deprecated and provided push methods which take
49+ the Filters argument only.
50+
51+ -- Pawel Stolowski <pawel.stolowski@canonical.com> Tue, 28 Jun 2016 10:11:22 +0200
52+
53 unity-scopes-api (1.0.6+16.10.20160617-0ubuntu1) yakkety; urgency=medium
54
55 [ Marcus Tomlinson ]
56
57=== modified file 'include/unity/scopes/SearchListenerBase.h'
58--- include/unity/scopes/SearchListenerBase.h 2015-09-01 22:19:45 +0000
59+++ include/unity/scopes/SearchListenerBase.h 2016-06-28 08:18:23 +0000
60@@ -96,10 +96,19 @@
61 /**
62 \brief Called once by the scopes to send all the filters and their state.
63
64+ \deprecated Please override the push(Filters& const) method instead. This method will be removed from future releases.
65+
66 The default implementation does nothing.
67 */
68 virtual void push(Filters const& filters, FilterState const& filter_state);
69
70+ /**
71+ \brief Called once by the scope to send all filters and their states.
72+
73+ The default implementation does nothing.
74+ */
75+ virtual void push(Filters const& filters);
76+
77 protected:
78 /// @cond
79 SearchListenerBase();
80
81=== modified file 'include/unity/scopes/SearchReply.h'
82--- include/unity/scopes/SearchReply.h 2015-10-29 02:35:50 +0000
83+++ include/unity/scopes/SearchReply.h 2016-06-28 08:18:23 +0000
84@@ -139,7 +139,8 @@
85 virtual bool push(experimental::Annotation const& annotation) = 0;
86
87 /**
88- \brief Sends all filters and their state to the source of a query.
89+ \brief Sends all filters and their states to the source of a query.
90+ \deprecated Sending filter state back to the UI is deprecated and will be removed from future releases. Please use the push(Filters const&) method instead.
91 \return True if the filters were accepted, false otherwise.
92 */
93 virtual bool push(Filters const& filters, FilterState const& filter_state) = 0;
94@@ -190,6 +191,12 @@
95 */
96 virtual void push_surfacing_results_from_cache() = 0;
97
98+ /**
99+ \brief Sends all filter definitions to the source of a query.
100+ \return True if the filters were accepted, false otherwise.
101+ */
102+ virtual bool push(Filters const& filters) = 0;
103+
104 protected:
105 /// @cond
106 SearchReply();
107
108=== modified file 'include/unity/scopes/internal/SearchReplyImpl.h'
109--- include/unity/scopes/internal/SearchReplyImpl.h 2015-02-27 05:28:09 +0000
110+++ include/unity/scopes/internal/SearchReplyImpl.h 2016-06-28 08:18:23 +0000
111@@ -80,6 +80,8 @@
112
113 virtual void push_surfacing_results_from_cache() noexcept override;
114
115+ virtual bool push(unity::scopes::Filters const& filters) override;
116+
117 private:
118 bool push(Category::SCPtr category);
119 void write_cached_results() noexcept;
120@@ -94,7 +96,6 @@
121
122 Department::SCPtr cached_departments_;
123 unity::scopes::Filters cached_filters_;
124- unity::scopes::FilterState cached_filter_state_;
125 std::vector<unity::scopes::CategorisedResult> cached_results_;
126 std::mutex mutex_;
127 };
128
129=== modified file 'include/unity/scopes/testing/MockSearchReply.h'
130--- include/unity/scopes/testing/MockSearchReply.h 2015-04-10 10:10:06 +0000
131+++ include/unity/scopes/testing/MockSearchReply.h 2016-06-28 08:18:23 +0000
132@@ -66,6 +66,7 @@
133 MOCK_METHOD1(lookup_category, Category::SCPtr(std::string const&));
134 MOCK_METHOD1(push, bool(CategorisedResult const&));
135 MOCK_METHOD2(push, bool(Filters const&, FilterState const&));
136+ MOCK_METHOD1(push, bool(Filters const&));
137 MOCK_METHOD1(push, bool(experimental::Annotation const& annotation));
138 MOCK_METHOD0(push_surfacing_results_from_cache, void());
139
140
141=== modified file 'include/unity/scopes/utility/internal/BufferedSearchReplyImpl.h'
142--- include/unity/scopes/utility/internal/BufferedSearchReplyImpl.h 2015-02-27 05:28:09 +0000
143+++ include/unity/scopes/utility/internal/BufferedSearchReplyImpl.h 2016-06-28 08:18:23 +0000
144@@ -78,6 +78,7 @@
145 std::string to_string() override;
146
147 void flush();
148+ bool push(unity::scopes::Filters const& filters) override;
149
150 private:
151 std::mutex mutex_;
152
153=== modified file 'src/scopes/SearchListenerBase.cpp'
154--- src/scopes/SearchListenerBase.cpp 2014-06-17 15:07:13 +0000
155+++ src/scopes/SearchListenerBase.cpp 2016-06-28 08:18:23 +0000
156@@ -44,6 +44,11 @@
157 // Intentionally empty: "do nothing" default implementation.
158 }
159
160+void SearchListenerBase::push(Filters const& /* filters */)
161+{
162+ // Intentionally empty: "do nothing" default implementation.
163+}
164+
165 void SearchListenerBase::push(Category::SCPtr const& /* category */)
166 {
167 // Intentionally empty: "do nothing" default implementation.
168
169=== modified file 'src/scopes/internal/ResultReplyObject.cpp'
170--- src/scopes/internal/ResultReplyObject.cpp 2016-02-24 16:49:34 +0000
171+++ src/scopes/internal/ResultReplyObject.cpp 2016-06-28 08:18:23 +0000
172@@ -74,16 +74,11 @@
173 }
174
175 Filters const filters = FilterBaseImpl::deserialize_filters(it->second.get_array(), groups);
176- it = data.find("filter_state");
177- if (it != data.end())
178- {
179- auto filter_state = FilterStateImpl::deserialize(it->second.get_dict());
180- receiver_->push(filters, filter_state);
181- }
182- else
183- {
184- throw InvalidArgumentException("ResultReplyObject::push(): filters present but missing filter_state data");
185- }
186+
187+ // temporarily support both variants of push until the one supporting filter state gets dropped.
188+ FilterState filter_state;
189+ receiver_->push(filters, filter_state);
190+ receiver_->push(filters);
191 }
192
193 it = data.find("category");
194
195=== modified file 'src/scopes/internal/SearchReplyImpl.cpp'
196--- src/scopes/internal/SearchReplyImpl.cpp 2016-02-25 16:08:01 +0000
197+++ src/scopes/internal/SearchReplyImpl.cpp 2016-06-28 08:18:23 +0000
198@@ -170,7 +170,12 @@
199 return true;
200 }
201
202-bool SearchReplyImpl::push(unity::scopes::Filters const& filters, unity::scopes::FilterState const& filter_state)
203+bool SearchReplyImpl::push(unity::scopes::Filters const& filters, unity::scopes::FilterState const&)
204+{
205+ return push(filters);
206+}
207+
208+bool SearchReplyImpl::push(unity::scopes::Filters const& filters)
209 {
210 // basic consistency check
211 try
212@@ -186,7 +191,6 @@
213 {
214 lock_guard<mutex> lock(mutex_);
215 cached_filters_ = filters;
216- cached_filter_state_ = filter_state;
217 }
218
219 VariantMap var;
220@@ -196,7 +200,6 @@
221 var["filter_groups"] = filter_groups;
222 }
223 var["filters"] = internal::FilterBaseImpl::serialize_filters(filters);
224- var["filter_state"] = filter_state.serialize();
225 return ReplyImpl::push(var);
226 }
227
228@@ -260,7 +263,6 @@
229 departments = cached_departments_->serialize();
230 }
231 auto filters = internal::FilterBaseImpl::serialize_filters(cached_filters_);
232- auto filter_state = cached_filter_state_.serialize();
233 VariantArray categories = cat_registry_->serialize();
234 VariantArray results;
235 for (auto const& r : cached_results_)
236@@ -279,7 +281,6 @@
237 }
238
239 vm["filters"] = move(filters);
240- vm["filter_state"] = move(filter_state);
241
242 vm["results"] = move(results);
243 string const json = Variant(move(vm)).serialize_json();
244@@ -371,13 +372,6 @@
245 }
246 auto filter_array = it->second.get_array();
247
248- it = vm.find("filter_state");
249- if (it == vm.end())
250- {
251- throw unity::scopes::NotFoundException("malformed cache file", "filter_state");
252- }
253- auto filter_state_dict = it->second.get_dict();
254-
255 it = vm.find("results");
256 if (it == vm.end())
257 {
258@@ -408,8 +402,7 @@
259 }
260
261 auto filters = FilterBaseImpl::deserialize_filters(move(filter_array), groups);
262- auto filter_state = FilterStateImpl::deserialize(move(filter_state_dict));
263- push(filters, filter_state);
264+ push(filters);
265
266 for (auto const& r : result_array)
267 {
268
269=== modified file 'src/scopes/testing/InProcessBenchmark.cpp'
270--- src/scopes/testing/InProcessBenchmark.cpp 2015-01-09 07:10:07 +0000
271+++ src/scopes/testing/InProcessBenchmark.cpp 2016-06-28 08:18:23 +0000
272@@ -204,6 +204,11 @@
273 return true;
274 }
275
276+ bool push(unity::scopes::Filters const&) override
277+ {
278+ return true;
279+ }
280+
281 bool push(unity::scopes::experimental::Annotation const&) override
282 {
283 return true;
284
285=== modified file 'src/scopes/utility/internal/BufferedSearchReplyImpl.cpp'
286--- src/scopes/utility/internal/BufferedSearchReplyImpl.cpp 2015-02-27 05:28:09 +0000
287+++ src/scopes/utility/internal/BufferedSearchReplyImpl.cpp 2016-06-28 08:18:23 +0000
288@@ -92,6 +92,11 @@
289 return upstream_->push(filters, filter_state);
290 }
291
292+bool BufferedSearchReplyImpl::push(unity::scopes::Filters const& filters)
293+{
294+ return upstream_->push(filters);
295+}
296+
297 void BufferedSearchReplyImpl::push_surfacing_results_from_cache() noexcept
298 {
299 upstream_->push_surfacing_results_from_cache();
300
301=== modified file 'test/gtest/scopes/Filters/Filters_test.cpp'
302--- test/gtest/scopes/Filters/Filters_test.cpp 2016-03-03 11:46:25 +0000
303+++ test/gtest/scopes/Filters/Filters_test.cpp 2016-06-28 08:18:23 +0000
304@@ -66,12 +66,19 @@
305 class SearchReceiver : public SearchListenerBase, public WaitUntilFinished
306 {
307 public:
308- virtual void push(CategorisedResult /* result */) override {}
309-
310- virtual void push(Filters const& filters, FilterState const& filter_state) override
311+ virtual void push(CategorisedResult result) override
312+ {
313+ result_uri = result.uri();
314+ }
315+
316+ virtual void push(Filters const& filters, FilterState const&) override
317+ {
318+ this->filters2 = filters;
319+ }
320+
321+ virtual void push(Filters const& filters) override
322 {
323 this->filters = filters;
324- this->filter_state = filter_state;
325 }
326
327 virtual void finished(CompletionDetails const& details) override
328@@ -81,7 +88,8 @@
329 }
330
331 Filters filters;
332- FilterState filter_state;
333+ Filters filters2;
334+ std::string result_uri;
335 };
336
337 template <typename ScopeType>
338@@ -135,8 +143,13 @@
339 auto ctrl = scope->search("test", hints, receiver);
340 receiver->wait_until_finished();
341
342- auto filter_state = receiver->filter_state; // copy filter state, it will be sent with 2nd query
343+ EXPECT_EQ("no options active", receiver->result_uri);
344+
345+ FilterState filter_state;
346 {
347+ // make sure the deprecated API push method for filters still works
348+ ASSERT_EQ(1u, receiver->filters2.size());
349+
350 auto filters = receiver->filters;
351 ASSERT_EQ(1u, filters.size());
352 EXPECT_EQ("f1", filters.front()->id());
353@@ -159,11 +172,9 @@
354 receiver->wait_until_finished();
355 {
356 auto filters = receiver->filters;
357- auto filter_state2 = receiver->filter_state;
358+ ASSERT_EQ(1u, filters.size());
359 auto selector = std::dynamic_pointer_cast<const OptionSelectorFilter>(filters.front());
360- ASSERT_EQ(1u, selector->active_options(filter_state2).size());
361- auto option1 = *(selector->active_options(filter_state2).begin());
362- EXPECT_EQ("o1", option1->id());
363+ EXPECT_EQ("option o1 active", receiver->result_uri);
364 }
365 }
366
367
368=== modified file 'test/gtest/scopes/Filters/TestScope.h'
369--- test/gtest/scopes/Filters/TestScope.h 2016-02-25 16:08:01 +0000
370+++ test/gtest/scopes/Filters/TestScope.h 2016-06-28 08:18:23 +0000
371@@ -21,6 +21,7 @@
372 #include <unity/scopes/CategorisedResult.h>
373 #include <unity/scopes/Category.h>
374 #include <unity/scopes/FilterGroup.h>
375+#include <unity/scopes/FilterOption.h>
376 #include <unity/scopes/OptionSelectorFilter.h>
377 #include <unity/scopes/ScopeBase.h>
378 #include <unity/scopes/SearchReply.h>
379@@ -49,11 +50,27 @@
380 filter->add_option("o2", "Option 2");
381 filters.push_back(filter);
382 auto active_opts = filter->active_options(query().filter_state());
383- reply->push(filters, query().filter_state()); // send unmodified state back
384+
385+ if (query().query_string() == "test")
386+ {
387+ reply->push(filters);
388+ }
389+ else
390+ {
391+ // use the deprecated push call
392+ reply->push(filters, query().filter_state());
393+ }
394
395 auto cat = reply->register_category("cat1", "Category 1", "");
396 CategorisedResult res(cat);
397- res.set_uri("uri");
398+ if (active_opts.size() == 1)
399+ {
400+ res.set_uri("option " + (*(active_opts.begin()))->id() + " active");
401+ }
402+ else
403+ {
404+ res.set_uri("no options active");
405+ }
406 res.set_dnd_uri("dnd_uri");
407 reply->push(res);
408 }
409
410=== modified file 'test/gtest/scopes/ResultCache/ResultCache_test.cpp'
411--- test/gtest/scopes/ResultCache/ResultCache_test.cpp 2016-02-25 17:28:22 +0000
412+++ test/gtest/scopes/ResultCache/ResultCache_test.cpp 2016-06-28 08:18:23 +0000
413@@ -46,11 +46,10 @@
414 dept_ = parent;
415 }
416
417- virtual void push(Filters const& filters, FilterState const& filter_state) override
418+ virtual void push(Filters const& filters) override
419 {
420 lock_guard<mutex> lock(mutex_);
421 filters_ = filters;
422- filter_state_ = filter_state;
423 }
424
425 virtual void push(CategorisedResult result) override
426@@ -86,12 +85,6 @@
427 return filters_;
428 }
429
430- FilterState filter_state() const
431- {
432- lock_guard<mutex> lock(mutex_);
433- return filter_state_;
434- }
435-
436 CategorisedResult::SCPtr result() const
437 {
438 lock_guard<mutex> lock(mutex_);
439@@ -101,7 +94,6 @@
440 private:
441 Department::SCPtr dept_;
442 Filters filters_;
443- FilterState filter_state_;
444 CategorisedResult::SCPtr result_;
445 bool query_complete_;
446 mutable mutex mutex_;
447@@ -248,9 +240,6 @@
448 auto osf = dynamic_pointer_cast<OptionSelectorFilter const>(f);
449 ASSERT_TRUE(osf != nullptr);
450 EXPECT_EQ("Choose an option", osf->label());
451- auto fs = receiver->filter_state();
452- EXPECT_TRUE(fs.has_filter("f1"));
453- EXPECT_TRUE(osf->has_active_option(fs));
454
455 // Cache file must still be there.
456 boost::system::error_code ec;
457@@ -290,9 +279,6 @@
458 auto osf = dynamic_pointer_cast<OptionSelectorFilter const>(f);
459 ASSERT_TRUE(osf != nullptr);
460 EXPECT_EQ("Choose an option", osf->label());
461- auto fs = receiver->filter_state();
462- EXPECT_TRUE(fs.has_filter("f1"));
463- EXPECT_TRUE(osf->has_active_option(fs));
464
465 // Cache file must still be there.
466 boost::system::error_code ec;
467@@ -344,9 +330,6 @@
468 auto osf = dynamic_pointer_cast<OptionSelectorFilter const>(f);
469 ASSERT_TRUE(osf != nullptr);
470 EXPECT_EQ("Choose an option", osf->label());
471- auto fs = receiver->filter_state();
472- EXPECT_TRUE(fs.has_filter("f1"));
473- EXPECT_TRUE(osf->has_active_option(fs));
474
475 // New cache file must have been created
476 boost::system::error_code ec;
477@@ -414,20 +397,6 @@
478 EXPECT_TRUE(boost::filesystem::exists(TEST_RUNTIME_PATH "/unconfined/CacheScope/.surfacing_cache", ec));
479 }
480
481-TEST_F(CacheScopeTest, missing_filter_state)
482-{
483- // Get coverage on missing filters_state entry
484- system("cp " TEST_SOURCE_PATH "/no_filter_state_cache " TEST_RUNTIME_PATH "/unconfined/CacheScope/.surfacing_cache");
485- auto receiver = make_shared<Receiver>();
486- scope()->search("", SearchMetadata("unused", "unused"), receiver);
487- receiver->wait_until_finished();
488- EXPECT_EQ(receiver->result(), nullptr);
489-
490- // Cache file must still be there, but decode will have failed.
491- boost::system::error_code ec;
492- EXPECT_TRUE(boost::filesystem::exists(TEST_RUNTIME_PATH "/unconfined/CacheScope/.surfacing_cache", ec));
493-}
494-
495 TEST_F(CacheScopeTest, missing_results)
496 {
497 // Get coverage on missing results entry
498
499=== removed file 'test/gtest/scopes/ResultCache/no_filter_state_cache'
500--- test/gtest/scopes/ResultCache/no_filter_state_cache 2015-02-05 09:35:42 +0000
501+++ test/gtest/scopes/ResultCache/no_filter_state_cache 1970-01-01 00:00:00 +0000
502@@ -1,1 +0,0 @@
503-{"categories":[{"icon":"","id":"CacheScope","renderer_template":"\n {\n \"schema-version\":1,\n \"template\":\n {\n \"category-layout\":\"grid\"\n },\n \"components\":\n {\n \"title\":\"title\",\n \"art\":\"art\"\n }\n }\n ","title":""}],"departments":{"departments":[{"label":"Sub","query":{"department_id":"sub","filter_state":{},"query_string":"","scope":"CacheScope"}}],"label":"Top","query":{"department_id":"","filter_state":{},"query_string":"","scope":"CacheScope"}},"filters":[{"filter_type":"option_selector","id":"f1","label":"Choose an option","multi_select":false,"options":[{"id":"o1","label":"Option 1"},{"id":"o2","label":"Option 2"}]}],"results":[{"attrs":{"title":"","uri":"uri"},"internal":{"cat_id":"CacheScope"}}]}

Subscribers

People subscribed via source and target branches

to all changes: