Skip to content

Commit

Permalink
Merge branch 'feat/members_setting' of github.com:reearth/reearth int…
Browse files Browse the repository at this point in the history
…o feat/members_setting
  • Loading branch information
airslice committed Oct 24, 2024
2 parents b5edc6f + 7a80757 commit 20d4a34
Show file tree
Hide file tree
Showing 40 changed files with 1,188 additions and 396 deletions.
82 changes: 50 additions & 32 deletions server/e2e/gql_project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,15 @@ func TestFindStarredByWorkspace(t *testing.T) {
project2ID := createProject(e, "Project 2")
project3ID := createProject(e, "Project 3")
project4ID := createProject(e, "Project 4")
project5ID := createProject(e, "Project 5")

starProject(e, project1ID)
starProject(e, project3ID)

// star and deleted 'Project 5'
starProject(e, project5ID)
deleteProject(e, project5ID)

requestBody := GraphQLRequest{
OperationName: "GetStarredProjects",
Query: `
Expand Down Expand Up @@ -251,6 +256,8 @@ func TestFindStarredByWorkspace(t *testing.T) {
nodeCount := int(nodes.Length().Raw())
assert.Equal(t, 2, nodeCount, "Expected 2 nodes in the response")

nodes.Length().Equal(2) // 'Project 1' and 'Project 3'

starredProjectsMap := make(map[string]bool)
for _, node := range nodes.Iter() {
obj := node.Object()
Expand All @@ -275,7 +282,6 @@ func TestFindStarredByWorkspace(t *testing.T) {
assert.True(t, starredProjectsMap[project3ID], "Project 3 should be starred")
assert.False(t, starredProjectsMap[project2ID], "Project 2 should not be starred")
assert.False(t, starredProjectsMap[project4ID], "Project 4 should not be starred")

}

func starProject(e *httpexpect.Expect, projectID string) {
Expand Down Expand Up @@ -467,39 +473,10 @@ func TestDeleteProjects(t *testing.T) {
createProject(e, "project3-test")

// Deleted 'project2'
requestBody := GraphQLRequest{
OperationName: "UpdateProject",
Query: `mutation UpdateProject($input: UpdateProjectInput!) {
updateProject(input: $input) {
project {
id
name
isDeleted
updatedAt
__typename
}
__typename
}
}`,
Variables: map[string]any{
"input": map[string]any{
"projectId": project2ID,
"deleted": true,
},
},
}

e.POST("/api/graphql").
WithHeader("Origin", "https://example.com").
WithHeader("X-Reearth-Debug-User", uID.String()).
WithHeader("Content-Type", "application/json").
WithJSON(requestBody).
Expect().
Status(http.StatusOK).
JSON()
deleteProject(e, project2ID)

// check
requestBody = GraphQLRequest{
requestBody := GraphQLRequest{
OperationName: "GetDeletedProjects",
Query: `
query GetDeletedProjects($teamId: ID!) {
Expand Down Expand Up @@ -530,3 +507,44 @@ func TestDeleteProjects(t *testing.T) {
deletedProjects.Value("nodes").Array().Length().Equal(1)
deletedProjects.Value("nodes").Array().First().Object().Value("name").Equal("project2-test")
}

func deleteProject(e *httpexpect.Expect, projectID string) {

updateProjectMutation := GraphQLRequest{
OperationName: "UpdateProject",
Query: `mutation UpdateProject($input: UpdateProjectInput!) {
updateProject(input: $input) {
project {
id
name
isDeleted
updatedAt
__typename
}
__typename
}
}`,
Variables: map[string]any{
"input": map[string]any{
"projectId": projectID,
"deleted": true,
},
},
}

response := e.POST("/api/graphql").
WithHeader("Origin", "https://example.com").
WithHeader("X-Reearth-Debug-User", uID.String()).
WithHeader("Content-Type", "application/json").
WithJSON(updateProjectMutation).
Expect().
Status(http.StatusOK).
JSON().
Object().
Value("data").Object().
Value("updateProject").Object().
Value("project").Object()

response.ValueEqual("id", projectID).
ValueEqual("isDeleted", true)
}
1 change: 1 addition & 0 deletions server/internal/adapter/gql/gqlmodel/convert_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func ToProject(p *project.Project) *Project {
EnableGa: p.EnableGA(),
TrackingID: p.TrackingID(),
Starred: p.Starred(),
IsDeleted: p.IsDeleted(),
}
}

Expand Down
1 change: 1 addition & 0 deletions server/internal/infrastructure/mongo/mongodoc/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,6 @@ func (d *ProjectDocument) Model() (*project.Project, error) {
TrackingID(d.TrackingID).
// Scene(scene).
Starred(d.Starred).
Deleted(d.Deleted).
Build()
}
4 changes: 4 additions & 0 deletions server/internal/infrastructure/mongo/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ func (r *Project) FindStarredByWorkspace(ctx context.Context, id accountdomain.W
filter := bson.M{
"team": id.String(),
"starred": true,
"$or": []bson.M{
{"deleted": false},
{"deleted": bson.M{"$exists": false}},
},
}

return r.find(ctx, filter)
Expand Down
5 changes: 5 additions & 0 deletions server/pkg/project/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,8 @@ func (b *Builder) Starred(starred bool) *Builder {
b.p.starred = starred
return b
}

func (b *Builder) Deleted(deleted bool) *Builder {
b.p.isDeleted = deleted
return b
}
61 changes: 16 additions & 45 deletions web/src/beta/features/AssetsManager/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import useLoadMore from "@reearth/beta/hooks/useLoadMore";
import { BreadcrumbItem } from "@reearth/beta/lib/reearth-ui";
import { ManagerLayout } from "@reearth/beta/ui/components/ManagerBase";
import { useAssetsFetcher } from "@reearth/services/api";
Expand Down Expand Up @@ -151,26 +152,11 @@ export default ({
isLoadingMoreRef.current = false;
}, [hasMoreAssets, isRefetching, fetchMore, endCursor]);

const loadMoreRef = useRef<() => void>(loadMore);
loadMoreRef.current = loadMore;

const assetsWrapperRef = useRef<HTMLDivElement>(null);
const assetsContentRef = useRef<HTMLDivElement>(null);

const checkSize = useCallback(() => {
const parentElement = assetsWrapperRef.current;
const childElement = assetsContentRef.current;

if (childElement && parentElement) {
if (childElement.offsetHeight - 14 < parentElement.offsetHeight) {
loadMoreRef.current?.();
}
}
}, []);

useEffect(() => {
checkSize();
}, [assets, checkSize]);
const { wrapperRef: assetsWrapperRef, contentRef: assetsContentRef } =
useLoadMore({
data: filteredAssets,
onLoadMore: loadMore
});

const [contentWidth, setContentWidth] = useState(0);

Expand All @@ -182,9 +168,6 @@ export default ({

const checkSize = () => {
if (childElement && parentElement) {
if (childElement.offsetHeight <= parentElement.offsetHeight) {
loadMoreRef.current?.();
}
setContentWidth(childElement.offsetWidth);
}
};
Expand All @@ -197,26 +180,11 @@ export default ({

checkSize();

const handleScroll = () => {
if (
childElement &&
childElement.scrollHeight -
parentElement.scrollTop -
parentElement.clientHeight <
50
) {
loadMoreRef.current?.();
}
};

parentElement.addEventListener("scroll", handleScroll);

return () => {
parentObserver.disconnect();
childObserver.disconnect();
parentElement.removeEventListener("scroll", handleScroll);
};
}, [filteredAssets]);
}, [filteredAssets, assetsWrapperRef, assetsContentRef]);

const handleAssetsCreate = useCallback(
async (files?: FileList) => {
Expand Down Expand Up @@ -247,12 +215,15 @@ export default ({
? (localStorage.getItem(ASSETS_LAYOUT_STORAGE_KEY) as ManagerLayout)
: "grid"
);
const handleLayoutChange = useCallback((newLayout?: ManagerLayout) => {
if (!newLayout) return;
localStorage.setItem(ASSETS_LAYOUT_STORAGE_KEY, newLayout);
setLayout(newLayout);
assetsWrapperRef.current?.scrollTo({ top: 0 });
}, []);
const handleLayoutChange = useCallback(
(newLayout?: ManagerLayout) => {
if (!newLayout) return;
localStorage.setItem(ASSETS_LAYOUT_STORAGE_KEY, newLayout);
setLayout(newLayout);
assetsWrapperRef.current?.scrollTo({ top: 0 });
},
[assetsWrapperRef]
);

// path
// TODO: support path with folder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Button, PopupMenu, TextInput } from "@reearth/beta/lib/reearth-ui";
import { styled, useTheme } from "@reearth/services/theme";
import { FC } from "react";

import ProjectRemoveModal from "../ProjectRemoveModal";

import useHooks from "./hooks";
import { ProjectProps } from "./types";

Expand All @@ -10,7 +12,8 @@ const ProjectGridViewItem: FC<ProjectProps> = ({
selectedProjectId,
onProjectOpen,
onProjectSelect,
onProjectUpdate
onProjectUpdate,
onProjectRemove
}) => {
const theme = useTheme();

Expand All @@ -21,19 +24,23 @@ const ProjectGridViewItem: FC<ProjectProps> = ({
isHovered,
isStarred,
hasMapOrStoryPublished,
projectRemoveModalVisible,
handleProjectNameChange,
handleProjectNameBlur,
handleProjectHover,
handleProjectNameDoubleClick,
handleProjectStarClick
handleProjectStarClick,
handleProjectRemoveModal,
handleProjectRemove
// exportModalVisible,
// closeExportModal,
// handleExportProject
} = useHooks({
project,
selectedProjectId,
onProjectUpdate,
onProjectSelect
onProjectSelect,
onProjectRemove
});

return (
Expand Down Expand Up @@ -87,6 +94,13 @@ const ProjectGridViewItem: FC<ProjectProps> = ({
/>
</CardFooter>
</Card>
{projectRemoveModalVisible && (
<ProjectRemoveModal
isVisible={projectRemoveModalVisible}
onClose={() => handleProjectRemoveModal(false)}
onProjectRemove={() => handleProjectRemove(project.id)}
/>
)}
{/* MEMO: this modal will be used in the future */}
{/* <Modal visible={exportModalVisible} size="small">
<ModalPanel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { formatRelativeTime } from "@reearth/beta/utils/time";
import { styled, useTheme } from "@reearth/services/theme";
import { FC, MouseEvent, useMemo } from "react";

import ProjectRemoveModal from "../ProjectRemoveModal";

import useHooks from "./hooks";
import { ProjectProps } from "./types";

Expand All @@ -16,7 +18,8 @@ const ProjectListViewItem: FC<ProjectProps> = ({
selectedProjectId,
onProjectOpen,
onProjectSelect,
onProjectUpdate
onProjectUpdate,
onProjectRemove
}) => {
const theme = useTheme();

Expand All @@ -38,19 +41,23 @@ const ProjectListViewItem: FC<ProjectProps> = ({
isHovered,
isStarred,
hasMapOrStoryPublished,
projectRemoveModalVisible,
handleProjectNameChange,
handleProjectNameBlur,
handleProjectHover,
handleProjectNameDoubleClick,
handleProjectStarClick
handleProjectStarClick,
handleProjectRemoveModal,
handleProjectRemove
// exportModalVisible,
// closeExportModal,
// handleExportProject
} = useHooks({
project,
selectedProjectId,
onProjectUpdate,
onProjectSelect
onProjectSelect,
onProjectRemove
});

return (
Expand Down Expand Up @@ -116,6 +123,13 @@ const ProjectListViewItem: FC<ProjectProps> = ({
/>
</ActionCol>
</ListWrapper>
{projectRemoveModalVisible && (
<ProjectRemoveModal
isVisible={projectRemoveModalVisible}
onClose={() => handleProjectRemoveModal(false)}
onProjectRemove={() => handleProjectRemove(project.id)}
/>
)}
{/* MEMO: this modal will be used in the future */}
{/* <Modal visible={exportModalVisible} size="small">
<ModalPanel
Expand Down
Loading

0 comments on commit 20d4a34

Please sign in to comment.