diff --git a/.config/api-rules/violation_exceptions.list b/.config/api-rules/violation_exceptions.list index 1e899164c..a407c5f37 100644 --- a/.config/api-rules/violation_exceptions.list +++ b/.config/api-rules/violation_exceptions.list @@ -54,7 +54,6 @@ API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/shared API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/shared,UIParameters,InstanceLabelPaths API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,ActionTemplate,Icons API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,ActionTemplateGroup,Items -API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,ActionTemplateGroupFilter,Items API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,ChartInfo,ValuesFiles API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,Dashboard,Panels API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,Dashboard,Vars @@ -74,7 +73,6 @@ API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1a API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,ResourceOutlineFilterSpec,Actions API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,ResourceOutlineFilterSpec,Pages API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,ResourcePageOutlineFilter,Sections -API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,SectionOutlineFilter,Blocks API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,UIParameters,Actions API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,UIParameters,InstanceLabelPaths API rule violation: list_type_missing,kmodules.xyz/resource-metadata/apis/ui/v1alpha1,VariantRef,Icons diff --git a/apis/ui/v1alpha1/openapi_generated.go b/apis/ui/v1alpha1/openapi_generated.go index ccb3b8a74..3ea281569 100644 --- a/apis/ui/v1alpha1/openapi_generated.go +++ b/apis/ui/v1alpha1/openapi_generated.go @@ -397,7 +397,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "kmodules.xyz/resource-metadata/apis/ui/v1alpha1.FeatureSetStatus": schema_resource_metadata_apis_ui_v1alpha1_FeatureSetStatus(ref), "kmodules.xyz/resource-metadata/apis/ui/v1alpha1.FeatureSpec": schema_resource_metadata_apis_ui_v1alpha1_FeatureSpec(ref), "kmodules.xyz/resource-metadata/apis/ui/v1alpha1.FeatureStatus": schema_resource_metadata_apis_ui_v1alpha1_FeatureStatus(ref), - "kmodules.xyz/resource-metadata/apis/ui/v1alpha1.ItemFilter": schema_resource_metadata_apis_ui_v1alpha1_ItemFilter(ref), "kmodules.xyz/resource-metadata/apis/ui/v1alpha1.PanelLinkRequest": schema_resource_metadata_apis_ui_v1alpha1_PanelLinkRequest(ref), "kmodules.xyz/resource-metadata/apis/ui/v1alpha1.ReadinessChecks": schema_resource_metadata_apis_ui_v1alpha1_ReadinessChecks(ref), "kmodules.xyz/resource-metadata/apis/ui/v1alpha1.Requirements": schema_resource_metadata_apis_ui_v1alpha1_Requirements(ref), @@ -19887,12 +19886,14 @@ func schema_resource_metadata_apis_ui_v1alpha1_ActionTemplateGroupFilter(ref com }, "items": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("kmodules.xyz/resource-metadata/apis/ui/v1alpha1.ItemFilter"), + Default: false, + Type: []string{"boolean"}, + Format: "", }, }, }, @@ -19902,8 +19903,6 @@ func schema_resource_metadata_apis_ui_v1alpha1_ActionTemplateGroupFilter(ref com Required: []string{"items"}, }, }, - Dependencies: []string{ - "kmodules.xyz/resource-metadata/apis/ui/v1alpha1.ItemFilter"}, } } @@ -20757,32 +20756,6 @@ func schema_resource_metadata_apis_ui_v1alpha1_FeatureStatus(ref common.Referenc } } -func schema_resource_metadata_apis_ui_v1alpha1_ItemFilter(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "name": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - "show": { - SchemaProps: spec.SchemaProps{ - Default: false, - Type: []string{"boolean"}, - Format: "", - }, - }, - }, - Required: []string{"show"}, - }, - }, - } -} - func schema_resource_metadata_apis_ui_v1alpha1_PanelLinkRequest(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -21362,12 +21335,14 @@ func schema_resource_metadata_apis_ui_v1alpha1_SectionOutlineFilter(ref common.R }, "blocks": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("kmodules.xyz/resource-metadata/apis/ui/v1alpha1.ItemFilter"), + Default: false, + Type: []string{"boolean"}, + Format: "", }, }, }, @@ -21377,8 +21352,6 @@ func schema_resource_metadata_apis_ui_v1alpha1_SectionOutlineFilter(ref common.R Required: []string{"info", "insight"}, }, }, - Dependencies: []string{ - "kmodules.xyz/resource-metadata/apis/ui/v1alpha1.ItemFilter"}, } } diff --git a/apis/ui/v1alpha1/resourceoutlinefilter_helpers.go b/apis/ui/v1alpha1/resourceoutlinefilter_helpers.go new file mode 100644 index 000000000..c77419fe9 --- /dev/null +++ b/apis/ui/v1alpha1/resourceoutlinefilter_helpers.go @@ -0,0 +1,53 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +func (a ResourceOutlineFilterSpec) GetPage(name string) ResourcePageOutlineFilter { + for _, page := range a.Pages { + if page.Name == name { + return page + } + } + return ResourcePageOutlineFilter{ + Name: name, + Sections: nil, + } +} + +func (a ResourceOutlineFilterSpec) GetAction(name string) ActionTemplateGroupFilter { + for _, action := range a.Actions { + if action.Name == name { + return action + } + } + return ActionTemplateGroupFilter{ + Name: name, + Items: nil, + } +} + +func (a ResourcePageOutlineFilter) GetSection(name string) SectionOutlineFilter { + for _, section := range a.Sections { + if section.Name == name { + return section + } + } + return SectionOutlineFilter{ + Name: name, + Blocks: nil, + } +} diff --git a/apis/ui/v1alpha1/resourceoutlinefilter_types.go b/apis/ui/v1alpha1/resourceoutlinefilter_types.go index abac97bb3..29066ae58 100644 --- a/apis/ui/v1alpha1/resourceoutlinefilter_types.go +++ b/apis/ui/v1alpha1/resourceoutlinefilter_types.go @@ -57,20 +57,15 @@ type ResourcePageOutlineFilter struct { } type ActionTemplateGroupFilter struct { - Name string `json:"name,omitempty"` - Items []ItemFilter `json:"items"` + Name string `json:"name,omitempty"` + Items map[string]bool `json:"items"` } type SectionOutlineFilter struct { - Name string `json:"name,omitempty"` - Info bool `json:"info"` - Insight bool `json:"insight"` - Blocks []ItemFilter `json:"blocks,omitempty"` -} - -type ItemFilter struct { - Name string `json:"name,omitempty"` - Show bool `json:"show"` + Name string `json:"name,omitempty"` + Info bool `json:"info"` + Insight bool `json:"insight"` + Blocks map[string]bool `json:"blocks,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/apis/ui/v1alpha1/zz_generated.deepcopy.go b/apis/ui/v1alpha1/zz_generated.deepcopy.go index 1d88eeaa6..027cf9a4f 100644 --- a/apis/ui/v1alpha1/zz_generated.deepcopy.go +++ b/apis/ui/v1alpha1/zz_generated.deepcopy.go @@ -87,8 +87,10 @@ func (in *ActionTemplateGroupFilter) DeepCopyInto(out *ActionTemplateGroupFilter *out = *in if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]ItemFilter, len(*in)) - copy(*out, *in) + *out = make(map[string]bool, len(*in)) + for key, val := range *in { + (*out)[key] = val + } } return } @@ -590,22 +592,6 @@ func (in Features) DeepCopy() Features { return *out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ItemFilter) DeepCopyInto(out *ItemFilter) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ItemFilter. -func (in *ItemFilter) DeepCopy() *ItemFilter { - if in == nil { - return nil - } - out := new(ItemFilter) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PanelLinkRequest) DeepCopyInto(out *PanelLinkRequest) { *out = *in @@ -973,8 +959,10 @@ func (in *SectionOutlineFilter) DeepCopyInto(out *SectionOutlineFilter) { *out = *in if in.Blocks != nil { in, out := &in.Blocks, &out.Blocks - *out = make([]ItemFilter, len(*in)) - copy(*out, *in) + *out = make(map[string]bool, len(*in)) + for key, val := range *in { + (*out)[key] = val + } } return } diff --git a/crds/meta.k8s.appscode.com_resourceoutlinefilters.yaml b/crds/meta.k8s.appscode.com_resourceoutlinefilters.yaml index 64e6db546..403cbb0cf 100644 --- a/crds/meta.k8s.appscode.com_resourceoutlinefilters.yaml +++ b/crds/meta.k8s.appscode.com_resourceoutlinefilters.yaml @@ -36,16 +36,9 @@ spec: items: properties: items: - items: - properties: - name: - type: string - show: - type: boolean - required: - - show - type: object - type: array + additionalProperties: + type: boolean + type: object name: type: string required: @@ -63,16 +56,9 @@ spec: items: properties: blocks: - items: - properties: - name: - type: string - show: - type: boolean - required: - - show - type: object - type: array + additionalProperties: + type: boolean + type: object info: type: boolean insight: diff --git a/crds/ui.k8s.appscode.com_resourceoutlinefilters.yaml b/crds/ui.k8s.appscode.com_resourceoutlinefilters.yaml index b95df6018..708758f75 100644 --- a/crds/ui.k8s.appscode.com_resourceoutlinefilters.yaml +++ b/crds/ui.k8s.appscode.com_resourceoutlinefilters.yaml @@ -36,16 +36,9 @@ spec: items: properties: items: - items: - properties: - name: - type: string - show: - type: boolean - required: - - show - type: object - type: array + additionalProperties: + type: boolean + type: object name: type: string required: @@ -63,16 +56,9 @@ spec: items: properties: blocks: - items: - properties: - name: - type: string - show: - type: boolean - required: - - show - type: object - type: array + additionalProperties: + type: boolean + type: object info: type: boolean insight: diff --git a/pkg/layouts/filter.go b/pkg/layouts/filter.go index f639d60ba..c05fa4a30 100644 --- a/pkg/layouts/filter.go +++ b/pkg/layouts/filter.go @@ -49,14 +49,10 @@ func GetDefaultResourceOutlineFilter(kc client.Client, outline *rsapi.ResourceOu for _, ag := range ed.Spec.UI.Actions { ag2 := uiapi.ActionTemplateGroupFilter{ Name: ag.Name, - Items: make([]uiapi.ItemFilter, 0, len(ag.Items)), + Items: make(map[string]bool, len(ag.Items)), } for _, a := range ag.Items { - a2 := uiapi.ItemFilter{ - Name: a.Name, - Show: true, - } - ag2.Items = append(ag2.Items, a2) + ag2.Items[a.Name] = true } result.Spec.Actions = append(result.Spec.Actions, ag2) } @@ -109,13 +105,11 @@ func GetDefaultResourceOutlineFilter(kc client.Client, outline *rsapi.ResourceOu Insight: sectionOutline.Insight != nil, } - var tables []uiapi.ItemFilter + tables := map[string]bool{} for _, block := range sectionOutline.Blocks { - blocks, err := FlattenPageBlockOutlineFilter(kc, src, block, rsapi.List) - if err != nil { + if err := FlattenPageBlockOutlineFilter(kc, src, block, rsapi.List, tables); err != nil { return nil, err } - tables = append(tables, blocks...) } section.Blocks = tables @@ -132,34 +126,28 @@ func FlattenPageBlockOutlineFilter( src kmapi.ResourceID, in rsapi.PageBlockOutline, priority rsapi.Priority, -) ([]uiapi.ItemFilter, error) { + out map[string]bool, +) error { if in.Kind == rsapi.TableKindSubTable || in.Kind == rsapi.TableKindConnection || in.Kind == rsapi.TableKindCustom || in.Kind == rsapi.TableKindSelf { - return []uiapi.ItemFilter{ - { - Name: in.Name, - Show: true, - }, - }, nil + out[in.Name] = true + return nil } else if in.Kind != rsapi.TableKindBlock { - return nil, fmt.Errorf("unknown block kind %+v", in) + return fmt.Errorf("unknown block kind %+v", in) } obj, err := blockdefs.LoadByName(in.Name) if err != nil { - return nil, err + return err } - var result []uiapi.ItemFilter for _, block := range obj.Spec.Blocks { - out, err := FlattenPageBlockOutlineFilter(kc, src, block, priority) - if err != nil { - return nil, err + if err := FlattenPageBlockOutlineFilter(kc, src, block, priority, out); err != nil { + return err } - result = append(result, out...) } - return result, nil + return nil } func GetResourceOutlineFilter(kc client.Client, outline *rsapi.ResourceOutline) (*uiapi.ResourceOutlineFilter, error) { diff --git a/pkg/layouts/lib.go b/pkg/layouts/lib.go index 645b0995e..b06116db3 100644 --- a/pkg/layouts/lib.go +++ b/pkg/layouts/lib.go @@ -162,6 +162,11 @@ func LoadResourceLayout(kc client.Client, name string) (*rsapi.ResourceLayout, e } func GetResourceLayout(kc client.Client, outline *rsapi.ResourceOutline) (*rsapi.ResourceLayout, error) { + filter, err := GetResourceOutlineFilter(kc, outline) + if err != nil { + return nil, err + } + src := outline.Spec.Resource var result rsapi.ResourceLayout @@ -195,29 +200,32 @@ func GetResourceLayout(kc client.Client, outline *rsapi.ResourceOutline) (*rsapi { result.Spec.UI.Actions = make([]*shared.ActionTemplateGroup, 0, len(ed.Spec.UI.Actions)) for _, ag := range ed.Spec.UI.Actions { + agFilter := filter.Spec.GetAction(ag.Name) ag2 := shared.ActionTemplateGroup{ ActionInfo: ag.ActionInfo, Items: make([]shared.ActionTemplate, 0, len(ag.Items)), } for _, a := range ag.Items { - a2 := shared.ActionTemplate{ - ActionInfo: a.ActionInfo, - Icons: a.Icons, - OperationID: a.OperationID, - Flow: a.Flow, - DisabledTemplate: a.DisabledTemplate, - EnforceQuota: a.EnforceQuota, + if agFilter.Items[a.Name] { + a2 := shared.ActionTemplate{ + ActionInfo: a.ActionInfo, + Icons: a.Icons, + OperationID: a.OperationID, + Flow: a.Flow, + DisabledTemplate: a.DisabledTemplate, + EnforceQuota: a.EnforceQuota, + } + a2.Editor = expand(a.Editor) + + ag2.Items = append(ag2.Items, a2) } - a2.Editor = expand(a.Editor) - - ag2.Items = append(ag2.Items, a2) } result.Spec.UI.Actions = append(result.Spec.UI.Actions, &ag2) } } } } - if outline.Spec.Header != nil { + if outline.Spec.Header != nil && filter.Spec.Header { tables, err := FlattenPageBlockOutline(kc, src, *outline.Spec.Header, rsapi.Field) if err != nil { return nil, err @@ -227,7 +235,7 @@ func GetResourceLayout(kc client.Client, outline *rsapi.ResourceOutline) (*rsapi } result.Spec.Header = &tables[0] } - if outline.Spec.TabBar != nil { + if outline.Spec.TabBar != nil && filter.Spec.TabBar { tables, err := FlattenPageBlockOutline(kc, src, *outline.Spec.TabBar, rsapi.Field) if err != nil { return nil, err @@ -271,12 +279,14 @@ func GetResourceLayout(kc client.Client, outline *rsapi.ResourceOutline) (*rsapi } for _, pageOutline := range pages { + pageFilter := filter.Spec.GetPage(pageOutline.Name) page := rsapi.ResourcePageLayout{ Name: pageOutline.Name, RequiredFeatureSets: pageOutline.RequiredFeatureSets, Sections: make([]rsapi.SectionLayout, 0, len(pageOutline.Sections)), } for _, sectionOutline := range pageOutline.Sections { + sectionFilter := pageFilter.GetSection(sectionOutline.Name) section := rsapi.SectionLayout{ Name: sectionOutline.Name, @@ -285,7 +295,7 @@ func GetResourceLayout(kc client.Client, outline *rsapi.ResourceOutline) (*rsapi Insight: nil, RequiredFeatureSets: sectionOutline.RequiredFeatureSets, } - if sectionOutline.Info != nil { + if sectionOutline.Info != nil && sectionFilter.Info { tables, err := FlattenPageBlockOutline(kc, src, *sectionOutline.Info, rsapi.Field) if err != nil { return nil, err @@ -295,7 +305,7 @@ func GetResourceLayout(kc client.Client, outline *rsapi.ResourceOutline) (*rsapi } section.Info = &tables[0] } - if sectionOutline.Insight != nil { + if sectionOutline.Insight != nil && sectionFilter.Insight { tables, err := FlattenPageBlockOutline(kc, src, *sectionOutline.Insight, rsapi.Field) if err != nil { return nil, err @@ -314,7 +324,15 @@ func GetResourceLayout(kc client.Client, outline *rsapi.ResourceOutline) (*rsapi } tables = append(tables, blocks...) } - section.Blocks = tables + + // https://go.dev/wiki/SliceTricks#filtering-without-allocating + b := tables[:0] + for _, x := range tables { + if sectionFilter.Blocks[x.Name] { + b = append(b, x) + } + } + section.Blocks = b page.Sections = append(page.Sections, section) }