리소스 타임라인

@dayflow-pro/resource-timeline은 DayFlow에 스케줄러 방식의 가로형 타임라인을 추가합니다. 시간이 왼쪽에서 오른쪽으로 흐르고 리소스마다 고유한 행을 가지며, 사람·회의실·프로젝트·장비에 걸친 업무 계획에 맞게 설계되었습니다.

라이브 데모를 사용해 보세요

기본 캘린더 뷰와 비교했을 때, 리소스 타임라인은 다음에 최적화되어 있습니다:

  • 장기간 이어지는 작업과 프로젝트 계획
  • 여러 레인에 걸친 리소스 배분
  • 마일스톤과 진행 상황 추적
  • 계층형 또는 그룹화된 리소스 목록

설치

npm install @dayflow-pro/resource-timeline
pnpm add @dayflow-pro/resource-timeline
yarn add @dayflow-pro/resource-timeline
bun add @dayflow-pro/resource-timeline

설치 단계는 Pro 설치 가이드를 참고하세요.

기본 사용법

import { DayFlowCalendar, useCalendarApp } from '@dayflow/react';
import { createResourceTimelineView } from '@dayflow-pro/resource-timeline';

function App() {
  const calendar = useCalendarApp({
    views: [
      createResourceTimelineView({
        resources: [
          {
            id: 'eng-alice',
            name: 'Alice Chen',
            groupId: 'engineering',
            groupName: 'Engineering',
            subtitle: 'Frontend',
          },
          {
            id: 'eng-bob',
            name: 'Bob Torres',
            groupId: 'engineering',
            groupName: 'Engineering',
            subtitle: 'Platform',
          },
        ],
        defaultView: 'week',
        height: 640,
        getResourceId: event =>
          (event as { resourceId?: string }).resourceId ?? event.calendarId,
      }),
    ],
  });

  return <DayFlowCalendar calendar={calendar} />;
}
<template>
  <DayFlowCalendar :calendar="calendar" />
</template>

<script setup>
import { DayFlowCalendar, useCalendarApp } from '@dayflow/vue';
import { createResourceTimelineView } from '@dayflow-pro/resource-timeline';

const calendar = useCalendarApp({
  views: [
    createResourceTimelineView({
      resources: [
        {
          id: 'eng-alice',
          name: 'Alice Chen',
          groupId: 'engineering',
          groupName: 'Engineering',
          subtitle: 'Frontend',
        },
        {
          id: 'eng-bob',
          name: 'Bob Torres',
          groupId: 'engineering',
          groupName: 'Engineering',
          subtitle: 'Platform',
        },
      ],
      defaultView: 'week',
      height: 640,
      getResourceId: event => event.resourceId ?? event.calendarId,
    }),
  ],
});
</script>
import { Component } from '@angular/core';
import { createResourceTimelineView } from '@dayflow-pro/resource-timeline';
import { DayFlowCalendarModule } from '@dayflow/angular';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [DayFlowCalendarModule],
  template: `
    <dayflow-calendar [calendar]="calendar"></dayflow-calendar>
  `
})
export class AppComponent {
  calendar = {
    views: [
      createResourceTimelineView({
        resources: [
          {
            id: 'eng-alice',
            name: 'Alice Chen',
            groupId: 'engineering',
            groupName: 'Engineering',
            subtitle: 'Frontend',
          },
          {
            id: 'eng-bob',
            name: 'Bob Torres',
            groupId: 'engineering',
            groupName: 'Engineering',
            subtitle: 'Platform',
          },
        ],
        defaultView: 'week',
        height: 640,
        getResourceId: (event: any) => event.resourceId ?? event.calendarId,
      }),
    ],
  };
}
<script>
  import { DayFlowCalendar, useCalendarApp } from '@dayflow/svelte';
  import { createResourceTimelineView } from '@dayflow-pro/resource-timeline';

  const calendar = useCalendarApp({
    views: [
      createResourceTimelineView({
        resources: [
          {
            id: 'eng-alice',
            name: 'Alice Chen',
            groupId: 'engineering',
            groupName: 'Engineering',
            subtitle: 'Frontend',
          },
          {
            id: 'eng-bob',
            name: 'Bob Torres',
            groupId: 'engineering',
            groupName: 'Engineering',
            subtitle: 'Platform',
          },
        ],
        defaultView: 'week',
        height: 640,
        getResourceId: event => event.resourceId ?? event.calendarId,
      }),
    ],
  });
</script>

<DayFlowCalendar {calendar} />

타임라인 스케일

스케일설명
day하루를 시간 단위 열로 표시합니다.
week한 주를 날짜 단위 열로 표시합니다.
month한 달을 날짜 단위 열로 표시합니다.
quarter3개월을 주 또는 월 단위로 묶어 표시합니다.
year로드맵 형태의 계획에 적합한 1년 전체입니다.

defaultView로 초기 스케일을 지정하세요. viewSwitcherMode로 전환 UI의 형태도 정할 수 있으며 buttons, select, filter를 지원합니다.

리소스 모델

리소스는 평범한 객체입니다. 실제 코드는 idname 외에도 더 많은 필드를 지원합니다:

type Resource = {
  id: string;
  name: string;
  parentId?: string;
  collapsed?: boolean;
  groupId?: string;
  groupName?: string;
  order?: number;
  subtitle?: string;
  avatar?: string;
  color?: string;
  style?: {
    colors: { color: string; textColor?: string };
    darkColors?: { color: string; textColor?: string };
    opacity?: number;
    borderRadius?: number;
  };
  meta?: Record<string, unknown>;
};

