-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8741a67
commit ba6793f
Showing
9 changed files
with
361 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
107 changes: 107 additions & 0 deletions
107
web/src/routes/ProjectView/GanttView/GantViewTimeline.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import React, { useState, useEffect } from 'react' | ||
|
||
export type GanttViewTimelineProps = { | ||
tasks?: Array<{ | ||
name: string | ||
startDate: Date | ||
endDate: Date | ||
}> | ||
} | ||
|
||
const dayWidth = 28 // Width for each day | ||
|
||
const GanttViewTimeline: React.FC<GanttViewTimelineProps> = ({ | ||
tasks = [], | ||
}) => { | ||
// State for days in the timeline | ||
const [days, setDays] = useState<Date[]>([]) | ||
|
||
useEffect(() => { | ||
// Determine the start and end of the current month | ||
const now = new Date() | ||
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1) | ||
const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0) | ||
const dates = [] | ||
|
||
// Loop through all days in the month and add them to state | ||
for ( | ||
let day = new Date(startOfMonth); | ||
day <= endOfMonth; | ||
day.setDate(day.getDate() + 1) | ||
) { | ||
dates.push(new Date(day)) | ||
} | ||
|
||
setDays(dates) | ||
}, []) // Empty dependency array means this effect will only run once | ||
|
||
return ( | ||
<div | ||
className="gantt-view-timeline" | ||
style={{ position: 'relative', overflowX: 'scroll', width: '100%' }} | ||
> | ||
{/* Render the days */} | ||
<div className="gantt-view-time-display"> | ||
<div className="gantt-view-month"> | ||
{days.length > 0 && | ||
days[0].toLocaleDateString('default', { month: 'long' })} | ||
</div> | ||
<div className="gantt-view-dates"> | ||
{days.map((day, index) => ( | ||
<div | ||
className="gantt-view-date" | ||
key={index} | ||
style={{ | ||
width: `${dayWidth}px`, | ||
}} | ||
> | ||
{day.getDate()} | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
|
||
{/* Render the tasks */} | ||
<div | ||
style={{ | ||
position: 'absolute', | ||
top: '20px', | ||
width: `${days.length * dayWidth}px`, | ||
}} | ||
> | ||
{' '} | ||
{/* Adjust positioning as needed */} | ||
{tasks.map((task, index) => { | ||
const startDayIndex = days.findIndex( | ||
(d) => d.toDateString() === task.startDate.toDateString() | ||
) | ||
const endDayIndex = days.findIndex( | ||
(d) => d.toDateString() === task.endDate.toDateString() | ||
) | ||
const duration = endDayIndex - startDayIndex + 1 // Include the end day in the duration | ||
const left = startDayIndex * dayWidth | ||
const width = duration * dayWidth | ||
|
||
return ( | ||
<div | ||
key={index} | ||
style={{ | ||
position: 'absolute', | ||
left: `${left}px`, | ||
width: `${width}px`, | ||
height: '20px', // Adjust height as needed | ||
backgroundColor: 'blue', // Adjust color as needed | ||
textAlign: 'center', | ||
color: 'white', | ||
}} | ||
> | ||
{task.name} | ||
</div> | ||
) | ||
})} | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
export default GanttViewTimeline |
60 changes: 60 additions & 0 deletions
60
web/src/routes/ProjectView/GanttView/GanttView.component.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import React, { useContext } from 'react' | ||
import './GanttView.scss' | ||
|
||
import { LayeringAlgorithm, Profile } from '../../../types' | ||
import ComputedOutcomeContext from '../../../context/ComputedOutcomeContext' | ||
import { Tag } from '../../../types' | ||
import { | ||
ActionHashB64, | ||
AgentPubKeyB64, | ||
WithActionHash, | ||
} from '../../../types/shared' | ||
import IndentedTreeView from '../../../components/IndentedTreeView/IndentedTreeView' | ||
import GanttViewContent from './GanttViewContent' | ||
// import OutcomeGanttWithFilters from '../../../components/OutcomeGanttWithFilters/OutcomeGanttWithFilters' | ||
|
||
export type GanttViewConnectorStateProps = { | ||
whoAmI: Profile | ||
topPriorityOutcomes: ActionHashB64[] | ||
presentMembers: AgentPubKeyB64[] | ||
projectMemberProfiles: Profile[] | ||
projectTags: WithActionHash<Tag>[] | ||
} | ||
|
||
export type GanttViewConnectorDispatchProps = { | ||
openExpandedView: (actionHash: ActionHashB64) => void | ||
goToOutcome: (actionHash: ActionHashB64) => void | ||
} | ||
|
||
export type GanttViewProps = GanttViewConnectorStateProps & | ||
GanttViewConnectorDispatchProps | ||
|
||
const GanttView: React.FC<GanttViewProps> = ({ | ||
whoAmI, | ||
topPriorityOutcomes, | ||
presentMembers, | ||
projectMemberProfiles, | ||
projectTags, | ||
openExpandedView, | ||
goToOutcome, | ||
}) => { | ||
const { computedOutcomesAsTree } = useContext(ComputedOutcomeContext) | ||
|
||
return ( | ||
<div className="gantt-view"> | ||
<GanttViewContent /> | ||
{/* <OutcomeGanttWithFilters | ||
topPriorityOutcomes={topPriorityOutcomes} | ||
projectTags={projectTags} | ||
whoAmI={whoAmI} | ||
presentMembers={presentMembers} | ||
projectMemberProfiles={projectMemberProfiles} | ||
computedOutcomesAsTree={computedOutcomesAsTree} | ||
openExpandedView={openExpandedView} | ||
goToOutcome={goToOutcome} | ||
/> */} | ||
</div> | ||
) | ||
} | ||
|
||
export default GanttView |
50 changes: 50 additions & 0 deletions
50
web/src/routes/ProjectView/GanttView/GanttView.connector.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { connect } from 'react-redux' | ||
import { RootState } from '../../../redux/reducer' | ||
import { openExpandedView } from '../../../redux/ephemeral/expanded-view/actions' | ||
import selectProjectMembersPresent from '../../../redux/persistent/projects/realtime-info-signal/select' | ||
import { ActionHashB64 } from '../../../types/shared' | ||
import GanttView, { | ||
GanttViewConnectorDispatchProps, | ||
GanttViewConnectorStateProps, | ||
} from './GanttView.component' | ||
import { WireRecord } from '../../../api/hdkCrud' | ||
import { Profile } from '../../../types' | ||
import { animatePanAndZoom } from '../../../redux/ephemeral/viewport/actions' | ||
|
||
function mapStateToProps(state: RootState): GanttViewConnectorStateProps { | ||
const projectId = state.ui.activeProject | ||
const whoAmIWireRecord = state.whoami || ({} as WireRecord<Profile>) | ||
// can be undefined, based on line above, intentionally | ||
const whoAmI = whoAmIWireRecord.entry | ||
const projectMeta = state.projects.projectMeta[projectId] | ||
const topPriorityOutcomes = projectMeta ? projectMeta.topPriorityOutcomes : [] | ||
const projectTagsObject = state.projects.tags[projectId] || {} | ||
const projectMembers = state.projects.members[projectId] || {} | ||
const projectMemberProfiles = Object.keys(projectMembers) | ||
.map((address) => state.agents[address]) | ||
.filter((agent) => agent) | ||
|
||
const presentMembers = projectId | ||
? selectProjectMembersPresent(state, projectId) | ||
: [] | ||
|
||
const projectTags = Object.values(projectTagsObject) | ||
return { | ||
whoAmI, | ||
topPriorityOutcomes, | ||
presentMembers, | ||
projectMemberProfiles, | ||
projectTags, | ||
} | ||
} | ||
function mapDispatchToProps(dispatch): GanttViewConnectorDispatchProps { | ||
return { | ||
openExpandedView: (actionHash: ActionHashB64) => { | ||
return dispatch(openExpandedView(actionHash)) | ||
}, | ||
goToOutcome: (actionHash: ActionHashB64) => { | ||
return dispatch(animatePanAndZoom(actionHash, true)) | ||
}, | ||
} | ||
} | ||
export default connect(mapStateToProps, mapDispatchToProps)(GanttView) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
.gantt-view { | ||
flex: 1; | ||
overflow: hidden; | ||
} | ||
|
||
.gantt-view-content { | ||
display: flex; | ||
flex-direction: row; | ||
width: 100vw; | ||
height: 100%; | ||
|
||
.gantt-view-content-timeline { | ||
flex: 1; | ||
overflow: auto; | ||
overflow: hidden; | ||
background-color: var(--bg-color-secondary); | ||
} | ||
} | ||
|
||
.gantt-view-timeline { | ||
display: flex; | ||
flex-direction: column; | ||
width: 100%; | ||
height: 100%; | ||
padding: 0 0 0 0; | ||
overflow: hidden; | ||
background-color: var(--bg-color-secondary); | ||
|
||
.gantt-view-time-display { | ||
// overflow-x: scroll; | ||
display: flex; | ||
flex-direction: column; | ||
|
||
.gantt-view-month { | ||
display: flex; | ||
flex-direction: row; | ||
justify-content: space-between; | ||
padding: var(--padding-0825rem); | ||
border-bottom: var(--border-gantt); | ||
font-size: var(--font-size-medium); | ||
font-family: var(--font-family-primary-semibold); | ||
} | ||
|
||
.gantt-view-dates { | ||
display: grid; | ||
grid-auto-flow: column; // ensures the grid flows horizontally | ||
overflow-x: auto; | ||
border-bottom: var(--border-gantt); | ||
|
||
.gantt-view-date { | ||
width: 3rem; | ||
padding: var(--padding-0825rem); | ||
border-right: var(--border-gantt); | ||
text-align: center; | ||
font-size: var(--font-size-xsmallPlus); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import React from 'react' | ||
import IndentedTreeView from '../../../components/IndentedTreeView/IndentedTreeView' | ||
import { LayeringAlgorithm } from '../../../types' | ||
import GantViewTimeline from './GantViewTimeline' | ||
|
||
export type GanttViewContentProps = {} | ||
|
||
const GanttViewContent: React.FC<GanttViewContentProps> = ({}) => { | ||
return ( | ||
// inside the div with gantt-view-timeline class, we will render the timeline | ||
|
||
<div className="gantt-view-content"> | ||
<IndentedTreeView | ||
outcomeTrees={[]} | ||
projectMeta={undefined} | ||
updateProjectMeta={function ( | ||
entry: { | ||
name: string | ||
image: string | ||
isImported: boolean | ||
creatorAgentPubKey: string | ||
createdAt: number | ||
passphrase: string | ||
isMigrated: string | ||
layeringAlgorithm: LayeringAlgorithm | ||
topPriorityOutcomes: string[] | ||
}, | ||
actionHash: string | ||
): Promise<void> { | ||
throw new Error('Function not implemented.') | ||
}} | ||
/> | ||
<div className="gantt-view-content-timeline"> | ||
<GantViewTimeline /> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
export default GanttViewContent |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters