From 1b99c6dc76c9a57c50699ae9293f72e6b22264e0 Mon Sep 17 00:00:00 2001 From: Basel Issmail <78056580+issmail-basel@users.noreply.github.com> Date: Fri, 17 Dec 2021 07:45:44 +0200 Subject: [PATCH] fix: return property with clusters data (#89) Co-authored-by: maherhamoui6 Co-authored-by: yk Co-authored-by: basel.issmail Co-authored-by: rot1024 --- go.mod | 44 +++++----- internal/adapter/gql/generated.go | 87 ++++++++++++++----- .../adapter/gql/gqlmodel/convert_scene.go | 6 +- internal/adapter/gql/gqlmodel/models_gen.go | 12 +-- .../adapter/gql/resolver_mutation_scene.go | 2 +- internal/adapter/gql/resolver_scene.go | 13 +++ internal/usecase/interactor/scene.go | 15 +++- internal/usecase/interfaces/scene.go | 2 +- pkg/builtin/manifest.yml | 56 ++++-------- pkg/builtin/manifest_ja.yml | 37 +++----- pkg/plugin/manifest/parser_translation.go | 21 +++++ pkg/scene/builder/encoder.go | 14 +++ pkg/scene/builder/scene.go | 23 +++-- pkg/scene/cluster_list.go | 11 +++ pkg/scene/scene.go | 1 + schema.graphql | 4 +- 16 files changed, 221 insertions(+), 127 deletions(-) diff --git a/go.mod b/go.mod index f514f562..11be3950 100644 --- a/go.mod +++ b/go.mod @@ -5,18 +5,10 @@ require ( cloud.google.com/go/storage v1.18.2 github.com/99designs/gqlgen v0.14.0 github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.0.0 - github.com/HdrHistogram/hdrhistogram-go v1.0.1 // indirect - github.com/agnivade/levenshtein v1.1.1 // indirect - github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a // indirect github.com/auth0/go-jwt-middleware v1.0.1 github.com/blang/semver v3.5.1+incompatible - github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect - github.com/dgryski/trifles v0.0.0-20200705224438-cafc02a1ee2b // indirect - github.com/fatih/color v1.12.0 // indirect github.com/form3tech-oss/jwt-go v3.2.2+incompatible - github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 // indirect github.com/goccy/go-yaml v1.9.4 - github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/iancoleman/strcase v0.2.0 github.com/idubinskiy/schematyper v0.0.0-20190118213059-f71b40dac30d github.com/jarcoal/httpmock v1.0.8 @@ -24,26 +16,19 @@ require ( github.com/jonas-p/go-shp v0.1.1 github.com/kelseyhightower/envconfig v1.4.0 github.com/kennygrant/sanitize v1.2.4 - github.com/klauspost/compress v1.13.6 // indirect github.com/labstack/echo/v4 v4.6.1 github.com/labstack/gommon v0.3.1 - github.com/mattn/go-isatty v0.0.14 // indirect github.com/mitchellh/mapstructure v1.4.2 github.com/oklog/ulid v1.3.1 - github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/paulmach/go.geojson v1.4.0 github.com/pkg/errors v0.9.1 github.com/ravilushqa/otelgqlgen v0.2.0 github.com/sirupsen/logrus v1.8.1 - github.com/smartystreets/assertions v1.1.1 // indirect github.com/spf13/afero v1.6.0 - github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/testify v1.7.0 - github.com/tidwall/pretty v1.0.1 // indirect github.com/twpayne/go-kml v1.5.2 github.com/uber/jaeger-client-go v2.29.1+incompatible github.com/uber/jaeger-lib v2.4.1+incompatible - github.com/urfave/cli/v2 v2.3.0 // indirect github.com/vektah/dataloaden v0.3.0 github.com/vektah/gqlparser/v2 v2.2.0 go.mongodb.org/mongo-driver v1.7.4 @@ -51,31 +36,31 @@ require ( go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.27.0 go.opentelemetry.io/otel v1.2.0 go.opentelemetry.io/otel/sdk v1.2.0 - go.uber.org/atomic v1.7.0 // indirect - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect - golang.org/x/mod v0.5.1 // indirect - golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect golang.org/x/text v0.3.7 - golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect golang.org/x/tools v0.1.7 google.golang.org/api v0.60.0 gopkg.in/go-playground/colors.v1 v1.2.0 gopkg.in/h2non/gock.v1 v1.1.2 - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) require ( cloud.google.com/go v0.97.0 // indirect cloud.google.com/go/trace v1.0.0 // indirect + github.com/HdrHistogram/hdrhistogram-go v1.0.1 // indirect + github.com/agnivade/levenshtein v1.1.1 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect + github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a // indirect github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/trifles v0.0.0-20200705224438-cafc02a1ee2b // indirect github.com/envoyproxy/go-control-plane v0.10.0 // indirect github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect + github.com/fatih/color v1.12.0 // indirect + github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 // indirect github.com/go-stack/stack v1.8.0 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -86,10 +71,18 @@ require ( github.com/googleapis/gax-go/v2 v2.1.1 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/klauspost/compress v1.13.6 // indirect github.com/mattn/go-colorable v0.1.11 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/smartystreets/assertions v1.1.1 // indirect + github.com/stretchr/objx v0.2.0 // indirect + github.com/tidwall/pretty v1.0.1 // indirect + github.com/urfave/cli/v2 v2.3.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.1 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect @@ -99,9 +92,14 @@ require ( go.opencensus.io v0.23.0 // indirect go.opentelemetry.io/contrib v0.23.0 // indirect go.opentelemetry.io/otel/trace v1.2.0 // indirect + go.uber.org/atomic v1.7.0 // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/mod v0.5.1 // indirect golang.org/x/net v0.0.0-20211101193420-4a448f8816b3 // indirect golang.org/x/oauth2 v0.0.0-20211028175245-ba495a64dcb5 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect + golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20211101144312-62acf1d99145 // indirect @@ -109,6 +107,8 @@ require ( google.golang.org/protobuf v1.27.1 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) go 1.17 diff --git a/internal/adapter/gql/generated.go b/internal/adapter/gql/generated.go index 1972bd81..f7e13ce8 100644 --- a/internal/adapter/gql/generated.go +++ b/internal/adapter/gql/generated.go @@ -42,6 +42,7 @@ type Config struct { type ResolverRoot interface { Asset() AssetResolver + Cluster() ClusterResolver Dataset() DatasetResolver DatasetField() DatasetFieldResolver DatasetSchema() DatasetSchemaResolver @@ -172,9 +173,10 @@ type ComplexityRoot struct { } Cluster struct { - ID func(childComplexity int) int - Name func(childComplexity int) int - Property func(childComplexity int) int + ID func(childComplexity int) int + Name func(childComplexity int) int + Property func(childComplexity int) int + PropertyID func(childComplexity int) int } CreateAssetPayload struct { @@ -1068,6 +1070,9 @@ type ComplexityRoot struct { type AssetResolver interface { Team(ctx context.Context, obj *gqlmodel.Asset) (*gqlmodel.Team, error) } +type ClusterResolver interface { + Property(ctx context.Context, obj *gqlmodel.Cluster) (*gqlmodel.Property, error) +} type DatasetResolver interface { Schema(ctx context.Context, obj *gqlmodel.Dataset) (*gqlmodel.DatasetSchema, error) Name(ctx context.Context, obj *gqlmodel.Dataset) (*string, error) @@ -1667,6 +1672,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Cluster.Property(childComplexity), true + case "Cluster.propertyId": + if e.complexity.Cluster.PropertyID == nil { + break + } + + return e.complexity.Cluster.PropertyID(childComplexity), true + case "CreateAssetPayload.asset": if e.complexity.CreateAssetPayload.Asset == nil { break @@ -7080,7 +7092,8 @@ type TagGroup implements Tag { type Cluster { id: ID! name: String! - property: ID! + propertyId: ID! + property: Property @goField(forceResolver: true) } # InputType @@ -7485,7 +7498,6 @@ input RemoveTagInput { input AddClusterInput { sceneId: ID! name: String! - propertyId: ID! } input UpdateClusterInput { @@ -11158,7 +11170,7 @@ func (ec *executionContext) _Cluster_name(ctx context.Context, field graphql.Col return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Cluster_property(ctx context.Context, field graphql.CollectedField, obj *gqlmodel.Cluster) (ret graphql.Marshaler) { +func (ec *executionContext) _Cluster_propertyId(ctx context.Context, field graphql.CollectedField, obj *gqlmodel.Cluster) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -11176,7 +11188,7 @@ func (ec *executionContext) _Cluster_property(ctx context.Context, field graphql ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Property, nil + return obj.PropertyID, nil }) if err != nil { ec.Error(ctx, err) @@ -11193,6 +11205,38 @@ func (ec *executionContext) _Cluster_property(ctx context.Context, field graphql return ec.marshalNID2githubᚗcomᚋreearthᚋreearthᚑbackendᚋpkgᚋidᚐID(ctx, field.Selections, res) } +func (ec *executionContext) _Cluster_property(ctx context.Context, field graphql.CollectedField, obj *gqlmodel.Cluster) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Cluster", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Cluster().Property(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*gqlmodel.Property) + fc.Result = res + return ec.marshalOProperty2ᚖgithubᚗcomᚋreearthᚋreearthᚑbackendᚋinternalᚋadapterᚋgqlᚋgqlmodelᚐProperty(ctx, field.Selections, res) +} + func (ec *executionContext) _CreateAssetPayload_asset(ctx context.Context, field graphql.CollectedField, obj *gqlmodel.CreateAssetPayload) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -32477,14 +32521,6 @@ func (ec *executionContext) unmarshalInputAddClusterInput(ctx context.Context, o if err != nil { return it, err } - case "propertyId": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("propertyId")) - it.PropertyID, err = ec.unmarshalNID2githubᚗcomᚋreearthᚋreearthᚑbackendᚋpkgᚋidᚐID(ctx, v) - if err != nil { - return it, err - } } } @@ -35879,18 +35915,29 @@ func (ec *executionContext) _Cluster(ctx context.Context, sel ast.SelectionSet, case "id": out.Values[i] = ec._Cluster_id(ctx, field, obj) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } case "name": out.Values[i] = ec._Cluster_name(ctx, field, obj) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } - case "property": - out.Values[i] = ec._Cluster_property(ctx, field, obj) + case "propertyId": + out.Values[i] = ec._Cluster_propertyId(ctx, field, obj) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } + case "property": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Cluster_property(ctx, field, obj) + return res + }) default: panic("unknown field " + strconv.Quote(field.Name)) } diff --git a/internal/adapter/gql/gqlmodel/convert_scene.go b/internal/adapter/gql/gqlmodel/convert_scene.go index 5fae166a..57855c0f 100644 --- a/internal/adapter/gql/gqlmodel/convert_scene.go +++ b/internal/adapter/gql/gqlmodel/convert_scene.go @@ -32,9 +32,9 @@ func ToScenePlugin(sp *scene.Plugin) *ScenePlugin { func ToCluster(c *scene.Cluster) *Cluster { return &Cluster{ - ID: c.ID().ID(), - Name: c.Name(), - Property: c.Property().ID(), + ID: c.ID().ID(), + Name: c.Name(), + PropertyID: c.Property().ID(), } } diff --git a/internal/adapter/gql/gqlmodel/models_gen.go b/internal/adapter/gql/gqlmodel/models_gen.go index 47e64697..34314fdd 100644 --- a/internal/adapter/gql/gqlmodel/models_gen.go +++ b/internal/adapter/gql/gqlmodel/models_gen.go @@ -36,9 +36,8 @@ type Tag interface { } type AddClusterInput struct { - SceneID id.ID `json:"sceneId"` - Name string `json:"name"` - PropertyID id.ID `json:"propertyId"` + SceneID id.ID `json:"sceneId"` + Name string `json:"name"` } type AddClusterPayload struct { @@ -205,9 +204,10 @@ type Camera struct { } type Cluster struct { - ID id.ID `json:"id"` - Name string `json:"name"` - Property id.ID `json:"property"` + ID id.ID `json:"id"` + Name string `json:"name"` + PropertyID id.ID `json:"propertyId"` + Property *Property `json:"property"` } type CreateAssetInput struct { diff --git a/internal/adapter/gql/resolver_mutation_scene.go b/internal/adapter/gql/resolver_mutation_scene.go index 306fcb2b..df92cefb 100644 --- a/internal/adapter/gql/resolver_mutation_scene.go +++ b/internal/adapter/gql/resolver_mutation_scene.go @@ -199,7 +199,7 @@ func (r *mutationResolver) UpgradePlugin(ctx context.Context, input gqlmodel.Upg func (r *mutationResolver) AddCluster(ctx context.Context, input gqlmodel.AddClusterInput) (*gqlmodel.AddClusterPayload, error) { exit := trace(ctx) defer exit() - s, c, err := r.usecases.Scene.AddCluster(ctx, id.SceneID(input.SceneID), input.Name, id.PropertyID(input.PropertyID), getOperator(ctx)) + s, c, err := r.usecases.Scene.AddCluster(ctx, id.SceneID(input.SceneID), input.Name, getOperator(ctx)) if err != nil { return nil, err } diff --git a/internal/adapter/gql/resolver_scene.go b/internal/adapter/gql/resolver_scene.go index 01b53e2e..fa9dd710 100644 --- a/internal/adapter/gql/resolver_scene.go +++ b/internal/adapter/gql/resolver_scene.go @@ -20,6 +20,10 @@ func (r *Resolver) SceneWidget() SceneWidgetResolver { return &sceneWidgetResolver{r} } +func (r *Resolver) Cluster() ClusterResolver { + return &clusterResolver{r} +} + type sceneResolver struct{ *Resolver } func (r *sceneResolver) Project(ctx context.Context, obj *gqlmodel.Scene) (*gqlmodel.Project, error) { @@ -144,3 +148,12 @@ func (r *sceneWidgetResolver) Property(ctx context.Context, obj *gqlmodel.SceneW return DataLoadersFromContext(ctx).Property.Load(id.PropertyID(obj.PropertyID)) } + +type clusterResolver struct{ *Resolver } + +func (r *clusterResolver) Property(ctx context.Context, obj *gqlmodel.Cluster) (*gqlmodel.Property, error) { + exit := trace(ctx) + defer exit() + + return DataLoadersFromContext(ctx).Property.Load(id.PropertyID(obj.PropertyID)) +} diff --git a/internal/usecase/interactor/scene.go b/internal/usecase/interactor/scene.go index aefeff75..56b6e7db 100644 --- a/internal/usecase/interactor/scene.go +++ b/internal/usecase/interactor/scene.go @@ -685,7 +685,7 @@ func (i *Scene) getPlugin(ctx context.Context, sid id.SceneID, p id.PluginID, e return plugin, extension, nil } -func (i *Scene) AddCluster(ctx context.Context, sceneID id.SceneID, name string, propertyID id.PropertyID, operator *usecase.Operator) (*scene.Scene, *scene.Cluster, error) { +func (i *Scene) AddCluster(ctx context.Context, sceneID id.SceneID, name string, operator *usecase.Operator) (*scene.Scene, *scene.Cluster, error) { tx, err := i.transaction.Begin() if err != nil { return nil, nil, err @@ -709,12 +709,23 @@ func (i *Scene) AddCluster(ctx context.Context, sceneID id.SceneID, name string, return nil, nil, err } + prop, err := property.New().NewID().Schema(id.MustPropertySchemaID("reearth/cluster")).Scene(sceneID).Build() + if err != nil { + return nil, nil, err + } + cid := id.NewClusterID() - cluster, err := scene.NewCluster(cid, name, propertyID) + cluster, err := scene.NewCluster(cid, name, prop.ID()) if err != nil { return nil, nil, err } s.Clusters().Add(cluster) + + err = i.propertyRepo.Save(ctx, prop) + if err != nil { + return nil, nil, err + } + err = i.sceneRepo.Save(ctx, s) if err != nil { return nil, nil, err diff --git a/internal/usecase/interfaces/scene.go b/internal/usecase/interfaces/scene.go index dae97817..9f9b2e31 100644 --- a/internal/usecase/interfaces/scene.go +++ b/internal/usecase/interfaces/scene.go @@ -27,7 +27,7 @@ type Scene interface { InstallPlugin(context.Context, id.SceneID, id.PluginID, *usecase.Operator) (*scene.Scene, id.PluginID, *id.PropertyID, error) UninstallPlugin(context.Context, id.SceneID, id.PluginID, *usecase.Operator) (*scene.Scene, error) UpgradePlugin(context.Context, id.SceneID, id.PluginID, id.PluginID, *usecase.Operator) (*scene.Scene, error) - AddCluster(context.Context, id.SceneID, string, id.PropertyID, *usecase.Operator) (*scene.Scene, *scene.Cluster, error) + AddCluster(context.Context, id.SceneID, string, *usecase.Operator) (*scene.Scene, *scene.Cluster, error) UpdateCluster(context.Context, UpdateClusterParam, *usecase.Operator) (*scene.Scene, *scene.Cluster, error) RemoveCluster(context.Context, id.SceneID, id.ClusterID, *usecase.Operator) (*scene.Scene, error) } diff --git a/pkg/builtin/manifest.yml b/pkg/builtin/manifest.yml index 2a0e238a..6a7c768d 100644 --- a/pkg/builtin/manifest.yml +++ b/pkg/builtin/manifest.yml @@ -94,7 +94,7 @@ extensions: description: Display the limiter boundaries. - id: cameraLimitterTargetArea type: camera - title: Target max height + title: Target max height description: The base position of the camera movement range. This position is the center point of the limit box in the horizontal and depth directions, and is the maximum height of the movable range. The camera will not be able to zoom out beyond the height specified here. - id: cameraLimitterTargetWidth type: number @@ -1651,11 +1651,7 @@ extensions: - id: default title: Cluster fields: - - id: cluster_name - type: string - title: Name - description: Sets the name of the cluster. - - id: cluster_pixelRange + - id: clusterPixelRange type: number description: Sets the minimum range between layers to get clustered together. title: Pixel range @@ -1663,49 +1659,31 @@ extensions: min: 1 max: 200 suffix: px - - id: cluster_minSize + - id: clusterMinSize type: number title: Minimum cluster size description: The minimum number of layers that can be clustered. defaultValue: 3 min: 2 max: 20 - - id: cluster_maxSize - title: Max cluster size - description: Sets the size of cluster entity. - defaultValue: 48 - type: number - min: 1 - max: 200 - - id: cluster_shapeType - type: string - title: Shape type - defaultValue: pin - description: Sets the shape of cluster entity. - choices: - - key: pin - label: Pin - - key: label - label: Label - - id: cluster_textColor - type: string - title: Text color - description: Sets the text color of cluster entity. - ui: color - availableIf: - field: cluster_shapeType - type: string - value: label - - id: cluster_backgroundColor - type: string - ui: color - title: Background color - description: Sets the background color of cluster entity. - - id: cluster_image + - id: clusterImage type: url title: Image description: Sets the image of cluster entity. ui: image + - id: clusterImageWidth + type: number + title: Width + suffix: px + description: Sets the image width. + - id: clusterImageHeight + type: number + title: Height + suffix: px + description: Sets the image height. + - id: clusterLabelTypography + type: typography + title: Font - id: layers title: Layers representativeField: layer diff --git a/pkg/builtin/manifest_ja.yml b/pkg/builtin/manifest_ja.yml index b2a606a3..a6baa0e1 100644 --- a/pkg/builtin/manifest_ja.yml +++ b/pkg/builtin/manifest_ja.yml @@ -782,32 +782,23 @@ extensions: description: レイヤーを自動的にまとめて表示することが可能なクラスタを設定します。 propertySchema: default: - title: デフォルト + title: クラスタ fields: - cluster_name: - title: クラスタ名 - description: クラスタの名前を指定します。 - cluster_pixelRange: + clusterPixelRange: title: 最小範囲 description: 画面上の何ピクセル分の範囲にあるレイヤーをクラスタにまとめるかを最小値で指定します。 - cluster_minSize: + clusterMinSize: title: 最小サイズ - description: クラスタが表示される最小のレイヤー数 - cluster_maxSize: - title: 最大サイズ - description: クラスタに属することが可能な最大レイヤー数 - cluster_shapeType: - title: 表示方法 - description: 画面上で表示されるクラスタの表示方法を指定します。 - choices: - pin: ピン - label: ラベル - cluster_textColor: - title: 文字色 - description: 画面上で表示されるクラスタの文字色を指定します。 - cluster_backgroundColor: - title: 背景色 - description: 画面上で表示されるクラスタの背景色を指定します。 - cluster_image: + description: クラスタが表示されるのに必要な最小のレイヤー数 + clusterImage: title: 画像 description: 画面上で表示されるクラスタの画像を指定します。 + clusterImageWidth: + title: 画像幅 + description: 画像の幅をピクセルで指定します。 + clusterImageHeight: + title: 画像高さ + description: 画像の高さをピクセルで指定します。 + clusterLabelTypography: + title: ラベル + description: ラベルのスタイルを指定します。 diff --git a/pkg/plugin/manifest/parser_translation.go b/pkg/plugin/manifest/parser_translation.go index 54dd00fa..1d35185b 100644 --- a/pkg/plugin/manifest/parser_translation.go +++ b/pkg/plugin/manifest/parser_translation.go @@ -52,12 +52,18 @@ func MergeManifestTranslation(m *Manifest, tl map[string]*TranslationRoot) *Mani if t.Name != nil { name := m.Plugin.Name() + if name == nil { + name = map[string]string{} + } name[lang] = *t.Name m.Plugin.Rename(name) } if t.Description != nil { des := m.Plugin.Description() + if des == nil { + des = map[string]string{} + } des[lang] = *t.Description m.Plugin.SetDescription(des) } @@ -70,12 +76,18 @@ func MergeManifestTranslation(m *Manifest, tl map[string]*TranslationRoot) *Mani if te.Name != nil { name := ext.Name() + if name == nil { + name = map[string]string{} + } name[lang] = *te.Name ext.Rename(name) } if te.Description != nil { des := ext.Description() + if des == nil { + des = map[string]string{} + } des[lang] = *te.Description ext.SetDescription(des) } @@ -99,6 +111,9 @@ func MergeManifestTranslation(m *Manifest, tl map[string]*TranslationRoot) *Mani if tsg.Title != nil { t := psg.Title() + if t == nil { + t = map[string]string{} + } t[lang] = *tsg.Title psg.SetTitle(t) } @@ -118,12 +133,18 @@ func MergeManifestTranslation(m *Manifest, tl map[string]*TranslationRoot) *Mani if tsf.Title != nil { t := psf.Title() + if t == nil { + t = map[string]string{} + } t[lang] = *tsf.Title psf.SetTitle(t) } if tsf.Description != nil { t := psf.Description() + if t == nil { + t = map[string]string{} + } t[lang] = *tsf.Description psf.SetDescription(t) } diff --git a/pkg/scene/builder/encoder.go b/pkg/scene/builder/encoder.go index bf313437..eb5f2cac 100644 --- a/pkg/scene/builder/encoder.go +++ b/pkg/scene/builder/encoder.go @@ -132,3 +132,17 @@ type widgetAreaJSON struct { WidgetIDs []string `json:"widgetIds"` Align string `json:"align"` } + +type widgetJSON struct { + ID string `json:"id"` + PluginID string `json:"pluginId"` + ExtensionID string `json:"extensionId"` + Property propertyJSON `json:"property"` + Extended bool `json:"extended"` +} + +type clusterJSON struct { + ID string `json:"id"` + Name string `json:"name"` + Property propertyJSON `json:"property"` +} diff --git a/pkg/scene/builder/scene.go b/pkg/scene/builder/scene.go index 5060f5d9..973598bb 100644 --- a/pkg/scene/builder/scene.go +++ b/pkg/scene/builder/scene.go @@ -18,14 +18,7 @@ type sceneJSON struct { Layers []*layerJSON `json:"layers"` Widgets []*widgetJSON `json:"widgets"` WidgetAlignSystem *widgetAlignSystemJSON `json:"widgetAlignSystem"` -} - -type widgetJSON struct { - ID string `json:"id"` - PluginID string `json:"pluginId"` - ExtensionID string `json:"extensionId"` - Property propertyJSON `json:"property"` - Extended bool `json:"extended"` + Clusters []*clusterJSON `json:"clusters"` } func (b *Builder) scene(ctx context.Context, s *scene.Scene, publishedAt time.Time, l []*layerJSON, p []*property.Property) *sceneJSON { @@ -36,6 +29,7 @@ func (b *Builder) scene(ctx context.Context, s *scene.Scene, publishedAt time.Ti Property: b.property(ctx, findProperty(p, s.Property())), Plugins: b.plugins(ctx, s, p), Widgets: b.widgets(ctx, s, p), + Clusters: b.clusters(ctx, s, p), Layers: l, WidgetAlignSystem: buildWidgetAlignSystem(s.WidgetAlignSystem()), } @@ -74,6 +68,19 @@ func (b *Builder) widgets(ctx context.Context, s *scene.Scene, p []*property.Pro return res } +func (b *Builder) clusters(ctx context.Context, s *scene.Scene, p []*property.Property) []*clusterJSON { + sceneClusters := s.Clusters().Clusters() + res := make([]*clusterJSON, 0, len(sceneClusters)) + for _, c := range sceneClusters { + res = append(res, &clusterJSON{ + ID: c.ID().String(), + Name: c.Name(), + Property: b.property(ctx, findProperty(p, c.Property())), + }) + } + return res +} + func (b *Builder) property(ctx context.Context, p *property.Property) propertyJSON { return property.SealProperty(ctx, p).Interface() } diff --git a/pkg/scene/cluster_list.go b/pkg/scene/cluster_list.go index 12d88e17..36a86f01 100644 --- a/pkg/scene/cluster_list.go +++ b/pkg/scene/cluster_list.go @@ -65,3 +65,14 @@ func (tl *ClusterList) Remove(clusters ...id.ClusterID) { } } } + +func (tl *ClusterList) Properties() []id.PropertyID { + if tl == nil { + return nil + } + res := make([]id.PropertyID, 0, len(tl.clusters)) + for _, c := range tl.clusters { + res = append(res, c.property) + } + return res +} diff --git a/pkg/scene/scene.go b/pkg/scene/scene.go index 182790d9..70898068 100644 --- a/pkg/scene/scene.go +++ b/pkg/scene/scene.go @@ -118,6 +118,7 @@ func (s *Scene) Properties() []id.PropertyID { ids := []id.PropertyID{s.property} ids = append(ids, s.pluginSystem.Properties()...) ids = append(ids, s.widgetSystem.Properties()...) + ids = append(ids, s.clusters.Properties()...) return ids } diff --git a/schema.graphql b/schema.graphql index bd8c8805..d45c51cb 100644 --- a/schema.graphql +++ b/schema.graphql @@ -831,7 +831,8 @@ type TagGroup implements Tag { type Cluster { id: ID! name: String! - property: ID! + propertyId: ID! + property: Property @goField(forceResolver: true) } # InputType @@ -1236,7 +1237,6 @@ input RemoveTagInput { input AddClusterInput { sceneId: ID! name: String! - propertyId: ID! } input UpdateClusterInput {