유용한 필드:

  • groupIdgroupName으로 리소스를 그룹 구획으로 묶을 수 있습니다.
  • parentIdcollapsed는 계층형 리소스 트리를 지원합니다.
  • subtitle, avatar, color, style로 사이드바 표현을 풍부하게 만들 수 있습니다.
  • meta는 보통 calendarId 같은 외부 식별자를 저장하는 데 사용합니다.

이벤트와 리소스 연결

뷰는 다음 순서로 각 이벤트가 놓일 행을 결정합니다:

  1. getResourceId(event) (제공된 경우)
  2. event.resourceId
  3. event.meta?.resourceId
  4. event.calendarId

즉, 이벤트 객체에 resourceId를 직접 저장하거나, 콜백을 사용해 기존 DayFlow 이벤트를 리소스에 매핑할 수 있습니다.

const event = {
  id: 'task-1',
  title: 'Build export flow',
  start: new Date(2026, 4, 10, 9, 0),
  end: new Date(2026, 4, 12, 18, 0),
  resourceId: 'eng-alice',
  progress: 65,
};

마일스톤과 이벤트 스타일

startend가 같은 이벤트는 자동으로 마일스톤으로 렌더링됩니다.

const milestone = {
  id: 'release-gate',
  title: 'Release approval',
  start: new Date(2026, 4, 14, 10, 0),
  end: new Date(2026, 4, 14, 10, 0),
  resourceId: 'eng-bob',
};
속성타입설명
milestoneLabelDisplay'hover' | 'always'마일스톤 레이블을 마우스를 올렸을 때만 보여 줄지, 항상 표시할지 결정합니다.
milestoneLaneBehavior'smart' | 'overlay'마일스톤이 가능한 경우 일반 레인을 공유할지, 그 위에 겹쳐 표시할지 결정합니다.
getEventType(event) => ResourceEventType이벤트를 타임라인 전용 이벤트 타입으로 매핑합니다.
getEventTooltip(event) => string | undefined이벤트의 툴팁 문구를 제공합니다.
styleRegistryRecord<string, EventStyle>사용자 정의 스타일 프리셋을 등록합니다.
getEventStyleId(event) => string | undefined이벤트에 적용할 스타일 프리셋을 선택합니다.

ResourceTimelineViewConfig

기본

속성타입설명
resourcesResource[]타임라인에 표시할 리소스 목록입니다(필수).
licensePackageLicenseConfig전역 등록을 사용하지 않을 때 지정하는 선택적 설정입니다.
defaultViewday | week | month | quarter | year타임라인의 초기 스케일입니다.
viewsSchedulerTimelineView[]전환 가능한 타임라인 스케일 목록을 재정의합니다.
viewTypeViewType | string고급 호스트에 통합할 때 사용하는 사용자 정의 뷰 타입입니다.
viewSwitcherMode'buttons' | 'select' | 'filter'스케일 전환 UI의 형태를 제어합니다.
heightnumber | string렌더링되는 뷰의 높이입니다.

레이아웃

속성타입설명
resourcePanelWidthnumber사이드바의 기본 너비입니다.
resourcePanelMinWidthnumber사이드바의 최소 너비입니다.
resourcePanelMaxWidthnumber사이드바의 최대 너비입니다.
rowHeightnumber각 리소스 행의 높이입니다.
headerHeightnumber타임라인 헤더의 높이입니다.
hourWidthnumberday 모드의 시간 스케일 너비입니다.
weekDayWidthnumberweek 모드에서 하루당 너비입니다.
dayWidthnumbermonth 모드에서 하루당 너비입니다.
monthDayWidthnumber조밀한 월 범위를 렌더링할 때 하루당 너비입니다.
quarterMonthWidthnumberquarter 모드에서 한 달당 너비입니다.
yearCellWidthnumberyear 모드에서 단위당 너비입니다.
yearRangePastnumber현재 연도 이전에 추가로 표시할 연수입니다.
yearRangeFuturenumber현재 연도 이후에 추가로 표시할 연수입니다.
overscanRowsnumber화면 밖에 추가로 렌더링할 행 수입니다.
bufferCellsnumber스크롤을 부드럽게 하기 위해 추가로 렌더링할 시간 셀 수입니다.

리소스 표시와 동기화

속성타입설명
resourceSorter(left, right) => number행 정렬 순서를 직접 지정합니다.
syncResourceVisibilityWithCalendarsboolean연결된 캘린더가 숨겨지면 해당 리소스 행도 숨깁니다.
getCalendarIdForResource(resource) => string | undefined리소스를 캘린더 표시 여부에 연결하는 방식을 재정의합니다.
onResourcesUpdate(resources) => voidUI에서 리소스 순서를 바꾸거나 접었을 때 호출됩니다.

캘린더 동기화가 활성화되면 리소스와 캘린더 간 대체 매핑은 resource.meta?.calendarId ?? resource.id입니다.

포커스, 사이드바, 연동

타임라인에는 놓치기 쉬운 몇 가지 연동 지점이 있습니다:

  • focusRequest를 사용하면 호스트 앱이 코드로 타임라인을 특정 이벤트와 날짜로 이동시킬 수 있습니다.
  • sidebar는 컨텍스트 메뉴 동작 등 스케줄러 사이드바 설정을 그대로 전달합니다.
  • 상세 UI를 직접 만들어야 한다면 customDetailPanelContentcustomEventDetailDialog를 뷰 props로 전달할 수 있습니다.
  • timeFormat24h12h를 지원합니다.
  • resizeTimeFormat은 이벤트 크기를 조절하는 동안 표시되는 레이블을 바꿉니다.

이 페이지의 내용