From 9169614dc32aff466a7130f1ce64bb3f4044b8d8 Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Fri, 17 Jul 2026 17:12:39 +0530 Subject: [PATCH 01/11] feat: default, pinned and required filters in explore --- proto/gen/rill/runtime/v1/resources.pb.go | 1690 +++++++++-------- .../gen/rill/runtime/v1/runtime.swagger.yaml | 12 + proto/rill/runtime/v1/resources.proto | 5 + runtime/parser/parse_explore.go | 31 +- .../features/canvas/stores/canvas-entity.ts | 3 +- .../features/canvas/stores/filter-manager.ts | 67 +- .../filters/ExploreFilterChipsReadOnly.svelte | 2 + .../filters/FilterChipsReadOnly.svelte | 3 + .../dashboards/filters/Filters.svelte | 4 +- .../state-managers/actions/filters.ts | 13 +- .../selectors/dimension-filters.ts | 12 +- .../selectors/measure-filters.ts | 8 + .../dashboards/stores/explore-state.ts | 5 + .../dashboards/stores/filter-utils.ts | 57 +- .../get-explore-state-from-yaml-config.ts | 40 + .../stores/get-rill-default-explore-state.ts | 1 + .../proto/gen/rill/runtime/v1/resources_pb.ts | 17 + .../src/runtime-client/gen/index.schemas.ts | 2 + 18 files changed, 1067 insertions(+), 905 deletions(-) diff --git a/proto/gen/rill/runtime/v1/resources.pb.go b/proto/gen/rill/runtime/v1/resources.pb.go index cd86c43ff2b9..3a0c904d7bb3 100644 --- a/proto/gen/rill/runtime/v1/resources.pb.go +++ b/proto/gen/rill/runtime/v1/resources.pb.go @@ -3210,6 +3210,11 @@ type ExplorePreset struct { Where *Expression `protobuf:"bytes,11,opt,name=where,proto3,oneof" json:"where,omitempty"` // Temporary to differentiate between "select" and "in list" modes. Expression will be replaced with UI specific state in the future. DimensionsWithInlistFilter []string `protobuf:"bytes,29,rep,name=dimensions_with_inlist_filter,json=dimensionsWithInlistFilter,proto3" json:"dimensions_with_inlist_filter,omitempty"` + // Array of dimension or measure names + PinnedFilters []string `protobuf:"bytes,39,rep,name=pinned_filters,json=pinnedFilters,proto3" json:"pinned_filters,omitempty"` + // Array of dimension or measure names that must have a value before the explore can render. + // Required filters are implicitly pinned. + RequiredFilters []string `protobuf:"bytes,40,rep,name=required_filters,json=requiredFilters,proto3" json:"required_filters,omitempty"` // Time range for the explore. // It corresponds to the `range` property of the explore's `time_ranges`. // If not found in `time_ranges`, it should be added to the list. @@ -3321,6 +3326,20 @@ func (x *ExplorePreset) GetDimensionsWithInlistFilter() []string { return nil } +func (x *ExplorePreset) GetPinnedFilters() []string { + if x != nil { + return x.PinnedFilters + } + return nil +} + +func (x *ExplorePreset) GetRequiredFilters() []string { + if x != nil { + return x.RequiredFilters + } + return nil +} + func (x *ExplorePreset) GetTimeRange() string { if x != nil && x.TimeRange != nil { return *x.TimeRange @@ -8642,7 +8661,7 @@ var file_rill_runtime_v1_resources_proto_rawDesc = []byte{ 0x6e, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, - 0x65, 0x22, 0x9e, 0x13, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x65, + 0x65, 0x22, 0xf0, 0x13, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4f, 0x0a, 0x13, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, @@ -8664,853 +8683,858 @@ var file_rill_runtime_v1_resources_proto_rawDesc = []byte{ 0x6f, 0x6e, 0x73, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x69, 0x6e, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x1d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1a, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x57, 0x69, 0x74, 0x68, 0x49, 0x6e, 0x6c, 0x69, - 0x73, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, - 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, - 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, - 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, - 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x69, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x47, 0x72, 0x61, 0x69, 0x6e, 0x88, 0x01, - 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x0f, - 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x88, - 0x01, 0x01, 0x12, 0x2a, 0x0a, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x22, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0d, 0x74, 0x69, - 0x6d, 0x65, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x4f, - 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x6f, 0x64, - 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, - 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x52, - 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, - 0x31, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, - 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x48, 0x06, 0x52, 0x10, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x88, - 0x01, 0x01, 0x12, 0x36, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, - 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x07, 0x52, 0x13, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x44, 0x69, - 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x38, 0x0a, 0x04, 0x76, 0x69, - 0x65, 0x77, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6c, 0x6f, - 0x72, 0x65, 0x57, 0x65, 0x62, 0x56, 0x69, 0x65, 0x77, 0x48, 0x08, 0x52, 0x04, 0x76, 0x69, 0x65, - 0x77, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, - 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x62, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x48, 0x09, 0x52, - 0x0d, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x53, 0x6f, 0x72, 0x74, 0x42, 0x79, 0x88, 0x01, - 0x01, 0x12, 0x2d, 0x0a, 0x10, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x6f, 0x72, - 0x74, 0x5f, 0x61, 0x73, 0x63, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x48, 0x0a, 0x52, 0x0e, 0x65, - 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x53, 0x6f, 0x72, 0x74, 0x41, 0x73, 0x63, 0x88, 0x01, 0x01, - 0x12, 0x51, 0x0a, 0x11, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x6f, 0x72, 0x74, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x72, 0x69, - 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, - 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x53, 0x6f, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x48, 0x0b, 0x52, - 0x0f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x53, 0x6f, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x88, 0x01, 0x01, 0x12, 0x41, 0x0a, 0x1a, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x65, - 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x48, 0x0c, 0x52, 0x18, 0x65, 0x78, 0x70, 0x6c, 0x6f, - 0x72, 0x65, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x4e, 0x0a, 0x21, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, - 0x65, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x6d, 0x65, - 0x61, 0x73, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x1e, 0x20, 0x01, 0x28, - 0x0d, 0x48, 0x0d, 0x52, 0x1e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x4c, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x40, 0x0a, 0x1c, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, - 0x65, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x6d, 0x65, - 0x61, 0x73, 0x75, 0x72, 0x65, 0x73, 0x18, 0x1f, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1a, 0x65, 0x78, - 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, - 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x73, 0x12, 0x6b, 0x0a, 0x31, 0x65, 0x78, 0x70, 0x6c, - 0x6f, 0x72, 0x65, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, - 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x66, 0x6f, 0x72, - 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x73, 0x18, 0x20, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x0e, 0x52, 0x2b, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x4c, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x68, 0x6f, 0x77, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x46, 0x6f, 0x72, 0x41, 0x6c, 0x6c, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, - 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x39, 0x0a, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x69, - 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x18, - 0x15, 0x20, 0x01, 0x28, 0x09, 0x48, 0x0f, 0x52, 0x14, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x69, 0x6d, - 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x88, 0x01, 0x01, - 0x12, 0x3e, 0x0a, 0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x16, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x10, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x69, 0x6d, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, - 0x12, 0x31, 0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x5f, 0x70, 0x69, 0x6e, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x48, 0x11, 0x52, 0x10, - 0x74, 0x69, 0x6d, 0x65, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x69, 0x6e, - 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x72, 0x6f, 0x77, - 0x73, 0x18, 0x18, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x52, 0x6f, - 0x77, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x63, 0x6f, 0x6c, 0x73, - 0x18, 0x19, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x43, 0x6f, 0x6c, - 0x73, 0x12, 0x27, 0x0a, 0x0d, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x5f, - 0x62, 0x79, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x12, 0x52, 0x0b, 0x70, 0x69, 0x76, 0x6f, - 0x74, 0x53, 0x6f, 0x72, 0x74, 0x42, 0x79, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, 0x0e, 0x70, 0x69, - 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x61, 0x73, 0x63, 0x18, 0x1b, 0x20, 0x01, - 0x28, 0x08, 0x48, 0x13, 0x52, 0x0c, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x53, 0x6f, 0x72, 0x74, 0x41, - 0x73, 0x63, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x10, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x14, 0x52, 0x0e, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x6f, 0x64, - 0x65, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x0f, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x72, 0x6f, - 0x77, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x21, 0x20, 0x01, 0x28, 0x05, 0x48, 0x15, 0x52, - 0x0d, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x52, 0x6f, 0x77, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x88, 0x01, - 0x01, 0x12, 0x3c, 0x0a, 0x18, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x5f, - 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x25, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x16, 0x52, 0x15, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x53, 0x68, 0x6f, 0x77, - 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x73, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x88, 0x01, 0x01, 0x12, - 0x36, 0x0a, 0x15, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x73, 0x5f, 0x72, 0x6f, 0x77, 0x18, 0x26, 0x20, 0x01, 0x28, 0x08, 0x48, 0x17, - 0x52, 0x12, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x53, 0x68, 0x6f, 0x77, 0x54, 0x6f, 0x74, 0x61, 0x6c, - 0x73, 0x52, 0x6f, 0x77, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x14, 0x63, 0x68, 0x61, 0x72, 0x74, - 0x5f, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x79, 0x5f, 0x61, 0x78, 0x69, 0x73, 0x18, - 0x23, 0x20, 0x01, 0x28, 0x08, 0x48, 0x18, 0x52, 0x11, 0x63, 0x68, 0x61, 0x72, 0x74, 0x44, 0x79, - 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x59, 0x41, 0x78, 0x69, 0x73, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, - 0x06, 0x5f, 0x77, 0x68, 0x65, 0x72, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x7a, - 0x6f, 0x6e, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x67, 0x72, 0x61, - 0x69, 0x6e, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x15, 0x0a, 0x13, 0x5f, - 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, - 0x67, 0x65, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, - 0x6e, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x0a, 0x05, 0x5f, - 0x76, 0x69, 0x65, 0x77, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, - 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x62, 0x79, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x65, 0x78, 0x70, - 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x61, 0x73, 0x63, 0x42, 0x14, 0x0a, - 0x12, 0x5f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x42, 0x1d, 0x0a, 0x1b, 0x5f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, - 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x42, 0x24, 0x0a, 0x22, 0x5f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x6c, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x75, - 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x34, 0x0a, 0x32, 0x5f, 0x65, 0x78, 0x70, - 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, - 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x66, 0x6f, - 0x72, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x73, 0x42, 0x19, - 0x0a, 0x17, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x42, 0x1c, 0x0a, 0x1a, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, - 0x72, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x69, 0x6e, 0x42, 0x10, - 0x0a, 0x0e, 0x5f, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x62, 0x79, - 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x5f, - 0x61, 0x73, 0x63, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x70, 0x69, 0x76, - 0x6f, 0x74, 0x5f, 0x72, 0x6f, 0x77, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x42, 0x1b, 0x0a, 0x19, - 0x5f, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x70, 0x69, - 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x73, 0x5f, - 0x72, 0x6f, 0x77, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x79, - 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x79, 0x5f, 0x61, 0x78, 0x69, 0x73, 0x4a, 0x04, 0x08, 0x24, - 0x10, 0x25, 0x22, 0xca, 0x01, 0x0a, 0x0d, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x03, - 0x61, 0x6c, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x03, 0x61, 0x6c, 0x6c, - 0x12, 0x3a, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x48, 0x00, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x16, 0x0a, 0x05, - 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x72, - 0x65, 0x67, 0x65, 0x78, 0x12, 0x2d, 0x0a, 0x11, 0x64, 0x75, 0x63, 0x6b, 0x64, 0x62, 0x5f, 0x65, - 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x00, 0x52, 0x10, 0x64, 0x75, 0x63, 0x6b, 0x64, 0x62, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, - 0x29, 0x0a, 0x0f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x76, 0x0a, 0x09, 0x4d, 0x69, - 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x35, 0x0a, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x69, 0x6c, - 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x67, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x22, 0x59, 0x0a, 0x0d, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x70, 0x65, 0x63, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x71, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x73, 0x71, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x2a, 0x0a, - 0x0e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x6d, 0x0a, 0x06, 0x52, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, - 0x73, 0x70, 0x65, 0x63, 0x12, 0x32, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x8f, 0x07, 0x0a, 0x0a, 0x52, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, - 0x69, 0x67, 0x67, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x69, - 0x67, 0x67, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x10, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, - 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x0f, 0x72, 0x65, 0x66, 0x72, 0x65, - 0x73, 0x68, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, - 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, - 0x48, 0x0a, 0x13, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x70, - 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x50, - 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x41, 0x72, 0x67, 0x73, 0x4a, 0x73, 0x6f, 0x6e, - 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x12, 0x42, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x66, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, + 0x73, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x69, 0x6e, 0x6e, + 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x27, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0d, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, + 0x29, 0x0a, 0x10, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x73, 0x18, 0x28, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x22, 0x0a, 0x0a, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, + 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1f, + 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x02, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x88, 0x01, 0x01, 0x12, + 0x22, 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x69, 0x6e, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x47, 0x72, 0x61, 0x69, 0x6e, + 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, + 0x52, 0x0f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, + 0x65, 0x88, 0x01, 0x01, 0x12, 0x2a, 0x0a, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x6d, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x22, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0d, + 0x74, 0x69, 0x6d, 0x65, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, + 0x12, 0x4f, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, + 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6c, + 0x6f, 0x72, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, + 0x65, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, + 0x65, 0x12, 0x31, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x48, 0x06, 0x52, + 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, + 0x65, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, + 0x6f, 0x6e, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x07, 0x52, 0x13, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, + 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x38, 0x0a, 0x04, + 0x76, 0x69, 0x65, 0x77, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, - 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x6f, 0x72, - 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x65, 0x78, 0x70, 0x6f, 0x72, - 0x74, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x09, 0x6e, - 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, - 0x69, 0x65, 0x72, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x72, 0x69, 0x6c, 0x6c, - 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, - 0x6b, 0x5f, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x10, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x49, 0x6e, 0x68, 0x65, 0x72, 0x69, - 0x74, 0x12, 0x34, 0x0a, 0x16, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x5f, 0x69, - 0x73, 0x6f, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x14, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x49, 0x73, 0x6f, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x76, 0x61, 0x6c, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, - 0x12, 0x38, 0x0a, 0x18, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x5f, 0x63, 0x68, - 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x6e, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x16, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x55, 0x6e, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, - 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x90, 0x02, 0x0a, 0x0b, 0x52, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3a, 0x0a, 0x0b, 0x6e, 0x65, - 0x78, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x6c, 0x6f, 0x72, 0x65, 0x57, 0x65, 0x62, 0x56, 0x69, 0x65, 0x77, 0x48, 0x08, 0x52, 0x04, 0x76, + 0x69, 0x65, 0x77, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, + 0x65, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x62, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x09, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x53, 0x6f, 0x72, 0x74, 0x42, 0x79, + 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x10, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x73, + 0x6f, 0x72, 0x74, 0x5f, 0x61, 0x73, 0x63, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x48, 0x0a, 0x52, + 0x0e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x53, 0x6f, 0x72, 0x74, 0x41, 0x73, 0x63, 0x88, + 0x01, 0x01, 0x12, 0x51, 0x0a, 0x11, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x6f, + 0x72, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, + 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x53, 0x6f, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x48, + 0x0b, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x53, 0x6f, 0x72, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x88, 0x01, 0x01, 0x12, 0x41, 0x0a, 0x1a, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, + 0x5f, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x48, 0x0c, 0x52, 0x18, 0x65, 0x78, 0x70, + 0x6c, 0x6f, 0x72, 0x65, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x44, 0x69, 0x6d, 0x65, + 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x4e, 0x0a, 0x21, 0x65, 0x78, 0x70, 0x6c, + 0x6f, 0x72, 0x65, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, + 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x1e, 0x20, + 0x01, 0x28, 0x0d, 0x48, 0x0d, 0x52, 0x1e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x4c, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x40, 0x0a, 0x1c, 0x65, 0x78, 0x70, 0x6c, + 0x6f, 0x72, 0x65, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, + 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x73, 0x18, 0x1f, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1a, + 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, + 0x72, 0x64, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x73, 0x12, 0x6b, 0x0a, 0x31, 0x65, 0x78, + 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, + 0x64, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x66, + 0x6f, 0x72, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x73, 0x18, + 0x20, 0x20, 0x01, 0x28, 0x08, 0x48, 0x0e, 0x52, 0x2b, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, + 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x68, 0x6f, 0x77, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x46, 0x6f, 0x72, 0x41, 0x6c, 0x6c, 0x4d, 0x65, 0x61, 0x73, + 0x75, 0x72, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x39, 0x0a, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x5f, + 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, + 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x48, 0x0f, 0x52, 0x14, 0x74, 0x69, 0x6d, 0x65, 0x44, + 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x88, + 0x01, 0x01, 0x12, 0x3e, 0x0a, 0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x16, 0x20, 0x01, 0x28, 0x09, 0x48, 0x10, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x69, 0x6d, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x88, + 0x01, 0x01, 0x12, 0x31, 0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x69, 0x6e, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x48, 0x11, + 0x52, 0x10, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x50, + 0x69, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x72, + 0x6f, 0x77, 0x73, 0x18, 0x18, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x69, 0x76, 0x6f, 0x74, + 0x52, 0x6f, 0x77, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x63, 0x6f, + 0x6c, 0x73, 0x18, 0x19, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x43, + 0x6f, 0x6c, 0x73, 0x12, 0x27, 0x0a, 0x0d, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x6f, 0x72, + 0x74, 0x5f, 0x62, 0x79, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x12, 0x52, 0x0b, 0x70, 0x69, + 0x76, 0x6f, 0x74, 0x53, 0x6f, 0x72, 0x74, 0x42, 0x79, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, 0x0e, + 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x61, 0x73, 0x63, 0x18, 0x1b, + 0x20, 0x01, 0x28, 0x08, 0x48, 0x13, 0x52, 0x0c, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x53, 0x6f, 0x72, + 0x74, 0x41, 0x73, 0x63, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x10, 0x70, 0x69, 0x76, 0x6f, 0x74, + 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x14, 0x52, 0x0e, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4d, + 0x6f, 0x64, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x0f, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, + 0x72, 0x6f, 0x77, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x21, 0x20, 0x01, 0x28, 0x05, 0x48, + 0x15, 0x52, 0x0d, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x52, 0x6f, 0x77, 0x4c, 0x69, 0x6d, 0x69, 0x74, + 0x88, 0x01, 0x01, 0x12, 0x3c, 0x0a, 0x18, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x68, 0x6f, + 0x77, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, + 0x25, 0x20, 0x01, 0x28, 0x08, 0x48, 0x16, 0x52, 0x15, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x53, 0x68, + 0x6f, 0x77, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x73, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x88, 0x01, + 0x01, 0x12, 0x36, 0x0a, 0x15, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x5f, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x73, 0x5f, 0x72, 0x6f, 0x77, 0x18, 0x26, 0x20, 0x01, 0x28, 0x08, + 0x48, 0x17, 0x52, 0x12, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x53, 0x68, 0x6f, 0x77, 0x54, 0x6f, 0x74, + 0x61, 0x6c, 0x73, 0x52, 0x6f, 0x77, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x14, 0x63, 0x68, 0x61, + 0x72, 0x74, 0x5f, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x79, 0x5f, 0x61, 0x78, 0x69, + 0x73, 0x18, 0x23, 0x20, 0x01, 0x28, 0x08, 0x48, 0x18, 0x52, 0x11, 0x63, 0x68, 0x61, 0x72, 0x74, + 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x59, 0x41, 0x78, 0x69, 0x73, 0x88, 0x01, 0x01, 0x42, + 0x08, 0x0a, 0x06, 0x5f, 0x77, 0x68, 0x65, 0x72, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x67, + 0x72, 0x61, 0x69, 0x6e, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x15, 0x0a, + 0x13, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, + 0x61, 0x6e, 0x67, 0x65, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, + 0x73, 0x6f, 0x6e, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x0a, + 0x05, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x65, 0x78, 0x70, 0x6c, 0x6f, + 0x72, 0x65, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x62, 0x79, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x65, + 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x61, 0x73, 0x63, 0x42, + 0x14, 0x0a, 0x12, 0x5f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x6f, 0x72, 0x74, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x1d, 0x0a, 0x1b, 0x5f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, + 0x65, 0x5f, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x24, 0x0a, 0x22, 0x5f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, + 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x6d, 0x65, 0x61, + 0x73, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x34, 0x0a, 0x32, 0x5f, 0x65, + 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, + 0x72, 0x64, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, + 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x73, + 0x42, 0x19, 0x0a, 0x17, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x42, 0x1c, 0x0a, 0x1a, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, + 0x68, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x69, 0x6e, + 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x5f, + 0x62, 0x79, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x6f, 0x72, + 0x74, 0x5f, 0x61, 0x73, 0x63, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x70, + 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x72, 0x6f, 0x77, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x42, 0x1b, + 0x0a, 0x19, 0x5f, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x74, 0x6f, + 0x74, 0x61, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x42, 0x18, 0x0a, 0x16, 0x5f, + 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x73, 0x5f, 0x72, 0x6f, 0x77, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x5f, + 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x79, 0x5f, 0x61, 0x78, 0x69, 0x73, 0x4a, 0x04, + 0x08, 0x24, 0x10, 0x25, 0x22, 0xca, 0x01, 0x0a, 0x0d, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x12, 0x12, + 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x03, 0x61, + 0x6c, 0x6c, 0x12, 0x3a, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x16, + 0x0a, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x12, 0x2d, 0x0a, 0x11, 0x64, 0x75, 0x63, 0x6b, 0x64, 0x62, + 0x5f, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x10, 0x64, 0x75, 0x63, 0x6b, 0x64, 0x62, 0x45, 0x78, 0x70, 0x72, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x22, 0x29, 0x0a, 0x0f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x76, 0x0a, 0x09, + 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x04, 0x73, 0x70, 0x65, + 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x35, 0x0a, + 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x22, 0x59, 0x0a, 0x0d, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x71, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x73, 0x71, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, + 0x2a, 0x0a, 0x0e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x6d, 0x0a, 0x06, 0x52, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, + 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x32, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x8f, 0x07, 0x0a, 0x0a, 0x52, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, + 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, + 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x10, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, + 0x68, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x0f, 0x72, 0x65, 0x66, + 0x72, 0x65, 0x73, 0x68, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x27, 0x0a, 0x0f, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, + 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, + 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, + 0x72, 0x12, 0x48, 0x0a, 0x13, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, + 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, + 0x72, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x71, 0x75, 0x65, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x41, 0x72, 0x67, 0x73, 0x4a, 0x73, + 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x42, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, + 0x78, 0x70, 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0c, 0x65, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x65, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, + 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x37, 0x0a, + 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x09, 0x6e, 0x6f, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x72, 0x69, + 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, + 0x61, 0x72, 0x6b, 0x5f, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x10, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x49, 0x6e, 0x68, 0x65, + 0x72, 0x69, 0x74, 0x12, 0x34, 0x0a, 0x16, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, + 0x5f, 0x69, 0x73, 0x6f, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x14, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x49, 0x73, + 0x6f, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x0e, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x4c, 0x69, 0x6d, + 0x69, 0x74, 0x12, 0x38, 0x0a, 0x18, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x5f, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x6e, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x18, 0x0f, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x55, 0x6e, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x1a, 0x3e, 0x0a, 0x10, + 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x90, 0x02, 0x0a, + 0x0b, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3a, 0x0a, 0x0b, + 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x6e, + 0x65, 0x78, 0x74, 0x52, 0x75, 0x6e, 0x4f, 0x6e, 0x12, 0x4d, 0x0a, 0x11, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x11, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x48, + 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, + 0x9d, 0x02, 0x0a, 0x0f, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x68, 0x6f, 0x63, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x05, 0x61, 0x64, 0x68, 0x6f, 0x63, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, + 0x0a, 0x08, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x08, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3b, 0x0a, 0x0b, 0x72, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x6e, 0x65, 0x78, - 0x74, 0x52, 0x75, 0x6e, 0x4f, 0x6e, 0x12, 0x4d, 0x0a, 0x11, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x11, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x69, 0x73, - 0x74, 0x6f, 0x72, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x9d, 0x02, - 0x0a, 0x0f, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x68, 0x6f, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x05, 0x61, 0x64, 0x68, 0x6f, 0x63, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, - 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3b, 0x0a, 0x0b, 0x72, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, - 0x5f, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x4f, 0x6e, - 0x12, 0x3b, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x0a, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x4f, 0x6e, 0x22, 0x6a, 0x0a, - 0x05, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, - 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x31, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0xf8, 0x08, 0x0a, 0x09, 0x41, 0x6c, - 0x65, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, - 0x69, 0x67, 0x67, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x69, - 0x67, 0x67, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x10, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, - 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x0f, 0x72, 0x65, 0x66, 0x72, 0x65, - 0x73, 0x68, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x77, 0x61, - 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, - 0x49, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x12, 0x34, 0x0a, 0x16, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x76, 0x61, 0x6c, 0x73, 0x5f, 0x69, 0x73, 0x6f, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, - 0x6c, 0x73, 0x49, 0x73, 0x6f, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, - 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, - 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x38, 0x0a, 0x18, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, - 0x61, 0x6c, 0x73, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x6e, 0x63, 0x6c, 0x6f, 0x73, - 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, - 0x61, 0x6c, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x6e, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, - 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x41, 0x72, 0x67, 0x73, 0x4a, 0x73, 0x6f, 0x6e, - 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, 0x16, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x13, - 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, - 0x69, 0x65, 0x73, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x52, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x70, - 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, - 0x66, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x66, 0x6f, 0x72, - 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x11, 0x71, 0x75, 0x65, 0x72, 0x79, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, - 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x4b, 0x0a, 0x14, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, - 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0d, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x72, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, + 0x4f, 0x6e, 0x12, 0x3b, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x6f, + 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x4f, 0x6e, 0x22, + 0x6a, 0x0a, 0x05, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x53, 0x70, + 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x31, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0xf8, 0x08, 0x0a, 0x09, + 0x41, 0x6c, 0x65, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, + 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, + 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x10, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, + 0x68, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x0f, 0x72, 0x65, 0x66, + 0x72, 0x65, 0x73, 0x68, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x2b, 0x0a, 0x11, + 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, + 0x72, 0x6b, 0x49, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x12, 0x34, 0x0a, 0x16, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x5f, 0x69, 0x73, 0x6f, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x76, 0x61, 0x6c, 0x73, 0x49, 0x73, 0x6f, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x5f, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, + 0x61, 0x6c, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x38, 0x0a, 0x18, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x73, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x6e, 0x63, 0x6c, + 0x6f, 0x73, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x6e, 0x63, 0x6c, 0x6f, 0x73, + 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, + 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x74, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x71, 0x75, 0x65, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x41, 0x72, 0x67, 0x73, 0x4a, 0x73, + 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, 0x16, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x48, + 0x0a, 0x13, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x75, 0x63, 0x74, 0x52, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x50, 0x72, + 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x46, 0x6f, 0x72, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x66, + 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x11, 0x71, 0x75, 0x65, 0x72, 0x79, 0x46, 0x6f, 0x72, 0x55, + 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x4b, 0x0a, 0x14, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, + 0x00, 0x52, 0x12, 0x71, 0x75, 0x65, 0x72, 0x79, 0x46, 0x6f, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, + 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x6f, 0x6e, 0x5f, 0x66, + 0x61, 0x69, 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6e, 0x6f, 0x74, 0x69, 0x66, + 0x79, 0x4f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x6f, 0x74, 0x69, 0x66, + 0x79, 0x5f, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0d, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, + 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x18, 0x12, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x08, 0x72, 0x65, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x12, 0x34, 0x0a, 0x16, 0x72, + 0x65, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x65, + 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x72, 0x65, 0x6e, + 0x6f, 0x74, 0x69, 0x66, 0x79, 0x41, 0x66, 0x74, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, + 0x73, 0x12, 0x37, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x18, 0x15, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, + 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x12, 0x4d, 0x0a, 0x0b, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, + 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x5f, 0x66, 0x6f, 0x72, 0x22, 0x61, 0x0a, 0x08, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x12, 0x37, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x00, 0x52, - 0x12, 0x71, 0x75, 0x65, 0x72, 0x79, 0x46, 0x6f, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x6f, 0x6e, - 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, - 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x12, - 0x24, 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x6f, 0x6e, 0x5f, 0x66, 0x61, 0x69, - 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4f, - 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, - 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, - 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1a, 0x0a, - 0x08, 0x72, 0x65, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x08, 0x72, 0x65, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x6e, - 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x72, 0x65, 0x6e, 0x6f, 0x74, - 0x69, 0x66, 0x79, 0x41, 0x66, 0x74, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, - 0x37, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x18, 0x15, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x09, 0x6e, - 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x12, 0x4d, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x6c, 0x65, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x5f, 0x66, 0x6f, 0x72, 0x22, 0x61, 0x0a, 0x08, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x37, - 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0a, 0x70, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0xc7, 0x02, 0x0a, 0x0a, 0x41, 0x6c, 0x65, 0x72, - 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x70, 0x65, 0x63, 0x5f, 0x68, - 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x70, 0x65, 0x63, 0x48, - 0x61, 0x73, 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x66, 0x73, 0x48, 0x61, 0x73, 0x68, - 0x12, 0x3a, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x52, 0x75, 0x6e, 0x4f, 0x6e, 0x12, 0x4c, 0x0a, 0x11, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0a, 0x70, + 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0xc7, 0x02, 0x0a, 0x0a, 0x41, 0x6c, + 0x65, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x70, 0x65, 0x63, + 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x70, 0x65, + 0x63, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x73, 0x5f, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x66, 0x73, 0x48, 0x61, + 0x73, 0x68, 0x12, 0x3a, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x52, 0x75, 0x6e, 0x4f, 0x6e, 0x12, 0x4c, + 0x0a, 0x11, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x65, 0x72, + 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4c, 0x0a, 0x11, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, + 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x45, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4c, 0x0a, 0x11, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x22, 0x91, 0x03, 0x0a, 0x0e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x68, 0x6f, 0x63, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x64, 0x68, 0x6f, 0x63, 0x12, 0x38, 0x0a, 0x06, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x69, 0x6c, - 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, - 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x6f, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x11, 0x73, 0x65, 0x6e, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, - 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x4f, - 0x6e, 0x12, 0x3b, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x6f, 0x6e, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x0a, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x4f, 0x6e, 0x12, 0x45, - 0x0a, 0x10, 0x73, 0x75, 0x70, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x73, 0x69, 0x6e, - 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x22, 0x91, 0x03, 0x0a, 0x0e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x68, 0x6f, 0x63, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x64, 0x68, 0x6f, 0x63, 0x12, 0x38, 0x0a, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x65, 0x6e, 0x74, 0x5f, 0x6e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x11, 0x73, 0x65, 0x6e, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, + 0x64, 0x4f, 0x6e, 0x12, 0x3b, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x5f, + 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x73, 0x75, 0x70, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, - 0x53, 0x69, 0x6e, 0x63, 0x65, 0x22, 0xc0, 0x01, 0x0a, 0x0f, 0x41, 0x73, 0x73, 0x65, 0x72, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x38, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, - 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, 0x65, - 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x66, 0x61, 0x69, 0x6c, 0x5f, 0x72, 0x6f, 0x77, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x07, - 0x66, 0x61, 0x69, 0x6c, 0x52, 0x6f, 0x77, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, - 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x85, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x66, - 0x72, 0x65, 0x73, 0x68, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x04, 0x73, - 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, - 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, - 0x65, 0x73, 0x68, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, - 0x73, 0x70, 0x65, 0x63, 0x12, 0x3a, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x72, 0x69, - 0x67, 0x67, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x22, 0x8f, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x72, 0x69, 0x67, - 0x67, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x12, 0x3b, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, - 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4d, 0x6f, - 0x64, 0x65, 0x6c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x65, - 0x6c, 0x73, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x72, 0x69, - 0x67, 0x67, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xcb, 0x01, 0x0a, 0x13, 0x52, 0x65, - 0x66, 0x72, 0x65, 0x73, 0x68, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, - 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x75, 0x6c, 0x6c, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x66, 0x75, 0x6c, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x70, - 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x61, - 0x6c, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x61, 0x6c, 0x6c, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x34, 0x0a, 0x16, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, - 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x14, 0x61, 0x6c, 0x6c, 0x53, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x50, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x6a, 0x0a, 0x05, 0x54, 0x68, 0x65, 0x6d, 0x65, - 0x12, 0x2e, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x4f, 0x6e, + 0x12, 0x45, 0x0a, 0x10, 0x73, 0x75, 0x70, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x73, + 0x69, 0x6e, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x73, 0x75, 0x70, 0x70, 0x72, 0x65, 0x73, 0x73, + 0x65, 0x64, 0x53, 0x69, 0x6e, 0x63, 0x65, 0x22, 0xc0, 0x01, 0x0a, 0x0f, 0x41, 0x73, 0x73, 0x65, + 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x38, 0x0a, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x72, 0x69, + 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, + 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x66, 0x61, 0x69, 0x6c, 0x5f, 0x72, 0x6f, + 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, + 0x52, 0x07, 0x66, 0x61, 0x69, 0x6c, 0x52, 0x6f, 0x77, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, + 0x0a, 0x08, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x08, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x85, 0x01, 0x0a, 0x0e, 0x52, + 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x37, 0x0a, + 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x69, + 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, + 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x3a, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, + 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x22, 0x8f, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x72, + 0x69, 0x67, 0x67, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x12, 0x3b, 0x0a, 0x09, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, + 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x06, 0x6d, 0x6f, + 0x64, 0x65, 0x6c, 0x73, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, + 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xcb, 0x01, 0x0a, 0x13, + 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x54, 0x72, 0x69, 0x67, + 0x67, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x75, 0x6c, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x66, 0x75, 0x6c, 0x6c, 0x12, 0x1e, 0x0a, + 0x0a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x34, 0x0a, + 0x16, 0x61, 0x6c, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x72, + 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x61, + 0x6c, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x70, + 0x65, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x14, 0x61, 0x6c, 0x6c, 0x53, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x50, + 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x6a, 0x0a, 0x05, 0x54, 0x68, 0x65, + 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, + 0x65, 0x63, 0x12, 0x31, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x98, 0x03, 0x0a, 0x09, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x53, + 0x70, 0x65, 0x63, 0x12, 0x40, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, + 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x72, 0x69, 0x6c, + 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, + 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0c, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6c, + 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x44, 0x0a, 0x0f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, + 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, - 0x12, 0x31, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x22, 0x98, 0x03, 0x0a, 0x09, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x53, 0x70, 0x65, - 0x63, 0x12, 0x40, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, - 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x6f, 0x72, - 0x48, 0x00, 0x52, 0x0c, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6c, 0x6f, 0x72, - 0x88, 0x01, 0x01, 0x12, 0x44, 0x0a, 0x0f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, - 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6f, 0x6c, 0x6f, 0x72, 0x48, 0x01, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, - 0x79, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x72, 0x69, - 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x61, 0x77, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x52, 0x61, 0x77, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, - 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x61, 0x77, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x11, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x52, 0x61, 0x77, 0x12, 0x37, 0x0a, 0x05, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x73, 0x48, 0x02, 0x52, 0x05, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x88, 0x01, 0x01, 0x12, 0x35, - 0x0a, 0x04, 0x64, 0x61, 0x72, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, - 0x68, 0x65, 0x6d, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x48, 0x03, 0x52, 0x04, 0x64, 0x61, - 0x72, 0x6b, 0x88, 0x01, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, - 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x08, 0x0a, 0x06, 0x5f, - 0x6c, 0x69, 0x67, 0x68, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x64, 0x61, 0x72, 0x6b, 0x22, 0x0c, - 0x0a, 0x0a, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xce, 0x01, 0x0a, - 0x0b, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, - 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, - 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, - 0x61, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x61, 0x72, 0x79, 0x12, 0x49, 0x0a, 0x09, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x43, - 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x1a, - 0x3c, 0x0a, 0x0e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x76, 0x0a, - 0x09, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x04, 0x73, 0x70, - 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, - 0x6e, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x35, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x2e, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x48, 0x01, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, + 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x2a, 0x0a, 0x11, 0x70, + 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x61, 0x77, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x43, + 0x6f, 0x6c, 0x6f, 0x72, 0x52, 0x61, 0x77, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x65, 0x63, 0x6f, 0x6e, + 0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x61, 0x77, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x43, + 0x6f, 0x6c, 0x6f, 0x72, 0x52, 0x61, 0x77, 0x12, 0x37, 0x0a, 0x05, 0x6c, 0x69, 0x67, 0x68, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x43, 0x6f, + 0x6c, 0x6f, 0x72, 0x73, 0x48, 0x02, 0x52, 0x05, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x88, 0x01, 0x01, + 0x12, 0x35, 0x0a, 0x04, 0x64, 0x61, 0x72, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x48, 0x03, 0x52, 0x04, + 0x64, 0x61, 0x72, 0x6b, 0x88, 0x01, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x70, 0x72, 0x69, 0x6d, + 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x65, + 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x08, 0x0a, + 0x06, 0x5f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x64, 0x61, 0x72, 0x6b, + 0x22, 0x0c, 0x0a, 0x0a, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xce, + 0x01, 0x0a, 0x0b, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x12, 0x18, + 0x0a, 0x07, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x63, 0x6f, + 0x6e, 0x64, 0x61, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x12, 0x49, 0x0a, 0x09, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, + 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x65, 0x6d, + 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + 0x73, 0x1a, 0x3c, 0x0a, 0x0e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0x76, 0x0a, 0x09, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x04, + 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x69, 0x6c, + 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, + 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, + 0x12, 0x35, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0xdc, 0x02, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x70, + 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, + 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, + 0x0a, 0x08, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x13, 0x72, 0x65, + 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, + 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, + 0x52, 0x12, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, + 0x74, 0x69, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x08, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x56, + 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x3a, + 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, + 0x6c, 0x65, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x65, + 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x49, 0x6e, + 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x22, 0x97, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, + 0x6e, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0xdc, 0x02, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, - 0x65, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, - 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x13, 0x72, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x12, - 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, - 0x65, 0x73, 0x12, 0x38, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x08, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, - 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x3a, 0x0a, 0x06, - 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, - 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x65, 0x66, 0x69, - 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x49, 0x6e, 0x43, 0x61, - 0x6e, 0x76, 0x61, 0x73, 0x22, 0x97, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, - 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x69, - 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x09, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x53, 0x70, 0x65, 0x63, 0x12, 0x46, 0x0a, 0x11, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x72, - 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x64, - 0x61, 0x74, 0x61, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x65, 0x64, 0x4f, 0x6e, 0x22, 0x78, - 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, - 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3b, 0x0a, 0x0d, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x6d, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x76, - 0x61, 0x73, 0x12, 0x2f, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, - 0x70, 0x65, 0x63, 0x12, 0x32, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x8a, 0x07, 0x0a, 0x0a, 0x43, 0x61, 0x6e, 0x76, - 0x61, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x61, 0x6e, - 0x6e, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x61, 0x6e, 0x6e, 0x65, - 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x57, 0x69, 0x64, 0x74, 0x68, 0x12, 0x13, - 0x0a, 0x05, 0x67, 0x61, 0x70, 0x5f, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x67, - 0x61, 0x70, 0x58, 0x12, 0x13, 0x0a, 0x05, 0x67, 0x61, 0x70, 0x5f, 0x79, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x04, 0x67, 0x61, 0x70, 0x59, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x68, 0x65, 0x6d, - 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x12, 0x41, - 0x0a, 0x0e, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x68, 0x65, 0x6d, 0x65, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x53, 0x70, - 0x65, 0x63, 0x52, 0x0d, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x54, 0x68, 0x65, 0x6d, - 0x65, 0x12, 0x42, 0x0a, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, - 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, - 0x54, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x52, - 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x17, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x63, - 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x43, 0x75, 0x73, - 0x74, 0x6f, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, - 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x7a, 0x6f, 0x6e, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x5a, 0x6f, 0x6e, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x66, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x12, 0x44, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, - 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, + 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x09, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x53, 0x70, 0x65, 0x63, 0x12, 0x46, 0x0a, 0x11, 0x64, 0x61, 0x74, 0x61, + 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x0f, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x65, 0x64, 0x4f, 0x6e, + 0x22, 0x78, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, + 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3b, 0x0a, + 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x64, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x6d, 0x0a, 0x06, 0x43, 0x61, + 0x6e, 0x76, 0x61, 0x73, 0x12, 0x2f, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x53, 0x70, 0x65, 0x63, 0x52, + 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x32, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x8a, 0x07, 0x0a, 0x0a, 0x43, 0x61, + 0x6e, 0x76, 0x61, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, + 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x62, + 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x61, 0x6e, + 0x6e, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x57, 0x69, 0x64, 0x74, 0x68, + 0x12, 0x13, 0x0a, 0x05, 0x67, 0x61, 0x70, 0x5f, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x04, 0x67, 0x61, 0x70, 0x58, 0x12, 0x13, 0x0a, 0x05, 0x67, 0x61, 0x70, 0x5f, 0x79, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x67, 0x61, 0x70, 0x59, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x68, + 0x65, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x68, 0x65, 0x6d, 0x65, + 0x12, 0x41, 0x0a, 0x0e, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x68, 0x65, + 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x65, 0x6d, 0x65, + 0x53, 0x70, 0x65, 0x63, 0x52, 0x0d, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x54, 0x68, + 0x65, 0x6d, 0x65, 0x12, 0x42, 0x0a, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6c, 0x6f, + 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0a, 0x74, 0x69, 0x6d, + 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x17, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x5f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, + 0x67, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x43, + 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1d, + 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x7a, 0x6f, 0x6e, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x5a, 0x6f, 0x6e, 0x65, 0x73, 0x12, 0x27, 0x0a, + 0x0f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x44, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, + 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x52, 0x0d, 0x64, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x12, 0x40, 0x0a, 0x09, + 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0x52, 0x09, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x2e, + 0x0a, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x61, 0x6e, 0x76, 0x61, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x52, 0x0d, 0x64, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x12, 0x40, 0x0a, 0x09, 0x76, 0x61, - 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, - 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, - 0x65, 0x52, 0x09, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x04, - 0x72, 0x6f, 0x77, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, - 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, - 0x76, 0x61, 0x73, 0x52, 0x6f, 0x77, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x12, 0x44, 0x0a, 0x0e, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x06, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, - 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x75, 0x6c, - 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x69, 0x6e, 0x6e, - 0x65, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x13, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x72, 0x69, 0x6c, 0x6c, - 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x76, - 0x61, 0x73, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0x91, 0x01, 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x73, 0x70, - 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, - 0x73, 0x53, 0x70, 0x65, 0x63, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x70, 0x65, 0x63, - 0x12, 0x46, 0x0a, 0x11, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, - 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x66, - 0x72, 0x65, 0x73, 0x68, 0x65, 0x64, 0x4f, 0x6e, 0x22, 0xc5, 0x01, 0x0a, 0x09, 0x43, 0x61, 0x6e, - 0x76, 0x61, 0x73, 0x52, 0x6f, 0x77, 0x12, 0x1b, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x75, 0x6e, - 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x55, 0x6e, 0x69, 0x74, 0x12, 0x31, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x49, 0x74, 0x65, 0x6d, - 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x3c, 0x0a, 0x09, 0x74, 0x61, 0x62, 0x5f, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x69, 0x6c, + 0x61, 0x6e, 0x76, 0x61, 0x73, 0x52, 0x6f, 0x77, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x12, 0x44, + 0x0a, 0x0e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, + 0x75, 0x6c, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x66, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x69, + 0x6e, 0x6e, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, + 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x13, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x72, 0x69, + 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, + 0x6e, 0x76, 0x61, 0x73, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x91, 0x01, 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x76, 0x61, + 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, + 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, - 0x76, 0x61, 0x73, 0x54, 0x61, 0x62, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x08, 0x74, 0x61, 0x62, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x22, 0x54, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x54, 0x61, 0x62, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x61, 0x62, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x54, 0x61, 0x62, - 0x52, 0x04, 0x74, 0x61, 0x62, 0x73, 0x22, 0x72, 0x0a, 0x09, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, - 0x54, 0x61, 0x62, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x72, 0x6f, - 0x77, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, - 0x73, 0x52, 0x6f, 0x77, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x22, 0x9a, 0x01, 0x0a, 0x0a, 0x43, - 0x61, 0x6e, 0x76, 0x61, 0x73, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, - 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, - 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x65, 0x66, 0x69, 0x6e, - 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x49, 0x6e, 0x43, 0x61, 0x6e, - 0x76, 0x61, 0x73, 0x12, 0x19, 0x0a, 0x05, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x0d, 0x48, 0x00, 0x52, 0x05, 0x77, 0x69, 0x64, 0x74, 0x68, 0x88, 0x01, 0x01, 0x12, 0x1d, - 0x0a, 0x0a, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5f, 0x75, 0x6e, 0x69, 0x74, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x42, 0x08, 0x0a, - 0x06, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x9c, 0x03, 0x0a, 0x0c, 0x43, 0x61, 0x6e, 0x76, - 0x61, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x12, 0x22, 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, - 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x4f, 0x0a, 0x0f, - 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x43, - 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0e, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x36, 0x0a, - 0x14, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x5f, 0x64, 0x69, 0x6d, 0x65, - 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x13, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x4e, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, - 0x65, 0x78, 0x70, 0x72, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x72, 0x69, 0x6c, + 0x76, 0x61, 0x73, 0x53, 0x70, 0x65, 0x63, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x70, + 0x65, 0x63, 0x12, 0x46, 0x0a, 0x11, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, + 0x73, 0x68, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x64, 0x61, 0x74, 0x61, 0x52, + 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x65, 0x64, 0x4f, 0x6e, 0x22, 0xc5, 0x01, 0x0a, 0x09, 0x43, + 0x61, 0x6e, 0x76, 0x61, 0x73, 0x52, 0x6f, 0x77, 0x12, 0x1b, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, + 0x75, 0x6e, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x31, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x49, 0x74, + 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x3c, 0x0a, 0x09, 0x74, 0x61, 0x62, + 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x61, 0x6e, 0x76, 0x61, 0x73, 0x54, 0x61, 0x62, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x08, 0x74, + 0x61, 0x62, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x22, 0x54, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x54, 0x61, 0x62, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x61, 0x62, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x54, + 0x61, 0x62, 0x52, 0x04, 0x74, 0x61, 0x62, 0x73, 0x22, 0x72, 0x0a, 0x09, 0x43, 0x61, 0x6e, 0x76, + 0x61, 0x73, 0x54, 0x61, 0x62, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, + 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x04, + 0x72, 0x6f, 0x77, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, - 0x76, 0x61, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x45, 0x78, 0x70, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x45, 0x78, 0x70, 0x72, 0x1a, 0x67, 0x0a, 0x0f, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x45, - 0x78, 0x70, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, - 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x66, 0x61, + 0x76, 0x61, 0x73, 0x52, 0x6f, 0x77, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x22, 0x9a, 0x01, 0x0a, + 0x0a, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x63, + 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x65, 0x66, + 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x49, 0x6e, 0x43, + 0x61, 0x6e, 0x76, 0x61, 0x73, 0x12, 0x19, 0x0a, 0x05, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x05, 0x77, 0x69, 0x64, 0x74, 0x68, 0x88, 0x01, 0x01, + 0x12, 0x1d, 0x0a, 0x0a, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5f, 0x75, 0x6e, 0x69, 0x74, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x42, + 0x08, 0x0a, 0x06, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x9c, 0x03, 0x0a, 0x0c, 0x43, 0x61, + 0x6e, 0x76, 0x61, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x12, 0x22, 0x0a, 0x0a, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, + 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x4f, + 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x6f, 0x64, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, + 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x52, + 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, + 0x36, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x5f, 0x64, 0x69, + 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, + 0x13, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x44, 0x69, 0x6d, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x4e, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x5f, 0x65, 0x78, 0x70, 0x72, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x61, 0x6e, 0x76, 0x61, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x45, 0x78, 0x70, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x66, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x45, 0x78, 0x70, 0x72, 0x1a, 0x67, 0x0a, 0x0f, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x45, 0x78, 0x70, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x72, 0x69, + 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x53, 0x51, 0x4c, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x42, + 0x17, 0x0a, 0x15, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x5f, 0x64, + 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x56, 0x0a, 0x17, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x53, 0x51, 0x4c, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0d, - 0x0a, 0x0b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x17, 0x0a, - 0x15, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x5f, 0x64, 0x69, 0x6d, - 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x56, 0x0a, 0x17, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x53, 0x51, 0x4c, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x12, 0x3b, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x64, - 0x0a, 0x03, 0x41, 0x50, 0x49, 0x12, 0x2c, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, - 0x70, 0x65, 0x63, 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x22, 0xf8, 0x03, 0x0a, 0x07, 0x41, 0x50, 0x49, 0x53, 0x70, 0x65, 0x63, - 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x13, - 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, - 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x52, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x70, - 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, - 0x69, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, - 0x36, 0x0a, 0x17, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, - 0x65, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x15, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x1b, 0x6f, 0x70, 0x65, 0x6e, 0x61, - 0x70, 0x69, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x6f, 0x70, - 0x65, 0x6e, 0x61, 0x70, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x1c, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, - 0x69, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x6f, 0x70, - 0x65, 0x6e, 0x61, 0x70, 0x69, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x6f, 0x70, 0x65, 0x6e, 0x61, - 0x70, 0x69, 0x5f, 0x64, 0x65, 0x66, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x44, 0x65, 0x66, - 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x44, 0x0a, 0x0e, 0x73, 0x65, 0x63, 0x75, 0x72, - 0x69, 0x74, 0x79, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x30, 0x0a, - 0x14, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x63, - 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73, 0x6b, 0x69, - 0x70, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x22, - 0x0a, 0x0a, 0x08, 0x41, 0x50, 0x49, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x9b, 0x01, 0x0a, 0x08, - 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x66, 0x5f, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x65, - 0x66, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x69, 0x73, 0x61, 0x62, - 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x5f, - 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, - 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x1b, 0x0a, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x74, 0x69, 0x6d, 0x65, 0x5a, 0x6f, 0x6e, 0x65, 0x22, 0xbf, 0x01, 0x0a, 0x0a, 0x50, 0x61, - 0x72, 0x73, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x44, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x4c, 0x6f, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0x50, 0x0a, 0x0f, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, - 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x70, - 0x65, 0x72, 0x74, 0x79, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x50, 0x61, 0x74, 0x68, 0x22, 0x4b, 0x0a, - 0x0f, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x74, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x22, 0x64, 0x0a, 0x03, 0x41, 0x50, 0x49, 0x12, 0x2c, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x53, 0x70, 0x65, 0x63, 0x52, + 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, + 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0xf8, 0x03, 0x0a, 0x07, 0x41, 0x50, 0x49, 0x53, 0x70, + 0x65, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x48, + 0x0a, 0x13, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x75, 0x63, 0x74, 0x52, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x50, 0x72, + 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, + 0x79, 0x12, 0x36, 0x0a, 0x17, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x5f, 0x70, 0x61, 0x72, + 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x15, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x1b, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, + 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x1c, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x73, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, + 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x5f, 0x64, 0x65, 0x66, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x44, + 0x65, 0x66, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x44, 0x0a, 0x0e, 0x73, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x75, 0x6c, 0x65, + 0x52, 0x0d, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, + 0x30, 0x0a, 0x14, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x73, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73, + 0x6b, 0x69, 0x70, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x22, 0x0a, 0x0a, 0x08, 0x41, 0x50, 0x49, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x9b, 0x01, + 0x0a, 0x08, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, + 0x66, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, + 0x72, 0x65, 0x66, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x69, 0x73, + 0x61, 0x62, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x69, 0x63, 0x6b, 0x65, + 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0d, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x1b, + 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x5a, 0x6f, 0x6e, 0x65, 0x22, 0xbf, 0x01, 0x0a, 0x0a, + 0x50, 0x61, 0x72, 0x73, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, + 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, + 0x68, 0x12, 0x44, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x72, + 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0x50, 0x0a, + 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, - 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x2a, 0x0a, 0x0e, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x22, 0x0a, 0x0c, 0x43, 0x68, 0x61, 0x72, 0x4c, 0x6f, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x78, 0x0a, 0x0b, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x56, 0x32, 0x12, 0x32, 0x0a, 0x04, 0x73, 0x70, 0x65, - 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x35, 0x0a, - 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x22, 0xf1, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x53, 0x70, 0x65, 0x63, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x12, 0x37, - 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, + 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, + 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x50, 0x61, 0x74, 0x68, 0x22, + 0x4b, 0x0a, 0x0f, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, + 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x2a, 0x0a, 0x0e, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x22, 0x0a, 0x0c, 0x43, 0x68, 0x61, 0x72, + 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x78, 0x0a, 0x0b, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x56, 0x32, 0x12, 0x32, 0x0a, 0x04, 0x73, + 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, + 0x35, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, + 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, + 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0xf1, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x53, 0x70, 0x65, 0x63, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x72, 0x69, 0x76, + 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, + 0x12, 0x37, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0a, 0x70, + 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x14, 0x74, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, + 0x65, 0x64, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x09, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0a, 0x70, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x14, 0x74, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x64, - 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x67, 0x73, 0x22, 0x2d, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x70, - 0x65, 0x63, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, - 0x70, 0x65, 0x63, 0x48, 0x61, 0x73, 0x68, 0x2a, 0x8a, 0x01, 0x0a, 0x0f, 0x52, 0x65, 0x63, 0x6f, - 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, 0x52, - 0x45, 0x43, 0x4f, 0x4e, 0x43, 0x49, 0x4c, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, - 0x15, 0x52, 0x45, 0x43, 0x4f, 0x4e, 0x43, 0x49, 0x4c, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, - 0x53, 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x43, 0x4f, - 0x4e, 0x43, 0x49, 0x4c, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x45, 0x4e, - 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x43, 0x4f, 0x4e, 0x43, - 0x49, 0x4c, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x55, 0x4e, 0x4e, 0x49, - 0x4e, 0x47, 0x10, 0x03, 0x2a, 0x8c, 0x01, 0x0a, 0x0f, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x4d, 0x4f, 0x44, 0x45, - 0x4c, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x4d, - 0x4f, 0x44, 0x45, 0x4c, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, - 0x5f, 0x52, 0x45, 0x53, 0x45, 0x54, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x4d, 0x4f, 0x44, 0x45, - 0x4c, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4d, 0x41, - 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x4f, 0x44, 0x45, 0x4c, 0x5f, - 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x41, 0x54, 0x43, - 0x48, 0x10, 0x03, 0x2a, 0xab, 0x01, 0x0a, 0x15, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x43, - 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x27, 0x0a, - 0x23, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49, - 0x53, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, - 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, - 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x45, 0x58, 0x50, 0x4c, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0d, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x67, 0x73, 0x22, 0x2d, 0x0a, 0x0e, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, + 0x73, 0x70, 0x65, 0x63, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x73, 0x70, 0x65, 0x63, 0x48, 0x61, 0x73, 0x68, 0x2a, 0x8a, 0x01, 0x0a, 0x0f, 0x52, 0x65, + 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, + 0x1c, 0x52, 0x45, 0x43, 0x4f, 0x4e, 0x43, 0x49, 0x4c, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, + 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x19, 0x0a, 0x15, 0x52, 0x45, 0x43, 0x4f, 0x4e, 0x43, 0x49, 0x4c, 0x45, 0x5f, 0x53, 0x54, 0x41, + 0x54, 0x55, 0x53, 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, + 0x43, 0x4f, 0x4e, 0x43, 0x49, 0x4c, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, + 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x43, 0x4f, + 0x4e, 0x43, 0x49, 0x4c, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x55, 0x4e, + 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x2a, 0x8c, 0x01, 0x0a, 0x0f, 0x4d, 0x6f, 0x64, 0x65, 0x6c, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x4d, 0x4f, + 0x44, 0x45, 0x4c, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, + 0x17, 0x4d, 0x4f, 0x44, 0x45, 0x4c, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x4d, 0x4f, + 0x44, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x45, 0x54, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x4d, 0x4f, + 0x44, 0x45, 0x4c, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, + 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x4f, 0x44, 0x45, + 0x4c, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x41, + 0x54, 0x43, 0x48, 0x10, 0x03, 0x2a, 0xab, 0x01, 0x0a, 0x15, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, + 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, + 0x27, 0x0a, 0x23, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, + 0x52, 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x4d, - 0x4f, 0x44, 0x45, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x25, 0x0a, 0x21, 0x45, 0x58, + 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e, - 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x49, 0x4d, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x10, - 0x03, 0x2a, 0xae, 0x01, 0x0a, 0x0e, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x57, 0x65, 0x62, - 0x56, 0x69, 0x65, 0x77, 0x12, 0x20, 0x0a, 0x1c, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, - 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, - 0x45, 0x5f, 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x45, 0x58, 0x50, 0x4c, 0x4f, - 0x52, 0x45, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, - 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x5f, 0x44, 0x49, - 0x4d, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x58, 0x50, - 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x50, 0x49, - 0x56, 0x4f, 0x54, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, - 0x5f, 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x43, 0x41, 0x4e, 0x56, 0x41, 0x53, - 0x10, 0x04, 0x2a, 0xdc, 0x01, 0x0a, 0x0f, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x53, 0x6f, - 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, - 0x45, 0x5f, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x45, 0x58, 0x50, - 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x56, - 0x41, 0x4c, 0x55, 0x45, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, - 0x45, 0x5f, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x45, 0x52, 0x43, - 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, - 0x5f, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x54, 0x41, - 0x5f, 0x50, 0x45, 0x52, 0x43, 0x45, 0x4e, 0x54, 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, 0x45, 0x58, - 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x44, 0x45, 0x4c, 0x54, 0x41, 0x5f, 0x41, 0x42, 0x53, 0x4f, 0x4c, 0x55, 0x54, 0x45, 0x10, 0x04, - 0x12, 0x1f, 0x0a, 0x1b, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x53, 0x4f, 0x52, 0x54, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x4d, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x10, - 0x05, 0x2a, 0x85, 0x01, 0x0a, 0x0f, 0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x53, 0x53, 0x45, 0x52, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x41, 0x53, 0x53, - 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x02, 0x12, 0x1a, 0x0a, - 0x16, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, - 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x42, 0xc1, 0x01, 0x0a, 0x13, 0x63, 0x6f, - 0x6d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, - 0x31, 0x42, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x72, 0x69, 0x6c, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x72, 0x69, 0x6c, 0x6c, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x72, 0x69, 0x6c, 0x6c, 0x2f, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x76, - 0x31, 0xa2, 0x02, 0x03, 0x52, 0x52, 0x58, 0xaa, 0x02, 0x0f, 0x52, 0x69, 0x6c, 0x6c, 0x2e, 0x52, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x52, 0x69, 0x6c, 0x6c, - 0x5c, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1b, 0x52, 0x69, - 0x6c, 0x6c, 0x5c, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x52, 0x69, 0x6c, 0x6c, - 0x3a, 0x3a, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x25, 0x0a, 0x21, + 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, + 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x49, 0x4d, 0x45, 0x4e, 0x53, 0x49, 0x4f, + 0x4e, 0x10, 0x03, 0x2a, 0xae, 0x01, 0x0a, 0x0e, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x57, + 0x65, 0x62, 0x56, 0x69, 0x65, 0x77, 0x12, 0x20, 0x0a, 0x1c, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, + 0x45, 0x5f, 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x58, 0x50, 0x4c, + 0x4f, 0x52, 0x45, 0x5f, 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x45, 0x58, 0x50, + 0x4c, 0x4f, 0x52, 0x45, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, + 0x45, 0x5f, 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x5f, + 0x44, 0x49, 0x4d, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x45, + 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, + 0x50, 0x49, 0x56, 0x4f, 0x54, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x45, 0x58, 0x50, 0x4c, 0x4f, + 0x52, 0x45, 0x5f, 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x43, 0x41, 0x4e, 0x56, + 0x41, 0x53, 0x10, 0x04, 0x2a, 0xdc, 0x01, 0x0a, 0x0f, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, + 0x53, 0x6f, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x4c, + 0x4f, 0x52, 0x45, 0x5f, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x45, + 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x45, 0x58, 0x50, 0x4c, + 0x4f, 0x52, 0x45, 0x5f, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x45, + 0x52, 0x43, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x58, 0x50, 0x4c, 0x4f, + 0x52, 0x45, 0x5f, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x4c, + 0x54, 0x41, 0x5f, 0x50, 0x45, 0x52, 0x43, 0x45, 0x4e, 0x54, 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, + 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x54, 0x41, 0x5f, 0x41, 0x42, 0x53, 0x4f, 0x4c, 0x55, 0x54, 0x45, + 0x10, 0x04, 0x12, 0x1f, 0x0a, 0x1b, 0x45, 0x58, 0x50, 0x4c, 0x4f, 0x52, 0x45, 0x5f, 0x53, 0x4f, + 0x52, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x4d, 0x45, 0x4e, 0x53, 0x49, 0x4f, + 0x4e, 0x10, 0x05, 0x2a, 0x85, 0x01, 0x0a, 0x0f, 0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x53, 0x53, 0x45, 0x52, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x53, 0x53, + 0x45, 0x52, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x41, + 0x53, 0x53, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x02, 0x12, + 0x1a, 0x0a, 0x16, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, + 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x42, 0xc1, 0x01, 0x0a, 0x13, + 0x63, 0x6f, 0x6d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x76, 0x31, 0x42, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x72, 0x69, 0x6c, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x72, 0x69, 0x6c, 0x6c, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x72, 0x69, 0x6c, 0x6c, 0x2f, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x52, 0x52, 0x58, 0xaa, 0x02, 0x0f, 0x52, 0x69, 0x6c, 0x6c, + 0x2e, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x52, 0x69, + 0x6c, 0x6c, 0x5c, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1b, + 0x52, 0x69, 0x6c, 0x6c, 0x5c, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5c, 0x56, 0x31, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x52, 0x69, + 0x6c, 0x6c, 0x3a, 0x3a, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/gen/rill/runtime/v1/runtime.swagger.yaml b/proto/gen/rill/runtime/v1/runtime.swagger.yaml index a47ccd1a5267..ed87ebc72c03 100644 --- a/proto/gen/rill/runtime/v1/runtime.swagger.yaml +++ b/proto/gen/rill/runtime/v1/runtime.swagger.yaml @@ -5342,6 +5342,18 @@ definitions: items: type: string description: Temporary to differentiate between "select" and "in list" modes. Expression will be replaced with UI specific state in the future. + pinnedFilters: + type: array + items: + type: string + title: Array of dimension or measure names + requiredFilters: + type: array + items: + type: string + description: |- + Array of dimension or measure names that must have a value before the explore can render. + Required filters are implicitly pinned. timeRange: type: string description: |- diff --git a/proto/rill/runtime/v1/resources.proto b/proto/rill/runtime/v1/resources.proto index f5ceda87999a..2b9b6e54f827 100644 --- a/proto/rill/runtime/v1/resources.proto +++ b/proto/rill/runtime/v1/resources.proto @@ -540,6 +540,11 @@ message ExplorePreset { optional Expression where = 11; // Temporary to differentiate between "select" and "in list" modes. Expression will be replaced with UI specific state in the future. repeated string dimensions_with_inlist_filter = 29; + // Array of dimension or measure names + repeated string pinned_filters = 39; + // Array of dimension or measure names that must have a value before the explore can render. + // Required filters are implicitly pinned. + repeated string required_filters = 40; // Time range for the explore. // It corresponds to the `range` property of the explore's `time_ranges`. diff --git a/runtime/parser/parse_explore.go b/runtime/parser/parse_explore.go index cb22a4227a2c..1ce347bb0768 100644 --- a/runtime/parser/parse_explore.go +++ b/runtime/parser/parse_explore.go @@ -7,13 +7,15 @@ import ( "time" runtimev1 "github.com/rilldata/rill/proto/gen/rill/runtime/v1" + "github.com/rilldata/rill/runtime/metricsview" + "github.com/rilldata/rill/runtime/metricsview/metricssql" "github.com/rilldata/rill/runtime/pkg/rilltime" "golang.org/x/exp/maps" "gopkg.in/yaml.v3" ) type ExploreYAML struct { - commonYAML `yaml:",inline"` // Not accessed here, only setting it so we can use KnownFields for YAML parsing + commonYAML `yaml:",inline"` // Not accessed here, only setting it so we can use KnownFields for YAML parsing DisplayName string `yaml:"display_name"` Title string `yaml:"title"` // Deprecated: use display_name Description string `yaml:"description"` @@ -32,6 +34,9 @@ type ExploreYAML struct { TimeRange string `yaml:"time_range"` ComparisonMode string `yaml:"comparison_mode"` ComparisonDimension string `yaml:"comparison_dimension"` + Filter string `yaml:"filter"` + Pinned []string `yaml:"pinned"` + Required []string `yaml:"required"` } `yaml:"defaults"` Embeds struct { HidePivot bool `yaml:"hide_pivot"` @@ -246,6 +251,27 @@ func (p *Parser) parseExplore(node *Node) error { if tmp.Defaults.ComparisonDimension != "" { compareDim = &tmp.Defaults.ComparisonDimension } + + var filter *runtimev1.Expression + if tmp.Defaults.Filter != "" { + expr, err := metricssql.ParseFilter(tmp.Defaults.Filter) + if err != nil { + return fmt.Errorf("invalid filter expression: %q: %w", tmp.Defaults.Filter, err) + } + + filter = metricsview.ExpressionToProto(expr) + } + + var pinnedMeasuresOrDimensions []string + if len(tmp.Defaults.Pinned) > 0 { + pinnedMeasuresOrDimensions = tmp.Defaults.Pinned + } + + var requiredFilters []string + if len(tmp.Defaults.Required) > 0 { + requiredFilters = tmp.Defaults.Required + } + defaultPreset = &runtimev1.ExplorePreset{ Dimensions: presetDimensions, DimensionsSelector: presetDimensionsSelector, @@ -254,6 +280,9 @@ func (p *Parser) parseExplore(node *Node) error { TimeRange: tr, ComparisonMode: mode, ComparisonDimension: compareDim, + Where: filter, + PinnedFilters: pinnedMeasuresOrDimensions, + RequiredFilters: requiredFilters, } } diff --git a/web-common/src/features/canvas/stores/canvas-entity.ts b/web-common/src/features/canvas/stores/canvas-entity.ts index 686517b3f2b8..8eb72b8b5b90 100644 --- a/web-common/src/features/canvas/stores/canvas-entity.ts +++ b/web-common/src/features/canvas/stores/canvas-entity.ts @@ -37,7 +37,7 @@ import { isChartComponentType, isTableComponentType, } from "../components/util"; -import { FilterManager, flattenExpression } from "./filter-manager"; +import { FilterManager } from "./filter-manager"; import { getFilterParam } from "./filter-state"; import { Grid } from "./grid"; import { TabGroup, type LayoutBlock } from "./tab-group"; @@ -50,6 +50,7 @@ import { DEFAULT_DASHBOARD_WIDTH, namePrefixFromPath } from "../layout-util"; import { createCustomMapStore } from "@rilldata/web-common/lib/custom-map-store"; import type { RuntimeClient } from "@rilldata/web-common/runtime-client/v2"; import { queryServiceConvertExpressionToMetricsSQL } from "@rilldata/web-common/runtime-client"; +import { flattenExpression } from "@rilldata/web-common/features/dashboards/stores/filter-utils.ts"; export const lastVisitedState = new Map(); diff --git a/web-common/src/features/canvas/stores/filter-manager.ts b/web-common/src/features/canvas/stores/filter-manager.ts index fea046dbb2f9..9ef31f002790 100644 --- a/web-common/src/features/canvas/stores/filter-manager.ts +++ b/web-common/src/features/canvas/stores/filter-manager.ts @@ -9,22 +9,16 @@ import type { V1Expression, V1MetricsView, } from "@rilldata/web-common/runtime-client"; -import { - V1Operation, - type MetricsViewSpecMeasure, -} from "@rilldata/web-common/runtime-client"; +import { type MetricsViewSpecMeasure } from "@rilldata/web-common/runtime-client"; import { derived, get, - writable, type Readable, + writable, type Writable, } from "svelte/store"; import { getDimensionDisplayName } from "../../dashboards/filters/getDisplayName"; -import { - createAndExpression, - flattenInExpressionValues, -} from "../../dashboards/stores/filter-utils"; +import { flattenExpression } from "../../dashboards/stores/filter-utils"; import { ExploreStateURLParams } from "../../dashboards/url-state/url-params"; import type { ParsedFilters } from "./filter-state"; import { FilterState } from "./filter-state"; @@ -952,61 +946,6 @@ function isMeasureItemEmpty(item: MeasureFilterItem): boolean { return !item.filter; } -// This should be deprecated eventually in favor of better support for variously formatted expressions -export function flattenExpression( - expression: V1Expression | undefined, -): V1Expression { - if (!expression) { - return createAndExpression([]); - } - - let root: V1Expression; - - // Ensure top level is an OPERATION_AND - if (!expression.cond || expression.cond.op !== V1Operation.OPERATION_AND) { - root = createAndExpression([expression]); - } else { - root = expression; - } - - const rootCond = root.cond; - if ( - !rootCond || - rootCond.op !== V1Operation.OPERATION_AND || - !Array.isArray(rootCond.exprs) - ) { - return root; - } - - // Recursively flatten all nested ANDs, preserving order - rootCond.exprs = flattenAndExprs(rootCond.exprs); - - // Normalize array-valued IN/NIN expressions into individual value expressions - rootCond.exprs = rootCond.exprs.map(flattenInExpressionValues); - - return root; -} - -function flattenAndExprs(exprs: V1Expression[]): V1Expression[] { - const result: V1Expression[] = []; - - for (const expr of exprs) { - const cond = expr.cond; - if ( - cond && - cond.op === V1Operation.OPERATION_AND && - Array.isArray(cond.exprs) - ) { - // Inline children in order - result.push(...flattenAndExprs(cond.exprs)); - } else { - result.push(expr); - } - } - - return result; -} - // wip - bgh function mergeFilters( metricsViewItems: Map>, diff --git a/web-common/src/features/dashboards/filters/ExploreFilterChipsReadOnly.svelte b/web-common/src/features/dashboards/filters/ExploreFilterChipsReadOnly.svelte index 7f7772b4e5d9..28e4adaf85ce 100644 --- a/web-common/src/features/dashboards/filters/ExploreFilterChipsReadOnly.svelte +++ b/web-common/src/features/dashboards/filters/ExploreFilterChipsReadOnly.svelte @@ -19,6 +19,7 @@ // But we need resolved start and end based on current time in dimension filters to get query for accurate results. export let queryTimeStart: string | undefined = undefined; export let queryTimeEnd: string | undefined = undefined; + export let pinnedFilters: Set = new Set(); const runtimeClient = useRuntimeClient(); @@ -44,4 +45,5 @@ {displayTimeRange} {queryTimeStart} {queryTimeEnd} + {pinnedFilters} /> diff --git a/web-common/src/features/dashboards/filters/FilterChipsReadOnly.svelte b/web-common/src/features/dashboards/filters/FilterChipsReadOnly.svelte index a217c3ad1b7c..13b8cb5e4b63 100644 --- a/web-common/src/features/dashboards/filters/FilterChipsReadOnly.svelte +++ b/web-common/src/features/dashboards/filters/FilterChipsReadOnly.svelte @@ -32,6 +32,7 @@ The main feature-set component for dashboard filters export let queryTimeEnd: string | undefined = undefined; export let hasBoldTimeRange: boolean = true; export let chipLayout: "wrap" | "scroll" = "wrap"; + export let pinnedFilters: Set = new Set(); let scrollContainer: HTMLDivElement; @@ -44,6 +45,7 @@ The main feature-set component for dashboard filters filters, dimensionsWithInlistFilter, metricsViewNames[0], + pinnedFilters, ); $: measureIdMap = getMapFromArray( @@ -53,6 +55,7 @@ The main feature-set component for dashboard filters $: measureFilters = getMeasureFilters( measureIdMap, dimensionThresholdFilters, + pinnedFilters, ); function handleWheel(event: WheelEvent) { diff --git a/web-common/src/features/dashboards/filters/Filters.svelte b/web-common/src/features/dashboards/filters/Filters.svelte index a047aebf6125..aad5195c04a8 100644 --- a/web-common/src/features/dashboards/filters/Filters.svelte +++ b/web-common/src/features/dashboards/filters/Filters.svelte @@ -75,7 +75,7 @@ }, measuresFilter: { setMeasureFilter, removeMeasureFilter }, - filters: { clearAllFilters, setTemporaryFilterName }, + filters: { clearAllFilters, setTemporaryFilterName, toggleFilterPin }, }, selectors: { dimensions: { allDimensions, timeDimensions }, @@ -568,6 +568,7 @@ applyDimensionInListMode(name, values)} applyDimensionContainsMode={async (name, searchText) => applyDimensionContainsMode(name, searchText)} + {toggleFilterPin} isUrlTooLongAfterInListFilter={(values) => isUrlTooLongAfterInListFilter(filterData.name, values)} /> @@ -578,6 +579,7 @@ removeMeasureFilter(filterData.dimensionName, filterData.name)} onApply={({ dimension, oldDimension, filter }) => diff --git a/web-common/src/features/dashboards/state-managers/actions/filters.ts b/web-common/src/features/dashboards/state-managers/actions/filters.ts index 32749c48449f..5aa618edbf6c 100644 --- a/web-common/src/features/dashboards/state-managers/actions/filters.ts +++ b/web-common/src/features/dashboards/state-managers/actions/filters.ts @@ -23,11 +23,22 @@ export function setTemporaryFilterName( dashboard.temporaryFilterName = name; } +export function toggleFilterPin( + { dashboard }: DashboardMutables, + name: string, +) { + const deleted = dashboard.pinnedFilters.delete(name); + + if (!deleted) { + dashboard.pinnedFilters.add(name); + } +} + export const filterActions = { /** * Clears all filters and resets related fields */ clearAllFilters, - setTemporaryFilterName, + toggleFilterPin, }; diff --git a/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts b/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts index 94fd870222cd..c33593f34e68 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts @@ -153,6 +153,7 @@ export function getDimensionFilterItems( dashData.dashboard.whereFilter, dashData.dashboard.dimensionsWithInlistFilter, dashData.validExplore?.metricsView, + dashData.dashboard.pinnedFilters, ); }; } @@ -162,6 +163,7 @@ export function getDimensionFiltersMap( filter: V1Expression | undefined, dimensionsWithInlistFilter: string[], metricsViewName: string | undefined, + pinnedFilters: Set, ): Map { if (!filter || !metricsViewName) return new Map(); const filteredDimensions: Map = new Map(); @@ -186,7 +188,7 @@ export function getDimensionFiltersMap( selectedValues: getValuesInExpression(e), isInclude: e.cond?.op === V1Operation.OPERATION_IN, inputText: undefined, - pinned: false, + pinned: pinnedFilters?.has(ident), dimensions: new Map([ [metricsViewName, dim], @@ -206,7 +208,7 @@ export function getDimensionFiltersMap( dimensions: new Map([ [metricsViewName, dim], ]), - pinned: false, + pinned: pinnedFilters?.has(ident), }); } }); @@ -219,6 +221,7 @@ export function getDimensionFilters( filter: V1Expression | undefined, dimensionsWithInlistFilter: string[], metricsViewName: string | undefined, + pinnedFilters: Set, ) { return Array.from( getDimensionFiltersMap( @@ -226,6 +229,7 @@ export function getDimensionFilters( filter, dimensionsWithInlistFilter, metricsViewName, + pinnedFilters, ).values(), ); } @@ -259,7 +263,9 @@ export const getAllDimensionFilterItems = ( dimensionIdMap.get(dashData.dashboard.temporaryFilterName)!, ], ]), - pinned: false, + pinned: dashData.dashboard.pinnedFilters?.has( + dashData.dashboard.temporaryFilterName, + ), }); } diff --git a/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts b/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts index b56f65e63c7a..761d0347db19 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts @@ -37,6 +37,7 @@ export const getMeasureFilterItems = ( return getMeasureFilters( measureIdMap, dashData.dashboard.dimensionThresholdFilters, + dashData.dashboard.pinnedFilters, ); }; }; @@ -44,6 +45,7 @@ export const getMeasureFilterItems = ( export function getMeasureFilters( measureIdMap: Map, dimensionThresholdFilters: DimensionThresholdFilter[], + pinnedFilters: Set, ) { const filteredMeasures = new Array(); const addedMeasure = new Set(); @@ -55,6 +57,7 @@ export function getMeasureFilters( dtf.filters, dtf.name, addedMeasure, + pinnedFilters.has(dtf.filters[0].measure), ), ); } @@ -67,6 +70,7 @@ export function getMeasureFilterForDimension( filters: MeasureFilterEntry[], name = "", addedMeasure = new Set(), + pinned = false, ) { if (!filters.length) return []; @@ -87,6 +91,7 @@ export function getMeasureFilterForDimension( name: filter.measure, label: measure.displayName || measure.expression || filter.measure, filter, + pinned, }); }); @@ -113,6 +118,9 @@ export const getAllMeasureFilterItems = ( label: getMeasureDisplayName( measureIdMap.get(dashData.dashboard.temporaryFilterName), ), + pinned: dashData.dashboard.pinnedFilters?.has( + dashData.dashboard.temporaryFilterName, + ), }); } diff --git a/web-common/src/features/dashboards/stores/explore-state.ts b/web-common/src/features/dashboards/stores/explore-state.ts index f37434e3a8ff..8849b8fd5928 100644 --- a/web-common/src/features/dashboards/stores/explore-state.ts +++ b/web-common/src/features/dashboards/stores/explore-state.ts @@ -100,6 +100,11 @@ export interface ExploreState { */ temporaryFilterName: string | null; + /** + * Filter pills that are always present even when no values are selected + */ + pinnedFilters: Set; + /** * user selected time range */ diff --git a/web-common/src/features/dashboards/stores/filter-utils.ts b/web-common/src/features/dashboards/stores/filter-utils.ts index f86914ae0087..cd99f9dee25b 100644 --- a/web-common/src/features/dashboards/stores/filter-utils.ts +++ b/web-common/src/features/dashboards/stores/filter-utils.ts @@ -1,11 +1,11 @@ import { mergeDimensionAndMeasureFilters } from "@rilldata/web-common/features/dashboards/filters/measure-filters/measure-filter-utils"; import type { DimensionThresholdFilter } from "@rilldata/web-common/features/dashboards/stores/explore-state"; import { - V1Operation, type MetricsViewSpecDimension, type MetricsViewSpecMeasure, type V1Condition, type V1Expression, + V1Operation, type V1Subquery, } from "@rilldata/web-common/runtime-client"; @@ -530,3 +530,58 @@ export function flattenInExpressionValues(expr: V1Expression) { expr.cond!.op === V1Operation.OPERATION_NIN, ); } + +// This should be deprecated eventually in favor of better support for variously formatted expressions +export function flattenExpression( + expression: V1Expression | undefined, +): V1Expression { + if (!expression) { + return createAndExpression([]); + } + + let root: V1Expression; + + // Ensure top level is an OPERATION_AND + if (!expression.cond || expression.cond.op !== V1Operation.OPERATION_AND) { + root = createAndExpression([expression]); + } else { + root = expression; + } + + const rootCond = root.cond; + if ( + !rootCond || + rootCond.op !== V1Operation.OPERATION_AND || + !Array.isArray(rootCond.exprs) + ) { + return root; + } + + // Recursively flatten all nested ANDs, preserving order + rootCond.exprs = flattenAndExprs(rootCond.exprs); + + // Normalize array-valued IN/NIN expressions into individual value expressions + rootCond.exprs = rootCond.exprs.map(flattenInExpressionValues); + + return root; +} + +function flattenAndExprs(exprs: V1Expression[]): V1Expression[] { + const result: V1Expression[] = []; + + for (const expr of exprs) { + const cond = expr.cond; + if ( + cond && + cond.op === V1Operation.OPERATION_AND && + Array.isArray(cond.exprs) + ) { + // Inline children in order + result.push(...flattenAndExprs(cond.exprs)); + } else { + result.push(expr); + } + } + + return result; +} diff --git a/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts b/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts index 6a6c9add412c..2b1c8a4adda9 100644 --- a/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts +++ b/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts @@ -21,6 +21,7 @@ import { V1TimeGrain, type V1ExploreSpec, type V1TimeRangeSummary, + V1Operation, } from "@rilldata/web-common/runtime-client"; import { createQuery } from "@tanstack/svelte-query"; import { derived, type Readable } from "svelte/store"; @@ -28,6 +29,11 @@ import { DateTimeUnitToV1TimeGrain, isGrainAllowed, } from "@rilldata/web-common/lib/time/new-grains"; +import { + createAndExpression, + flattenExpression, +} from "@rilldata/web-common/features/dashboards/stores/filter-utils.ts"; +import { splitWhereFilter } from "@rilldata/web-common/features/dashboards/filters/measure-filters/measure-filter-utils.ts"; export function getExploreStateFromYAMLConfig( exploreSpec: V1ExploreSpec, @@ -38,6 +44,7 @@ export function getExploreStateFromYAMLConfig( return >{ activePage: DashboardState_ActivePage.DEFAULT, + ...getExploreFilterStateFromYAMLConfig(exploreSpec), ...getExploreTimeStateFromYAMLConfig( exploreSpec, timeRangeSummary, @@ -89,6 +96,39 @@ export function createUrlForExploreYAMLDefaultState( ); } +export function getExploreFilterStateFromYAMLConfig( + exploreSpec: V1ExploreSpec, +): Partial { + const filter = exploreSpec.defaultPreset?.where; + if (!filter && !exploreSpec.defaultPreset?.pinnedFilters?.length) { + return {}; + } + + const flattened = filter + ? flattenExpression(filter) + : createAndExpression([]); + + const { dimensionThresholdFilters, dimensionFilters } = + splitWhereFilter(flattened); + + // Build dimensionFilterExcludeMode from the parsed filter expressions. + // NIN (NOT IN) operations indicate exclude mode for that dimension. + const dimensionFilterExcludeMode = new Map(); + for (const expr of dimensionFilters.cond?.exprs ?? []) { + const ident = expr.cond?.exprs?.[0]?.ident; + if (ident && expr.cond?.op === V1Operation.OPERATION_NIN) { + dimensionFilterExcludeMode.set(ident, true); + } + } + + return { + whereFilter: dimensionFilters, + dimensionThresholdFilters, + dimensionFilterExcludeMode, + pinnedFilters: new Set(exploreSpec.defaultPreset?.pinnedFilters ?? []), + }; +} + function getExploreTimeStateFromYAMLConfig( exploreSpec: V1ExploreSpec, timeRangeSummary: V1TimeRangeSummary | undefined, diff --git a/web-common/src/features/dashboards/stores/get-rill-default-explore-state.ts b/web-common/src/features/dashboards/stores/get-rill-default-explore-state.ts index 25394b35e76d..e96d704a7852 100644 --- a/web-common/src/features/dashboards/stores/get-rill-default-explore-state.ts +++ b/web-common/src/features/dashboards/stores/get-rill-default-explore-state.ts @@ -49,6 +49,7 @@ export function getRillDefaultExploreState( dimensionsWithInlistFilter: [], dimensionFilterExcludeMode: new Map(), temporaryFilterName: null, + pinnedFilters: new Set(), ...getRillDefaultExploreTimeState( metricsViewSpec, diff --git a/web-common/src/proto/gen/rill/runtime/v1/resources_pb.ts b/web-common/src/proto/gen/rill/runtime/v1/resources_pb.ts index 9507f7d9eb9c..7f32c7fad3e1 100644 --- a/web-common/src/proto/gen/rill/runtime/v1/resources_pb.ts +++ b/web-common/src/proto/gen/rill/runtime/v1/resources_pb.ts @@ -3102,6 +3102,21 @@ export class ExplorePreset extends Message { */ dimensionsWithInlistFilter: string[] = []; + /** + * Array of dimension or measure names + * + * @generated from field: repeated string pinned_filters = 39; + */ + pinnedFilters: string[] = []; + + /** + * Array of dimension or measure names that must have a value before the explore can render. + * Required filters are implicitly pinned. + * + * @generated from field: repeated string required_filters = 40; + */ + requiredFilters: string[] = []; + /** * Time range for the explore. * It corresponds to the `range` property of the explore's `time_ranges`. @@ -3268,6 +3283,8 @@ export class ExplorePreset extends Message { { no: 10, name: "measures_selector", kind: "message", T: FieldSelector }, { no: 11, name: "where", kind: "message", T: Expression, opt: true }, { no: 29, name: "dimensions_with_inlist_filter", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 39, name: "pinned_filters", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 40, name: "required_filters", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, { no: 6, name: "time_range", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, { no: 12, name: "timezone", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, { no: 13, name: "time_grain", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, diff --git a/web-common/src/runtime-client/gen/index.schemas.ts b/web-common/src/runtime-client/gen/index.schemas.ts index 86e8594e1cab..10f59118e060 100644 --- a/web-common/src/runtime-client/gen/index.schemas.ts +++ b/web-common/src/runtime-client/gen/index.schemas.ts @@ -916,6 +916,8 @@ export interface V1ExplorePreset { where?: V1Expression; /** Temporary to differentiate between "select" and "in list" modes. Expression will be replaced with UI specific state in the future. */ dimensionsWithInlistFilter?: string[]; + pinnedFilters?: string[]; + requiredFilters?: string[]; /** Time range for the explore. It corresponds to the `range` property of the explore's `time_ranges`. If not found in `time_ranges`, it should be added to the list. */ From 2e1060cedce77dfe4df66206a3af34301d66ee7c Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Fri, 17 Jul 2026 18:57:36 +0530 Subject: [PATCH 02/11] Persist pinned filters --- .../dashboards/filters/Filters.svelte | 20 +++++++++++-- .../state-managers/actions/filters.ts | 12 -------- .../selectors/dimension-filters.ts | 12 ++++---- .../selectors/measure-filters.ts | 12 ++++---- .../dashboards/stores/explore-state.ts | 5 ---- .../get-explore-state-from-yaml-config.ts | 3 +- .../stores/get-rill-default-explore-state.ts | 1 - .../stores/yaml-only-explore-state.svelte.ts | 29 +++++++++++++++++++ .../dashboards/workspace/Dashboard.svelte | 20 ++++++++++++- 9 files changed, 81 insertions(+), 33 deletions(-) create mode 100644 web-common/src/features/dashboards/stores/yaml-only-explore-state.svelte.ts diff --git a/web-common/src/features/dashboards/filters/Filters.svelte b/web-common/src/features/dashboards/filters/Filters.svelte index aad5195c04a8..4ddff60b879a 100644 --- a/web-common/src/features/dashboards/filters/Filters.svelte +++ b/web-common/src/features/dashboards/filters/Filters.svelte @@ -50,6 +50,7 @@ import { getPinnedTimeZones } from "../url-state/getDefaultExplorePreset"; import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2"; import { m } from "@rilldata/web-common/lib/i18n/gen/messages"; + import { type YAMLOnlyExploreState } from "@rilldata/web-common/features/dashboards/stores/yaml-only-explore-state.svelte.ts"; const { rillTime } = featureFlags; @@ -57,6 +58,7 @@ export let timeRanges: V1ExploreTimeRange[]; export let metricsViewName: string; export let hasTimeSeries: boolean; + export let yamlOnlyState: YAMLOnlyExploreState; /** the height of a row of chips */ const ROW_HEIGHT = "26px"; @@ -75,7 +77,7 @@ }, measuresFilter: { setMeasureFilter, removeMeasureFilter }, - filters: { clearAllFilters, setTemporaryFilterName, toggleFilterPin }, + filters: { clearAllFilters, setTemporaryFilterName }, }, selectors: { dimensions: { allDimensions, timeDimensions }, @@ -152,16 +154,21 @@ $: measures = $allMeasures; $: measureIdMap = getMapFromArray(measures, (m) => m.name as string); - $: currentDimensionFilters = $getDimensionFilterItems(dimensionIdMap); + $: currentDimensionFilters = $getDimensionFilterItems( + dimensionIdMap, + new Set(yamlOnlyState.pinnedFilters.value), + ); $: allDimensionFilters = $getAllDimensionFilterItems( currentDimensionFilters, dimensionIdMap, + new Set(yamlOnlyState.pinnedFilters.value), ); $: currentMeasureFilters = $getMeasureFilterItems(measureIdMap); $: allMeasureFilters = $getAllMeasureFilterItems( currentMeasureFilters, measureIdMap, + new Set(yamlOnlyState.pinnedFilters.value), ); // hasFilter only checks for complete filters and excludes temporary ones @@ -429,6 +436,13 @@ const url = dashboardStateSync.getUrlForExploreState(exploreState); return isUrlTooLong(url); } + + $: toggleFilterPin = yamlOnlyState?.editable + ? (name: string) => yamlOnlyState.pinnedFilters.toggle(name) + : undefined; + $: toggleFilterRequired = yamlOnlyState?.editable + ? (name: string) => yamlOnlyState.requiredFilters.toggle(name) + : undefined;
@@ -569,6 +583,7 @@ applyDimensionContainsMode={async (name, searchText) => applyDimensionContainsMode(name, searchText)} {toggleFilterPin} + {toggleFilterRequired} isUrlTooLongAfterInListFilter={(values) => isUrlTooLongAfterInListFilter(filterData.name, values)} /> @@ -580,6 +595,7 @@ {filterData} allDimensions={dimensions} {toggleFilterPin} + {toggleFilterRequired} onRemove={() => removeMeasureFilter(filterData.dimensionName, filterData.name)} onApply={({ dimension, oldDimension, filter }) => diff --git a/web-common/src/features/dashboards/state-managers/actions/filters.ts b/web-common/src/features/dashboards/state-managers/actions/filters.ts index 5aa618edbf6c..9dd766c2fba9 100644 --- a/web-common/src/features/dashboards/state-managers/actions/filters.ts +++ b/web-common/src/features/dashboards/state-managers/actions/filters.ts @@ -23,22 +23,10 @@ export function setTemporaryFilterName( dashboard.temporaryFilterName = name; } -export function toggleFilterPin( - { dashboard }: DashboardMutables, - name: string, -) { - const deleted = dashboard.pinnedFilters.delete(name); - - if (!deleted) { - dashboard.pinnedFilters.add(name); - } -} - export const filterActions = { /** * Clears all filters and resets related fields */ clearAllFilters, setTemporaryFilterName, - toggleFilterPin, }; diff --git a/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts b/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts index c33593f34e68..69a670bff58c 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts @@ -147,13 +147,16 @@ export type DimensionFilterItem = { export function getDimensionFilterItems( dashData: AtLeast, ) { - return (dimensionIdMap: Map) => { + return ( + dimensionIdMap: Map, + pinnedFilters: Set = new Set(), + ) => { return getDimensionFilters( dimensionIdMap, dashData.dashboard.whereFilter, dashData.dashboard.dimensionsWithInlistFilter, dashData.validExplore?.metricsView, - dashData.dashboard.pinnedFilters, + pinnedFilters, ); }; } @@ -240,6 +243,7 @@ export const getAllDimensionFilterItems = ( return ( dimensionFilterItem: DimensionFilterItem[], dimensionIdMap: Map, + pinnedFilters: Set = new Set(), ) => { const allDimensionFilterItem = [...dimensionFilterItem]; @@ -263,9 +267,7 @@ export const getAllDimensionFilterItems = ( dimensionIdMap.get(dashData.dashboard.temporaryFilterName)!, ], ]), - pinned: dashData.dashboard.pinnedFilters?.has( - dashData.dashboard.temporaryFilterName, - ), + pinned: pinnedFilters.has(dashData.dashboard.temporaryFilterName), }); } diff --git a/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts b/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts index 761d0347db19..651d09fb6334 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts @@ -33,11 +33,14 @@ export type MeasureFilterItem = { export const getMeasureFilterItems = ( dashData: AtLeast, ) => { - return (measureIdMap: Map) => { + return ( + measureIdMap: Map, + pinnedFilters: Set = new Set(), + ) => { return getMeasureFilters( measureIdMap, dashData.dashboard.dimensionThresholdFilters, - dashData.dashboard.pinnedFilters, + pinnedFilters, ); }; }; @@ -104,6 +107,7 @@ export const getAllMeasureFilterItems = ( return ( measureFilterItems: Array, measureIdMap: Map, + pinnedFilters: Set = new Set(), ) => { const allMeasureFilterItems = [...measureFilterItems]; @@ -118,9 +122,7 @@ export const getAllMeasureFilterItems = ( label: getMeasureDisplayName( measureIdMap.get(dashData.dashboard.temporaryFilterName), ), - pinned: dashData.dashboard.pinnedFilters?.has( - dashData.dashboard.temporaryFilterName, - ), + pinned: pinnedFilters.has(dashData.dashboard.temporaryFilterName), }); } diff --git a/web-common/src/features/dashboards/stores/explore-state.ts b/web-common/src/features/dashboards/stores/explore-state.ts index 8849b8fd5928..f37434e3a8ff 100644 --- a/web-common/src/features/dashboards/stores/explore-state.ts +++ b/web-common/src/features/dashboards/stores/explore-state.ts @@ -100,11 +100,6 @@ export interface ExploreState { */ temporaryFilterName: string | null; - /** - * Filter pills that are always present even when no values are selected - */ - pinnedFilters: Set; - /** * user selected time range */ diff --git a/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts b/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts index 2b1c8a4adda9..1c1e67ec7061 100644 --- a/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts +++ b/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts @@ -100,7 +100,7 @@ export function getExploreFilterStateFromYAMLConfig( exploreSpec: V1ExploreSpec, ): Partial { const filter = exploreSpec.defaultPreset?.where; - if (!filter && !exploreSpec.defaultPreset?.pinnedFilters?.length) { + if (!filter) { return {}; } @@ -125,7 +125,6 @@ export function getExploreFilterStateFromYAMLConfig( whereFilter: dimensionFilters, dimensionThresholdFilters, dimensionFilterExcludeMode, - pinnedFilters: new Set(exploreSpec.defaultPreset?.pinnedFilters ?? []), }; } diff --git a/web-common/src/features/dashboards/stores/get-rill-default-explore-state.ts b/web-common/src/features/dashboards/stores/get-rill-default-explore-state.ts index e96d704a7852..25394b35e76d 100644 --- a/web-common/src/features/dashboards/stores/get-rill-default-explore-state.ts +++ b/web-common/src/features/dashboards/stores/get-rill-default-explore-state.ts @@ -49,7 +49,6 @@ export function getRillDefaultExploreState( dimensionsWithInlistFilter: [], dimensionFilterExcludeMode: new Map(), temporaryFilterName: null, - pinnedFilters: new Set(), ...getRillDefaultExploreTimeState( metricsViewSpec, diff --git a/web-common/src/features/dashboards/stores/yaml-only-explore-state.svelte.ts b/web-common/src/features/dashboards/stores/yaml-only-explore-state.svelte.ts new file mode 100644 index 000000000000..f7780b5e0afe --- /dev/null +++ b/web-common/src/features/dashboards/stores/yaml-only-explore-state.svelte.ts @@ -0,0 +1,29 @@ +import { + ArrayRuneStore, + InMemoryRuneStore, +} from "@rilldata/web-common/lib/store-utils/types.svelte.ts"; +import type { V1ExploreSpec } from "@rilldata/web-common/runtime-client"; + +export interface YAMLOnlyExploreState { + editable: boolean; + pinnedFilters: ArrayRuneStore; + requiredFilters: ArrayRuneStore; +} + +export class ReadonlyYAMLExploreState implements YAMLOnlyExploreState { + public readonly editable = false; + public pinnedFilters: ArrayRuneStore; + public requiredFilters: ArrayRuneStore; + + public constructor() { + this.pinnedFilters = new ArrayRuneStore(new InMemoryRuneStore([])); + this.requiredFilters = new ArrayRuneStore(new InMemoryRuneStore([])); + } + + public sync(exploreSpec: V1ExploreSpec) { + this.pinnedFilters.setter(exploreSpec.defaultPreset?.pinnedFilters ?? []); + this.requiredFilters.setter( + exploreSpec.defaultPreset?.requiredFilters ?? [], + ); + } +} diff --git a/web-common/src/features/dashboards/workspace/Dashboard.svelte b/web-common/src/features/dashboards/workspace/Dashboard.svelte index cbac3e2f4682..de64ec77bf86 100644 --- a/web-common/src/features/dashboards/workspace/Dashboard.svelte +++ b/web-common/src/features/dashboards/workspace/Dashboard.svelte @@ -38,11 +38,16 @@ exploreTimeseriesWidth, tddChartHeight, } from "./dashboard-layout-store"; + import { + ReadonlyYAMLExploreState, + type YAMLOnlyExploreState, + } from "@rilldata/web-common/features/dashboards/stores/yaml-only-explore-state.svelte.ts"; export let exploreName: string; export let metricsViewName: string; export let isEmbedded: boolean = false; export let embedThemeName: Readable | null = null; + export let yamlOnlyState: YAMLOnlyExploreState | undefined = undefined; // Vertical space reserved below the chart for the chart toolbar, axis, big // number, and a minimum detail table height when computing the drag maximum. @@ -145,6 +150,14 @@ // Publish the resolved theme to the shared store for external components (e.g., chat in layout) $: activeDashboardTheme.set($theme); + $: resolvedYamlOnlyState = yamlOnlyState ?? new ReadonlyYAMLExploreState(); + $: if ( + resolvedYamlOnlyState instanceof ReadonlyYAMLExploreState && + exploreSpec + ) { + resolvedYamlOnlyState.sync(exploreSpec); + } + // Clear the active theme when this dashboard is destroyed onDestroy(() => activeDashboardTheme.set(undefined)); @@ -166,7 +179,12 @@ {:else} {#key exploreName}
- +
From a3b28089c613455247e4bb0652616b33b8bae1b7 Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Mon, 20 Jul 2026 12:10:44 +0530 Subject: [PATCH 03/11] Add save defaults button --- .../get-explore-state-from-yaml-config.ts | 41 +++-- .../workspace/SaveDefaultsButton.svelte | 78 +++++++++ .../workspace/save-explore-defaults.ts | 90 +++++++++++ .../workspace/viewing-explore-defaults.ts | 35 ++++ .../workspaces/ExploreWorkspace.svelte | 7 +- .../workspaces/VisualExploreEditing.svelte | 150 +----------------- 6 files changed, 235 insertions(+), 166 deletions(-) create mode 100644 web-common/src/features/dashboards/workspace/SaveDefaultsButton.svelte create mode 100644 web-common/src/features/dashboards/workspace/save-explore-defaults.ts create mode 100644 web-common/src/features/dashboards/workspace/viewing-explore-defaults.ts diff --git a/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts b/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts index 1c1e67ec7061..dea5618a4a6f 100644 --- a/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts +++ b/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts @@ -22,6 +22,7 @@ import { type V1ExploreSpec, type V1TimeRangeSummary, V1Operation, + type V1MetricsViewSpec, } from "@rilldata/web-common/runtime-client"; import { createQuery } from "@tanstack/svelte-query"; import { derived, type Readable } from "svelte/store"; @@ -54,6 +55,30 @@ export function getExploreStateFromYAMLConfig( }; } +export function getUrlForExploreYAMLDefaultState( + metricsViewSpec: V1MetricsViewSpec, + exploreSpec: V1ExploreSpec, + timeRangeSummary: V1TimeRangeSummary | undefined, +) { + const exploreStateFromYAMLConfig = getExploreStateFromYAMLConfig( + exploreSpec, + timeRangeSummary, + metricsViewSpec.smallestTimeGrain, + ); + const timeControlState = getTimeControlState( + metricsViewSpec, + exploreSpec, + timeRangeSummary, + exploreStateFromYAMLConfig as ExploreState, + ); + return convertPartialExploreStateToUrlParams( + exploreSpec, + metricsViewSpec, + exploreStateFromYAMLConfig, + timeControlState, + ); +} + export function createUrlForExploreYAMLDefaultState( client: RuntimeClient, exploreNameStore: Readable, @@ -72,24 +97,10 @@ export function createUrlForExploreYAMLDefaultState( const exploreSpec = validSpecResp.data?.exploreSpec ?? {}; const timeRangeSummary = timeRangeResp.data?.timeRangeSummary; - const exploreStateFromYAMLConfig = getExploreStateFromYAMLConfig( - exploreSpec, - timeRangeSummary, - metricsViewSpec.smallestTimeGrain, - ); - - const timeControlState = getTimeControlState( + const urlParams = getUrlForExploreYAMLDefaultState( metricsViewSpec, exploreSpec, timeRangeSummary, - exploreStateFromYAMLConfig as ExploreState, - ); - - const urlParams = convertPartialExploreStateToUrlParams( - exploreSpec, - metricsViewSpec, - exploreStateFromYAMLConfig, - timeControlState, ); return `?${urlParams.toString()}`; }, diff --git a/web-common/src/features/dashboards/workspace/SaveDefaultsButton.svelte b/web-common/src/features/dashboards/workspace/SaveDefaultsButton.svelte new file mode 100644 index 000000000000..b5eddbd08fd3 --- /dev/null +++ b/web-common/src/features/dashboards/workspace/SaveDefaultsButton.svelte @@ -0,0 +1,78 @@ + + + diff --git a/web-common/src/features/dashboards/workspace/save-explore-defaults.ts b/web-common/src/features/dashboards/workspace/save-explore-defaults.ts new file mode 100644 index 000000000000..653d0e1b269c --- /dev/null +++ b/web-common/src/features/dashboards/workspace/save-explore-defaults.ts @@ -0,0 +1,90 @@ +import { mergeDimensionAndMeasureFilters } from "@rilldata/web-common/features/dashboards/filters/measure-filters/measure-filter-utils.ts"; +import type { ExploreState } from "@rilldata/web-common/features/dashboards/stores/explore-state.ts"; +import type { FileArtifact } from "@rilldata/web-common/features/entity-management/file-artifact.ts"; +import { TimeRangePreset } from "@rilldata/web-common/lib/time/types.ts"; +import { queryServiceConvertExpressionToMetricsSQL } from "@rilldata/web-common/runtime-client"; +import { get } from "svelte/store"; +import { parseDocument } from "yaml"; +import { RuntimeClient } from "@rilldata/web-common/runtime-client/v2"; + +export type ComparisonModeValue = + | "none" + | "time" + | "dimension" + | "rill-PP" + | "rill-PD" + | "rill-PW" + | "rill-PM" + | "rill-PQ" + | "rill-PY"; + +export type ExploreDefaults = { + filter?: string; + measures?: string[]; + dimensions?: string[]; + comparison_mode?: ComparisonModeValue; + comparison_dimension?: string; + time_range?: string; + pinned?: string[]; +}; + +export async function saveExploreDefaults( + runtimeClient: RuntimeClient, + fileArtifact: FileArtifact, + exploreState: ExploreState, + autoSave: boolean, +) { + const doc = parseDocument(get(fileArtifact.editorContent) ?? ""); + const defaults: ExploreDefaults = {}; + + // Time range (skip CUSTOM and ALL_TIME) + const timeRangeName = exploreState.selectedTimeRange?.name; + if ( + timeRangeName && + timeRangeName !== TimeRangePreset.CUSTOM && + timeRangeName !== TimeRangePreset.ALL_TIME + ) { + defaults.time_range = timeRangeName; + } + + // Comparison + if (exploreState.showTimeComparison) { + defaults.comparison_mode = "time"; // TODO: set comparison time + } else if (exploreState.selectedComparisonDimension) { + defaults.comparison_mode = "dimension"; + defaults.comparison_dimension = exploreState.selectedComparisonDimension; + } + + // Visible measures/dimensions + if (exploreState.visibleMeasures?.length) { + defaults.measures = [...exploreState.visibleMeasures]; + } + if (exploreState.visibleDimensions?.length) { + defaults.dimensions = [...exploreState.visibleDimensions]; + } + + // Filters → SQL string via queryServiceConvertExpressionToMetricsSQL + const merged = mergeDimensionAndMeasureFilters( + exploreState.whereFilter, + exploreState.dimensionThresholdFilters ?? [], + ); + if (merged?.cond?.exprs?.length) { + try { + const { sql } = await queryServiceConvertExpressionToMetricsSQL( + runtimeClient, + { expression: merged as any }, + ); + if (sql) defaults.filter = sql; + } catch { + // If conversion fails, skip filter + } + } + + // Pinned filters + if (exploreState.pinnedFilters?.size) { + defaults.pinned = Array.from(exploreState.pinnedFilters); + } + + doc.set("defaults", defaults); + fileArtifact.updateEditorContent(doc.toString(), false, autoSave); +} diff --git a/web-common/src/features/dashboards/workspace/viewing-explore-defaults.ts b/web-common/src/features/dashboards/workspace/viewing-explore-defaults.ts new file mode 100644 index 000000000000..dbf48b1a3361 --- /dev/null +++ b/web-common/src/features/dashboards/workspace/viewing-explore-defaults.ts @@ -0,0 +1,35 @@ +import type { + V1ExploreSpec, + V1MetricsViewSpec, + V1TimeRangeSummary, +} from "@rilldata/web-common/runtime-client"; +import { getRillDefaultExploreUrlParams } from "@rilldata/web-common/features/dashboards/url-state/get-rill-default-explore-url-params.ts"; +import { getUrlForExploreYAMLDefaultState } from "@rilldata/web-common/features/dashboards/stores/get-explore-state-from-yaml-config.ts"; +import { cleanUrlParams } from "@rilldata/web-common/features/dashboards/url-state/clean-url-params.ts"; +import { unorderedParamsAreEqual } from "@rilldata/web-common/lib/url-utils.ts"; + +export function viewingExploreDefaults( + curUrlParams: URLSearchParams, + metricsViewSpec: V1MetricsViewSpec, + exploreSpec: V1ExploreSpec, + timeRangeSummary: V1TimeRangeSummary | undefined, +) { + const rillDefaultUrlParams = getRillDefaultExploreUrlParams( + metricsViewSpec, + exploreSpec, + timeRangeSummary, + ); + const yamlDefaultUrlParams = getUrlForExploreYAMLDefaultState( + metricsViewSpec, + exploreSpec, + timeRangeSummary, + ); + // No defaults defined, so nothing to save as default + if (yamlDefaultUrlParams.size === 0) return false; + + const cleanedYamlDefaults = cleanUrlParams( + yamlDefaultUrlParams, + rillDefaultUrlParams, + ); + return unorderedParamsAreEqual(cleanedYamlDefaults, curUrlParams); +} diff --git a/web-common/src/features/workspaces/ExploreWorkspace.svelte b/web-common/src/features/workspaces/ExploreWorkspace.svelte index e46528084aa9..cd2649751191 100644 --- a/web-common/src/features/workspaces/ExploreWorkspace.svelte +++ b/web-common/src/features/workspaces/ExploreWorkspace.svelte @@ -26,6 +26,7 @@ import StateManagersProvider from "../dashboards/state-managers/StateManagersProvider.svelte"; import DashboardStateManager from "../dashboards/state-managers/loaders/DashboardStateManager.svelte"; import Dashboard from "../dashboards/workspace/Dashboard.svelte"; + import SaveDefaultsButton from "@rilldata/web-common/features/dashboards/workspace/SaveDefaultsButton.svelte"; export let fileArtifact: FileArtifact; export let hideCodeToggle = false; @@ -40,6 +41,7 @@ resourceName, fileName, remoteContent, + saveState: { saving }, } = fileArtifact); $: exploreName = $resourceName?.name ?? getNameFromFile(filePath); @@ -108,6 +110,9 @@ > {#snippet cta()}
+ {#if ready && selectedView === "viz"} + + {/if} {#if !inPreviewMode} selectedViewStore.set("code")} /> {/if} diff --git a/web-common/src/features/workspaces/VisualExploreEditing.svelte b/web-common/src/features/workspaces/VisualExploreEditing.svelte index cd7d87a925f1..d9eb058740bd 100644 --- a/web-common/src/features/workspaces/VisualExploreEditing.svelte +++ b/web-common/src/features/workspaces/VisualExploreEditing.svelte @@ -1,10 +1,7 @@ + +
+ +
diff --git a/web-common/src/features/dashboards/filters/required/required-filters.ts b/web-common/src/features/dashboards/filters/required/required-filters.ts new file mode 100644 index 000000000000..9956909e0d6d --- /dev/null +++ b/web-common/src/features/dashboards/filters/required/required-filters.ts @@ -0,0 +1,50 @@ +import type { V1ExploreSpec } from "@rilldata/web-common/runtime-client"; +import type { DimensionFilterItem } from "@rilldata/web-common/features/dashboards/state-managers/selectors/dimension-filters.ts"; +import type { MeasureFilterItem } from "@rilldata/web-common/features/dashboards/state-managers/selectors/measure-filters.ts"; + +export type MissingRequiredFilter = { + key: string; + name: string; + label: string; +}; + +export function getMissingRequiredFilters( + exploreSpec: V1ExploreSpec, + dimensionFilters: DimensionFilterItem[], + measureFilters: MeasureFilterItem[], +) { + if (!exploreSpec.defaultPreset?.requiredFilters?.length) return []; + + const missing: MissingRequiredFilter[] = []; + exploreSpec.defaultPreset.requiredFilters.forEach((name) => { + const dimItem = dimensionFilters.find((d) => d.name === name); + if (dimItem) { + if (isDimensionItemEmpty(dimItem)) { + missing.push({ key: name, name, label: dimItem.label || name }); + } + return; + } + + const measureItem = measureFilters.find((m) => m.name === name); + if (measureItem) { + if (isMeasureItemEmpty(measureItem)) { + missing.push({ key: name, name, label: measureItem.label || name }); + } + return; + } + + // Required filter has no entry in the UI filter map at all => unsatisfied. + missing.push({ key: name, name, label: name }); + }); + return missing; +} + +function isDimensionItemEmpty(item: DimensionFilterItem): boolean { + const hasSelectedValues = (item.selectedValues?.length ?? 0) > 0; + const hasInputText = !!item.inputText && item.inputText.length > 0; + return !hasSelectedValues && !hasInputText; +} + +function isMeasureItemEmpty(item: MeasureFilterItem): boolean { + return !item.filter; +} diff --git a/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts b/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts index 69a670bff58c..f7be074dfeec 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts @@ -271,6 +271,28 @@ export const getAllDimensionFilterItems = ( }); } + pinnedFilters.values().forEach((pinnedFilter) => { + const existing = allDimensionFilterItem.find( + (dfi) => dfi.name === pinnedFilter, + ); + if (existing) return; + + const dim = dimensionIdMap.get(pinnedFilter); + if (!dim) return; + + allDimensionFilterItem.push({ + name: pinnedFilter, + label: getDimensionDisplayName(dim), + mode: DimensionFilterMode.Select, + selectedValues: [], + isInclude: true, + dimensions: new Map([ + [dashData.validExplore!.metricsView!, dim], + ]), + pinned: true, + }); + }); + // sort based on name to make sure toggling include/exclude is not jarring return allDimensionFilterItem.sort(filterItemsSortFunction); }; diff --git a/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts b/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts index 651d09fb6334..e9f887f22d64 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts @@ -1,4 +1,7 @@ -import { getMeasureDisplayName } from "@rilldata/web-common/features/dashboards/filters/getDisplayName"; +import { + getDimensionDisplayName, + getMeasureDisplayName, +} from "@rilldata/web-common/features/dashboards/filters/getDisplayName"; import type { MeasureFilterEntry } from "@rilldata/web-common/features/dashboards/filters/measure-filters/measure-filter-entry"; import type { DashboardDataSources } from "@rilldata/web-common/features/dashboards/state-managers/selectors/types"; import type { AtLeast } from "@rilldata/web-common/features/dashboards/state-managers/types"; @@ -7,6 +10,7 @@ import { type MetricsViewSpecDimension, type MetricsViewSpecMeasure, } from "@rilldata/web-common/runtime-client"; +import { DimensionFilterMode } from "@rilldata/web-common/features/dashboards/filters/dimension-filters/constants.ts"; export const measureHasFilter = ( dashData: AtLeast, @@ -126,6 +130,20 @@ export const getAllMeasureFilterItems = ( }); } + pinnedFilters.values().forEach((pinnedFilter) => { + const existing = allMeasureFilterItems.find( + (mfi) => mfi.name === pinnedFilter, + ); + if (existing || !measureIdMap.has(pinnedFilter)) return; + + allMeasureFilterItems.push({ + dimensionName: "", + name: pinnedFilter, + label: getMeasureDisplayName(measureIdMap.get(pinnedFilter)), + pinned: true, + }); + }); + return allMeasureFilterItems; }; }; diff --git a/web-common/src/features/dashboards/stores/yaml-only-explore-state.svelte.ts b/web-common/src/features/dashboards/stores/yaml-only-explore-state.svelte.ts index f7780b5e0afe..018ab45cf647 100644 --- a/web-common/src/features/dashboards/stores/yaml-only-explore-state.svelte.ts +++ b/web-common/src/features/dashboards/stores/yaml-only-explore-state.svelte.ts @@ -4,18 +4,11 @@ import { } from "@rilldata/web-common/lib/store-utils/types.svelte.ts"; import type { V1ExploreSpec } from "@rilldata/web-common/runtime-client"; -export interface YAMLOnlyExploreState { - editable: boolean; - pinnedFilters: ArrayRuneStore; - requiredFilters: ArrayRuneStore; -} - -export class ReadonlyYAMLExploreState implements YAMLOnlyExploreState { - public readonly editable = false; +export class YAMLOnlyExploreState { public pinnedFilters: ArrayRuneStore; public requiredFilters: ArrayRuneStore; - public constructor() { + public constructor(public readonly editable: boolean) { this.pinnedFilters = new ArrayRuneStore(new InMemoryRuneStore([])); this.requiredFilters = new ArrayRuneStore(new InMemoryRuneStore([])); } @@ -27,3 +20,8 @@ export class ReadonlyYAMLExploreState implements YAMLOnlyExploreState { ); } } + +export type YAMLOnlyExploreConfig = { + pinnedFilters: string[]; + requiredFilters: string[]; +}; diff --git a/web-common/src/features/dashboards/workspace/Dashboard.svelte b/web-common/src/features/dashboards/workspace/Dashboard.svelte index de64ec77bf86..b6e6e3e04eff 100644 --- a/web-common/src/features/dashboards/workspace/Dashboard.svelte +++ b/web-common/src/features/dashboards/workspace/Dashboard.svelte @@ -38,10 +38,10 @@ exploreTimeseriesWidth, tddChartHeight, } from "./dashboard-layout-store"; - import { - ReadonlyYAMLExploreState, - type YAMLOnlyExploreState, - } from "@rilldata/web-common/features/dashboards/stores/yaml-only-explore-state.svelte.ts"; + import { YAMLOnlyExploreState } from "@rilldata/web-common/features/dashboards/stores/yaml-only-explore-state.svelte.ts"; + import { getMapFromArray } from "@rilldata/web-common/lib/arrayUtils.ts"; + import { getMissingRequiredFilters } from "@rilldata/web-common/features/dashboards/filters/required/required-filters.ts"; + import RequiredFiltersMessage from "@rilldata/web-common/features/dashboards/filters/required/RequiredFiltersMessage.svelte"; export let exploreName: string; export let metricsViewName: string; @@ -55,8 +55,10 @@ const StateManagers = getStateManagers(); const { selectors: { - measures: { visibleMeasures }, - dimensions: { getDimensionByName }, + measures: { allMeasures, visibleMeasures }, + measureFilters: { getMeasureFilterItems, getAllMeasureFilterItems }, + dimensions: { allDimensions, getDimensionByName }, + dimensionFilters: { getDimensionFilterItems, getAllDimensionFilterItems }, pivot: { showPivot }, }, dashboardStore, @@ -150,14 +152,43 @@ // Publish the resolved theme to the shared store for external components (e.g., chat in layout) $: activeDashboardTheme.set($theme); - $: resolvedYamlOnlyState = yamlOnlyState ?? new ReadonlyYAMLExploreState(); - $: if ( - resolvedYamlOnlyState instanceof ReadonlyYAMLExploreState && - exploreSpec - ) { + $: resolvedYamlOnlyState = yamlOnlyState ?? new YAMLOnlyExploreState(false); + $: if (exploreSpec) { resolvedYamlOnlyState.sync(exploreSpec); } + $: dimensions = $allDimensions; + $: dimensionIdMap = getMapFromArray( + dimensions, + (dimension) => (dimension.name || dimension.column) as string, + ); + + $: measures = $allMeasures; + $: measureIdMap = getMapFromArray(measures, (m) => m.name as string); + + $: currentDimensionFilters = $getDimensionFilterItems( + dimensionIdMap, + new Set(resolvedYamlOnlyState.pinnedFilters.value), + ); + $: allDimensionFilters = $getAllDimensionFilterItems( + currentDimensionFilters, + dimensionIdMap, + new Set(resolvedYamlOnlyState.pinnedFilters.value), + ); + + $: currentMeasureFilters = $getMeasureFilterItems(measureIdMap); + $: allMeasureFilters = $getAllMeasureFilterItems( + currentMeasureFilters, + measureIdMap, + new Set(resolvedYamlOnlyState.pinnedFilters.value), + ); + + $: missingRequiredFilters = getMissingRequiredFilters( + exploreSpec ?? {}, + allDimensionFilters, + allMeasureFilters, + ); + // Clear the active theme when this dashboard is destroyed onDestroy(() => activeDashboardTheme.set(undefined)); @@ -193,7 +224,9 @@ {/if}
- {#if mockUserHasNoAccess} + {#if missingRequiredFilters.length} + + {:else if mockUserHasNoAccess} - {#if (isRillDeveloper || $cloudDataViewer) && !showTimeDimensionDetail && !mockUserHasNoAccess} + {#if (isRillDeveloper || $cloudDataViewer) && !showTimeDimensionDetail && !mockUserHasNoAccess && !missingRequiredFilters.length} {/if} diff --git a/web-common/src/features/dashboards/workspace/SaveDefaultsButton.svelte b/web-common/src/features/dashboards/workspace/SaveDefaultsButton.svelte index b5eddbd08fd3..ec8376194e78 100644 --- a/web-common/src/features/dashboards/workspace/SaveDefaultsButton.svelte +++ b/web-common/src/features/dashboards/workspace/SaveDefaultsButton.svelte @@ -9,13 +9,16 @@ import { useRuntimeClient } from "web-common/src/runtime-client/v2"; import { viewingExploreDefaults } from "@rilldata/web-common/features/dashboards/workspace/viewing-explore-defaults.ts"; import { page } from "$app/state"; + import type { YAMLOnlyExploreState } from "@rilldata/web-common/features/dashboards/stores/yaml-only-explore-state.svelte.ts"; let { fileArtifact, saving, + yamlOnlyState, }: { fileArtifact: FileArtifact; saving: boolean; + yamlOnlyState: YAMLOnlyExploreState; } = $props(); const runtimeClient = useRuntimeClient(); @@ -36,6 +39,10 @@ metricsViewSpec, exploreSpec, timeRangeSummary, + { + pinnedFilters: yamlOnlyState.pinnedFilters.value, + requiredFilters: yamlOnlyState.requiredFilters.value, + }, ), ); @@ -51,7 +58,7 @@ runtimeClient, fileArtifact, $dashboardStore, - true, + yamlOnlyState, ); setTimeout(() => { justClickedSaveAsDefault = false; diff --git a/web-common/src/features/dashboards/workspace/save-explore-defaults.ts b/web-common/src/features/dashboards/workspace/save-explore-defaults.ts index 653d0e1b269c..fd1ce460d7d0 100644 --- a/web-common/src/features/dashboards/workspace/save-explore-defaults.ts +++ b/web-common/src/features/dashboards/workspace/save-explore-defaults.ts @@ -6,33 +6,26 @@ import { queryServiceConvertExpressionToMetricsSQL } from "@rilldata/web-common/ import { get } from "svelte/store"; import { parseDocument } from "yaml"; import { RuntimeClient } from "@rilldata/web-common/runtime-client/v2"; +import type { YAMLOnlyExploreState } from "@rilldata/web-common/features/dashboards/stores/yaml-only-explore-state.svelte.ts"; -export type ComparisonModeValue = - | "none" - | "time" - | "dimension" - | "rill-PP" - | "rill-PD" - | "rill-PW" - | "rill-PM" - | "rill-PQ" - | "rill-PY"; +export type ComparisonModeValue = "none" | "time" | "dimension"; export type ExploreDefaults = { filter?: string; + pinned_filters?: string[]; + required_filters?: string[]; measures?: string[]; dimensions?: string[]; comparison_mode?: ComparisonModeValue; comparison_dimension?: string; time_range?: string; - pinned?: string[]; }; export async function saveExploreDefaults( runtimeClient: RuntimeClient, fileArtifact: FileArtifact, exploreState: ExploreState, - autoSave: boolean, + yamlOnlyConfig: YAMLOnlyExploreState, ) { const doc = parseDocument(get(fileArtifact.editorContent) ?? ""); const defaults: ExploreDefaults = {}; @@ -81,10 +74,17 @@ export async function saveExploreDefaults( } // Pinned filters - if (exploreState.pinnedFilters?.size) { - defaults.pinned = Array.from(exploreState.pinnedFilters); + if (yamlOnlyConfig.pinnedFilters.value.length) { + defaults.pinned_filters = Array.from(yamlOnlyConfig.pinnedFilters.value); + } + + // Required filters + if (yamlOnlyConfig.requiredFilters.value.length) { + defaults.required_filters = Array.from( + yamlOnlyConfig.requiredFilters.value, + ); } doc.set("defaults", defaults); - fileArtifact.updateEditorContent(doc.toString(), false, autoSave); + fileArtifact.updateEditorContent(doc.toString(), false, true); } diff --git a/web-common/src/features/dashboards/workspace/viewing-explore-defaults.ts b/web-common/src/features/dashboards/workspace/viewing-explore-defaults.ts index dbf48b1a3361..5d258046ac26 100644 --- a/web-common/src/features/dashboards/workspace/viewing-explore-defaults.ts +++ b/web-common/src/features/dashboards/workspace/viewing-explore-defaults.ts @@ -7,12 +7,15 @@ import { getRillDefaultExploreUrlParams } from "@rilldata/web-common/features/da import { getUrlForExploreYAMLDefaultState } from "@rilldata/web-common/features/dashboards/stores/get-explore-state-from-yaml-config.ts"; import { cleanUrlParams } from "@rilldata/web-common/features/dashboards/url-state/clean-url-params.ts"; import { unorderedParamsAreEqual } from "@rilldata/web-common/lib/url-utils.ts"; +import type { YAMLOnlyExploreConfig } from "@rilldata/web-common/features/dashboards/stores/yaml-only-explore-state.svelte.ts"; +import { arrayUnorderedEquals } from "@rilldata/web-common/lib/arrayUtils.ts"; export function viewingExploreDefaults( curUrlParams: URLSearchParams, metricsViewSpec: V1MetricsViewSpec, exploreSpec: V1ExploreSpec, timeRangeSummary: V1TimeRangeSummary | undefined, + yamlOnlyConfig: YAMLOnlyExploreConfig, ) { const rillDefaultUrlParams = getRillDefaultExploreUrlParams( metricsViewSpec, @@ -31,5 +34,19 @@ export function viewingExploreDefaults( yamlDefaultUrlParams, rillDefaultUrlParams, ); - return unorderedParamsAreEqual(cleanedYamlDefaults, curUrlParams); + const paramsAreEqual = unorderedParamsAreEqual( + cleanedYamlDefaults, + curUrlParams, + ); + + const pinnedFiltersAreEqual = arrayUnorderedEquals( + yamlOnlyConfig.pinnedFilters, + exploreSpec.defaultPreset?.pinnedFilters ?? [], + ); + const requiredFiltersAreEqual = arrayUnorderedEquals( + yamlOnlyConfig.requiredFilters, + exploreSpec.defaultPreset?.requiredFilters ?? [], + ); + + return paramsAreEqual && pinnedFiltersAreEqual && requiredFiltersAreEqual; } diff --git a/web-common/src/features/workspaces/ExploreWorkspace.svelte b/web-common/src/features/workspaces/ExploreWorkspace.svelte index cd2649751191..09adae100b37 100644 --- a/web-common/src/features/workspaces/ExploreWorkspace.svelte +++ b/web-common/src/features/workspaces/ExploreWorkspace.svelte @@ -27,6 +27,7 @@ import DashboardStateManager from "../dashboards/state-managers/loaders/DashboardStateManager.svelte"; import Dashboard from "../dashboards/workspace/Dashboard.svelte"; import SaveDefaultsButton from "@rilldata/web-common/features/dashboards/workspace/SaveDefaultsButton.svelte"; + import { YAMLOnlyExploreState } from "@rilldata/web-common/features/dashboards/stores/yaml-only-explore-state.svelte.ts"; export let fileArtifact: FileArtifact; export let hideCodeToggle = false; @@ -79,6 +80,8 @@ ? ($rootCauseQuery?.data ?? reconcileError) : undefined; + const yamlOnlyState = new YAMLOnlyExploreState(true); + async function onChangeCallback(newTitle: string) { const newRoute = await handleEntityRename( runtimeClient, @@ -111,7 +114,11 @@ {#snippet cta()}
{#if ready && selectedView === "viz"} - + {/if} {#if !inPreviewMode} {:else if exploreName && metricsViewName} - + {:else} From 37ceac25a9cea52e865272c19b5c411cee02b7a7 Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Mon, 20 Jul 2026 19:07:34 +0530 Subject: [PATCH 05/11] Self review --- runtime/parser/parse_explore.go | 14 ++------- .../canvas/CanvasDashboardWrapper.svelte | 31 ++----------------- .../dashboards/filters/Filters.svelte | 11 +++++-- .../required/RequiredFiltersMessage.svelte | 12 +++---- .../filters/test/render-filter-component.ts | 2 ++ .../selectors/dimension-filters.ts | 2 +- .../selectors/measure-filters.ts | 4 +-- .../get-explore-state-from-yaml-config.ts | 10 ++---- .../dashboards/workspace/Dashboard.svelte | 11 +++++-- .../workspace/save-explore-defaults.ts | 2 +- .../workspaces/VisualExploreEditing.svelte | 6 ---- web-common/src/lib/i18n/messages/en.json | 11 +++++++ web-common/src/lib/i18n/messages/es.json | 11 +++++++ 13 files changed, 56 insertions(+), 71 deletions(-) diff --git a/runtime/parser/parse_explore.go b/runtime/parser/parse_explore.go index 6aa1739b0973..6dbb514618ae 100644 --- a/runtime/parser/parse_explore.go +++ b/runtime/parser/parse_explore.go @@ -262,16 +262,6 @@ func (p *Parser) parseExplore(node *Node) error { filter = metricsview.ExpressionToProto(expr) } - var pinnedMeasuresOrDimensions []string - if len(tmp.Defaults.PinnedFilters) > 0 { - pinnedMeasuresOrDimensions = tmp.Defaults.PinnedFilters - } - - var requiredFilters []string - if len(tmp.Defaults.RequiredFilters) > 0 { - requiredFilters = tmp.Defaults.RequiredFilters - } - defaultPreset = &runtimev1.ExplorePreset{ Dimensions: presetDimensions, DimensionsSelector: presetDimensionsSelector, @@ -281,8 +271,8 @@ func (p *Parser) parseExplore(node *Node) error { ComparisonMode: mode, ComparisonDimension: compareDim, Where: filter, - PinnedFilters: pinnedMeasuresOrDimensions, - RequiredFilters: requiredFilters, + PinnedFilters: tmp.Defaults.PinnedFilters, + RequiredFilters: tmp.Defaults.RequiredFilters, } } diff --git a/web-common/src/features/canvas/CanvasDashboardWrapper.svelte b/web-common/src/features/canvas/CanvasDashboardWrapper.svelte index cab84a40e072..2755328d5ea5 100644 --- a/web-common/src/features/canvas/CanvasDashboardWrapper.svelte +++ b/web-common/src/features/canvas/CanvasDashboardWrapper.svelte @@ -2,11 +2,11 @@ import { dynamicHeight } from "@rilldata/web-common/layout/layout-settings.ts"; import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2"; import CellInspector from "@rilldata/web-common/components/CellInspector.svelte"; - import WarningIcon from "@rilldata/web-common/components/icons/WarningIcon.svelte"; import CanvasFilters from "./filters/CanvasFilters.svelte"; import { getCanvasStore } from "./state-managers/state-managers"; import ThemeProvider from "../dashboards/ThemeProvider.svelte"; import CanvasPdfExportView from "../exports/pdf/CanvasPdfExportView.svelte"; + import RequiredFiltersMessage from "@rilldata/web-common/features/dashboards/filters/required/RequiredFiltersMessage.svelte"; const client = useRuntimeClient(); @@ -87,34 +87,7 @@ }} > {#if hasMissingRequired} -
- -
+ {:else}
m.name as string); + $: pinnedFilters = new Set([ + ...yamlOnlyState.pinnedFilters.value, + ...yamlOnlyState.requiredFilters.value, + ]); + $: currentDimensionFilters = $getDimensionFilterItems( dimensionIdMap, - new Set(yamlOnlyState.pinnedFilters.value), + pinnedFilters, ); $: allDimensionFilters = $getAllDimensionFilterItems( currentDimensionFilters, dimensionIdMap, - new Set(yamlOnlyState.pinnedFilters.value), + pinnedFilters, ); $: currentMeasureFilters = $getMeasureFilterItems(measureIdMap); $: allMeasureFilters = $getAllMeasureFilterItems( currentMeasureFilters, measureIdMap, - new Set(yamlOnlyState.pinnedFilters.value), + pinnedFilters, ); // hasFilter only checks for complete filters and excludes temporary ones diff --git a/web-common/src/features/dashboards/filters/required/RequiredFiltersMessage.svelte b/web-common/src/features/dashboards/filters/required/RequiredFiltersMessage.svelte index a3e57337b3d9..44a0bccb63fc 100644 --- a/web-common/src/features/dashboards/filters/required/RequiredFiltersMessage.svelte +++ b/web-common/src/features/dashboards/filters/required/RequiredFiltersMessage.svelte @@ -1,6 +1,7 @@ + +
+ {#if hasDefaults} +
+

+ The filters listed below are saved as your default view and will + automatically apply each time you open this dashboard in Rill Cloud. +

+ + +
+ +
+ +
+ {:else} +
+

+ No default state configured. Use the "Save as default" button in the + header to save the current dashboard state as the default view. +

+
+ {/if} +
+ + diff --git a/web-common/src/features/workspaces/VisualExploreEditing.svelte b/web-common/src/features/workspaces/VisualExploreEditing.svelte index 219a0e08be5c..236683243fce 100644 --- a/web-common/src/features/workspaces/VisualExploreEditing.svelte +++ b/web-common/src/features/workspaces/VisualExploreEditing.svelte @@ -36,6 +36,8 @@ setRootYamlTags, } from "../visual-editing/tag-utils"; import ThemeInput from "../visual-editing/ThemeInput.svelte"; + import Tab from "@rilldata/web-common/features/dashboards/tab-bar/Tab.svelte"; + import ExploreDefaultFilterDisplay from "@rilldata/web-common/features/dashboards/workspace/ExploreDefaultFilterDisplay.svelte"; const itemTypes = ["measures", "dimensions"] as const; @@ -47,6 +49,8 @@ const runtimeClient = useRuntimeClient(); + let activeTab: "options" | "filters" = "options"; + $: if (exploreSpec) metricsExplorerStore.sync(exploreName, exploreSpec); $: ({ editorContent, path, updateEditorContent } = fileArtifact); @@ -284,196 +288,226 @@ - - {#if autoSave} -

Changes below will be auto-saved.

- {/if} - - { - updateProperties({ display_name: title }, ["title"]); - }} - onEnter={() => { - updateProperties({ display_name: title }); - }} - /> - - - - ({ - label: name, - value: name, - }))} - onChange={() => { - killState(); - - updateProperties( - { - metrics_view: metricsView, - measures: "*", - dimensions: "*", - }, - ["defaults"], - ); - }} - /> - - {#each itemTypes as type (type)} - {@const items = type === "measures" ? measures : dimensions} - { - updateProperties({ [type]: "*" }); - }} - onSelectExpression={() => { - updateProperties({ [type]: { expr: "*" } }); - }} - setItems={(items, exclude) => { - const deleteKeys = [["defaults", type]]; - if (type === "dimensions") { - deleteKeys.push(["defaults", "comparison_dimension"]); - deleteKeys.push(["defaults", "comparison_mode"]); - } - - if (exclude) { - updateProperties({ [type]: { exclude: items } }, deleteKeys); - } else { - updateProperties({ [type]: items }, deleteKeys); - } - }} - onExpressionBlur={(value) => { - const deleteKeys = [["defaults", type]]; - if (type === "dimensions") { - deleteKeys.push(["defaults", "comparison_dimension"]); - deleteKeys.push(["defaults", "comparison_mode"]); - } - updateProperties({ [type]: { expr: value } }, deleteKeys); - }} - onSelectSubsetItem={(item) => { - const deleted = subsets[type].delete(item); - if (!deleted) { - subsets[type].add(item); - } + +
+
+ (activeTab = "options")} + > + Options + + (activeTab = "filters")} + > + Filters + +
+
+ + {#if activeTab === "options"} +
+ {#if autoSave} +

+ Changes below will be auto-saved. +

+ {/if} + + { + updateProperties({ display_name: title }, ["title"]); + }} + onEnter={() => { + updateProperties({ display_name: title }); + }} + /> + + + + ({ + label: name, + value: name, + }))} + onChange={() => { + killState(); - const deleteKeys = [["defaults", type]]; - if (type === "dimensions") { - deleteKeys.push(["defaults", "comparison_dimension"]); - deleteKeys.push(["defaults", "comparison_mode"]); - } - - if (excludeMode[type]) { updateProperties( - { [type]: { exclude: Array.from(subsets[type]) } }, - deleteKeys, + { + metrics_view: metricsView, + measures: "*", + dimensions: "*", + }, + ["defaults"], ); - } else { - updateProperties({ [type]: Array.from(subsets[type]) }, deleteKeys); - } - }} - /> - {/each} - - { - if (time_ranges.length === 0) { - updateProperties({ time_ranges }, [["defaults", "time_range"]]); - } else { - updateProperties({ time_ranges }); - } - }} - let:item - > - {DEFAULT_TIME_RANGES[item]?.label ?? item} - - - { - updateProperties({}, ["time_zones"]); - }} - onSelectCustomItem={(item) => { - const deleted = timeZones.delete(item); - if (!deleted) timeZones.add(item); - - updateProperties({ time_zones: Array.from(timeZones) }); - }} - setItems={(time_zones) => { - updateProperties({ time_zones }); - }} - let:item - > - - - - { - if (!value) { - updateProperties({}, ["theme"]); - } else { - updateProperties({ theme: value }); - } - }} - onColorChange={(primary, secondary, isDarkMode) => { - const modeKey = isDarkMode ? "dark" : "light"; - const altMode = isDarkMode ? "light" : "dark"; - - // check if theme exists for alt mode - const setAltMode = !parsedDocument.hasIn(["theme", altMode]); - - parsedDocument.setIn(["theme", modeKey, "primary"], primary); - parsedDocument.setIn(["theme", modeKey, "secondary"], secondary); - - if (setAltMode) { - parsedDocument.setIn(["theme", altMode, "primary"], primary); - parsedDocument.setIn(["theme", altMode, "secondary"], secondary); - } - - killState(); - - updateEditorContent(parsedDocument.toString(), false, autoSave); - }} - /> - - + }} + /> + + {#each itemTypes as type (type)} + {@const items = type === "measures" ? measures : dimensions} + { + updateProperties({ [type]: "*" }); + }} + onSelectExpression={() => { + updateProperties({ [type]: { expr: "*" } }); + }} + setItems={(items, exclude) => { + const deleteKeys = [["defaults", type]]; + if (type === "dimensions") { + deleteKeys.push(["defaults", "comparison_dimension"]); + deleteKeys.push(["defaults", "comparison_mode"]); + } + + if (exclude) { + updateProperties({ [type]: { exclude: items } }, deleteKeys); + } else { + updateProperties({ [type]: items }, deleteKeys); + } + }} + onExpressionBlur={(value) => { + const deleteKeys = [["defaults", type]]; + if (type === "dimensions") { + deleteKeys.push(["defaults", "comparison_dimension"]); + deleteKeys.push(["defaults", "comparison_mode"]); + } + updateProperties({ [type]: { expr: value } }, deleteKeys); + }} + onSelectSubsetItem={(item) => { + const deleted = subsets[type].delete(item); + if (!deleted) { + subsets[type].add(item); + } + + const deleteKeys = [["defaults", type]]; + if (type === "dimensions") { + deleteKeys.push(["defaults", "comparison_dimension"]); + deleteKeys.push(["defaults", "comparison_mode"]); + } + + if (excludeMode[type]) { + updateProperties( + { [type]: { exclude: Array.from(subsets[type]) } }, + deleteKeys, + ); + } else { + updateProperties( + { [type]: Array.from(subsets[type]) }, + deleteKeys, + ); + } + }} + /> + {/each} + + { + if (time_ranges.length === 0) { + updateProperties({ time_ranges }, [["defaults", "time_range"]]); + } else { + updateProperties({ time_ranges }); + } + }} + let:item + > + {DEFAULT_TIME_RANGES[item]?.label ?? item} + + + { + updateProperties({}, ["time_zones"]); + }} + onSelectCustomItem={(item) => { + const deleted = timeZones.delete(item); + if (!deleted) timeZones.add(item); + + updateProperties({ time_zones: Array.from(timeZones) }); + }} + setItems={(time_zones) => { + updateProperties({ time_zones }); + }} + let:item + > + + + + { + if (!value) { + updateProperties({}, ["theme"]); + } else { + updateProperties({ theme: value }); + } + }} + onColorChange={(primary, secondary, isDarkMode) => { + const modeKey = isDarkMode ? "dark" : "light"; + const altMode = isDarkMode ? "light" : "dark"; + + // check if theme exists for alt mode + const setAltMode = !parsedDocument.hasIn(["theme", altMode]); + + parsedDocument.setIn(["theme", modeKey, "primary"], primary); + parsedDocument.setIn(["theme", modeKey, "secondary"], secondary); + + if (setAltMode) { + parsedDocument.setIn(["theme", altMode, "primary"], primary); + parsedDocument.setIn(["theme", altMode, "secondary"], secondary); + } + + killState(); + + updateEditorContent(parsedDocument.toString(), false, autoSave); + }} + /> +
+ {:else if activeTab === "filters"} + + {/if}
From 3c45592c6dd6627565debc018d4272b00c6e3e82 Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Tue, 21 Jul 2026 19:29:22 +0530 Subject: [PATCH 07/11] Fix defaults check with grains --- runtime/parser/parse_explore.go | 9 ++++++++- .../stores/get-explore-state-from-yaml-config.ts | 8 ++++++++ .../dashboards/workspace/save-explore-defaults.ts | 6 ++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/runtime/parser/parse_explore.go b/runtime/parser/parse_explore.go index 8d1145ff629c..6dc717185022 100644 --- a/runtime/parser/parse_explore.go +++ b/runtime/parser/parse_explore.go @@ -15,7 +15,7 @@ import ( ) type ExploreYAML struct { - commonYAML `yaml:",inline"` // Not accessed here, only setting it so we can use KnownFields for YAML parsing + commonYAML `yaml:",inline"` // Not accessed here, only setting it so we can use KnownFields for YAML parsing DisplayName string `yaml:"display_name"` Title string `yaml:"title"` // Deprecated: use display_name Description string `yaml:"description"` @@ -32,6 +32,7 @@ type ExploreYAML struct { Dimensions *FieldSelectorYAML `yaml:"dimensions"` Measures *FieldSelectorYAML `yaml:"measures"` TimeRange string `yaml:"time_range"` + TimeGrain string `yaml:"time_grain"` ComparisonMode string `yaml:"comparison_mode"` ComparisonDimension string `yaml:"comparison_dimension"` Filter string `yaml:"filter"` @@ -247,6 +248,11 @@ func (p *Parser) parseExplore(node *Node) error { if tmp.Defaults.TimeRange != "" { tr = &tmp.Defaults.TimeRange } + var tg *string + if tmp.Defaults.TimeGrain != "" { + tg = &tmp.Defaults.TimeGrain + } + var compareDim *string if tmp.Defaults.ComparisonDimension != "" { compareDim = &tmp.Defaults.ComparisonDimension @@ -268,6 +274,7 @@ func (p *Parser) parseExplore(node *Node) error { Measures: presetMeasures, MeasuresSelector: presetMeasuresSelector, TimeRange: tr, + TimeGrain: tg, ComparisonMode: mode, ComparisonDimension: compareDim, Where: filter, diff --git a/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts b/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts index 8d5b0d4cf776..968fd166bff7 100644 --- a/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts +++ b/web-common/src/features/dashboards/stores/get-explore-state-from-yaml-config.ts @@ -68,6 +68,14 @@ export function getUrlForExploreYAMLDefaultState( timeRangeSummary, exploreStateFromYAMLConfig as ExploreState, ); + // Temp fix to avoid refactoring TimeControlState + if ( + exploreStateFromYAMLConfig.selectedTimeRange?.interval && + timeControlState?.selectedTimeRange + ) { + timeControlState.selectedTimeRange.interval = + exploreStateFromYAMLConfig.selectedTimeRange.interval; + } return convertPartialExploreStateToUrlParams( exploreSpec, metricsViewSpec, diff --git a/web-common/src/features/dashboards/workspace/save-explore-defaults.ts b/web-common/src/features/dashboards/workspace/save-explore-defaults.ts index fd0d90c494b7..81d87fccb09c 100644 --- a/web-common/src/features/dashboards/workspace/save-explore-defaults.ts +++ b/web-common/src/features/dashboards/workspace/save-explore-defaults.ts @@ -7,6 +7,7 @@ import { get } from "svelte/store"; import { parseDocument } from "yaml"; import { RuntimeClient } from "@rilldata/web-common/runtime-client/v2"; import type { YAMLOnlyExploreState } from "@rilldata/web-common/features/dashboards/stores/yaml-only-explore-state.svelte.ts"; +import { V1TimeGrainToDateTimeUnit } from "@rilldata/web-common/lib/time/new-grains.ts"; export type ComparisonModeValue = "none" | "time" | "dimension"; @@ -19,6 +20,8 @@ export type ExploreDefaults = { comparison_mode?: ComparisonModeValue; comparison_dimension?: string; time_range?: string; + // TODO: comparison time range + time_grain?: string; }; export async function saveExploreDefaults( @@ -38,6 +41,9 @@ export async function saveExploreDefaults( timeRangeName !== TimeRangePreset.ALL_TIME ) { defaults.time_range = timeRangeName; + if (exploreState.selectedTimeRange!.interval) + defaults.time_grain = + V1TimeGrainToDateTimeUnit[exploreState.selectedTimeRange!.interval]; } // Comparison From 9c5605f14bb0e0b248f44fd5c1bd74dfbefe2794 Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Wed, 22 Jul 2026 11:09:55 +0530 Subject: [PATCH 08/11] Fix misc issues --- runtime/parser/parse_explore.go | 11 +++++ .../features/canvas/stores/filter-manager.ts | 1 + .../dashboards/filters/Filters.svelte | 10 +++-- .../selectors/dimension-filters.ts | 40 ++++++++++++++++++- .../selectors/measure-filters.ts | 35 +++++++++++++++- .../src/features/dashboards/stores/Filters.ts | 3 ++ .../dashboards/workspace/Dashboard.svelte | 11 +++-- .../workspace/save-explore-defaults.ts | 8 ++-- 8 files changed, 104 insertions(+), 15 deletions(-) diff --git a/runtime/parser/parse_explore.go b/runtime/parser/parse_explore.go index 6dc717185022..693151f6b6f3 100644 --- a/runtime/parser/parse_explore.go +++ b/runtime/parser/parse_explore.go @@ -33,6 +33,7 @@ type ExploreYAML struct { Measures *FieldSelectorYAML `yaml:"measures"` TimeRange string `yaml:"time_range"` TimeGrain string `yaml:"time_grain"` + ComparisonTimeRange string `yaml:"comparison_time_range"` ComparisonMode string `yaml:"comparison_mode"` ComparisonDimension string `yaml:"comparison_dimension"` Filter string `yaml:"filter"` @@ -253,6 +254,15 @@ func (p *Parser) parseExplore(node *Node) error { tg = &tmp.Defaults.TimeGrain } + var ctr *string + if tmp.Defaults.ComparisonTimeRange != "" { + ctr = &tmp.Defaults.ComparisonTimeRange + // Only set comparison mode to time if not directly set + if tmp.Defaults.ComparisonMode == "" { + mode = runtimev1.ExploreComparisonMode_EXPLORE_COMPARISON_MODE_TIME + } + } + var compareDim *string if tmp.Defaults.ComparisonDimension != "" { compareDim = &tmp.Defaults.ComparisonDimension @@ -275,6 +285,7 @@ func (p *Parser) parseExplore(node *Node) error { MeasuresSelector: presetMeasuresSelector, TimeRange: tr, TimeGrain: tg, + CompareTimeRange: ctr, ComparisonMode: mode, ComparisonDimension: compareDim, Where: filter, diff --git a/web-common/src/features/canvas/stores/filter-manager.ts b/web-common/src/features/canvas/stores/filter-manager.ts index ec6197ac5151..f58ff89ad0e6 100644 --- a/web-common/src/features/canvas/stores/filter-manager.ts +++ b/web-common/src/features/canvas/stores/filter-manager.ts @@ -544,6 +544,7 @@ export class FilterManager { merged.hasFilters = merged.hasClearableFilters || pinnedFilters.size > 0 || + requiredFilters.size > 0 || temporaryFilterKeys.size > 0; // Sorting to ensure that pills don't jump around unnecessarily in the UI diff --git a/web-common/src/features/dashboards/filters/Filters.svelte b/web-common/src/features/dashboards/filters/Filters.svelte index cdeacb367ce9..aa7d105f0a59 100644 --- a/web-common/src/features/dashboards/filters/Filters.svelte +++ b/web-common/src/features/dashboards/filters/Filters.svelte @@ -154,29 +154,31 @@ $: measures = $allMeasures; $: measureIdMap = getMapFromArray(measures, (m) => m.name as string); - $: pinnedFilters = new Set([ - ...yamlOnlyState.pinnedFilters.value, - ...yamlOnlyState.requiredFilters.value, - ]); + $: pinnedFilters = new Set(yamlOnlyState.pinnedFilters.value); + $: requiredFilters = new Set(yamlOnlyState.requiredFilters.value); $: currentDimensionFilters = $getDimensionFilterItems( dimensionIdMap, pinnedFilters, + requiredFilters, ); $: allDimensionFilters = $getAllDimensionFilterItems( currentDimensionFilters, dimensionIdMap, pinnedFilters, + requiredFilters, ); $: currentMeasureFilters = $getMeasureFilterItems( measureIdMap, pinnedFilters, + requiredFilters, ); $: allMeasureFilters = $getAllMeasureFilterItems( currentMeasureFilters, measureIdMap, pinnedFilters, + requiredFilters, ); // hasFilter only checks for complete filters and excludes temporary ones diff --git a/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts b/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts index dcd586afbe8d..cac63907b7f5 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/dimension-filters.ts @@ -150,6 +150,7 @@ export function getDimensionFilterItems( return ( dimensionIdMap: Map, pinnedFilters: Set = new Set(), + requiredFilters: Set = new Set(), ) => { return getDimensionFilters( dimensionIdMap, @@ -157,6 +158,7 @@ export function getDimensionFilterItems( dashData.dashboard.dimensionsWithInlistFilter, dashData.validExplore?.metricsView, pinnedFilters, + requiredFilters, ); }; } @@ -167,6 +169,7 @@ export function getDimensionFiltersMap( dimensionsWithInlistFilter: string[], metricsViewName: string | undefined, pinnedFilters: Set, + requiredFilters: Set, ): Map { if (!filter || !metricsViewName) return new Map(); const filteredDimensions: Map = new Map(); @@ -191,7 +194,8 @@ export function getDimensionFiltersMap( selectedValues: getValuesInExpression(e), isInclude: e.cond?.op === V1Operation.OPERATION_IN, inputText: undefined, - pinned: pinnedFilters?.has(ident), + pinned: pinnedFilters?.has(ident) || requiredFilters.has(ident), + required: requiredFilters?.has(ident), dimensions: new Map([ [metricsViewName, dim], @@ -225,6 +229,7 @@ export function getDimensionFilters( dimensionsWithInlistFilter: string[], metricsViewName: string | undefined, pinnedFilters: Set, + requiredFilters: Set, ) { const dimensionFilters = Array.from( getDimensionFiltersMap( @@ -233,6 +238,7 @@ export function getDimensionFilters( dimensionsWithInlistFilter, metricsViewName, pinnedFilters, + requiredFilters, ).values(), ); if (!metricsViewName) return dimensionFilters; @@ -258,6 +264,30 @@ export function getDimensionFilters( }); }); + // Add required filters that dont have values selected + requiredFilters.forEach((requiredFilter) => { + const existing = dimensionFilters.some( + (dfi) => dfi.name === requiredFilter, + ); + if (existing) return; + + const dim = dimensionIdMap.get(requiredFilter); + if (!dim) return; + + dimensionFilters.push({ + name: requiredFilter, + label: getDimensionDisplayName(dim), + mode: DimensionFilterMode.Select, + selectedValues: [], + isInclude: true, + dimensions: new Map([ + [metricsViewName, dim], + ]), + pinned: true, + required: true, + }); + }); + return dimensionFilters; } @@ -268,6 +298,7 @@ export const getAllDimensionFilterItems = ( dimensionFilterItem: DimensionFilterItem[], dimensionIdMap: Map, pinnedFilters: Set = new Set(), + requiredFilters: Set = new Set(), ) => { const allDimensionFilterItem = [...dimensionFilterItem]; @@ -280,6 +311,9 @@ export const getAllDimensionFilterItems = ( (dfi) => dfi.name !== dashData.dashboard.temporaryFilterName, ) ) { + const required = requiredFilters.has( + dashData.dashboard.temporaryFilterName, + ); allDimensionFilterItem.push({ name: dashData.dashboard.temporaryFilterName, label: getDimensionDisplayName( @@ -294,7 +328,9 @@ export const getAllDimensionFilterItems = ( dimensionIdMap.get(dashData.dashboard.temporaryFilterName)!, ], ]), - pinned: pinnedFilters.has(dashData.dashboard.temporaryFilterName), + pinned: + required || pinnedFilters.has(dashData.dashboard.temporaryFilterName), + required, }); } diff --git a/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts b/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts index 1f2cfb019072..22ecc5adebfe 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/measure-filters.ts @@ -36,11 +36,13 @@ export const getMeasureFilterItems = ( return ( measureIdMap: Map, pinnedFilters: Set = new Set(), + requiredFilters: Set = new Set(), ) => { return getMeasureFilters( measureIdMap, dashData.dashboard.dimensionThresholdFilters, pinnedFilters, + requiredFilters, ); }; }; @@ -49,18 +51,24 @@ export function getMeasureFilters( measureIdMap: Map, dimensionThresholdFilters: DimensionThresholdFilter[], pinnedFilters: Set, + requiredFilters: Set, ) { const filteredMeasures = new Array(); const addedMeasure = new Set(); for (const dtf of dimensionThresholdFilters) { + const required = dtf.filters[0] + ? requiredFilters.has(dtf.filters[0].measure) + : false; filteredMeasures.push( ...getMeasureFilterForDimension( measureIdMap, dtf.filters, dtf.name, addedMeasure, - dtf.filters[0] ? pinnedFilters.has(dtf.filters[0].measure) : false, + required || + (dtf.filters[0] ? pinnedFilters.has(dtf.filters[0].measure) : false), + required, ), ); } @@ -77,6 +85,21 @@ export function getMeasureFilters( }); }); + requiredFilters.forEach((requiredFilter) => { + const existing = filteredMeasures.some( + (mfi) => mfi.name === requiredFilter, + ); + if (existing || !measureIdMap.has(requiredFilter)) return; + + filteredMeasures.push({ + dimensionName: "", + name: requiredFilter, + label: getMeasureDisplayName(measureIdMap.get(requiredFilter)), + pinned: true, + required: true, + }); + }); + return filteredMeasures; } @@ -86,6 +109,7 @@ export function getMeasureFilterForDimension( name = "", addedMeasure = new Set(), pinned = false, + required = false, ) { if (!filters.length) return []; @@ -107,6 +131,7 @@ export function getMeasureFilterForDimension( label: measure.displayName || measure.expression || filter.measure, filter, pinned, + required, }); }); @@ -120,6 +145,7 @@ export const getAllMeasureFilterItems = ( measureFilterItems: Array, measureIdMap: Map, pinnedFilters: Set = new Set(), + requiredFilters: Set = new Set(), ) => { const allMeasureFilterItems = [...measureFilterItems]; @@ -131,13 +157,18 @@ export const getAllMeasureFilterItems = ( (mfi) => mfi.name !== dashData.dashboard.temporaryFilterName, ) ) { + const required = requiredFilters.has( + dashData.dashboard.temporaryFilterName, + ); allMeasureFilterItems.push({ dimensionName: "", name: dashData.dashboard.temporaryFilterName, label: getMeasureDisplayName( measureIdMap.get(dashData.dashboard.temporaryFilterName), ), - pinned: pinnedFilters.has(dashData.dashboard.temporaryFilterName), + pinned: + required || pinnedFilters.has(dashData.dashboard.temporaryFilterName), + required, }); } diff --git a/web-common/src/features/dashboards/stores/Filters.ts b/web-common/src/features/dashboards/stores/Filters.ts index 1c6c98ddc6e0..cb71600a3ddf 100644 --- a/web-common/src/features/dashboards/stores/Filters.ts +++ b/web-common/src/features/dashboards/stores/Filters.ts @@ -162,6 +162,9 @@ export class Filters { $whereFilter, $dimensionsWithInlistFilter, this.metricsViewMetadata.metricsViewName, + // Not supported in alerts/reports, the consumers of this class + new Set(), + new Set(), ); }, ); diff --git a/web-common/src/features/dashboards/workspace/Dashboard.svelte b/web-common/src/features/dashboards/workspace/Dashboard.svelte index 4e3635fa2e33..1964b4ce1dca 100644 --- a/web-common/src/features/dashboards/workspace/Dashboard.svelte +++ b/web-common/src/features/dashboards/workspace/Dashboard.svelte @@ -152,6 +152,7 @@ // Publish the resolved theme to the shared store for external components (e.g., chat in layout) $: activeDashboardTheme.set($theme); + // Create a readonly yaml explore state if not passed an instance. $: resolvedYamlOnlyState = yamlOnlyState ?? new YAMLOnlyExploreState(false); $: if (exploreSpec) { resolvedYamlOnlyState.sync(exploreSpec); @@ -166,29 +167,31 @@ $: measures = $allMeasures; $: measureIdMap = getMapFromArray(measures, (m) => m.name as string); - $: pinnedFilters = new Set([ - ...resolvedYamlOnlyState.pinnedFilters.value, - ...resolvedYamlOnlyState.requiredFilters.value, - ]); + $: pinnedFilters = new Set(resolvedYamlOnlyState.pinnedFilters.value); + $: requiredFilters = new Set(resolvedYamlOnlyState.requiredFilters.value); $: currentDimensionFilters = $getDimensionFilterItems( dimensionIdMap, pinnedFilters, + requiredFilters, ); $: allDimensionFilters = $getAllDimensionFilterItems( currentDimensionFilters, dimensionIdMap, pinnedFilters, + requiredFilters, ); $: currentMeasureFilters = $getMeasureFilterItems( measureIdMap, pinnedFilters, + requiredFilters, ); $: allMeasureFilters = $getAllMeasureFilterItems( currentMeasureFilters, measureIdMap, pinnedFilters, + requiredFilters, ); $: missingRequiredFilters = getMissingRequiredFilters( diff --git a/web-common/src/features/dashboards/workspace/save-explore-defaults.ts b/web-common/src/features/dashboards/workspace/save-explore-defaults.ts index 81d87fccb09c..e4e25f04b5b7 100644 --- a/web-common/src/features/dashboards/workspace/save-explore-defaults.ts +++ b/web-common/src/features/dashboards/workspace/save-explore-defaults.ts @@ -17,11 +17,11 @@ export type ExploreDefaults = { required_filters?: string[]; measures?: string[]; dimensions?: string[]; - comparison_mode?: ComparisonModeValue; - comparison_dimension?: string; time_range?: string; - // TODO: comparison time range time_grain?: string; + comparison_time_range?: string; + comparison_mode?: ComparisonModeValue; + comparison_dimension?: string; }; export async function saveExploreDefaults( @@ -49,6 +49,8 @@ export async function saveExploreDefaults( // Comparison if (exploreState.showTimeComparison) { defaults.comparison_mode = "time"; + defaults.comparison_time_range = + exploreState.selectedComparisonTimeRange?.name || "rill-PP"; } else if (exploreState.selectedComparisonDimension) { defaults.comparison_mode = "dimension"; defaults.comparison_dimension = exploreState.selectedComparisonDimension; From c75618791386fe322ed2590eb389b3c1a4fba77a Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Thu, 23 Jul 2026 12:28:23 +0530 Subject: [PATCH 09/11] PR comments --- runtime/parser/parse_explore.go | 2 +- runtime/reconcilers/explore.go | 16 +++++ runtime/reconcilers/explore_test.go | 72 +++++++++++++++++++ .../filters/ExploreFilterChipsReadOnly.svelte | 2 + .../filters/FilterChipsReadOnly.svelte | 3 + .../ExploreDefaultFilterDisplay.svelte | 9 +-- 6 files changed, 97 insertions(+), 7 deletions(-) diff --git a/runtime/parser/parse_explore.go b/runtime/parser/parse_explore.go index 693151f6b6f3..b244777cd376 100644 --- a/runtime/parser/parse_explore.go +++ b/runtime/parser/parse_explore.go @@ -15,7 +15,7 @@ import ( ) type ExploreYAML struct { - commonYAML `yaml:",inline"` // Not accessed here, only setting it so we can use KnownFields for YAML parsing + commonYAML `yaml:",inline"` // Not accessed here, only setting it so we can use KnownFields for YAML parsing DisplayName string `yaml:"display_name"` Title string `yaml:"title"` // Deprecated: use display_name Description string `yaml:"description"` diff --git a/runtime/reconcilers/explore.go b/runtime/reconcilers/explore.go index 4fa9acfa5f8d..57d243a6402a 100644 --- a/runtime/reconcilers/explore.go +++ b/runtime/reconcilers/explore.go @@ -245,6 +245,22 @@ func (r *ExploreReconciler) validateAndRewrite(ctx context.Context, self *runtim } p.Measures = measures p.MeasuresSelector = nil + + // Validate that required filters reference a dimension or measure on the explore. + if len(p.RequiredFilters) > 0 { + known := make(map[string]bool, len(spec.Dimensions)+len(spec.Measures)) + for _, d := range spec.Dimensions { + known[d] = true + } + for _, m := range spec.Measures { + known[m] = true + } + for _, name := range p.RequiredFilters { + if !known[name] { + return nil, nil, fmt.Errorf("required filter %q is not a dimension or measure on this explore", name) + } + } + } } // Done with rewriting diff --git a/runtime/reconcilers/explore_test.go b/runtime/reconcilers/explore_test.go index 8ae9b07dbe9a..35a5b77132ad 100644 --- a/runtime/reconcilers/explore_test.go +++ b/runtime/reconcilers/explore_test.go @@ -114,6 +114,78 @@ defaults: }) } +func TestExploreRequiredFilters(t *testing.T) { + rt, id := testruntime.NewInstance(t) + testruntime.PutFiles(t, rt, id, map[string]string{ + "models/m1.sql": `SELECT 'foo' as foo, 'bar' as bar, 1 as x`, + "metrics_views/mv1.yaml": ` +version: 1 +type: metrics_view +model: m1 +dimensions: +- column: foo +- column: bar +measures: +- name: x + expression: sum(x) +security: + access: true +`, + }) + + // A required filter naming an unknown field should fail validation. + testruntime.PutFiles(t, rt, id, map[string]string{ + "explores/e1.yaml": ` +type: explore +metrics_view: mv1 +dimensions: '*' +measures: '*' +defaults: + required_filters: ['doesnt_exist'] +`, + }) + testruntime.ReconcileParserAndWait(t, rt, id) + testruntime.RequireReconcileState(t, rt, id, 4, 1, 0) + e1 := testruntime.GetResource(t, rt, id, runtime.ResourceKindExplore, "e1") + require.Nil(t, e1.GetExplore().State.ValidSpec) + require.Contains(t, e1.Meta.ReconcileError, `required filter "doesnt_exist"`) + + // A required filter that names a dimension omitted from the explore should also fail. + testruntime.PutFiles(t, rt, id, map[string]string{ + "explores/e1.yaml": ` +type: explore +metrics_view: mv1 +dimensions: + exclude: ['bar'] +measures: '*' +defaults: + required_filters: ['bar'] +`, + }) + testruntime.ReconcileParserAndWait(t, rt, id) + testruntime.RequireReconcileState(t, rt, id, 4, 1, 0) + e1 = testruntime.GetResource(t, rt, id, runtime.ResourceKindExplore, "e1") + require.Nil(t, e1.GetExplore().State.ValidSpec) + require.Contains(t, e1.Meta.ReconcileError, `required filter "bar"`) + + // A required filter that names a valid explore field should succeed. + testruntime.PutFiles(t, rt, id, map[string]string{ + "explores/e1.yaml": ` +type: explore +metrics_view: mv1 +dimensions: '*' +measures: '*' +defaults: + required_filters: ['foo', 'x'] +`, + }) + testruntime.ReconcileParserAndWait(t, rt, id) + testruntime.RequireReconcileState(t, rt, id, 4, 0, 0) + e1 = testruntime.GetResource(t, rt, id, runtime.ResourceKindExplore, "e1") + require.NotNil(t, e1.GetExplore().State.ValidSpec) + require.Equal(t, []string{"foo", "x"}, e1.GetExplore().State.ValidSpec.DefaultPreset.RequiredFilters) +} + func TestExploreTheme(t *testing.T) { // Create source and model rt, id := testruntime.NewInstance(t) diff --git a/web-common/src/features/dashboards/filters/ExploreFilterChipsReadOnly.svelte b/web-common/src/features/dashboards/filters/ExploreFilterChipsReadOnly.svelte index 28e4adaf85ce..b2e003b840e7 100644 --- a/web-common/src/features/dashboards/filters/ExploreFilterChipsReadOnly.svelte +++ b/web-common/src/features/dashboards/filters/ExploreFilterChipsReadOnly.svelte @@ -20,6 +20,7 @@ export let queryTimeStart: string | undefined = undefined; export let queryTimeEnd: string | undefined = undefined; export let pinnedFilters: Set = new Set(); + export let requiredFilters: Set = new Set(); const runtimeClient = useRuntimeClient(); @@ -46,4 +47,5 @@ {queryTimeStart} {queryTimeEnd} {pinnedFilters} + {requiredFilters} /> diff --git a/web-common/src/features/dashboards/filters/FilterChipsReadOnly.svelte b/web-common/src/features/dashboards/filters/FilterChipsReadOnly.svelte index 7cca34a3abb5..8859f66c7c9d 100644 --- a/web-common/src/features/dashboards/filters/FilterChipsReadOnly.svelte +++ b/web-common/src/features/dashboards/filters/FilterChipsReadOnly.svelte @@ -33,6 +33,7 @@ The main feature-set component for dashboard filters export let hasBoldTimeRange: boolean = true; export let chipLayout: "wrap" | "scroll" = "wrap"; export let pinnedFilters: Set = new Set(); + export let requiredFilters: Set = new Set(); let scrollContainer: HTMLDivElement; @@ -46,6 +47,7 @@ The main feature-set component for dashboard filters dimensionsWithInlistFilter, metricsViewNames[0], pinnedFilters, + requiredFilters, ); $: measureIdMap = getMapFromArray( @@ -56,6 +58,7 @@ The main feature-set component for dashboard filters measureIdMap, dimensionThresholdFilters, pinnedFilters, + requiredFilters, ); function handleWheel(event: WheelEvent) { diff --git a/web-common/src/features/dashboards/workspace/ExploreDefaultFilterDisplay.svelte b/web-common/src/features/dashboards/workspace/ExploreDefaultFilterDisplay.svelte index 741a12be05ff..82e8a259bca9 100644 --- a/web-common/src/features/dashboards/workspace/ExploreDefaultFilterDisplay.svelte +++ b/web-common/src/features/dashboards/workspace/ExploreDefaultFilterDisplay.svelte @@ -41,12 +41,8 @@ exploreSpec ? getExploreFilterStateFromYAMLConfig(exploreSpec) : {}, ); - let pinnedFilters = $derived( - new Set([ - ...(defaultPreset?.pinnedFilters ?? []), - ...(defaultPreset?.requiredFilters ?? []), - ]), - ); + let pinnedFilters = $derived(new Set(defaultPreset?.pinnedFilters ?? [])); + let requiredFilters = $derived(new Set(defaultPreset?.requiredFilters ?? [])); let comparisonTimeRange = $derived( getComparisonTimeRange( @@ -90,6 +86,7 @@ displayTimeRange={{ expression: defaultPreset?.timeRange }} displayComparisonTimeRange={comparisonTimeRange} {pinnedFilters} + {requiredFilters} />
From 3db44606af57419ba7cdfc305af1242b03268ee1 Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Thu, 23 Jul 2026 16:24:18 +0530 Subject: [PATCH 10/11] UXQA --- .../alerts/metadata/AlertFilters.svelte | 10 +- .../dashboards/filters/Filters.svelte | 247 ++++++++++-------- .../dashboards/filters/PinButton.svelte | 2 +- .../dashboards/filters/RequiredButton.svelte | 2 +- 4 files changed, 151 insertions(+), 110 deletions(-) diff --git a/web-admin/src/features/alerts/metadata/AlertFilters.svelte b/web-admin/src/features/alerts/metadata/AlertFilters.svelte index f06f250bf186..39068df752c3 100644 --- a/web-admin/src/features/alerts/metadata/AlertFilters.svelte +++ b/web-admin/src/features/alerts/metadata/AlertFilters.svelte @@ -54,8 +54,16 @@ whereFilter, dimensionsWithInlistFilter, metricsViewName, + // Not supported in alerts/reports as of now + new Set(), + new Set(), + ); + $: currentMeasureFilters = getMeasureFilters( + measureIdMap, + havingFilter, // Not supported in alerts/reports as of now + new Set(), + new Set(), ); - $: currentMeasureFilters = getMeasureFilters(measureIdMap, havingFilter);
diff --git a/web-common/src/features/dashboards/filters/Filters.svelte b/web-common/src/features/dashboards/filters/Filters.svelte index aa7d105f0a59..1997140ae4ef 100644 --- a/web-common/src/features/dashboards/filters/Filters.svelte +++ b/web-common/src/features/dashboards/filters/Filters.svelte @@ -54,11 +54,19 @@ const { rillTime } = featureFlags; - export let readOnly = false; - export let timeRanges: V1ExploreTimeRange[]; - export let metricsViewName: string; - export let hasTimeSeries: boolean; - export let yamlOnlyState: YAMLOnlyExploreState; + let { + readOnly = false, + timeRanges, + metricsViewName, + hasTimeSeries, + yamlOnlyState, + }: { + readOnly?: boolean; + timeRanges: V1ExploreTimeRange[]; + metricsViewName: string; + hasTimeSeries: boolean; + yamlOnlyState: YAMLOnlyExploreState; + } = $props(); /** the height of a row of chips */ const ROW_HEIGHT = "26px"; @@ -106,132 +114,150 @@ const client = useRuntimeClient(); - $: timeRangeQuery = useMetricsViewTimeRange(client, metricsViewName); + let timeRangeQuery = $derived( + useMetricsViewTimeRange(client, metricsViewName), + ); - $: timeRangeSummary = $timeRangeQuery.data?.timeRangeSummary; + let timeRangeSummary = $derived($timeRangeQuery.data?.timeRangeSummary); - $: watermark = timeRangeSummary?.watermark; + let watermark = $derived(timeRangeSummary?.watermark); - $: maxQueryTimeRangeMillis = Number( - $timeRangeQuery.data?.maxQueryTimeRangeMillis ?? 0, + let maxQueryTimeRangeMillis = $derived( + Number($timeRangeQuery.data?.maxQueryTimeRangeMillis ?? 0), ); - $: maxQueryTimeRange = + let maxQueryTimeRange = $derived( maxQueryTimeRangeMillis > 0 ? Duration.fromMillis(maxQueryTimeRangeMillis) - : undefined; - - $: ({ - selectedTimeRange, - allTimeRange, - showTimeComparison, - selectedComparisonTimeRange, - minTimeGrain, - timeStart, - timeEnd, - ready: timeControlsReady, - } = $timeControlsStore); - - $: exploreSpec = $validSpecStore.data?.explore ?? {}; - $: metricsViewSpec = $validSpecStore.data?.metricsView ?? {}; - - $: exploreState = useExploreState($exploreName); - $: activeTimeZone = $exploreState?.selectedTimezone; - - $: selectedRangeAlias = + : undefined, + ); + + let selectedTimeRange = $derived($timeControlsStore.selectedTimeRange); + let allTimeRange = $derived($timeControlsStore.allTimeRange); + let showTimeComparison = $derived($timeControlsStore.showTimeComparison); + let selectedComparisonTimeRange = $derived( + $timeControlsStore.selectedComparisonTimeRange, + ); + let minTimeGrain = $derived($timeControlsStore.minTimeGrain); + let timeStart = $derived($timeControlsStore.timeStart); + let timeEnd = $derived($timeControlsStore.timeEnd); + let timeControlsReady = $derived($timeControlsStore.ready); + + let exploreSpec = $derived($validSpecStore.data?.explore ?? {}); + let metricsViewSpec = $derived($validSpecStore.data?.metricsView ?? {}); + + let exploreState = $derived(useExploreState($exploreName)); + let activeTimeZone = $derived($exploreState?.selectedTimezone); + + let selectedRangeAlias = $derived( selectedTimeRange?.name === TimeRangePreset.CUSTOM ? `${selectedTimeRange.start.toISOString()},${selectedTimeRange.end.toISOString()}` - : selectedTimeRange?.name; + : selectedTimeRange?.name, + ); - $: activeTimeGrain = selectedTimeRange?.interval; - $: defaultTimeRange = exploreSpec.defaultPreset?.timeRange; + let activeTimeGrain = $derived(selectedTimeRange?.interval); + let defaultTimeRange = $derived(exploreSpec.defaultPreset?.timeRange); - $: dimensions = $allDimensions; - $: dimensionIdMap = getMapFromArray( - dimensions, - (dimension) => (dimension.name || dimension.column) as string, + let dimensions = $derived($allDimensions); + let dimensionIdMap = $derived( + getMapFromArray( + dimensions, + (dimension) => (dimension.name || dimension.column) as string, + ), ); - $: measures = $allMeasures; - $: measureIdMap = getMapFromArray(measures, (m) => m.name as string); + let measures = $derived($allMeasures); + let measureIdMap = $derived( + getMapFromArray(measures, (m) => m.name as string), + ); - $: pinnedFilters = new Set(yamlOnlyState.pinnedFilters.value); - $: requiredFilters = new Set(yamlOnlyState.requiredFilters.value); + let pinnedFilters = $derived(new Set(yamlOnlyState.pinnedFilters.value)); + let requiredFilters = $derived(new Set(yamlOnlyState.requiredFilters.value)); - $: currentDimensionFilters = $getDimensionFilterItems( - dimensionIdMap, - pinnedFilters, - requiredFilters, + let currentDimensionFilters = $derived( + $getDimensionFilterItems(dimensionIdMap, pinnedFilters, requiredFilters), ); - $: allDimensionFilters = $getAllDimensionFilterItems( - currentDimensionFilters, - dimensionIdMap, - pinnedFilters, - requiredFilters, + let allDimensionFilters = $derived( + $getAllDimensionFilterItems( + currentDimensionFilters, + dimensionIdMap, + pinnedFilters, + requiredFilters, + ), ); - $: currentMeasureFilters = $getMeasureFilterItems( - measureIdMap, - pinnedFilters, - requiredFilters, + let currentMeasureFilters = $derived( + $getMeasureFilterItems(measureIdMap, pinnedFilters, requiredFilters), ); - $: allMeasureFilters = $getAllMeasureFilterItems( - currentMeasureFilters, - measureIdMap, - pinnedFilters, - requiredFilters, + let allMeasureFilters = $derived( + $getAllMeasureFilterItems( + currentMeasureFilters, + measureIdMap, + pinnedFilters, + requiredFilters, + ), ); // hasFilter only checks for complete filters and excludes temporary ones - $: hasFilters = - currentDimensionFilters.length > 0 || currentMeasureFilters.length > 0; - - $: ({ whereFilter, selectedTimeDimension } = $dashboardStore); + let hasFilters = $derived( + currentDimensionFilters.length > 0 || currentMeasureFilters.length > 0, + ); - $: isComplexFilter = isExpressionUnsupported(whereFilter); + let whereFilter = $derived($dashboardStore.whereFilter); + let selectedTimeDimension = $derived($dashboardStore.selectedTimeDimension); - $: availableTimeZones = getPinnedTimeZones(exploreSpec); + let isComplexFilter = $derived(isExpressionUnsupported(whereFilter)); - $: allTimeRangeInterval = allTimeRange - ? Interval.fromDateTimes(allTimeRange.start, allTimeRange.end) - : Interval.invalid("Invalid interval"); + let availableTimeZones = $derived(getPinnedTimeZones(exploreSpec)); - $: maybeInterval = selectedTimeRange - ? Interval.fromDateTimes( - DateTime.fromJSDate(selectedTimeRange.start).setZone(activeTimeZone), - DateTime.fromJSDate(selectedTimeRange.end).setZone(activeTimeZone), - ) - : allTimeRange + let allTimeRangeInterval = $derived( + allTimeRange ? Interval.fromDateTimes(allTimeRange.start, allTimeRange.end) - : undefined; + : Interval.invalid("Invalid interval"), + ); - $: interval = maybeInterval?.isValid ? maybeInterval : undefined; + let maybeInterval = $derived( + selectedTimeRange + ? Interval.fromDateTimes( + DateTime.fromJSDate(selectedTimeRange.start).setZone(activeTimeZone), + DateTime.fromJSDate(selectedTimeRange.end).setZone(activeTimeZone), + ) + : allTimeRange + ? Interval.fromDateTimes(allTimeRange.start, allTimeRange.end) + : undefined, + ); - $: baseTimeRange = selectedTimeRange?.start && - selectedTimeRange?.end && { - name: selectedTimeRange?.name, - start: selectedTimeRange.start, - end: selectedTimeRange.end, - }; + let interval = $derived(maybeInterval?.isValid ? maybeInterval : undefined); + + let baseTimeRange = $derived( + selectedTimeRange?.start && + selectedTimeRange?.end && { + name: selectedTimeRange?.name, + start: selectedTimeRange.start, + end: selectedTimeRange.end, + }, + ); - $: primaryTimeDimension = metricsViewSpec.timeDimension; + let primaryTimeDimension = $derived(metricsViewSpec.timeDimension); - $: timeDimensionOptions = $timeDimensions.map((timeDim) => { - return { - value: timeDim.name!, - label: timeDim.displayName || timeDim.name!, - description: timeDim.description, - }; - }); + let timeDimensionOptions = $derived( + $timeDimensions.map((timeDim) => { + return { + value: timeDim.name!, + label: timeDim.displayName || timeDim.name!, + description: timeDim.description, + }; + }), + ); - $: maybeMinDate = allTimeRange?.start - ? DateTime.fromJSDate(allTimeRange.start) - : undefined; - $: maybeMaxDate = allTimeRange?.end - ? DateTime.fromJSDate(allTimeRange.end) - : undefined; + let maybeMinDate = $derived( + allTimeRange?.start ? DateTime.fromJSDate(allTimeRange.start) : undefined, + ); + let maybeMaxDate = $derived( + allTimeRange?.end ? DateTime.fromJSDate(allTimeRange.end) : undefined, + ); - $: minDate = maybeMinDate?.isValid ? maybeMinDate : undefined; - $: maxDate = maybeMaxDate?.isValid ? maybeMaxDate : undefined; + let minDate = $derived(maybeMinDate?.isValid ? maybeMinDate : undefined); + let maxDate = $derived(maybeMaxDate?.isValid ? maybeMaxDate : undefined); function handleMeasureFilterApply( dimension: string, @@ -415,9 +441,10 @@ metricsExplorerStore.setTimeZone($exploreName, timeZone); } - $: usingRillTime = + let usingRillTime = $derived( !selectedRangeAlias?.startsWith("P") && - !selectedRangeAlias?.startsWith("rill-"); + !selectedRangeAlias?.startsWith("rill-"), + ); function onTimeGrainSelect(timeGrain: V1TimeGrain) { if (usingRillTime && selectedRangeAlias) { @@ -447,12 +474,16 @@ return isUrlTooLong(url); } - $: toggleFilterPin = yamlOnlyState?.editable - ? (name: string) => yamlOnlyState.pinnedFilters.toggle(name) - : undefined; - $: toggleFilterRequired = yamlOnlyState?.editable - ? (name: string) => yamlOnlyState.requiredFilters.toggle(name) - : undefined; + let toggleFilterPin = $derived( + yamlOnlyState?.editable + ? (name: string) => yamlOnlyState.pinnedFilters.toggle(name) + : undefined, + ); + let toggleFilterRequired = $derived( + yamlOnlyState?.editable + ? (name: string) => yamlOnlyState.requiredFilters.toggle(name) + : undefined, + );
@@ -568,6 +599,8 @@ {timeEnd} timeDimension={selectedTimeDimension} {timeControlsReady} + openOnMount={$dashboardStore.temporaryFilterName === + filterData.name} removeDimensionFilter={async (name) => removeDimensionFilter(name)} toggleDimensionFilterMode={async (name) => { diff --git a/web-common/src/features/dashboards/filters/PinButton.svelte b/web-common/src/features/dashboards/filters/PinButton.svelte index 0075dae168ec..6339ae02591b 100644 --- a/web-common/src/features/dashboards/filters/PinButton.svelte +++ b/web-common/src/features/dashboards/filters/PinButton.svelte @@ -23,7 +23,7 @@ {m.filter_pin_tooltip()} diff --git a/web-common/src/features/dashboards/filters/RequiredButton.svelte b/web-common/src/features/dashboards/filters/RequiredButton.svelte index b76a9156cb66..150a8a66c687 100644 --- a/web-common/src/features/dashboards/filters/RequiredButton.svelte +++ b/web-common/src/features/dashboards/filters/RequiredButton.svelte @@ -19,7 +19,7 @@ {m.filter_required_tooltip()} From fe4119ddc3193585464c01d8f175c1d5b9c12cea Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Tue, 28 Jul 2026 16:22:12 +0530 Subject: [PATCH 11/11] Fix openOnMount --- .../src/features/dashboards/stores/dashboard-stores.ts | 6 ++++++ .../features/dashboards/workspace/SaveDefaultsButton.svelte | 3 ++- .../features/dashboards/workspace/save-explore-defaults.ts | 3 +++ web-common/src/features/explores/PreviewButton.svelte | 3 ++- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/web-common/src/features/dashboards/stores/dashboard-stores.ts b/web-common/src/features/dashboards/stores/dashboard-stores.ts index 6beecd0c54b3..17863381647a 100644 --- a/web-common/src/features/dashboards/stores/dashboard-stores.ts +++ b/web-common/src/features/dashboards/stores/dashboard-stores.ts @@ -547,6 +547,12 @@ const metricsViewReducers = { }); }, + reset(name: string) { + updateMetricsExplorerByName(name, (exploreState) => { + exploreState.temporaryFilterName = null; + }); + }, + setPivotTableMode( name: string, tableMode: PivotTableMode, diff --git a/web-common/src/features/dashboards/workspace/SaveDefaultsButton.svelte b/web-common/src/features/dashboards/workspace/SaveDefaultsButton.svelte index ec8376194e78..7c0895fb08fe 100644 --- a/web-common/src/features/dashboards/workspace/SaveDefaultsButton.svelte +++ b/web-common/src/features/dashboards/workspace/SaveDefaultsButton.svelte @@ -25,7 +25,7 @@ let justClickedSaveAsDefault = $state(false); - const { dashboardStore, validSpecStore, timeRangeSummaryStore } = + const { dashboardStore, validSpecStore, timeRangeSummaryStore, exploreName } = getStateManagers(); let exploreSpec = $derived($validSpecStore.data?.explore ?? {}); let metricsViewSpec = $derived($validSpecStore.data?.metricsView ?? {}); @@ -57,6 +57,7 @@ await saveExploreDefaults( runtimeClient, fileArtifact, + $exploreName, $dashboardStore, yamlOnlyState, ); diff --git a/web-common/src/features/dashboards/workspace/save-explore-defaults.ts b/web-common/src/features/dashboards/workspace/save-explore-defaults.ts index e4e25f04b5b7..b15b5ee92e78 100644 --- a/web-common/src/features/dashboards/workspace/save-explore-defaults.ts +++ b/web-common/src/features/dashboards/workspace/save-explore-defaults.ts @@ -8,6 +8,7 @@ import { parseDocument } from "yaml"; import { RuntimeClient } from "@rilldata/web-common/runtime-client/v2"; import type { YAMLOnlyExploreState } from "@rilldata/web-common/features/dashboards/stores/yaml-only-explore-state.svelte.ts"; import { V1TimeGrainToDateTimeUnit } from "@rilldata/web-common/lib/time/new-grains.ts"; +import { metricsExplorerStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores.ts"; export type ComparisonModeValue = "none" | "time" | "dimension"; @@ -27,6 +28,7 @@ export type ExploreDefaults = { export async function saveExploreDefaults( runtimeClient: RuntimeClient, fileArtifact: FileArtifact, + exploreName: string, exploreState: ExploreState, yamlOnlyConfig: YAMLOnlyExploreState, ) { @@ -95,4 +97,5 @@ export async function saveExploreDefaults( doc.set("defaults", defaults); fileArtifact.updateEditorContent(doc.toString(), false, true); + metricsExplorerStore.reset(exploreName); } diff --git a/web-common/src/features/explores/PreviewButton.svelte b/web-common/src/features/explores/PreviewButton.svelte index 1aee69aefcd2..e90ccb23fb81 100644 --- a/web-common/src/features/explores/PreviewButton.svelte +++ b/web-common/src/features/explores/PreviewButton.svelte @@ -12,6 +12,7 @@ MetricsEventSpace, } from "@rilldata/web-common/metrics/service/MetricsTypes"; import { Play } from "lucide-svelte"; + import { metricsExplorerStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores.ts"; export let disabled: boolean; export let href: string | null; @@ -19,9 +20,9 @@ const viewDashboard = () => { if (!href) return; - // temporary fix. we should do a proper fix by removing this on rill-dev when navigated to preview const [, entityType, entityName] = href.split("/"); if (entityType === "explore") { + metricsExplorerStore.reset(entityName); clearExploreSessionStore(entityName, undefined); clearMostRecentExploreState(entityName, undefined); }