Index

src/app/app.config.ts

appConfig
Type : ApplicationConfig
Default value : { providers: [ provideAnalytics(withRouterEvents(), withErrorHandler()), provideAppConfiguration({ name: 'cns-website', version: '1.0.0', url: 'https://cns.iu.edu/', }), provideBrandLogos({ label: 'CNS Website', url: 'https://cns.iu.edu', logos: [ { size: 'regular', src: 'assets/brand/logo/cns-regular.svg', width: 140, height: 47, }, { size: 'small', src: 'assets/brand/logo/cns-small.svg', width: 84, height: 28, }, ], }), provideContentTemplateDefs([ ActionCardDef, ApiCommandDef, ButtonDef, FlexContainerDef, GridContainerDef, IconDef, ImageDef, MarkdownDef, PageSectionDef, PageTableDef, ProfileCardDef, TextHyperlinkDef, YouTubePlayerDef, GoogleMapsDef, ]), provideDesignSystem(), provideMarkdown({ loader: HttpClient }), provideRouter( appRoutes, withComponentInputBinding(), withInMemoryScrolling({ anchorScrolling: 'enabled', scrollPositionRestoration: 'enabled' }), withNavigationErrorHandler(handleNavigationError), ), provideRouterExt(), provideSocials(CNS_SOCIALS), provideZonelessChangeDetection(), ], }

Application configuration

src/app/app.routes.ts

