Skip to content

Commit

Permalink
Merge pull request #40 from saisandeepvaddi/v2.0.0
Browse files Browse the repository at this point in the history
V2.0.0
  • Loading branch information
saisandeepvaddi committed Aug 14, 2019
2 parents 96bd1f5 + e0423dd commit 8e4a0f3
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 7 deletions.
6 changes: 6 additions & 0 deletions app/server/controllers/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@ export function deleteProject(req: Request, res: Response) {
const project = db.deleteProject(projectId);
return res.status(200).send(project);
}

export function reorderProjects(req: Request, res: Response) {
const { projectIds } = req.body;
const reorderProjectIds = db.reorderProjects(projectIds);
return res.status(200).send(reorderProjectIds);
}
7 changes: 4 additions & 3 deletions app/server/routes/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import commandRoutes from "./commands";
import {
getAllProjects,
addProject,
deleteProject
deleteProject,
reorderProjects
} from "../controllers/projects";

// GET http://localhost:5010/projects
Expand All @@ -33,10 +34,10 @@ Content-Type: application/json
*/
router.post("/", addProject);

/*
router.post("/reorder", reorderProjects);

/*
DELETE http://localhost:5010/projects/3aa49e37-b58c-443d-a87c-5b35cd8b4345
*/
router.delete("/:projectId", deleteProject);

Expand Down
5 changes: 4 additions & 1 deletion app/server/services/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ class Database {
return this._instance || (this._instance = new this());
}

public reorderProjects(projectIds: string[]) {}
public reorderProjects(projectIds: string[]) {
this.db.set("projectsOrder", projectIds).write();
return projectIds;
}

public getProjects(): IProject[] {
const projects: IProject[] = this.db.get("projects").value() || [];
Expand Down
7 changes: 4 additions & 3 deletions ui/src/components/ProjectsList/ProjectsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import JobTerminalManager from "../shared/JobTerminalManager";
import { useProjects } from "../shared/Projects";

import chalk from "chalk";
import ProjectsListContainer from "./ProjectsListContainer";

const Container = styled.div`
height: 100%;
Expand Down Expand Up @@ -121,20 +122,20 @@ const ProjectsList = React.memo(() => {

return (
<Container>
<Tabs
<ProjectsListContainer />
{/* <Tabs
vertical={true}
className={`w-100`}
large={true}
onChange={changeActiveProject}
defaultSelectedTabId={projects[0]._id}
selectedTabId={activeProject._id || projects[0]._id}
>
{/* <InputGroup className={Classes.FILL} type="text" placeholder="Search..." /> */}
<Divider />
{projects.map(project => (
<Tab key={project._id} id={project._id} title={project.name} />
))}
</Tabs>
</Tabs> */}
</Container>
);
});
Expand Down
211 changes: 211 additions & 0 deletions ui/src/components/ProjectsList/ProjectsListContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import { Classes, Icon } from "@blueprintjs/core";
import Axios from "axios";
import React from "react";
import {
DragDropContext,
Draggable,
DraggableProvided,
DragStart,
Droppable,
DroppableProvided,
DroppableStateSnapshot,
DropResult,
} from "react-beautiful-dnd";
import styled from "styled-components";
import { useConfig } from "../shared/Config";
import { useProjects } from "../shared/Projects";
import { useTheme } from "../shared/Themes";

const Container = styled.div`
margin-top: 1em;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
position: relative;
`;

const Item = styled.div`
padding: 0 10px;
width: 100%;
display: flex;
border-radius: 3px;
user-select: none;
line-height: 40px;
font-size: 14px;
max-width: 100%;
overflor: hidden;
justify-content: space-between;
align-items: center;
.drag-handle-container {
display: none;
}
&:hover {
cursor: pointer;
.drag-handle-container {
display: block;
}
color: ${props => (props.theme === Classes.DARK ? "#48aff0" : "#106ba3")} !important;
}
`;

const TabSwitchAnimator = styled.div`
position: absolute;
transition: height, transform, width, -webkit-transform;
transition-duration: 0.2s;
transition-timing-function: cubic-bezier(0.4, 1, 0.75, 0.9);
height: 40px;
width: 100%;
top: 0;
left: 0;
background: rgba(19, 124, 189, 0.2);
`;

interface IProjectsListContainerProps {}

const ProjectsListContainer: React.FC<IProjectsListContainerProps> = () => {
const { projects: tempProjects, setActiveProject, activeProject } = useProjects();
const { theme } = useTheme();
const [selectedItemIndex, setSelectedItemIndex] = React.useState<number>(0);
const [projects, setProjects] = React.useState<any>([]);
const [activeProjectIndexBeforeDrag, setActiveProjectIndexBeforeDrag] = React.useState<number>(0);
const { config } = useConfig();

React.useEffect(() => {
if (!tempProjects) {
return;
}

setProjects(tempProjects);
}, [tempProjects]);

const changeActiveProject = React.useCallback(
(projectId, index: number) => {
const activeProjectWithId = projects.find(project => project._id === projectId);
if (activeProjectWithId) {
setActiveProject(activeProjectWithId);

setSelectedItemIndex(index);
} else {
setActiveProject({
_id: "",
name: "",
type: "",
path: "",
commands: [],
});
}
},
[projects],
);

const saveNewProjectsOrder = React.useCallback(
(projects: IProject[]) => {
const save = async (projects: IProject[]) => {
try {
console.info("Saving new projects order");
const projectIds = projects.map(project => project._id);
await Axios.post(`http://localhost:${config.port}/projects/reorder`, {
projectIds,
});
setProjects(projects);
} catch (error) {
console.log("Error Reordering:", error);
}
};
save(projects);
},
[projects],
);

