From e828520da1be9bad61c0f22aa72ab387f98399dc Mon Sep 17 00:00:00 2001 From: KeisukeYamashita <19yamashita15@gmail.com> Date: Sun, 20 Oct 2024 15:45:04 +0200 Subject: [PATCH 01/14] ci: migrate to Google Cloud workload federation (#1274) ci: migrate to workload federation Signed-off-by: KeisukeYamashita <19yamashita15@gmail.com> --- .github/workflows/cron_ion_token_test.yml | 3 ++- .github/workflows/deploy_test.yml | 12 ++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cron_ion_token_test.yml b/.github/workflows/cron_ion_token_test.yml index 6123204774..380340154a 100644 --- a/.github/workflows/cron_ion_token_test.yml +++ b/.github/workflows/cron_ion_token_test.yml @@ -12,7 +12,8 @@ jobs: steps: - uses: google-github-actions/auth@v2 with: - credentials_json: ${{ secrets.GCP_SA_KEY }} + service_account: ${{ secrets.GCP_SA_EMAIL }} + workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v2 - name: Download reearth config diff --git a/.github/workflows/deploy_test.yml b/.github/workflows/deploy_test.yml index cf3c1126f5..7054c623cb 100644 --- a/.github/workflows/deploy_test.yml +++ b/.github/workflows/deploy_test.yml @@ -55,7 +55,8 @@ jobs: run: tar -xvf reearth-cms-web.tar.gz - uses: google-github-actions/auth@v2 with: - credentials_json: "${{ secrets.GCP_SA_KEY }}" + service_account: ${{ secrets.GCP_SA_EMAIL }} + workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v2 - name: Deploy @@ -70,7 +71,8 @@ jobs: - uses: google-github-actions/auth@v2 with: - credentials_json: ${{ secrets.GCP_SA_KEY }} + service_account: ${{ secrets.GCP_SA_EMAIL }} + workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v2 - name: Configure docker @@ -97,7 +99,8 @@ jobs: - uses: google-github-actions/auth@v2 with: - credentials_json: ${{ secrets.GCP_SA_KEY }} + service_account: ${{ secrets.GCP_SA_EMAIL }} + workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v2 - name: Configure docker @@ -124,7 +127,8 @@ jobs: - uses: google-github-actions/auth@v2 with: - credentials_json: ${{ secrets.GCP_SA_KEY }} + service_account: ${{ secrets.GCP_SA_EMAIL }} + workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v2 - name: Configure docker From f27d5081e742896d3ad731d6e66500d1171869c0 Mon Sep 17 00:00:00 2001 From: KeisukeYamashita <19yamashita15@gmail.com> Date: Sun, 20 Oct 2024 16:58:31 +0200 Subject: [PATCH 02/14] ci: add missing `id-token:write` permission for Google Cloud (#1276) * ci: add missing id-token permission for gc auth Signed-off-by: KeisukeYamashita <19yamashita15@gmail.com> * ci: add missing `actions/checkout` before google cloud auth Signed-off-by: KeisukeYamashita <19yamashita15@gmail.com> --------- Signed-off-by: KeisukeYamashita <19yamashita15@gmail.com> --- .github/workflows/cron_ion_token_test.yml | 7 ++++++- .github/workflows/deploy_test.yml | 20 ++++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cron_ion_token_test.yml b/.github/workflows/cron_ion_token_test.yml index 380340154a..791d19bf59 100644 --- a/.github/workflows/cron_ion_token_test.yml +++ b/.github/workflows/cron_ion_token_test.yml @@ -9,11 +9,16 @@ env: jobs: update_ion_token: runs-on: ubuntu-latest + permissions: + contents: read # To checkout + id-token: write # To authenticate with Google Cloud using OIDC steps: + - uses: actions/checkout@v4 + - uses: google-github-actions/auth@v2 with: service_account: ${{ secrets.GCP_SA_EMAIL }} - workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}} + workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v2 - name: Download reearth config diff --git a/.github/workflows/deploy_test.yml b/.github/workflows/deploy_test.yml index 7054c623cb..d16b6db40f 100644 --- a/.github/workflows/deploy_test.yml +++ b/.github/workflows/deploy_test.yml @@ -34,6 +34,9 @@ jobs: name: Deploy web to test env if: github.event.repository.full_name == 'reearth/reearth-cms' && github.event.workflow_run.name == 'ci-web' && github.event.workflow_run.conclusion != 'failure' && github.event.workflow_run.head_branch == 'main' runs-on: ubuntu-latest + permissions: + contents: read # To checkout + id-token: write # To authenticate with Google Cloud using OIDC steps: - uses: actions/create-github-app-token@v1 id: app-token @@ -56,7 +59,7 @@ jobs: - uses: google-github-actions/auth@v2 with: service_account: ${{ secrets.GCP_SA_EMAIL }} - workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}} + workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v2 - name: Deploy @@ -66,13 +69,16 @@ jobs: name: Deploy server to test env runs-on: ubuntu-latest if: github.event.repository.full_name == 'reearth/reearth-cms' && github.event.workflow_run.name == 'server-build' && github.event.workflow_run.conclusion != 'failure' && github.event.workflow_run.head_branch == 'main' + permissions: + contents: read # To checkout + id-token: write # To authenticate with Google Cloud using OIDC steps: - uses: actions/checkout@v4 - uses: google-github-actions/auth@v2 with: service_account: ${{ secrets.GCP_SA_EMAIL }} - workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}} + workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v2 - name: Configure docker @@ -94,13 +100,16 @@ jobs: name: Deploy web to test env runs-on: ubuntu-latest if: github.event.repository.full_name == 'reearth/reearth-cms' && github.event.workflow_run.name == 'web-build' && github.event.workflow_run.conclusion != 'failure' && github.event.workflow_run.head_branch == 'main' + permissions: + contents: read # To checkout + id-token: write # To authenticate with Google Cloud using OIDC steps: - uses: actions/checkout@v4 - uses: google-github-actions/auth@v2 with: service_account: ${{ secrets.GCP_SA_EMAIL }} - workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}} + workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v2 - name: Configure docker @@ -122,13 +131,16 @@ jobs: name: Deploy worker to test env runs-on: ubuntu-latest if: github.event.repository.full_name == 'reearth/reearth-cms' && github.event.workflow_run.name == 'worker-build' && github.event.workflow_run.conclusion != 'failure' && github.event.workflow_run.head_branch == 'main' + permissions: + contents: read # To checkout + id-token: write # To authenticate with Google Cloud using OIDC steps: - uses: actions/checkout@v4 - uses: google-github-actions/auth@v2 with: service_account: ${{ secrets.GCP_SA_EMAIL }} - workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}} + workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v2 - name: Configure docker From afe6c7a6362729f61ef239ec779c3531a0a3385b Mon Sep 17 00:00:00 2001 From: KeisukeYamashita <19yamashita15@gmail.com> Date: Mon, 21 Oct 2024 16:36:36 +0200 Subject: [PATCH 03/14] ci: update Cesium ION token of `reearth-cms-web` Cloud Run service (#1275) --- .github/workflows/cron_ion_token_test.yml | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/.github/workflows/cron_ion_token_test.yml b/.github/workflows/cron_ion_token_test.yml index 791d19bf59..4504d60ec7 100644 --- a/.github/workflows/cron_ion_token_test.yml +++ b/.github/workflows/cron_ion_token_test.yml @@ -4,8 +4,8 @@ on: - cron: "0 0 2 * *" workflow_dispatch: env: - GCS_DOMAIN: gs://cms.test.reearth.dev - REEARTH_CONFIG_FILENAME: reearth_config.json + CMS_WEB: reearth-cms-web + REGION: us-central1 jobs: update_ion_token: runs-on: ubuntu-latest @@ -14,15 +14,10 @@ jobs: id-token: write # To authenticate with Google Cloud using OIDC steps: - uses: actions/checkout@v4 - - uses: google-github-actions/auth@v2 with: service_account: ${{ secrets.GCP_SA_EMAIL }} - workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} - - name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@v2 - - name: Download reearth config - run: gsutil cp "${{ env.GCS_DOMAIN }}/${{ env.REEARTH_CONFIG_FILENAME }}" . + workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}} - name: Get Cesium Ion token id: ion_token run: | @@ -41,9 +36,9 @@ jobs: " \ ) echo "token=${ION_TOKEN}" >> $GITHUB_OUTPUT - - name: Update Ion token in reearth config + - name: Update Cloud Run run: | - echo $(cat ${{ env.REEARTH_CONFIG_FILENAME }} | jq -r '.cesiumIonAccessToken |= "${{ steps.ion_token.outputs.token }}"') > ${{ env.REEARTH_CONFIG_FILENAME }} - echo $(cat ${{ env.REEARTH_CONFIG_FILENAME }}) - - name: Upload reearth config - run: gsutil -h "Cache-Control:no-store" cp reearth_config.json "${{ env.GCS_DOMAIN }}/${{ env.REEARTH_CONFIG_FILENAME }}" \ No newline at end of file + gcloud run services update $CMS_WEB \ + --update-env-vars REEARTH_CMS_CESIUM_ION_ACCESS_TOKEN=${{ steps.ion_token.outputs.token }} \ + --region $REGION \ + --platform managed From 06366b31231e204afc7ca4fd4df186bd030e3285 Mon Sep 17 00:00:00 2001 From: yk-eukarya <81808708+yk-eukarya@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:24:49 +0200 Subject: [PATCH 04/14] ci: set go-setup cache key (#1278) imp --- .github/workflows/ci_server.yml | 3 +++ .github/workflows/ci_worker.yml | 2 ++ 2 files changed, 5 insertions(+) diff --git a/.github/workflows/ci_server.yml b/.github/workflows/ci_server.yml index 5041479b96..e5862816e2 100644 --- a/.github/workflows/ci_server.yml +++ b/.github/workflows/ci_server.yml @@ -15,6 +15,7 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} + cache-dependency-path: server/go.mod - name: golangci-lint uses: golangci/golangci-lint-action@v6 with: @@ -35,6 +36,7 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} + cache-dependency-path: server/go.mod - name: check forgotten translations working-directory: server run: make i18n-ci @@ -53,6 +55,7 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} + cache-dependency-path: server/go.mod - name: test run: go test ./... -v -race -coverprofile=coverage.txt -covermode=atomic -timeout 10m working-directory: server diff --git a/.github/workflows/ci_worker.yml b/.github/workflows/ci_worker.yml index 158faf18ca..6bc96bcea6 100644 --- a/.github/workflows/ci_worker.yml +++ b/.github/workflows/ci_worker.yml @@ -14,6 +14,7 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} + cache-dependency-path: worker/go.mod - name: golangci-lint uses: golangci/golangci-lint-action@v6 with: @@ -36,6 +37,7 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} + cache-dependency-path: worker/go.mod - name: test run: go test ./... -v -race -coverprofile=coverage.txt -covermode=atomic -timeout 10m working-directory: worker From c83a8144f1b2ac29c9d0ae2679c32f5806567894 Mon Sep 17 00:00:00 2001 From: caichi <54824604+caichi-t@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:56:32 +0900 Subject: [PATCH 05/14] fix(web): add some missing styling (#1279) * comment column * fix: filter max width * asset and request header * fix: asset page --- web/src/components/atoms/Icon/icons.ts | 2 ++ .../molecules/Asset/Asset/AssetBody/Asset.tsx | 2 ++ .../Asset/Asset/AssetBody/sideBarCard.tsx | 8 +++---- .../molecules/Asset/AssetList/index.tsx | 2 +- .../molecules/Common/CommentsPanel/index.tsx | 8 ++++--- .../Content/Table/DropdownRender/index.tsx | 4 ++++ .../Content/Table/filterDropdown.tsx | 9 +++++++- .../molecules/Content/Table/index.tsx | 23 +++++++++++-------- .../molecules/Request/List/index.tsx | 2 +- 9 files changed, 41 insertions(+), 19 deletions(-) diff --git a/web/src/components/atoms/Icon/icons.ts b/web/src/components/atoms/Icon/icons.ts index ba1edb677e..78223bb232 100644 --- a/web/src/components/atoms/Icon/icons.ts +++ b/web/src/components/atoms/Icon/icons.ts @@ -51,6 +51,7 @@ import { ReloadOutlined, SortAscendingOutlined, FilterOutlined, + CommentOutlined, } from "@ant-design/icons"; import ArrowSquareOut from "./Icons/arrowSquareOut.svg"; @@ -177,4 +178,5 @@ export default { editorCopy: EditorCopy, circle: Circle, rectangle: Rectangle, + comment: CommentOutlined, }; diff --git a/web/src/components/molecules/Asset/Asset/AssetBody/Asset.tsx b/web/src/components/molecules/Asset/Asset/AssetBody/Asset.tsx index 023bbcfcd4..ba11e35ff9 100644 --- a/web/src/components/molecules/Asset/Asset/AssetBody/Asset.tsx +++ b/web/src/components/molecules/Asset/Asset/AssetBody/Asset.tsx @@ -223,6 +223,7 @@ const BodyContainer = styled.div` flex-direction: row; width: 100%; height: calc(100% - 72px); + border-top: 1px solid #00000008; .ant-tree-show-line .ant-tree-switcher { background-color: transparent; } @@ -239,6 +240,7 @@ const BodyWrapper = styled.div` const SideBarWrapper = styled.div` padding: 8px; width: 272px; + background-color: #fafafa; `; const StyledButton = styled(Button)` diff --git a/web/src/components/molecules/Asset/Asset/AssetBody/sideBarCard.tsx b/web/src/components/molecules/Asset/Asset/AssetBody/sideBarCard.tsx index 92ae23e3ac..342b7a5558 100644 --- a/web/src/components/molecules/Asset/Asset/AssetBody/sideBarCard.tsx +++ b/web/src/components/molecules/Asset/Asset/AssetBody/sideBarCard.tsx @@ -1,15 +1,14 @@ import styled from "@emotion/styled"; -import { CSSProperties, ReactNode } from "react"; +import { ReactNode } from "react"; type Props = { title: string; children?: ReactNode; - style?: CSSProperties; }; -const SideBarCard: React.FC = ({ title, children, style }) => { +const SideBarCard: React.FC = ({ title, children }) => { return ( - + {title} {children} @@ -23,6 +22,7 @@ const SideBarCardWrapper = styled.div` display: flex; flex-direction: column; box-shadow: 0 4px 4px 0 #00000025; + background-color: #fff; `; const CardTitle = styled.span` diff --git a/web/src/components/molecules/Asset/AssetList/index.tsx b/web/src/components/molecules/Asset/AssetList/index.tsx index ecf86b3438..cdf466f1fc 100644 --- a/web/src/components/molecules/Asset/AssetList/index.tsx +++ b/web/src/components/molecules/Asset/AssetList/index.tsx @@ -179,5 +179,5 @@ const Wrapper = styled.div` `; const StyledPageHeader = styled(PageHeader)` - margin: 0 8px; + border-bottom: 1px solid #00000008; `; diff --git a/web/src/components/molecules/Common/CommentsPanel/index.tsx b/web/src/components/molecules/Common/CommentsPanel/index.tsx index c747eebc3d..e78befcf26 100644 --- a/web/src/components/molecules/Common/CommentsPanel/index.tsx +++ b/web/src/components/molecules/Common/CommentsPanel/index.tsx @@ -42,7 +42,7 @@ const CommentsPanel: React.FC = ({ trigger={}> {collapsed ? ( - onCollapse(false)} /> + onCollapse(false)} /> ) : ( <> @@ -72,7 +72,8 @@ const CommentsPanel: React.FC = ({ export default CommentsPanel; const StyledIcon = styled(Icon)` - padding: 12px 20px; + padding-top: 12px; + justify-content: center; `; const ThreadWrapper = styled.div` @@ -81,7 +82,8 @@ const ThreadWrapper = styled.div` `; const Title = styled.h3` - font-size: 18px; + font-size: 16px; + line-height: 1.5; cursor: pointer; `; diff --git a/web/src/components/molecules/Content/Table/DropdownRender/index.tsx b/web/src/components/molecules/Content/Table/DropdownRender/index.tsx index 50f267e6cc..b6b4f7accd 100644 --- a/web/src/components/molecules/Content/Table/DropdownRender/index.tsx +++ b/web/src/components/molecules/Content/Table/DropdownRender/index.tsx @@ -156,6 +156,10 @@ const StyledFormItem = styled(Form.Item)` const TextWrapper = styled.span` min-width: 137px; + max-width: 300px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; text-align: left; `; diff --git a/web/src/components/molecules/Content/Table/filterDropdown.tsx b/web/src/components/molecules/Content/Table/filterDropdown.tsx index 9446bf7082..c33672d0d7 100644 --- a/web/src/components/molecules/Content/Table/filterDropdown.tsx +++ b/web/src/components/molecules/Content/Table/filterDropdown.tsx @@ -77,7 +77,7 @@ const FilterDropdown: React.FC = ({ - {filter.title} + {filter.title}
@@ -95,6 +95,13 @@ const StyledButton = styled(Button)` background-color: #f8f8f8; `; +const Title = styled.div` + max-width: 300px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +`; + const StyledIcon = styled(Icon)` color: rgba(0, 0, 0, 0.45); :hover { diff --git a/web/src/components/molecules/Content/Table/index.tsx b/web/src/components/molecules/Content/Table/index.tsx index 9f1ae87b4e..7be4e5e916 100644 --- a/web/src/components/molecules/Content/Table/index.tsx +++ b/web/src/components/molecules/Content/Table/index.tsx @@ -526,7 +526,7 @@ const ContentTable: React.FC = ({ const sharedProps = useMemo( () => ({ menu: { items }, - dropdownRender: (menu: React.ReactNode): React.ReactNode => ( + dropdownRender: (menu: React.ReactNode) => ( = ({ onChange={handleChange} /> - {React.cloneElement(menu as React.ReactElement, { style: menuStyle })} + {React.cloneElement(menu as React.ReactElement)} ), arrow: false, @@ -710,7 +710,7 @@ const ContentTable: React.FC = ({ currentView.columns?.forEach((col, index) => { const colKey = (metaColumn as readonly string[]).includes(col.field.type) ? col.field.type - : col.field.id ?? ""; + : (col.field.id ?? ""); cols[colKey] = { show: col.visible, order: index, fixed: col.fixed }; }); return cols; @@ -880,10 +880,15 @@ const Wrapper = styled.div` 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05); + .ant-dropdown-menu { + box-shadow: none; + overflow-y: auto; + max-height: 256px; + max-width: 332px; + .ant-dropdown-menu-title-content { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } `; - -const menuStyle: React.CSSProperties = { - boxShadow: "none", - overflowY: "auto", - maxHeight: "256px", -}; diff --git a/web/src/components/molecules/Request/List/index.tsx b/web/src/components/molecules/Request/List/index.tsx index a0c25a033f..c0bbdcd35f 100644 --- a/web/src/components/molecules/Request/List/index.tsx +++ b/web/src/components/molecules/Request/List/index.tsx @@ -108,7 +108,7 @@ const Content = styled.div` `; const StyledPageHeader = styled(PageHeader)` - margin: 0 8px; + border-bottom: 1px solid #00000008; `; export default RequestListMolecule; From fb598bc05ace5d0c346180e665b230fdf954fe3e Mon Sep 17 00:00:00 2001 From: yk-eukarya <81808708+yk-eukarya@users.noreply.github.com> Date: Wed, 23 Oct 2024 08:57:28 +0200 Subject: [PATCH 06/14] feat(server): support float fields (#1263) * imp * imp * imp * imp * fix test cases --- server/e2e/gql_field_test.go | 13 + server/e2e/gql_item_test.go | 6 +- server/e2e/integration_item_test.go | 6 +- server/e2e/integration_schema_test.go | 72 +++- server/internal/adapter/gql/generated.go | 307 +++++++++++++++++- .../adapter/gql/gqlmodel/convert_schema.go | 22 ++ .../adapter/gql/gqlmodel/models_gen.go | 19 +- .../adapter/integration/item_import.go | 6 +- server/internal/adapter/integration/schema.go | 3 + .../adapter/integration/server.gen.go | 74 ++--- server/pkg/integrationapi/types.gen.go | 1 + server/schemas/field.graphql | 15 + server/schemas/integration.yml | 1 + 13 files changed, 493 insertions(+), 52 deletions(-) diff --git a/server/e2e/gql_field_test.go b/server/e2e/gql_field_test.go index eb69ae270a..309428b62b 100644 --- a/server/e2e/gql_field_test.go +++ b/server/e2e/gql_field_test.go @@ -134,6 +134,7 @@ type fIds struct { boolFId string selectFId string integerFId string + numberFId string urlFId string dateFId string tagFID string @@ -192,6 +193,16 @@ func createFieldOfEachType(t *testing.T, e *httpexpect.Expect, mId string) fIds }, }) + numberFId, _ := createField(e, mId, "number", "number", "number", + false, false, false, false, "Number", + map[string]any{ + "number": map[string]any{ + "defaultValue": nil, + "min": nil, + "max": nil, + }, + }) + urlFId, _ := createField(e, mId, "url", "url", "url", false, false, false, false, "URL", map[string]any{ @@ -260,6 +271,7 @@ func createFieldOfEachType(t *testing.T, e *httpexpect.Expect, mId string) fIds boolFId, selectFId, integerFId, + numberFId, urlFId, dateFId, tagFId, @@ -276,6 +288,7 @@ func createFieldOfEachType(t *testing.T, e *httpexpect.Expect, mId string) fIds boolFId: boolFId, selectFId: selectFId, integerFId: integerFId, + numberFId: numberFId, urlFId: urlFId, dateFId: dateFId, tagFID: tagFId, diff --git a/server/e2e/gql_item_test.go b/server/e2e/gql_item_test.go index b1bbe7c31b..9355382081 100644 --- a/server/e2e/gql_item_test.go +++ b/server/e2e/gql_item_test.go @@ -412,7 +412,7 @@ func TestClearItemValues(t *testing.T) { }) fields := r1.Path("$.data.createItem.item.fields[:].value").Raw().([]any) assert.Equal(t, []any{ - "Text", "TextArea", "MarkdownText", aid.String(), true, "s1", float64(1), "https://www.1s.com", "2023-01-01T00:00:00Z", tagIds[0], true, "{\n\t\"type\": \"Point\",\n\t\"coordinates\": [102.0, 0.5]\n}", "{\n\t\"type\": \"Point\",\n\t\"coordinates\": [102.0, 0.5]\n}", + "Text", "TextArea", "MarkdownText", aid.String(), true, "s1", float64(1), nil, "https://www.1s.com", "2023-01-01T00:00:00Z", tagIds[0], true, "{\n\t\"type\": \"Point\",\n\t\"coordinates\": [102.0, 0.5]\n}", "{\n\t\"type\": \"Point\",\n\t\"coordinates\": [102.0, 0.5]\n}", }, fields) i1ver, _ := getItem(e, iid) _, r2 := updateItem(e, iid, i1ver, []map[string]any{ @@ -432,7 +432,7 @@ func TestClearItemValues(t *testing.T) { }) fields = r2.Path("$.data.updateItem.item.fields[:].value").Raw().([]any) assert.Equal(t, []any{ - nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, }, fields) iid2, _ := createItem(e, mId, sId, nil, []map[string]any{ @@ -453,7 +453,7 @@ func TestClearItemValues(t *testing.T) { _, r3 := getItem(e, iid2) fields2 := r3.Path("$.data.node.fields[:].value").Raw().([]any) assert.Equal(t, []any{ - nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, }, fields2) } diff --git a/server/e2e/integration_item_test.go b/server/e2e/integration_item_test.go index 773baf6492..3feadddc36 100644 --- a/server/e2e/integration_item_test.go +++ b/server/e2e/integration_item_test.go @@ -1450,7 +1450,7 @@ func TestIntegrationModelImportJSONWithJsonInput(t *testing.T) { mId, _ := createModel(e, pId, "test", "test", "test-1") createFieldOfEachType(t, e, mId) - jsonContent := `[{"text": "test1", "bool": true, "integer": 1},{"text": "test2", "bool": false, "integer": 2},{"text": "test3", "bool": null, "integer": null}]` + jsonContent := `[{"text": "test1", "bool": true, "number": 1.1},{"text": "test2", "bool": false, "number": 2},{"text": "test3", "bool": null, "number": null}]` aId := UploadAsset(e, pId, "./test1.json", jsonContent).Object().Value("id").String().Raw() res := IntegrationModelImportJSON(e, mId, aId, "json", "insert", false, nil) res.Object().IsEqual(map[string]any{ @@ -1573,7 +1573,7 @@ func TestIntegrationItemsAsCSV(t *testing.T) { }) res := IntegrationItemsAsCSV(e, mId, 1, 10, i1Id, "", "", nil) - expected := fmt.Sprintf("id,location_lat,location_lng,text,textArea,markdown,asset,bool,select,integer,url,date,tag,checkbox\n%s,139.28179282584915,36.58570985749664,test1,,,,,,,,,,\n", i1Id) + expected := fmt.Sprintf("id,location_lat,location_lng,text,textArea,markdown,asset,bool,select,integer,number,url,date,tag,checkbox\n%s,139.28179282584915,36.58570985749664,test1,,,,,,,,,,,\n", i1Id) res.IsEqual(expected) } @@ -1593,7 +1593,7 @@ func TestIntegrationItemsWithProjectAsCSV(t *testing.T) { }) res := IntegrationItemsWithProjectAsCSV(e, pId, mId, 1, 10, i1Id, "", "", nil) - expected := fmt.Sprintf("id,location_lat,location_lng,text,textArea,markdown,asset,bool,select,integer,url,date,tag,checkbox\n%s,139.28179282584915,36.58570985749664,test1,,,,,,30,,,,\n", i1Id) + expected := fmt.Sprintf("id,location_lat,location_lng,text,textArea,markdown,asset,bool,select,integer,number,url,date,tag,checkbox\n%s,139.28179282584915,36.58570985749664,test1,,,,,,30,,,,,\n", i1Id) res.IsEqual(expected) } diff --git a/server/e2e/integration_schema_test.go b/server/e2e/integration_schema_test.go index 4ba0a8ae92..04ecbf605e 100644 --- a/server/e2e/integration_schema_test.go +++ b/server/e2e/integration_schema_test.go @@ -177,6 +177,52 @@ func TestIntegrationFieldCreateAPI(t *testing.T) { res.ContainsKey("id") + res = e.GET("/api/models/{modelId}", mId1). + WithHeader("authorization", "Bearer "+secret). + Expect(). + Status(http.StatusOK). + JSON(). + Object() + + res.ContainsSubset(map[string]any{ + "name": "m1", + "id": mId1.String(), + "description": "m1 desc", + "public": true, + "key": ikey1.String(), + "projectId": pid, + "schemaId": sid1, + }) + + res.Value("createdAt").NotNull() + res.Value("updatedAt").NotNull() + res.Value("lastModified").NotNull() + resf := res.Value("schema").Object().Value("fields").Array() + resf.Length().IsEqual(3) + resf.Value(2).Object().ContainsSubset(map[string]any{ + // "id": "", // generated + "key": "テスト", + "type": "text", + "required": false, + }) + // endregion + + //region bool + res = e.POST(endpoint, sid1). + WithHeader("authorization", "Bearer "+secret). + WithJSON(map[string]interface{}{ + "key": "fKey1", + "type": "bool", + "multiple": false, + "required": false, + }). + Expect(). + Status(http.StatusOK). + JSON(). + Object() + + res.ContainsKey("id") + res = e.GET("/api/models/{modelId}", mId1). WithHeader("authorization", "Bearer "+secret). Expect(). @@ -192,18 +238,25 @@ func TestIntegrationFieldCreateAPI(t *testing.T) { HasValue("projectId", pid). HasValue("schemaId", sid1) - res.Value("schema").Object().Value("fields").Array().Length().IsEqual(3) res.Value("createdAt").NotNull() res.Value("updatedAt").NotNull() res.Value("lastModified").NotNull() + resf = res.Value("schema").Object().Value("fields").Array() + resf.Length().IsEqual(4) + resf.Value(3).Object().ContainsSubset(map[string]any{ + // "id": "", // generated + "key": "fKey1", + "type": "bool", + "required": false, + }) // endregion - //region bool + //region number res = e.POST(endpoint, sid1). WithHeader("authorization", "Bearer "+secret). WithJSON(map[string]interface{}{ - "key": "fKey1", - "type": "bool", + "key": "fKey2", + "type": "number", "multiple": false, "required": false, }). @@ -229,17 +282,24 @@ func TestIntegrationFieldCreateAPI(t *testing.T) { HasValue("projectId", pid). HasValue("schemaId", sid1) - res.Value("schema").Object().Value("fields").Array().Length().IsEqual(4) res.Value("createdAt").NotNull() res.Value("updatedAt").NotNull() res.Value("lastModified").NotNull() + resf = res.Value("schema").Object().Value("fields").Array() + resf.Length().IsEqual(5) + resf.Value(4).Object().ContainsSubset(map[string]any{ + // "id": "", // generated + "key": "fKey2", + "type": "number", + "required": false, + }) // endregion // region GeoObject res = e.POST(endpoint, sid1). WithHeader("authorization", "Bearer "+secret). WithJSON(map[string]interface{}{ - "key": "fKey2", + "key": "fKey3", "type": "geometryObject", "multiple": false, "required": false, diff --git a/server/internal/adapter/gql/generated.go b/server/internal/adapter/gql/generated.go index 002574bcbe..e9eda2b4e8 100644 --- a/server/internal/adapter/gql/generated.go +++ b/server/internal/adapter/gql/generated.go @@ -688,6 +688,12 @@ type ComplexityRoot struct { MaxLength func(childComplexity int) int } + SchemaFieldNumber struct { + DefaultValue func(childComplexity int) int + Max func(childComplexity int) int + Min func(childComplexity int) int + } + SchemaFieldReference struct { CorrespondingField func(childComplexity int) int CorrespondingFieldID func(childComplexity int) int @@ -4003,6 +4009,27 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.SchemaFieldMarkdown.MaxLength(childComplexity), true + case "SchemaFieldNumber.defaultValue": + if e.complexity.SchemaFieldNumber.DefaultValue == nil { + break + } + + return e.complexity.SchemaFieldNumber.DefaultValue(childComplexity), true + + case "SchemaFieldNumber.max": + if e.complexity.SchemaFieldNumber.Max == nil { + break + } + + return e.complexity.SchemaFieldNumber.Max(childComplexity), true + + case "SchemaFieldNumber.min": + if e.complexity.SchemaFieldNumber.Min == nil { + break + } + + return e.complexity.SchemaFieldNumber.Min(childComplexity), true + case "SchemaFieldReference.correspondingField": if e.complexity.SchemaFieldReference.CorrespondingField == nil { break @@ -4758,6 +4785,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputSchemaFieldGroupInput, ec.unmarshalInputSchemaFieldIntegerInput, ec.unmarshalInputSchemaFieldLineStringInput, + ec.unmarshalInputSchemaFieldNumberInput, ec.unmarshalInputSchemaFieldReferenceInput, ec.unmarshalInputSchemaFieldRichTextInput, ec.unmarshalInputSchemaFieldSelectInput, @@ -5159,6 +5187,7 @@ extend type Mutation { Select Tag Integer + Number Reference Checkbox URL @@ -5231,6 +5260,7 @@ union SchemaFieldTypeProperty = | SchemaFieldSelect | SchemaFieldTag | SchemaFieldInteger + | SchemaFieldNumber | SchemaFieldReference | SchemaFieldURL | SchemaFieldCheckbox @@ -5292,6 +5322,12 @@ type SchemaFieldInteger { max: Int } +type SchemaFieldNumber { + defaultValue: Any + min: Float + max: Float +} + type SchemaFieldReference { modelId: ID! schemaId: ID! @@ -5382,6 +5418,12 @@ input SchemaFieldIntegerInput { max: Int } +input SchemaFieldNumberInput { + defaultValue: Any + min: Float + max: Float +} + input CorrespondingFieldInput { fieldId: ID title: String! @@ -5430,6 +5472,7 @@ input SchemaFieldTypePropertyInput @onlyOne { tag: SchemaFieldTagInput checkbox: SchemaFieldCheckboxInput integer: SchemaFieldIntegerInput + number: SchemaFieldNumberInput reference: SchemaFieldReferenceInput url: SchemaFieldURLInput group: SchemaFieldGroupInput @@ -6384,6 +6427,7 @@ input CreateRequestInput { items: [RequestItemInput!]! } + input UpdateRequestInput { requestId: ID! title: String @@ -28701,6 +28745,129 @@ func (ec *executionContext) fieldContext_SchemaFieldMarkdown_maxLength(_ context return fc, nil } +func (ec *executionContext) _SchemaFieldNumber_defaultValue(ctx context.Context, field graphql.CollectedField, obj *gqlmodel.SchemaFieldNumber) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_SchemaFieldNumber_defaultValue(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DefaultValue, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(any) + fc.Result = res + return ec.marshalOAny2interface(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_SchemaFieldNumber_defaultValue(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SchemaFieldNumber", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Any does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _SchemaFieldNumber_min(ctx context.Context, field graphql.CollectedField, obj *gqlmodel.SchemaFieldNumber) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_SchemaFieldNumber_min(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Min, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*float64) + fc.Result = res + return ec.marshalOFloat2ᚖfloat64(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_SchemaFieldNumber_min(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SchemaFieldNumber", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Float does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _SchemaFieldNumber_max(ctx context.Context, field graphql.CollectedField, obj *gqlmodel.SchemaFieldNumber) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_SchemaFieldNumber_max(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Max, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*float64) + fc.Result = res + return ec.marshalOFloat2ᚖfloat64(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_SchemaFieldNumber_max(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SchemaFieldNumber", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Float does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _SchemaFieldReference_modelId(ctx context.Context, field graphql.CollectedField, obj *gqlmodel.SchemaFieldReference) (ret graphql.Marshaler) { fc, err := ec.fieldContext_SchemaFieldReference_modelId(ctx, field) if err != nil { @@ -38185,6 +38352,47 @@ func (ec *executionContext) unmarshalInputSchemaFieldLineStringInput(ctx context return it, nil } +func (ec *executionContext) unmarshalInputSchemaFieldNumberInput(ctx context.Context, obj interface{}) (gqlmodel.SchemaFieldNumberInput, error) { + var it gqlmodel.SchemaFieldNumberInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"defaultValue", "min", "max"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "defaultValue": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("defaultValue")) + data, err := ec.unmarshalOAny2interface(ctx, v) + if err != nil { + return it, err + } + it.DefaultValue = data + case "min": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("min")) + data, err := ec.unmarshalOFloat2ᚖfloat64(ctx, v) + if err != nil { + return it, err + } + it.Min = data + case "max": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("max")) + data, err := ec.unmarshalOFloat2ᚖfloat64(ctx, v) + if err != nil { + return it, err + } + it.Max = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputSchemaFieldReferenceInput(ctx context.Context, obj interface{}) (gqlmodel.SchemaFieldReferenceInput, error) { var it gqlmodel.SchemaFieldReferenceInput asMap := map[string]interface{}{} @@ -38444,7 +38652,7 @@ func (ec *executionContext) unmarshalInputSchemaFieldTypePropertyInput(ctx conte asMap[k] = v } - fieldsInOrder := [...]string{"text", "textArea", "richText", "markdownText", "asset", "date", "bool", "select", "tag", "checkbox", "integer", "reference", "url", "group", "geometryObject", "geometryEditor"} + fieldsInOrder := [...]string{"text", "textArea", "richText", "markdownText", "asset", "date", "bool", "select", "tag", "checkbox", "integer", "number", "reference", "url", "group", "geometryObject", "geometryEditor"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -38737,6 +38945,32 @@ func (ec *executionContext) unmarshalInputSchemaFieldTypePropertyInput(ctx conte err := fmt.Errorf(`unexpected type %T from directive, should be *github.com/reearth/reearth-cms/server/internal/adapter/gql/gqlmodel.SchemaFieldIntegerInput`, tmp) return it, graphql.ErrorOnPath(ctx, err) } + case "number": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("number")) + directive0 := func(ctx context.Context) (interface{}, error) { + return ec.unmarshalOSchemaFieldNumberInput2ᚖgithubᚗcomᚋreearthᚋreearthᚑcmsᚋserverᚋinternalᚋadapterᚋgqlᚋgqlmodelᚐSchemaFieldNumberInput(ctx, v) + } + + directive1 := func(ctx context.Context) (interface{}, error) { + if ec.directives.OnlyOne == nil { + var zeroVal *gqlmodel.SchemaFieldNumberInput + return zeroVal, errors.New("directive onlyOne is not implemented") + } + return ec.directives.OnlyOne(ctx, obj, directive0) + } + + tmp, err := directive1(ctx) + if err != nil { + return it, graphql.ErrorOnPath(ctx, err) + } + if data, ok := tmp.(*gqlmodel.SchemaFieldNumberInput); ok { + it.Number = data + } else if tmp == nil { + it.Number = nil + } else { + err := fmt.Errorf(`unexpected type %T from directive, should be *github.com/reearth/reearth-cms/server/internal/adapter/gql/gqlmodel.SchemaFieldNumberInput`, tmp) + return it, graphql.ErrorOnPath(ctx, err) + } case "reference": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("reference")) directive0 := func(ctx context.Context) (interface{}, error) { @@ -40644,6 +40878,13 @@ func (ec *executionContext) _SchemaFieldTypeProperty(ctx context.Context, sel as return graphql.Null } return ec._SchemaFieldInteger(ctx, sel, obj) + case gqlmodel.SchemaFieldNumber: + return ec._SchemaFieldNumber(ctx, sel, &obj) + case *gqlmodel.SchemaFieldNumber: + if obj == nil { + return graphql.Null + } + return ec._SchemaFieldNumber(ctx, sel, obj) case gqlmodel.SchemaFieldReference: return ec._SchemaFieldReference(ctx, sel, &obj) case *gqlmodel.SchemaFieldReference: @@ -46592,6 +46833,46 @@ func (ec *executionContext) _SchemaFieldMarkdown(ctx context.Context, sel ast.Se return out } +var schemaFieldNumberImplementors = []string{"SchemaFieldNumber", "SchemaFieldTypeProperty"} + +func (ec *executionContext) _SchemaFieldNumber(ctx context.Context, sel ast.SelectionSet, obj *gqlmodel.SchemaFieldNumber) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, schemaFieldNumberImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("SchemaFieldNumber") + case "defaultValue": + out.Values[i] = ec._SchemaFieldNumber_defaultValue(ctx, field, obj) + case "min": + out.Values[i] = ec._SchemaFieldNumber_min(ctx, field, obj) + case "max": + out.Values[i] = ec._SchemaFieldNumber_max(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var schemaFieldReferenceImplementors = []string{"SchemaFieldReference", "SchemaFieldTypeProperty"} func (ec *executionContext) _SchemaFieldReference(ctx context.Context, sel ast.SelectionSet, obj *gqlmodel.SchemaFieldReference) graphql.Marshaler { @@ -52132,6 +52413,22 @@ func (ec *executionContext) marshalOFieldsPayload2ᚖgithubᚗcomᚋreearthᚋre return ec._FieldsPayload(ctx, sel, v) } +func (ec *executionContext) unmarshalOFloat2ᚖfloat64(ctx context.Context, v interface{}) (*float64, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalFloatContext(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOFloat2ᚖfloat64(ctx context.Context, sel ast.SelectionSet, v *float64) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalFloatContext(*v) + return graphql.WrapContextMarshaler(ctx, res) +} + func (ec *executionContext) marshalOGroup2ᚖgithubᚗcomᚋreearthᚋreearthᚑcmsᚋserverᚋinternalᚋadapterᚋgqlᚋgqlmodelᚐGroup(ctx context.Context, sel ast.SelectionSet, v *gqlmodel.Group) graphql.Marshaler { if v == nil { return graphql.Null @@ -52849,6 +53146,14 @@ func (ec *executionContext) unmarshalOSchemaFieldIntegerInput2ᚖgithubᚗcomᚋ return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalOSchemaFieldNumberInput2ᚖgithubᚗcomᚋreearthᚋreearthᚑcmsᚋserverᚋinternalᚋadapterᚋgqlᚋgqlmodelᚐSchemaFieldNumberInput(ctx context.Context, v interface{}) (*gqlmodel.SchemaFieldNumberInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputSchemaFieldNumberInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOSchemaFieldReferenceInput2ᚖgithubᚗcomᚋreearthᚋreearthᚑcmsᚋserverᚋinternalᚋadapterᚋgqlᚋgqlmodelᚐSchemaFieldReferenceInput(ctx context.Context, v interface{}) (*gqlmodel.SchemaFieldReferenceInput, error) { if v == nil { return nil, nil diff --git a/server/internal/adapter/gql/gqlmodel/convert_schema.go b/server/internal/adapter/gql/gqlmodel/convert_schema.go index f3d5312ad0..7a1cdef0ba 100644 --- a/server/internal/adapter/gql/gqlmodel/convert_schema.go +++ b/server/internal/adapter/gql/gqlmodel/convert_schema.go @@ -556,6 +556,28 @@ func FromSchemaTypeProperty(tp *SchemaFieldTypePropertyInput, t SchemaFieldType, err = err2 } tpRes = tpi.TypeProperty() + case SchemaFieldTypeNumber: + x := tp.Number + if x == nil { + return nil, nil, ErrInvalidTypeProperty + } + if multiple { + dv = value.NewMultiple(value.TypeNumber, unpackArray(x.DefaultValue)) + } else { + dv = FromValue(SchemaFieldTypeNumber, x.DefaultValue).AsMultiple() + } + var min, max *float64 + if x.Min != nil { + min = lo.ToPtr(float64(*x.Min)) + } + if x.Max != nil { + max = lo.ToPtr(float64(*x.Max)) + } + tpi, err2 := schema.NewNumber(min, max) + if err2 != nil { + err = err2 + } + tpRes = tpi.TypeProperty() case SchemaFieldTypeReference: x := tp.Reference if x == nil { diff --git a/server/internal/adapter/gql/gqlmodel/models_gen.go b/server/internal/adapter/gql/gqlmodel/models_gen.go index c584fef548..4c2e33e311 100644 --- a/server/internal/adapter/gql/gqlmodel/models_gen.go +++ b/server/internal/adapter/gql/gqlmodel/models_gen.go @@ -1030,6 +1030,20 @@ type SchemaFieldMarkdown struct { func (SchemaFieldMarkdown) IsSchemaFieldTypeProperty() {} +type SchemaFieldNumber struct { + DefaultValue any `json:"defaultValue,omitempty"` + Min *float64 `json:"min,omitempty"` + Max *float64 `json:"max,omitempty"` +} + +func (SchemaFieldNumber) IsSchemaFieldTypeProperty() {} + +type SchemaFieldNumberInput struct { + DefaultValue any `json:"defaultValue,omitempty"` + Min *float64 `json:"min,omitempty"` + Max *float64 `json:"max,omitempty"` +} + type SchemaFieldReference struct { ModelID ID `json:"modelId"` SchemaID ID `json:"schemaId"` @@ -1130,6 +1144,7 @@ type SchemaFieldTypePropertyInput struct { Tag *SchemaFieldTagInput `json:"tag,omitempty"` Checkbox *SchemaFieldCheckboxInput `json:"checkbox,omitempty"` Integer *SchemaFieldIntegerInput `json:"integer,omitempty"` + Number *SchemaFieldNumberInput `json:"number,omitempty"` Reference *SchemaFieldReferenceInput `json:"reference,omitempty"` URL *SchemaFieldURLInput `json:"url,omitempty"` Group *SchemaFieldGroupInput `json:"group,omitempty"` @@ -2430,6 +2445,7 @@ const ( SchemaFieldTypeSelect SchemaFieldType = "Select" SchemaFieldTypeTag SchemaFieldType = "Tag" SchemaFieldTypeInteger SchemaFieldType = "Integer" + SchemaFieldTypeNumber SchemaFieldType = "Number" SchemaFieldTypeReference SchemaFieldType = "Reference" SchemaFieldTypeCheckbox SchemaFieldType = "Checkbox" SchemaFieldTypeURL SchemaFieldType = "URL" @@ -2449,6 +2465,7 @@ var AllSchemaFieldType = []SchemaFieldType{ SchemaFieldTypeSelect, SchemaFieldTypeTag, SchemaFieldTypeInteger, + SchemaFieldTypeNumber, SchemaFieldTypeReference, SchemaFieldTypeCheckbox, SchemaFieldTypeURL, @@ -2459,7 +2476,7 @@ var AllSchemaFieldType = []SchemaFieldType{ func (e SchemaFieldType) IsValid() bool { switch e { - case SchemaFieldTypeText, SchemaFieldTypeTextArea, SchemaFieldTypeRichText, SchemaFieldTypeMarkdownText, SchemaFieldTypeAsset, SchemaFieldTypeDate, SchemaFieldTypeBool, SchemaFieldTypeSelect, SchemaFieldTypeTag, SchemaFieldTypeInteger, SchemaFieldTypeReference, SchemaFieldTypeCheckbox, SchemaFieldTypeURL, SchemaFieldTypeGroup, SchemaFieldTypeGeometryObject, SchemaFieldTypeGeometryEditor: + case SchemaFieldTypeText, SchemaFieldTypeTextArea, SchemaFieldTypeRichText, SchemaFieldTypeMarkdownText, SchemaFieldTypeAsset, SchemaFieldTypeDate, SchemaFieldTypeBool, SchemaFieldTypeSelect, SchemaFieldTypeTag, SchemaFieldTypeInteger, SchemaFieldTypeNumber, SchemaFieldTypeReference, SchemaFieldTypeCheckbox, SchemaFieldTypeURL, SchemaFieldTypeGroup, SchemaFieldTypeGeometryObject, SchemaFieldTypeGeometryEditor: return true } return false diff --git a/server/internal/adapter/integration/item_import.go b/server/internal/adapter/integration/item_import.go index 029656cf91..5fddfff1b6 100644 --- a/server/internal/adapter/integration/item_import.go +++ b/server/internal/adapter/integration/item_import.go @@ -251,6 +251,10 @@ func isAssignable(vt1, vt2 value.Type) bool { return true } if vt1 == value.TypeInteger && + (vt2 == value.TypeText || vt2 == value.TypeRichText || vt2 == value.TypeMarkdown || vt2 == value.TypeNumber) { + return true + } + if vt1 == value.TypeNumber && (vt2 == value.TypeText || vt2 == value.TypeRichText || vt2 == value.TypeMarkdown) { return true } @@ -282,7 +286,7 @@ func FieldFrom(k string, v any, sp schema.Package) interfaces.CreateFieldParam { case reflect.Uint64: case reflect.Float32: case reflect.Float64: - t = value.TypeInteger + t = value.TypeNumber case reflect.String: t = value.TypeText default: diff --git a/server/internal/adapter/integration/schema.go b/server/internal/adapter/integration/schema.go index 01f7f630b2..38741c00ef 100644 --- a/server/internal/adapter/integration/schema.go +++ b/server/internal/adapter/integration/schema.go @@ -392,6 +392,9 @@ func FromSchemaTypeProperty(t integrationapi.ValueType, multiple bool) (tpRes *s case integrationapi.ValueTypeInteger: tpi, _ := schema.NewInteger(nil, nil) tpRes = tpi.TypeProperty() + case integrationapi.ValueTypeNumber: + tpi, _ := schema.NewNumber(nil, nil) + tpRes = tpi.TypeProperty() case integrationapi.ValueTypeReference: if multiple { return nil, nil, ErrMultipleReference diff --git a/server/internal/adapter/integration/server.gen.go b/server/internal/adapter/integration/server.gen.go index 5c4eb9a8ac..03082bd41a 100644 --- a/server/internal/adapter/integration/server.gen.go +++ b/server/internal/adapter/integration/server.gen.go @@ -4596,43 +4596,43 @@ var swaggerSpec = []string{ "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/server/pkg/integrationapi/types.gen.go b/server/pkg/integrationapi/types.gen.go index eaab7a4a88..bbfad53ec8 100644 --- a/server/pkg/integrationapi/types.gen.go +++ b/server/pkg/integrationapi/types.gen.go @@ -163,6 +163,7 @@ const ( ValueTypeGroup ValueType = "group" ValueTypeInteger ValueType = "integer" ValueTypeMarkdown ValueType = "markdown" + ValueTypeNumber ValueType = "number" ValueTypeReference ValueType = "reference" ValueTypeRichText ValueType = "richText" ValueTypeSelect ValueType = "select" diff --git a/server/schemas/field.graphql b/server/schemas/field.graphql index 9d2ac4be34..42b44308bf 100644 --- a/server/schemas/field.graphql +++ b/server/schemas/field.graphql @@ -9,6 +9,7 @@ enum SchemaFieldType { Select Tag Integer + Number Reference Checkbox URL @@ -81,6 +82,7 @@ union SchemaFieldTypeProperty = | SchemaFieldSelect | SchemaFieldTag | SchemaFieldInteger + | SchemaFieldNumber | SchemaFieldReference | SchemaFieldURL | SchemaFieldCheckbox @@ -142,6 +144,12 @@ type SchemaFieldInteger { max: Int } +type SchemaFieldNumber { + defaultValue: Any + min: Float + max: Float +} + type SchemaFieldReference { modelId: ID! schemaId: ID! @@ -232,6 +240,12 @@ input SchemaFieldIntegerInput { max: Int } +input SchemaFieldNumberInput { + defaultValue: Any + min: Float + max: Float +} + input CorrespondingFieldInput { fieldId: ID title: String! @@ -280,6 +294,7 @@ input SchemaFieldTypePropertyInput @onlyOne { tag: SchemaFieldTagInput checkbox: SchemaFieldCheckboxInput integer: SchemaFieldIntegerInput + number: SchemaFieldNumberInput reference: SchemaFieldReferenceInput url: SchemaFieldURLInput group: SchemaFieldGroupInput diff --git a/server/schemas/integration.yml b/server/schemas/integration.yml index 4c00b83451..4b9d187750 100644 --- a/server/schemas/integration.yml +++ b/server/schemas/integration.yml @@ -1671,6 +1671,7 @@ components: - bool - select - integer + - number - reference - url - group From 0f3f72ad643d34dd76009e2619eee6248299bb30 Mon Sep 17 00:00:00 2001 From: Nour Balaha Date: Wed, 23 Oct 2024 16:19:10 +0900 Subject: [PATCH 07/14] fix(server): remove workspaces without settings (#1280) fix: remove workspace with no workspace settings --- server/internal/adapter/gql/resolver_workspace.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/internal/adapter/gql/resolver_workspace.go b/server/internal/adapter/gql/resolver_workspace.go index 9770358e6d..c795a0683d 100644 --- a/server/internal/adapter/gql/resolver_workspace.go +++ b/server/internal/adapter/gql/resolver_workspace.go @@ -6,11 +6,13 @@ package gql import ( "context" + "errors" "github.com/reearth/reearth-cms/server/internal/adapter/gql/gqlmodel" "github.com/reearth/reearth-cms/server/internal/usecase/interfaces" "github.com/reearth/reearthx/account/accountdomain" "github.com/reearth/reearthx/account/accountdomain/workspace" + "github.com/reearth/reearthx/rerror" ) // CreateWorkspace is the resolver for the createWorkspace field. @@ -37,9 +39,8 @@ func (r *mutationResolver) DeleteWorkspace(ctx context.Context, input gqlmodel.D return nil, err } - if err := usecases(ctx).WorkspaceSettings.Delete(ctx, interfaces.DeleteWorkspaceSettingsParam{ - ID: wid, - }, getOperator(ctx)); err != nil { + err = usecases(ctx).WorkspaceSettings.Delete(ctx, interfaces.DeleteWorkspaceSettingsParam{ID: wid}, getOperator(ctx)) + if err != nil && !errors.Is(err, rerror.ErrNotFound) { return nil, err } From 00acd2f45aafbcba1952ac72341c33f594b60690 Mon Sep 17 00:00:00 2001 From: caichi <54824604+caichi-t@users.noreply.github.com> Date: Thu, 24 Oct 2024 12:33:47 +0900 Subject: [PATCH 08/14] fix(web): link to asset and refer to item icons (#1272) * link to assets and reference icon * fix refer icon * i18n --- .../atoms/Icon/Icons/arrowUpRightSlash.svg | 3 + web/src/components/atoms/Icon/icons.ts | 2 + .../Common/LinkAssetModal/LinkAssetModal.tsx | 15 +- .../Common/ResizableProTable/index.tsx | 4 + .../Content/Form/ReferenceFormItem/index.tsx | 13 +- .../molecules/Content/LinkItemModal/index.tsx | 19 +- .../LinkItemRequestModal.tsx | 4 +- web/src/i18n/translations/en.yml | 1113 +++++++++-------- web/src/i18n/translations/ja.yml | 1113 +++++++++-------- 9 files changed, 1141 insertions(+), 1145 deletions(-) create mode 100644 web/src/components/atoms/Icon/Icons/arrowUpRightSlash.svg diff --git a/web/src/components/atoms/Icon/Icons/arrowUpRightSlash.svg b/web/src/components/atoms/Icon/Icons/arrowUpRightSlash.svg new file mode 100644 index 0000000000..fafb0dfd5f --- /dev/null +++ b/web/src/components/atoms/Icon/Icons/arrowUpRightSlash.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/src/components/atoms/Icon/icons.ts b/web/src/components/atoms/Icon/icons.ts index 78223bb232..ae99373869 100644 --- a/web/src/components/atoms/Icon/icons.ts +++ b/web/src/components/atoms/Icon/icons.ts @@ -56,6 +56,7 @@ import { import ArrowSquareOut from "./Icons/arrowSquareOut.svg"; import ArrowUpRight from "./Icons/arrowUpRight.svg"; +import ArrowUpRightSlash from "./Icons/arrowUpRightSlash.svg"; import Asset from "./Icons/asset.svg"; import Boolean from "./Icons/boolean.svg"; import CheckSquare from "./Icons/checkSquare.svg"; @@ -124,6 +125,7 @@ export default { asset: Asset, listBullets: ListBullets, arrowUpRight: ArrowUpRight, + arrowUpRightSlash: ArrowUpRightSlash, numberNine: NumberNine, link: Link, linkSolid: LinkSolid, diff --git a/web/src/components/molecules/Common/LinkAssetModal/LinkAssetModal.tsx b/web/src/components/molecules/Common/LinkAssetModal/LinkAssetModal.tsx index c21340cba4..774111e9e4 100644 --- a/web/src/components/molecules/Common/LinkAssetModal/LinkAssetModal.tsx +++ b/web/src/components/molecules/Common/LinkAssetModal/LinkAssetModal.tsx @@ -1,5 +1,5 @@ import styled from "@emotion/styled"; -import { useState, useRef, useCallback, useMemo } from "react"; +import { useRef, useCallback, useMemo } from "react"; import Button from "@reearth-cms/components/atoms/Button"; import Icon from "@reearth-cms/components/atoms/Icon"; @@ -74,7 +74,6 @@ const LinkAssetModal: React.FC = ({ onUploadAndLink, }) => { const t = useT(); - const [hoveredAssetId, setHoveredAssetId] = useState(); const resetFlag = useRef(false); const options: OptionConfig = useMemo( @@ -127,14 +126,10 @@ const LinkAssetModal: React.FC = ({ width: 48, minWidth: 48, render: (_, asset) => { - const isLink = - (asset.id === linkedAsset?.id && hoveredAssetId !== asset.id) || - (asset.id !== linkedAsset?.id && hoveredAssetId === asset.id); + const isLink = asset.id !== linkedAsset?.id; return (