fix(nav): register Journal/Planner shapes, fix headerColor crash, enable academic week expansion
Bugs fixed: - 'cc-teacher-timetable-node' missing from NODE_TYPE_THEMES caused Cannot read properties of undefined (reading 'headerColor') crash when clicking My Timetable - 'cc-journal-node' and 'cc-planner-node' had no shape utils registered, causing 'No shape util found for type' error on Journal/Planner click - Added null safety (?? fallback) to getNodeTheme to prevent future crashes from any other unmapped type - Removed AcademicWeek from canExpand exclusion so weeks can be expanded to show individual academic days Added: - CCJournalNodeShapeUtil and CCPlannerNodeShapeUtil (stub shapes) - CCJournalNodeProps and CCPlannerNodeProps types - Journal/Planner added to CCNodeTypes, ccGraphShapeProps, NODE_TYPE_THEMES - 'cc-department-structure-node' mapping added to NODE_TYPE_THEMES Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0f5dbd12bf
commit
61ef95a35e
36
src/utils/tldraw/cc-base/cc-graph/CCJournalNodeShapeUtil.tsx
Normal file
36
src/utils/tldraw/cc-base/cc-graph/CCJournalNodeShapeUtil.tsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { CCBaseShapeUtil } from '../CCBaseShapeUtil'
|
||||||
|
import { CCBaseShape } from '../cc-types'
|
||||||
|
import { ccGraphShapeProps, getDefaultCCJournalNodeProps } from './cc-graph-props'
|
||||||
|
import { getNodeStyles, NODE_THEMES, NODE_TYPE_THEMES } from './cc-graph-styles'
|
||||||
|
import { CCJournalNodeProps } from './cc-graph-types'
|
||||||
|
|
||||||
|
export interface CCJournalNodeShape extends CCBaseShape {
|
||||||
|
type: 'cc-journal-node'
|
||||||
|
props: CCJournalNodeProps
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CCJournalNodeShapeUtil extends CCBaseShapeUtil<CCJournalNodeShape> {
|
||||||
|
static type = 'cc-journal-node' as const
|
||||||
|
static props = ccGraphShapeProps['cc-journal-node']
|
||||||
|
|
||||||
|
getDefaultProps(): CCJournalNodeShape['props'] {
|
||||||
|
const defaultProps = getDefaultCCJournalNodeProps()
|
||||||
|
const theme = NODE_THEMES[NODE_TYPE_THEMES[CCJournalNodeShapeUtil.type]] ?? NODE_THEMES.resource
|
||||||
|
return {
|
||||||
|
...defaultProps,
|
||||||
|
headerColor: theme.headerColor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultComponent = () => null
|
||||||
|
|
||||||
|
renderContent = (shape: CCJournalNodeShape) => {
|
||||||
|
const styles = getNodeStyles(shape.type)
|
||||||
|
return (
|
||||||
|
<div style={styles.container}>
|
||||||
|
<div style={{ ...styles.header, color: shape.props.headerColor }}>Journal</div>
|
||||||
|
<div style={{ fontSize: 11, color: 'var(--color-text-2)' }}>Personal teaching journal</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/utils/tldraw/cc-base/cc-graph/CCPlannerNodeShapeUtil.tsx
Normal file
36
src/utils/tldraw/cc-base/cc-graph/CCPlannerNodeShapeUtil.tsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { CCBaseShapeUtil } from '../CCBaseShapeUtil'
|
||||||
|
import { CCBaseShape } from '../cc-types'
|
||||||
|
import { ccGraphShapeProps, getDefaultCCPlannerNodeProps } from './cc-graph-props'
|
||||||
|
import { getNodeStyles, NODE_THEMES, NODE_TYPE_THEMES } from './cc-graph-styles'
|
||||||
|
import { CCPlannerNodeProps } from './cc-graph-types'
|
||||||
|
|
||||||
|
export interface CCPlannerNodeShape extends CCBaseShape {
|
||||||
|
type: 'cc-planner-node'
|
||||||
|
props: CCPlannerNodeProps
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CCPlannerNodeShapeUtil extends CCBaseShapeUtil<CCPlannerNodeShape> {
|
||||||
|
static type = 'cc-planner-node' as const
|
||||||
|
static props = ccGraphShapeProps['cc-planner-node']
|
||||||
|
|
||||||
|
getDefaultProps(): CCPlannerNodeShape['props'] {
|
||||||
|
const defaultProps = getDefaultCCPlannerNodeProps()
|
||||||
|
const theme = NODE_THEMES[NODE_TYPE_THEMES[CCPlannerNodeShapeUtil.type]] ?? NODE_THEMES.resource
|
||||||
|
return {
|
||||||
|
...defaultProps,
|
||||||
|
headerColor: theme.headerColor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultComponent = () => null
|
||||||
|
|
||||||
|
renderContent = (shape: CCPlannerNodeShape) => {
|
||||||
|
const styles = getNodeStyles(shape.type)
|
||||||
|
return (
|
||||||
|
<div style={styles.container}>
|
||||||
|
<div style={{ ...styles.header, color: shape.props.headerColor }}>Planner</div>
|
||||||
|
<div style={{ fontSize: 11, color: 'var(--color-text-2)' }}>Lesson and weekly planner</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -272,6 +272,14 @@ export const ccGraphShapeProps = {
|
|||||||
school_db_name: T.string,
|
school_db_name: T.string,
|
||||||
school_period_id: T.string,
|
school_period_id: T.string,
|
||||||
},
|
},
|
||||||
|
'cc-journal-node': {
|
||||||
|
...graphBaseProps,
|
||||||
|
path: T.string,
|
||||||
|
},
|
||||||
|
'cc-planner-node': {
|
||||||
|
...graphBaseProps,
|
||||||
|
path: T.string,
|
||||||
|
},
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
// Default props getters
|
// Default props getters
|
||||||
@ -640,3 +648,17 @@ export const getDefaultCCUserTeacherTimetableNodeProps = () => ({
|
|||||||
school_db_name: '',
|
school_db_name: '',
|
||||||
school_timetable_id: '',
|
school_timetable_id: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const getDefaultCCJournalNodeProps = () => ({
|
||||||
|
...getDefaultBaseProps(),
|
||||||
|
title: 'Journal',
|
||||||
|
__primarylabel__: 'Journal',
|
||||||
|
path: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
export const getDefaultCCPlannerNodeProps = () => ({
|
||||||
|
...getDefaultBaseProps(),
|
||||||
|
title: 'Planner',
|
||||||
|
__primarylabel__: 'Planner',
|
||||||
|
path: '',
|
||||||
|
})
|
||||||
@ -148,12 +148,18 @@ export const NODE_TYPE_THEMES: Record<string, keyof typeof NODE_THEMES> = {
|
|||||||
'cc-department-node': 'resource',
|
'cc-department-node': 'resource',
|
||||||
'cc-room-node': 'resource',
|
'cc-room-node': 'resource',
|
||||||
'cc-subject-class-node': 'resource',
|
'cc-subject-class-node': 'resource',
|
||||||
|
// Timetable nodes (missing from original map)
|
||||||
|
'cc-teacher-timetable-node': 'academic',
|
||||||
|
'cc-department-structure-node': 'resource',
|
||||||
|
// Personal nodes
|
||||||
|
'cc-journal-node': 'calendar',
|
||||||
|
'cc-planner-node': 'calendar',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
// Helper function to get theme for a node type
|
// Helper function to get theme for a node type
|
||||||
export const getNodeTheme = (nodeType: string) => {
|
export const getNodeTheme = (nodeType: string) => {
|
||||||
const themeKey = NODE_TYPE_THEMES[nodeType]
|
const themeKey = NODE_TYPE_THEMES[nodeType]
|
||||||
return themeKey ? NODE_THEMES[themeKey] : NODE_THEMES.resource // Default to resource theme
|
return (themeKey ? NODE_THEMES[themeKey] : null) ?? NODE_THEMES.resource
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to get theme from primary label
|
// Helper function to get theme from primary label
|
||||||
|
|||||||
@ -279,6 +279,14 @@ export type CCTimetableLessonNodeProps = CCGraphShapeProps & {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Define a type-safe mapping of node types to their configurations
|
// Define a type-safe mapping of node types to their configurations
|
||||||
|
export type CCJournalNodeProps = CCGraphShapeProps & {
|
||||||
|
path: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CCPlannerNodeProps = CCGraphShapeProps & {
|
||||||
|
path: string
|
||||||
|
}
|
||||||
|
|
||||||
export type CCNodeTypes = {
|
export type CCNodeTypes = {
|
||||||
User: { props: CCUserNodeProps }
|
User: { props: CCUserNodeProps }
|
||||||
Developer: { props: CCUserNodeProps }
|
Developer: { props: CCUserNodeProps }
|
||||||
@ -316,6 +324,8 @@ export type CCNodeTypes = {
|
|||||||
DepartmentStructure: { props: CCDepartmentStructureNodeProps }
|
DepartmentStructure: { props: CCDepartmentStructureNodeProps }
|
||||||
UserTeacherTimetable: { props: CCUserTeacherTimetableNodeProps }
|
UserTeacherTimetable: { props: CCUserTeacherTimetableNodeProps }
|
||||||
UserTimetableLesson: { props: CCTimetableLessonNodeProps }
|
UserTimetableLesson: { props: CCTimetableLessonNodeProps }
|
||||||
|
Journal: { props: CCJournalNodeProps }
|
||||||
|
Planner: { props: CCPlannerNodeProps }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to get shape type from node type
|
// Helper function to get shape type from node type
|
||||||
@ -376,5 +386,7 @@ export const isValidNodeType = (type: string): type is keyof CCNodeTypes => {
|
|||||||
DepartmentStructure: true,
|
DepartmentStructure: true,
|
||||||
UserTeacherTimetable: true,
|
UserTeacherTimetable: true,
|
||||||
UserTimetableLesson: true,
|
UserTimetableLesson: true,
|
||||||
|
Journal: true,
|
||||||
|
Planner: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -43,6 +43,8 @@ import { CCDepartmentStructureNodeShapeUtil } from './cc-base/cc-graph/CCDepartm
|
|||||||
import { CCUserTeacherTimetableNodeShapeUtil } from './cc-base/cc-graph/CCUserTeacherTimetableNodeShapeUtil'
|
import { CCUserTeacherTimetableNodeShapeUtil } from './cc-base/cc-graph/CCUserTeacherTimetableNodeShapeUtil'
|
||||||
import { CCSearchShapeUtil } from './cc-base/cc-search/CCSearchShapeUtil'
|
import { CCSearchShapeUtil } from './cc-base/cc-search/CCSearchShapeUtil'
|
||||||
import { CCWebBrowserShapeUtil } from './cc-base/cc-web-browser/CCWebBrowserUtil'
|
import { CCWebBrowserShapeUtil } from './cc-base/cc-web-browser/CCWebBrowserUtil'
|
||||||
|
import { CCJournalNodeShapeUtil } from './cc-base/cc-graph/CCJournalNodeShapeUtil'
|
||||||
|
import { CCPlannerNodeShapeUtil } from './cc-base/cc-graph/CCPlannerNodeShapeUtil'
|
||||||
// Define all shape utils in a single object for easy maintenance
|
// Define all shape utils in a single object for easy maintenance
|
||||||
export const ShapeUtils = {
|
export const ShapeUtils = {
|
||||||
CCSlideShow: CCSlideShowShapeUtil,
|
CCSlideShow: CCSlideShowShapeUtil,
|
||||||
@ -89,6 +91,8 @@ export const ShapeUtils = {
|
|||||||
CCUserTeacherTimetableNode: CCUserTeacherTimetableNodeShapeUtil,
|
CCUserTeacherTimetableNode: CCUserTeacherTimetableNodeShapeUtil,
|
||||||
CCSearch: CCSearchShapeUtil,
|
CCSearch: CCSearchShapeUtil,
|
||||||
CCWebBrowser: CCWebBrowserShapeUtil,
|
CCWebBrowser: CCWebBrowserShapeUtil,
|
||||||
|
CCJournalNode: CCJournalNodeShapeUtil,
|
||||||
|
CCPlannerNode: CCPlannerNodeShapeUtil,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const allShapeUtils = Object.values(ShapeUtils)
|
export const allShapeUtils = Object.values(ShapeUtils)
|
||||||
@ -137,7 +137,6 @@ function TreeItem({ node, depth, onSelect, onExpand }: TreeItemProps) {
|
|||||||
|
|
||||||
const canExpand = node.has_children !== false
|
const canExpand = node.has_children !== false
|
||||||
&& node.node_type !== 'CalendarDay'
|
&& node.node_type !== 'CalendarDay'
|
||||||
&& node.node_type !== 'AcademicWeek'
|
|
||||||
&& node.status !== 'empty'
|
&& node.status !== 'empty'
|
||||||
&& node.status !== 'no_school'
|
&& node.status !== 'no_school'
|
||||||
&& node.status !== 'not_initialized';
|
&& node.status !== 'not_initialized';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user