const onDragStart = (result: DragStart) => {
// Save Index of active project before.
// So that, we can move animated blue background only if active project changed position.
const newProjects = [...projects];
const activeProjectIndex: number = newProjects.findIndex(x => x._id === activeProject._id);
if (activeProjectIndex) {
setActiveProjectIndexBeforeDrag(activeProjectIndex);
}
};

const onDragEnd = (result: DropResult) => {
const { destination, source } = result;
if (!destination) {
return;
}

if (destination.droppableId === source.droppableId && destination.index === source.index) {
return;
}

const newProjects = [...projects];

const sourceProject = newProjects[source.index];
newProjects.splice(source.index, 1);
newProjects.splice(destination.index, 0, sourceProject);

setProjects(newProjects);
saveNewProjectsOrder(newProjects);

// Check if activeProject is moved
const activeProjectIndexAfterDrag: number = newProjects.findIndex(x => x._id === activeProject._id);
console.log("activeProjectIndexBeforeDrag:", activeProjectIndexBeforeDrag);
console.log("activeProjectIndexAfterDrag:", activeProjectIndexAfterDrag);
if (activeProjectIndexBeforeDrag !== activeProjectIndexAfterDrag) {
setSelectedItemIndex(activeProjectIndexAfterDrag);
}
};

if (projects.length === 0) {
return <div />;
}

return (
<>
<DragDropContext onDragStart={onDragStart} onDragEnd={onDragEnd}>
<Droppable droppableId={"project-list-droppable"}>
{(provided: DroppableProvided) => (
<Container ref={provided.innerRef} {...provided.droppableProps}>
<TabSwitchAnimator
style={{
transform: `translateY(${selectedItemIndex * 40}px)`,
}}
/>
{projects.map((project, index) => (
<Draggable draggableId={project._id} index={index} key={project._id}>
{(provided: DraggableProvided) => (
<Item
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
onClick={() => changeActiveProject(project._id, index)}
theme={theme}
style={{
...provided.draggableProps.style,
color:
activeProject._id === project._id
? theme === Classes.DARK
? "#48aff0"
: "#106ba3"
: "inherit",
}}
>
{project.name}
<div className="drag-handle-container">
<Icon icon="drag-handle-horizontal" />
</div>
</Item>
)}
</Draggable>
))}
{provided.placeholder}
</Container>
)}
</Droppable>
</DragDropContext>
</>
);
};

export default ProjectsListContainer;

0 comments on commit 8e4a0f3

Please sign in to comment.