Our pure JavaScript Scheduler component


Post by v-paulrausch »

Hi team ,
I am trying to add grouping feature for resources column but its not showing up as grouped .Is it because of i have custom column renderer or it should work with or without custom column renderer?

Attachments
Screenshot 3.png
Screenshot 3.png (47.33 KiB) Viewed 77 times
Screenshot2.png
Screenshot2.png (86.94 KiB) Viewed 77 times
screenshot1.png
screenshot1.png (25.56 KiB) Viewed 77 times

Post by tasnim »

Hi,

Do you have grouping feature enabled? https://bryntum.com/products/scheduler/docs/api/Grid/feature/Group
We have a demo regarding grouping in scheduler https://bryntum.com/products/scheduler/docs/api/Grid/feature/Group where you can check how it is implemented.

Having a column renderer shouldn't make any difference. Could you please share the config of your scheduler so we can check what is wrong?

Best regards 🙂,
Tasnim


Post by v-paulrausch »

Hi Tasnim,
here are my config and column renderer

const [schedulerBoardConfig] = useState<BryntumSchedulerProProps>({
  columnLines: false,
  viewPreset: {
    base: "hourAndDay",
    headers: [
      {
        unit: "HOUR",
        align: "center",
        dateFormat: "h A"
      },
      {
        unit: "hour",
        renderer: (startDate: Date) => {
          const currentHour = startDate.getHours();
          const startTime = new Date(props.shiftPlanConfiguration.getStartTime()).getHours();
          const endTime = new Date(props.shiftPlanConfiguration.getEndTime()).getHours() - 1;

      if (
        currentHour >= startTime &&
        currentHour <= endTime &&
        props.shiftPlanConfiguration
          .getWeeklyRecurrence()
          .includes(props.shiftPlanConfiguration.getSelectedDate().getDay() + 1)
      ) {
        return props.shiftPlanConfiguration.getRequiredStaff();
      }
      return "";
    }
  },
  {
    unit: "hour",
    renderer: (startDate: Date, _endDate: Date, _headerConfig: object, _i: number) => {
      return hourlyCountRenderer(startDate, props.shiftPlanConfiguration, _hourlyBookingsCount);
    }
  }
]
  },
  features: {
    group: {
      field: "team"
    },
    scheduleMenu: {
      items: {
        addEvent: false
      }
    },
    eventMenu: {
      keyMap: {
        Enter: "edit"
      }
    },
    eventTooltip: {
      template: (data) => {
        const actualStartDate = (data.eventRecord as any).actualStartDate;
        const actualEndDate = (data.eventRecord as any).actualEndDate;
        const start = new Date(
          actualStartDate.getFullYear(),
          actualStartDate.getMonth(),
          actualStartDate.getDate(),
          data.startDate.getHours(),
          data.startDate.getMinutes()
        );
        const end = new Date(
          actualEndDate.getFullYear(),
          actualEndDate.getMonth(),
          actualEndDate.getDate(),
          data.endDate.getHours(),
          data.endDate.getMinutes()
        );
        return renderSchedulerEventTooltip(
          data.eventRecord.name,
          start,
          end,
          data.eventRecord.resource.name,
          (data.eventRecord as any).statusName,
          (data.eventRecord as any).shiftPlanName,
          props.localizedStrings
        );
      },
      showOnClick: true,
      showOnHover: true
    },
    cellMenu: false,
    headerMenu: false,
    columnResize: false
  },
  listeners: {
    eventSelectionChange({ action, source, selected }) {
      if (action === "select") {
        const eventElement = source.getElementFromEventRecord(selected[0]);
        eventElement.click();
      }
    }
  },
  barMargin: 5,
  zoomOnMouseWheel: false,
  resourceMargin: 5,
  eventStyle: "border",
  tickSize: 80,
  resourceTimeRangesFeature: true,
  hideRowHover: true,
  createEventOnDblClick: false,
  eventLayout,
  rowHeight: 60,
  filterBarFeature: false,
  cellEditFeature: false,
  taskEditFeature: false,
  eventEditFeature: false,
  timeAxisHeaderMenuFeature: false,
  showOnHover: false,
  eventDragCreateFeature: false,
  eventResizeFeature: false,
  eventDragFeature: false,
  eventDragSelectFeature: false,
  rowExpanderFeature: false,
  managedEventSizing: true,
  scheduleTooltipFeature: false,
  dependenciesFeature: false,
  allowCreate: true,
  eventMenuFeature: true,
  regionResizeFeature: true,
  zoomOnTimeAxisDoubleClick: false,
  timeSpanHighlightFeature: true,
  onEventKeyDown: onEventContextMenuInvokeByKey,
  onScheduleContextMenu: onScheduleContextMenuInvoke,
  onEventContextMenu: onEventContextMenuInvoke,
  subGridConfigs: {
    locked: {
      width: 260
    }
  },
  resourceStore: {
    // Additional resource fields
    fields: ["team"],
    // Sort by name initially
    sorters: [{ field: "name", ascending: true }]
  }
});
  const [columns] = useState<Partial<GridColumnConfig>[]>([
    {
      text: "&nbsp;",
      flex: 1,
      headerRenderer: () => {
        const jsxElement = (
          <Stack horizontal verticalAlign="center">
            <span
              style={{
                verticalAlign: "middle",
                marginRight: "5px",
                marginLeft: "25px"
              }}
            >
              &nbsp;
            </span>
          </Stack>
        );
        const renderedString = renderToString(jsxElement);
        return renderedString;
      },
      children: [
        {
          headerRenderer: () => requiredStaffingRenderer(props.localizedStrings),
          flex: 1,
          children: [
            {
              type: "resourceInfo",
              flex: 1,
              minWidth: 200,
              headerRenderer: () => currentStaffingRenderer(props.localizedStrings),
              readOnly: false,
              sortable: false,
              showImage: true,
              renderer: ({ value, record }: { value: any; record: any }) => {
                return (
                  <Stack
                    horizontal
                    styles={{
                      root: {
                        paddingLeft: 28
                      }
                    }}
                    tokens={{ childrenGap: 5 }}
                  >
                    <Stack.Item>
                      <Checkbox
                        checked={record.isSelected}
                        onChange={(_ev?: React.FormEvent<HTMLElement | HTMLInputElement>, checked?: boolean) => {
                          onResourceChecked(checked, record);
                        }}
                      />
                    </Stack.Item>
                    <Stack.Item>
                      <Persona
                        imageUrl={record.imageUrl}
                        key={record.id}
                        imageAlt={value}
                        text={value}
                        size={PersonaSize.size24}
                        styles={{
                          primaryText: {
                            overflow: "hidden",
                            textOverflow: "ellipsis"
                          }
                        }}
                      />
                    </Stack.Item>
                  </Stack>
                );
              }
            },
            {
              width: 70,
              align: "right",
              style: {
                border: "none"
              },
              renderer: ({ record }: { record: any }) => {
                return (
                  <Stack>
                    {!record.isBiddable && (
                      <IconButton
                        onClick={() => onAddToShiftPlanClick(record, false)}
                        iconProps={{ iconName: IconUtil.names.PlusIcon }}
                      />
                    )}
                    {record.isBiddable && (
                      <Stack horizontal horizontalAlign="center">
                        <IconButton
                          onClick={() => onAddToShiftPlanClick(record, true)}
                          iconProps={{ iconName: IconUtil.names.CheckMarkIcon }}
                          styles={{
                            icon: { fill: "#212121", height: 16, width: 16 }
                          }}
                        />
                        <IconButton
                          onClick={() => onDeclineBidClick(record)}
                          iconProps={{ iconName: IconUtil.names.DeclineMarkIcon }}
                          styles={{
                            icon: { fill: "#212121", height: 16, width: 16 }
                          }}
                        />
                      </Stack>
                    )}
                  </Stack>
                );
              }
            }
          ]
        }
      ]
    }
  ]);

Post by tasnim »

Hi,

Thanks for sharing the configs

Your config looks correct to me. Would it be possible to share a runnable test case where we can reproduce the issue and debug it?

Best regards,
Tasnim


Post Reply