appRoutes
Type : Route[]
Default value : [ { path: '', pathMatch: 'full', component: LandingPageComponent, resolve: { featuredContent: createJsonSpecResolver(FEATURED_INDEX_URL, FeaturedDataSchema), eventTypes: createJsonSpecResolver(EVENT_TYPES_INDEX_URL, ResearchTypesDataSchema), publicationTypes: createJsonSpecResolver(PUBLICATION_TYPES_INDEX_URL, ResearchTypesDataSchema), fundingTypes: createJsonSpecResolver(FUNDING_TYPES_INDEX_URL, ResearchTypesDataSchema), tags: createJsonSpecResolver(TAGS_INDEX_URL, TagsDataSchema), }, }, // Content pages // Please try to keep sorted in alphabetical order { path: 'about', component: ContentPageComponent, resolve: { data: createYamlSpecResolver('assets/content/about-page/data.yaml', ContentPageDataSchema), }, }, { path: 'amatria', component: ContentPageComponent, resolve: { data: createYamlSpecResolver('assets/content/amatria/data.yaml', ContentPageDataSchema), }, }, { path: 'jobs', component: ContentPageComponent, resolve: { data: createYamlSpecResolver('assets/content/jobs-page/data.yaml', ContentPageDataSchema), }, }, { path: 'people', children: [ { path: '', pathMatch: 'full', component: CurrentTeamComponent, resolve: { data: createJsonSpecResolver(PEOPLE_INDEX_URL, PeopleDataSchema), }, }, { path: ':slug', component: PeopleProfileComponent, resolve: { data: createPersonResolver(PERSON_BASE_URL), }, }, ], }, { path: 'privacy-policy', component: ContentPageComponent, resolve: { data: createYamlSpecResolver('assets/content/privacy-policy-page/data.yaml', ContentPageDataSchema), }, }, { path: 'research', component: ResearchPageComponent, resolve: { news: createJsonSpecResolver(NEWS_INDEX_URL, ResearchDataSchema), publications: createJsonSpecResolver(PUBLICATIONS_INDEX_URL, ResearchDataSchema), events: createJsonSpecResolver(EVENT_INDEX_URL, ResearchDataSchema), funding: createJsonSpecResolver(FUNDING_INDEX_URL, ResearchDataSchema), visualizations: createJsonSpecResolver(VISUALIZATIONS_INDEX_URL, ResearchDataSchema), people: createJsonSpecResolver(PEOPLE_INDEX_URL, PeopleDataSchema), publicationTypes: createJsonSpecResolver(PUBLICATION_TYPES_INDEX_URL, ResearchTypesDataSchema), eventTypes: createJsonSpecResolver(EVENT_TYPES_INDEX_URL, ResearchTypesDataSchema), fundingTypes: createJsonSpecResolver(FUNDING_TYPES_INDEX_URL, ResearchTypesDataSchema), tags: createJsonSpecResolver(TAGS_INDEX_URL, TagsDataSchema), }, }, { path: 'visitor-info', component: ContentPageComponent, resolve: { data: createYamlSpecResolver('assets/content/visitor-info-page/data.yaml', ContentPageDataSchema), }, }, // Error pages { path: '500', component: ServerErrorPageComponent, }, { path: '**', component: NotFoundPageComponent, }, ]

Application routes

EVENT_INDEX_URL
Type : string
Default value : 'https://cns-iu.github.io/cns-website/assets/indexes/app-events.json'

Events content index URL

EVENT_TYPES_INDEX_URL
Type : string
Default value : 'https://cns-iu.github.io/cns-website/assets/indexes/app-event-types.json'

Event types content index URL

FEATURED_INDEX_URL
Type : string
Default value : 'https://cns-iu.github.io/cns-website/assets/indexes/app-featured.json'

Featured content index URL

FUNDING_INDEX_URL
Type : string
Default value : 'https://cns-iu.github.io/cns-website/assets/indexes/app-funding.json'

Funding content index URL

FUNDING_TYPES_INDEX_URL
Type : string
Default value : 'https://cns-iu.github.io/cns-website/assets/indexes/app-funding-types.json'

Funding types content index URL

NEWS_INDEX_URL
Type : string
Default value : 'https://cns-iu.github.io/cns-website/assets/indexes/app-news.json'

News content index URL

PEOPLE_INDEX_URL
Type : string
Default value : 'https://cns-iu.github.io/cns-website/assets/indexes/app-people.json'

People index URL

PERSON_BASE_URL
Type : string
Default value : 'https://cns-iu.github.io/cns-website/content/people'

Base URL for person content

PUBLICATION_TYPES_INDEX_URL
Type : string
Default value : 'https://cns-iu.github.io/cns-website/assets/indexes/app-publication-types.json'

Publication types content index URL

PUBLICATIONS_INDEX_URL
Type : string
Default value : 'https://cns-iu.github.io/cns-website/assets/indexes/app-publications.json'

Publications content index URL

TAGS_INDEX_URL
Type : string
Default value : 'https://cns-iu.github.io/cns-website/assets/indexes/app-tags.json'

Tags content index URL

VISUALIZATIONS_INDEX_URL
Type : string
Default value : 'https://cns-iu.github.io/cns-website/assets/indexes/app-visualizations.json'

Visualizations content index URL

src/app/schemas/roles.schema.ts

BaseRoleSchema
Type : unknown
Default value : z.object({ dateStart: z.coerce.date(), dateEnd: z.union([z.literal('').transform(() => null), z.coerce.date()]).nullable(), })

Base role schema with common fields

CollaboratorRoleSchema
Type : unknown
Default value : z .object({ ...BaseRoleSchema.shape, type: z.literal('collaborator'), project: z.string(), }) .meta({ id: 'RoleCollaborator' })

Collaborator role schema

MemberRoleSchema
Type : unknown
Default value : z .object({ ...BaseRoleSchema.shape, type: z.literal('member'), title: z.string(), displayOrder: z.number().nullish(), office: z.string(), phone: z.string(), fax: z.string(), email: z.string(), education: z.string(), background: z.string(), interests: z.string(), }) .meta({ id: 'RoleMember' })

Member role schema

RoleSchema
Type : unknown
Default value : z .discriminatedUnion('type', [MemberRoleSchema, StudentRoleSchema, CollaboratorRoleSchema]) .meta({ id: 'Role' })

Discriminated union of all role types

StudentRoleSchema
Type : unknown
Default value : z .object({ ...BaseRoleSchema.shape, type: z.literal('student'), topic: z.string(), degree: z.enum(['Ph.D.', 'Masters']).nullable(), department: z.string(), }) .meta({ id: 'RoleStudent' })

Student role schema

src/app/pages/research-page/state/with-filters.feature.ts

CATEGORIES_FILTER
Type : FilterOptionCategory<CategoryOption>
Default value : { id: 'category', label: 'Category', options: CATEGORY_OPTIONS, selected: [], }

Category filter configuration

CATEGORY_OPTIONS
Type : CategoryOption[]
Default value : [ { id: 'data-tool' as ResearchCategoryId, label: 'Data & tools' }, { id: 'event' as ResearchCategoryId, label: 'Events' }, { id: 'funding' as ResearchCategoryId, label: 'Funding' }, { id: 'display' as ResearchCategoryId, label: 'Interactive displays' }, { id: 'miscellaneous' as ResearchCategoryId, label: 'Miscellaneous' }, { id: 'news' as ResearchCategoryId, label: 'News' }, { id: 'publication' as ResearchCategoryId, label: 'Publications' }, { id: 'software' as ResearchCategoryId, label: 'Software Products' }, { id: 'teaching' as ResearchCategoryId, label: 'Teaching' }, { id: 'visualization' as ResearchCategoryId, label: 'Visualizations' }, ]

Category filter options

EVENTS_FILTER
Type : FilterOptionCategory<EventOption>
Default value : { id: 'event-type', label: 'Event type', options: [], selected: [], }

Event filter configuration

FUNDING_FILTER
Type : FilterOptionCategory<FundingOption>
Default value : { id: 'funding-type', label: 'Funding type', options: [], selected: [], }

Funding filter configuration

initialState
Type : FilterState
Default value : { categories: null, publicationIds: null, eventIds: null, fundingIds: null, peopleIds: null, years: null, search: null, }

Initial filter state with no selections

PEOPLE_FILTER
Type : FilterOptionCategory<PeopleOption>
Default value : { id: 'people', label: 'People', options: [], selected: [], }

People filter configuration

PUBLICATIONS_FILTER
Type : FilterOptionCategory<PublicationOption>
Default value : { id: 'publication-type', label: 'Publication type', options: [], selected: [], }

Publication filter configuration

YEAR_OPTIONS
Type : YearOption[]
Default value : createYearList(1991).map((year) => ({ id: year.toString(), label: year.toString(), year, }))

Year filter options from 1991 to current year

YEARS_FILTER
Type : FilterOptionCategory<YearOption>
Default value : { id: 'year', label: 'Year', options: YEAR_OPTIONS, selected: [], }

Year filter configuration

src/app/components/static-data/parsed.ts

CNS_SOCIAL_IDS
Type : unknown
Default value : CNS_SOCIALS.map(({ id }) => id)

All available CNS social ids

CNS_SOCIALS
Type : unknown
Default value : SocialsSchema.parse(RAW_CNS_SOCIALS).socials

Parsed CNS social media items

src/app/pages/landing-page/landing-page.component.ts

CONTENT_TYPE_ITEMS
Type : ContentTypeItem[]
Default value : [ { label: 'Featured', slug: 'featured' }, { label: 'Publications', slug: 'publications' }, { label: 'News', slug: 'news' }, ]

Predefined content type items for the landing page

src/app/pages/current-team/state/current-team.store.ts

CurrentTeamStore
Type : unknown
Default value : signalStore( withPeople(), withFilters(), withOrdering(), withHooks({ onInit(store) { const teamType = createWritableStateSlice(store.team, store.setTeam); const roles = createWritableStateSlice(store.roles, store.setRoles); const years = createWritableStateSlice(store.years, store.setYears); const search = createWritableStateSlice(store.search, store.setSearch); const sortBy = createWritableStateSlice(store._sortBy, store.setSortBy); const groupBy = createWritableStateSlice(store.groupBy, store.setGroupBy); const commonOptions = { replaceUrl: true, preserveFragment: true }; linkedQueryParam('team', { source: teamType, parse: parseTeamType, ...commonOptions }); linkedQueryParam('roles', { source: roles, parse: parseRoles, stringify: serializeRoles, ...commonOptions }); linkedQueryParam('years', { source: years, parse: parseYears, stringify: serializeYears, ...commonOptions }); linkedQueryParam('search', { source: search, parse: parseSearch, ...commonOptions }); linkedQueryParam('sortBy', { source: sortBy, parse: parseSortBy, ...commonOptions }); linkedQueryParam('groupBy', { source: groupBy, parse: parseGroupBy, ...commonOptions }); }, }), )

Signal store for managing current team state. Combines people management, filtering, and ordering features.

src/app/components/header/header.component.ts

DESKTOP_MENU_POSITIONS
Type : ConnectedPosition[]
Default value : [ { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetX: -16, offsetY: 16 }, ]

Position of the desktop menu overlay

MOBILE_MENU_POSITIONS
Type : ConnectedPosition[]
Default value : [ { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'top' }, ]

Position of the mobile menu overlay

src/app/schemas/featured.schema.ts

FeaturedDataSchema
Type : unknown
Default value : z .object({ featured: z.array(ResearchItemSchema), news: z.array(ResearchItemSchema), publications: z.array(ResearchItemSchema), }) .meta({ id: 'FeaturedData' })

Featured data schema

src/app/components/footer/static-data/parsed.ts

FUNDER_IDS
Type : unknown
Default value : FUNDERS.map(({ id }) => id)

All available funder ids

FUNDERS
Type : unknown
Default value : FundersSchema.parse(RAW_FUNDERS).funders

Parsed funders static data

src/app/components/footer/types/funders.schema.ts

FunderSchema
Type : unknown
Default value : z .object({ id: z.string().brand<'FunderId'>(), name: z.string(), link: z.string().url(), image: z.string(), }) .meta({ id: 'CnsFunder' })

Schema for a funder item

FundersSchema
Type : unknown
Default value : z .object({ $schema: z.string(), funders: FunderSchema.array(), }) .meta({ id: 'CnsFunders' })

Schema for multiple funders

src/app/pages/current-team/state/with-ordering.feature.ts

GROUP_BY_KEY_LABELS
Type : Record<GroupByKey, string>
Default value : { '': '', current: 'Current', skip: '', unknown: 'Unknown', [RefinedRoleType.Collaborator]: 'Collaborators', [RefinedRoleType.MasterStudent]: 'Master Students', [RefinedRoleType.PhDStudent]: 'PhD Students', [RefinedRoleType.Staff]: 'Staff', [RefinedRoleType.Student]: 'Students', }

Labels for groupBy keys

GROUP_BY_KEY_ORDER
Type : Record<GroupByKey, number>
Default value : { '': 9999, current: -1, skip: 9999, unknown: 6, [RefinedRoleType.Collaborator]: 5, [RefinedRoleType.MasterStudent]: 3, [RefinedRoleType.PhDStudent]: 2, [RefinedRoleType.Staff]: 0, [RefinedRoleType.Student]: 4, }

Order of groupBy keys for sorting. Some keys should never appear at this point, but are included to ensure consistency. They are instead given high values (9999). Also 'current' should only appear in combination with numeric years and is always placed before any year.

initialOrderingState
Type : OrderingState
Default value : { _sortBy: null, groupBy: null, }

Initial state for ordering

src/app/pages/current-team/state/with-filters.feature.ts

initialFilterState
Type : FilterState
Default value : { team: TeamType.Current, roles: null, years: null, search: null, }

Initial state for filters

ROLES_FILTER
Type : FilterOptionCategory<RoleTypeOption>
Default value : { id: 'roles', label: 'Role', disableSearch: true, options: REFINED_ROLE_TYPE_OPTIONS, selected: [], }

Filter configuration for roles with all available role type options

YEAR_OPTIONS
Type : YearOption[]
Default value : createYearList(2000).map((year) => ({ id: year.toString(), label: year.toString(), year, }))

Available year options for filtering team members by active year (from 2000 to current year)

YEARS_FILTER
Type : FilterOptionCategory<YearOption>
Default value : { id: 'years', label: 'Active year', options: YEAR_OPTIONS, selected: [], }

Filter configuration for years with all available year options

src/app/state/sidebar/sidebar.store.ts

initialState
Type : SidebarState
Default value : { sidebar: null, }

Initial state for sidebar

SidebarStore
Type : unknown
Default value : signalStore( { providedIn: 'root' }, withState(initialState), withComputed((store) => { const hasSidebar = computed(() => store.sidebar() !== null); const _isWideScreen = watchBreakpoint('(min-width: 1100px)'); const mode = computed(() => (_isWideScreen() ? 'side' : 'over')); return { hasSidebar, mode, _isWideScreen }; }), withLinkedState((store) => ({ isOpen: () => store._isWideScreen(), })), withMethods((store) => ({ setSidebar: (sidebar: MatSidenav) => { if (untracked(store.sidebar) !== null) { throw new Error('Sidebar has already been set.'); } patchState(store, { sidebar }); }, clearSidebar: () => patchState(store, { sidebar: null }), open: () => patchState(store, { isOpen: true }), close: () => patchState(store, { isOpen: false }), toggle: () => patchState(store, (state) => ({ isOpen: !state.isOpen })), })), )

Global store for managing the sidebar state

src/app/pages/research-page/state/with-ordering.feature.ts

initialState
Type : OrderingState
Default value : { sortBy: SortBy.Newest, groupBy: null, }

Default ordering state (newest, no grouping)

src/app/pages/research-page/state/with-research.feature.ts

initialState
Type : ResearchState
Default value : { researchItems: [], peopleItems: [], pubTypes: [], eventTypes: [], fundingTypes: [], tags: [], }

Initial empty research state

src/app/pages/research-page/state/with-view.feature.ts

initialState
Type : ViewState
Default value : { view: View.Gallery, }

Default view state (gallery)

src/app/components/header/types/menus.schema.ts

MenuGroupSchema
Type : unknown
Default value : z .object({ type: z.literal('group'), label: z.string(), description: z.string().optional(), external: z.boolean().optional(), target: z.string().optional(), items: MenuItemSchema.array(), }) .meta({ id: 'CnsHeaderMenuGroup' })

Schema for a menu group

MenuItemSchema
Type : unknown
Default value : z .object({ type: z.literal('item'), label: z.string(), url: z.string().url(), tagline: z.string().optional(), imgSrc: z.string().optional(), external: z.boolean().optional(), target: z.string().optional(), }) .meta({ id: 'CnsHeaderMenuItem' })

Schema for a menu item

MenuSchema
Type : unknown
Default value : z .object({ type: z.literal('menu'), id: z.string(), label: z.string(), items: MenuGroupSchema.array().optional(), featured: MenuItemSchema.optional(), }) .meta({ id: 'CnsHeaderMenu' })

Schema for a menu

MenusSchema
Type : unknown
Default value : z .object({ $schema: z.string(), options: z.union([MenuSchema, MenuItemSchema]).array(), }) .meta({ id: 'CnsHeaderMenus' })

Schema for multiple menus

src/app/components/header/static-data/parsed.ts

MENUS
Type : unknown
Default value : menus as Menus

Menus objects

src/app/pages/current-team/state/with-people.feature.ts

peopleConfig
Type : unknown
Default value : entityConfig({ collection: 'people', entity: type<PeopleItem>(), selectId: (person) => person.slug, })

Entity configuration for people

src/app/schemas/people.schema.ts

PeopleDataSchema
Type : unknown
Default value : z.array(PeopleItemSchema)

People data schema (array of items)

PeopleIdSchema
Type : unknown
Default value : z.string().brand('PeopleId')

Branded type for people identifiers

PeopleItemSchema
Type : unknown
Default value : z .object({ slug: PeopleIdSchema, name: z.string(), lastName: z.string(), image: z.string().optional(), roles: z.array(RoleSchema).transform((roles) => roles.sort(compareRolesByEndDateDesc)), }) .meta({ id: 'PeopleItem' })

People item schema

src/app/utils/refined-roles.ts

REFINED_ROLE_TYPE_OPTIONS
Type : literal type[]
Default value : [ { id: RefinedRoleType.Collaborator, label: 'Collaborator' }, { id: RefinedRoleType.MasterStudent, label: 'Masters student' }, { id: RefinedRoleType.PhDStudent, label: 'PhD student' }, { id: RefinedRoleType.Staff, label: 'Staff' }, { id: RefinedRoleType.Student, label: 'Student' }, ]

Refined role types along with their labels

src/app/schemas/research.schema.ts

ResearchCategoryIdSchema
Type : unknown
Default value : z.string().brand('ResearchCategoryId')

Type for research category identifier

ResearchDataSchema
Type : unknown
Default value : z.array(ResearchItemSchema).meta({ id: 'ResearchData' })

Research data schema - array of research items

ResearchIdSchema
Type : unknown
Default value : z.string().brand('ResearchId')

Branded type for research identifiers

ResearchItemSchema
Type : unknown
Default value : z .object({ /** Research slug identifier */ slug: ResearchIdSchema, /** Category of the item */ category: ResearchCategoryIdSchema, /** Research type identifier */ type: ResearchTypeIdSchema, /** Title of the research */ title: z.string(), /** Description of the research */ description: z.string(), /** Start date of the research */ dateStart: z.coerce.date(), /** End date of the research */ dateEnd: z.coerce.date(), /** Link associated with the research */ link: z.string().optional(), /** People associated with the research */ people: z.array(PeopleIdSchema), /** Tags for categorizing the research */ tags: z.array(TagIdSchema).transform((tags) => uniqueValues(tags)), /** Image source URL */ image: z.string().optional(), }) .meta({ id: 'Research' })

Research schema

src/app/pages/research-page/state/research.store.ts

ResearchStore
Type : unknown
Default value : signalStore( withResearch(), withView(), withFilters(), withOrdering(), withHooks({ onInit(store) { /** Writable signal slices for linkedQueryParam compatibility */ const view = createWritableStateSlice(store.view, store.setView); const categories = createWritableStateSlice(store.categories, store.setCategories); const events = createWritableStateSlice(store.eventIds, store.setEventIds); const funding = createWritableStateSlice(store.fundingIds, store.setFundingIds); const publications = createWritableStateSlice(store.publicationIds, store.setPublicationIds); const people = createWritableStateSlice(store.peopleIds, store.setPeopleIds); const years = createWritableStateSlice(store.years, store.setYears); const search = createWritableStateSlice(store.search, store.setSearch); const sortBy = createWritableStateSlice(store.sortBy, store.setSortBy); const groupBy = createWritableStateSlice(store.groupBy, store.setGroupBy); const commonOptions = { replaceUrl: true, preserveFragment: true }; linkedQueryParam('category', { source: categories, parse: parseCategories, stringify: serializeCategories, ...commonOptions, }); linkedQueryParam('event', { source: events, parse: parseEventIds, stringify: serializeEventIds, ...commonOptions, }); linkedQueryParam('funding', { source: funding, parse: parseFundingIds, stringify: serializeFundingIds, ...commonOptions, }); linkedQueryParam('publication', { source: publications, parse: parsePublicationIds, stringify: serializePublicationIds, ...commonOptions, }); linkedQueryParam('people', { source: people, parse: parsePeopleIds, stringify: serializePeopleIds, ...commonOptions, }); linkedQueryParam('year', { source: years, parse: parseYears, stringify: serializeYears, ...commonOptions, }); linkedQueryParam('search', { source: search, parse: parseSearch, ...commonOptions }); linkedQueryParam('view', { source: view, parse: parseView, ...commonOptions, }); linkedQueryParam('sort-by', { source: sortBy, parse: parseSortBy, ...commonOptions, }); linkedQueryParam('group-by', { source: groupBy, parse: parseGroupBy, ...commonOptions }); }, }), )

Research page state store combining data, filters, view, and ordering. Keeps state in sync with URL query parameters for sharing and navigation.

src/app/schemas/research-type.schema.ts

ResearchTypeIdSchema
Type : unknown
Default value : z.string().brand('ResearchTypeId')

Branded type for research type identifiers

ResearchTypeItemSchema
Type : unknown
Default value : z .object({ /** Label for the research type */ label: z.string(), /** Value for the research type */ value: ResearchTypeIdSchema, }) .meta({ id: 'ResearchTypeItem' })

Research type item schema

ResearchTypesDataSchema
Type : unknown
Default value : z.array(ResearchTypeItemSchema).meta({ id: 'ResearchTypesData' })

Research types data schema - array of research type items

src/app/schemas/tags.schema.ts

TagIdSchema
Type : unknown
Default value : z.string().brand('TagId')

Branded type for tag identifiers

TagItemSchema
Type : unknown
Default value : z .object({ /** Tag identifier */ slug: TagIdSchema, /** Display name of the tag */ name: z.string(), /** Description of the tag */ description: z.string(), }) .meta({ id: 'TagItem' })

Tag item schema

TagsDataSchema
Type : unknown
Default value : z.array(TagItemSchema).meta({ id: 'TagsData' })

Tags data schema - array of tag items

results matching ""

    No results matching ""