Skip to content

Conversation

@aleksei-semikozov
Copy link
Contributor

No description provided.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR rewrites the Scheduler Templates demo for Angular and Vue frameworks, updating the visual design and form configuration patterns. The changes include modernized appointment and tooltip templates with improved styling, a refactored form editing configuration that moves from event-based to declarative configuration, and updated color schemes for movie resources.

Key changes:

  • Refactored appointment form handling from onAppointmentFormOpening event handler to declarative editing.form configuration
  • Updated appointment and tooltip templates with new CSS classes and flexbox-based layouts
  • Changed movie resource colors from vibrant to softer pastel tones

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
apps/demos/Demos/Scheduler/Templates/Vue/styles.css Added new CSS rules for movie preview layouts and form styling; includes width rules for scheduler views
apps/demos/Demos/Scheduler/Templates/Vue/data.ts Updated movie resource colors to pastel palette; improved string escaping
apps/demos/Demos/Scheduler/Templates/Vue/AppointmentTooltipTemplate.vue Updated template structure to use flexbox-based movie info layout with preview image
apps/demos/Demos/Scheduler/Templates/Vue/AppointmentTemplate.vue Rewrote appointment display to include movie preview image and improved layout structure
apps/demos/Demos/Scheduler/Templates/Vue/App.vue Major refactoring to use declarative form configuration with custom movie info template and inline HTML generation
apps/demos/Demos/Scheduler/Templates/Angular/app/app.service.ts Updated movie resource colors to match Vue implementation
apps/demos/Demos/Scheduler/Templates/Angular/app/app.component.ts Refactored from event-based form handling to declarative form configuration with custom templates
apps/demos/Demos/Scheduler/Templates/Angular/app/app.component.html Updated templates to use new movie preview layout with flexbox structure
apps/demos/Demos/Scheduler/Templates/Angular/app/app.component.css Added new CSS rules for movie preview layouts and form styling to match Vue implementation
Comments suppressed due to low confidence (2)

apps/demos/Demos/Scheduler/Templates/Vue/AppointmentTemplate.vue:61

  • These scoped styles reference .movie-tooltip class which doesn't exist in this component's template. The template uses .movie-preview and .movie-details classes instead. These unused styles should be removed to avoid confusion and maintain code cleanliness.
  .movie-tooltip .movie-info {
    display: inline-block;
    margin-left: 10px;
    vertical-align: top;
    text-align: left;
  }

  .movie-tooltip img {
    height: 80px;
    margin-bottom: 10px;
  }

  .movie-tooltip .movie-title {
    font-size: 1.5em;
    line-height: 40px;
  }

apps/demos/Demos/Scheduler/Templates/Vue/AppointmentTooltipTemplate.vue:20

  • The scoped styles in this file (lines 40-106 in the full file) include classes like .appointment-content, .appointment-badge, .appointment-dates, .appointment-text, and .delete-appointment that don't correspond to any classes used in this component's template. The template only uses .movie-info, .movie-preview-image, and .movie-details classes. These unused styles should be removed to avoid confusion and maintain code cleanliness.
<template>
  <div class="movie-info">
    <div class="movie-preview-image">
      <img
        :src="movieData.image"
        :alt="movieData.text"
      >
    </div>
    <div class="movie-details">
      <div class="title">
        {{ movieData.text }} ({{ movieData.year }})
      </div>
      <div>
        Director: {{ movieData.director }}
      </div>
      <div>
        Duration: {{ movieData.duration }} minutes
      </div>
    </div>
  </div>

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 13 comments.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

apps/demos/Demos/Scheduler/Templates/Vue/AppointmentTemplate.vue:61

  • These scoped styles reference .movie-tooltip classes that don't exist in the template (the template uses .movie-preview instead). These appear to be leftover styles from the old implementation that should have been removed along with the old template code. Consider removing these unused styles to avoid confusion.
  .movie-tooltip .movie-info {
    display: inline-block;
    margin-left: 10px;
    vertical-align: top;
    text-align: left;
  }

  .movie-tooltip img {
    height: 80px;
    margin-bottom: 10px;
  }

  .movie-tooltip .movie-title {
    font-size: 1.5em;
    line-height: 40px;
  }

@@ -1,10 +1,16 @@
<template>
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The template references movieData which is computed from getMovieById, but this function (lines 32-36, not shown in diff) has an incorrect type signature (resourceId: string should be number) and incorrect filter syntax. This could cause runtime issues when comparing the numeric id field with the parameter.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings December 1, 2025 07:27
@aleksei-semikozov aleksei-semikozov force-pushed the rewrite-scheduler-demo branch 2 times, most recently from b059adb to 560b312 Compare December 1, 2025 07:28
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 12 comments.

Comments suppressed due to low confidence (1)

apps/demos/Demos/Scheduler/Templates/Vue/AppointmentTooltipTemplate.vue:20

  • Inconsistent filter syntax across Vue components. In App.vue (line 136), the filter uses three parameters: .filter(['id', '=', resourceId]), while in AppointmentTemplate.vue and AppointmentTooltipTemplate.vue, it uses two parameters: .filter(['id', resourceId]). Although both may work, this inconsistency makes the codebase harder to maintain. Consider standardizing on one approach across all Vue components.
<template>
  <div class="movie-info">
    <div class="movie-preview-image">
      <img
        :src="movieData.image"
        :alt="movieData.text"
      >
    </div>
    <div class="movie-details">
      <div class="title">
        {{ movieData.text }} ({{ movieData.year }})
      </div>
      <div>
        Director: {{ movieData.director }}
      </div>
      <div>
        Duration: {{ movieData.duration }} minutes
      </div>
    </div>
  </div>


<dxi-scheduler-item
name="endDateGroup"
[disabled]="true"
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The disabled attribute is used here on a scheduler item, which may be an undocumented feature (similar to React implementations which use @ts-expect-error). This could break in future versions of DevExtreme. Consider verifying if this is an officially supported feature and document its usage, or find a documented alternative approach.

Suggested change
[disabled]="true"
[editorOptions]="{ disabled: true }"

Copilot uses AI. Check for mistakes.
Comment on lines +86 to +87
.dx-scheduler-appointment::before {
opacity: 0.26 !important;
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of !important is a code smell that indicates specificity issues in CSS. Using !important makes styles harder to override and maintain. Consider increasing selector specificity instead (e.g., using a more specific selector chain) to avoid needing !important.

Suggested change
.dx-scheduler-appointment::before {
opacity: 0.26 !important;
.dx-scheduler-work-space-week .dx-scheduler-appointment::before,
.dx-scheduler-timeline-day .dx-scheduler-appointment::before {
opacity: 0.26;

Copilot uses AI. Check for mistakes.
Comment on lines +86 to +87
.dx-scheduler-appointment::before {
opacity: 0.26 !important;
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of !important is a code smell that indicates specificity issues in CSS. Using !important makes styles harder to override and maintain. Consider increasing selector specificity instead (e.g., using a more specific selector chain) to avoid needing !important.

Suggested change
.dx-scheduler-appointment::before {
opacity: 0.26 !important;
.dx-scheduler-work-space .dx-scheduler-appointment::before {
opacity: 0.26;

Copilot uses AI. Check for mistakes.
DxForm as DxSchedulerForm,
type DxSchedulerTypes,
} from 'devextreme-vue/scheduler';
import DxForm, { DxItem, type DxFormTypes } from 'devextreme-vue/form';
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import: DxForm is imported but never used in this component. The form instance type is referenced using DxForm['instance'] on line 132, but this could use the direct import from 'devextreme/ui/form' instead (as done in the React/Angular implementations). Consider removing this import or using it consistently.

Copilot uses AI. Check for mistakes.
};
const onFormInitialized = (e: DxFormTypes.InitializedEvent): void => {
const form = e.component!;
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The non-null assertion operator (!) is used on e.component, but there's no guarantee that e.component is non-null. If e.component is null or undefined, this will cause a runtime error. The React and Angular implementations don't use this assertion. Consider adding a null check or removing the assertion if the component is guaranteed to exist.

Suggested change
const form = e.component!;
const form = e.component;
if (!form) {
return;
}

Copilot uses AI. Check for mistakes.
@aleksei-semikozov aleksei-semikozov changed the title Rewrite Customization/Templates demo(Angular/Vue) Rewrite Customization/Templates demo Dec 3, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 21 comments.

<Editing
allowAdding={false}
popup={{
maxWidth: 440,
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The property name maxWidth is used here, but in the Vue implementation and Angular implementation, width is used. This inconsistency could lead to different popup behaviors across framework implementations. Consider using width consistently to ensure uniform appearance.

Suggested change
maxWidth: 440,
width: 440,

Copilot uses AI. Check for mistakes.
v-else
class="movie-info"
>
<div class="movie-preview-image"/>
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The empty movie-preview-image div in the "no movie selected" state should include an aria-label or other accessible indicator to inform screen reader users that this is a placeholder image area.

Suggested change
<div class="movie-preview-image"/>
<div class="movie-preview-image" aria-label="Movie preview image placeholder"/>

Copilot uses AI. Check for mistakes.
const isMaterialOrFluent = document.querySelector('.dx-theme-fluent, .dx-theme-material');
return isMaterialOrFluent ? 'filled' : 'outlined';
};
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getEditorStylingMode function is called directly in the template binding, which means it will be executed on every render. This can impact performance. Consider computing this value once during initialization or memoizing it, especially since theme detection is unlikely to change during component lifecycle.

Suggested change
// Compute once during setup
const editorStylingMode = getEditorStylingMode();

Copilot uses AI. Check for mistakes.
import { query as Query } from 'devextreme-react/common/data';
import { moviesData } from './data.js';

const getMovieById = (id) => Query(moviesData).filter(['id', id]).toArray()[0];
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getMovieById function has incorrect filter syntax. It should use ['id', '=', id] instead of ['id', id] to match the query filter API and be consistent with other implementations.

Suggested change
const getMovieById = (id) => Query(moviesData).filter(['id', id]).toArray()[0];
const getMovieById = (id) => Query(moviesData).filter(['id', '=', id]).toArray()[0];

Copilot uses AI. Check for mistakes.
formInstanceRef: React.RefObject<dxForm | null>;
};

const getMovieById = (id: number) => query(moviesData).filter(['id', id]).toArray()[0];
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getMovieById function has incorrect filter syntax. It should use ['id', '=', id] instead of ['id', id] to match the query filter API and be consistent with other implementations (Vue at line 136, Angular at line 63).

Suggested change
const getMovieById = (id: number) => query(moviesData).filter(['id', id]).toArray()[0];
const getMovieById = (id: number) => query(moviesData).filter(['id', '=', id]).toArray()[0];

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +30
const updateEndDate = (form, movie) => {
const formData = form.option('formData');
const { startDate } = formData;
if (startDate && movie?.duration) {
const newEndDate = new Date(startDate.getTime() + 60 * 1000 * movie.duration);
form.updateData('endDate', newEndDate);
}
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updateEndDate function doesn't check if formData exists before accessing startDate. While the outer checks for startDate exist, adding a null check for formData would make the code more robust and prevent potential runtime errors.

Copilot uses AI. Check for mistakes.
Comment on lines +35 to +41
const updateEndDate = (form: dxForm, movie: MovieResource): void => {
const formData = form.option('formData');
const { startDate } = formData;
if (startDate && movie?.duration) {
const newEndDate = new Date(startDate.getTime() + 60 * 1000 * movie.duration);
form.updateData('endDate', newEndDate);
}
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updateEndDate function doesn't check if formData exists before accessing startDate. While the outer checks for startDate exist, adding a null check for formData would make the code more robust and prevent potential runtime errors.

Copilot uses AI. Check for mistakes.
</ng-container>
<ng-template #noMovieSelected>
<div class="movie-info">
<div class="movie-preview-image"></div>
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The empty movie-preview-image div in the "no movie selected" state should include an aria-label or other accessible indicator to inform screen reader users that this is a placeholder image area.

Suggested change
<div class="movie-preview-image"></div>
<div class="movie-preview-image" aria-label="Movie image placeholder"></div>

Copilot uses AI. Check for mistakes.
items: moviesData,
displayExpr: 'text',
valueExpr: 'id',
stylingMode: getEditorStylingMode(),
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getEditorStylingMode function is called directly in the editorOptions, which means it will be executed on every render. Consider memoizing this value using useMemo since theme detection is unlikely to change during component lifecycle.

Copilot uses AI. Check for mistakes.
Comment on lines +129 to +135
{{
(model.targetedAppointmentData.displayStartDate
| date : "shortTime") +
" - " +
(model.targetedAppointmentData.displayEndDate
| date : "shortTime")
}}
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The date formatting expression is split across multiple lines in a complex way. Consider extracting this formatting logic to a method in the component for better readability and maintainability.

Suggested change
{{
(model.targetedAppointmentData.displayStartDate
| date : "shortTime") +
" - " +
(model.targetedAppointmentData.displayEndDate
| date : "shortTime")
}}
{{ formatAppointmentTime(model.targetedAppointmentData) }}

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 19 comments.

Copilot AI review requested due to automatic review settings December 3, 2025 18:53
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 9 comments.

<DxEditing
:allow-adding="false"
:popup="{
maxWidth: 440,
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent popup width property across frameworks. Vue uses width: 440 while React (line 116 in React/App.tsx), ReactJs (line 95 in ReactJs/App.js), and Angular (line 34 in Angular/app.component.html) all use maxWidth: 440. This should be maxWidth to be consistent with other implementations and to match the popup configuration pattern used in the rest of the codebase.

Copilot uses AI. Check for mistakes.
/>
</DxItem>

<DxItem name="startDateGroup"/>
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing itemType="group" attribute. React (line 153 in React/App.tsx), ReactJs (line 137 in ReactJs/App.js), and Angular (line 79 in Angular/app.component.html) all specify itemType="group" for startDateGroup. Vue should include item-type="group" for consistency.

Suggested change
<DxItem name="startDateGroup"/>
<DxItem name="startDateGroup" item-type="group"/>

Copilot uses AI. Check for mistakes.

<DxItem
:disabled="true"
name="endDateGroup"
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing item-type="group" attribute. React (line 155 in React/App.tsx), ReactJs (line 143 in ReactJs/App.js), and Angular (line 82 in Angular/app.component.html) all specify itemType="group" for endDateGroup. Vue should include item-type="group" for consistency.

Suggested change
name="endDateGroup"
name="endDateGroup"
item-type="group"

Copilot uses AI. Check for mistakes.
import { query } from 'devextreme-react/common/data';
import { moviesData } from './data.js';

const getMovieById = (id) => query(moviesData).filter(['id', id]).toArray()[0];
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent query filter syntax. This uses filter(['id', id]) while Vue (line 136 in Vue/App.vue) and Angular (line 63 in Angular/app.component.ts) use filter(['id', '=', id]) with an explicit equality operator. For consistency and clarity, consider using the explicit 3-parameter form: filter(['id', '=', id])

Suggested change
const getMovieById = (id) => query(moviesData).filter(['id', id]).toArray()[0];
const getMovieById = (id) => query(moviesData).filter(['id', '=', id]).toArray()[0];

Copilot uses AI. Check for mistakes.
import { query as Query } from 'devextreme-react/common/data';
import { moviesData } from './data.js';

const getMovieById = (id) => Query(moviesData).filter(['id', id]).toArray()[0];
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent query filter syntax. This uses filter(['id', id]) while Vue (line 136 in Vue/App.vue) and Angular (line 63 in Angular/app.component.ts) use filter(['id', '=', id]) with an explicit equality operator. For consistency and clarity, consider using the explicit 3-parameter form: filter(['id', '=', id])

Suggested change
const getMovieById = (id) => Query(moviesData).filter(['id', id]).toArray()[0];
const getMovieById = (id) => Query(moviesData).filter(['id', '=', id]).toArray()[0];

Copilot uses AI. Check for mistakes.
import { moviesData } from './data.ts';

const getMovieById = (id) => Query(moviesData).filter(['id', id]).toArray()[0];
const getMovieById = (id: number) => Query(moviesData).filter(['id', id]).toArray()[0];
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent query filter syntax. This uses filter(['id', id]) while Vue (line 136 in Vue/App.vue) and Angular (line 63 in Angular/app.component.ts) use filter(['id', '=', id]) with an explicit equality operator. For consistency and clarity, consider using the explicit 3-parameter form: filter(['id', '=', id])

Suggested change
const getMovieById = (id: number) => Query(moviesData).filter(['id', id]).toArray()[0];
const getMovieById = (id: number) => Query(moviesData).filter(['id', '=', id]).toArray()[0];

Copilot uses AI. Check for mistakes.
const formData = form.option('formData');
if (formData?.movieId) {
const movie = this.getMovieById(formData.movieId);
this.currentSelectedMovie = movie;
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential type mismatch. currentSelectedMovie is typed as MovieData | null (line 55), but getMovieById returns MovieData | undefined (line 63). The assignment on line 116 should handle the undefined case explicitly. Consider changing the type to MovieData | null | undefined or converting undefined to null explicitly: this.currentSelectedMovie = movie ?? null;

Copilot uses AI. Check for mistakes.
},
},
]);
const getMovieById = (id) => query(moviesData).filter(['id', id]).toArray()[0];
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent query filter syntax. This uses filter(['id', id]) while Vue (line 136 in Vue/App.vue) and Angular (line 63 in Angular/app.component.ts) use filter(['id', '=', id]) with an explicit equality operator. For consistency and clarity, consider using the explicit 3-parameter form: filter(['id', '=', id])

Suggested change
const getMovieById = (id) => query(moviesData).filter(['id', id]).toArray()[0];
const getMovieById = (id) => query(moviesData).filter(['id', '=', id]).toArray()[0];

Copilot uses AI. Check for mistakes.
import { formatDate } from 'devextreme-react/common/core/localization';
import { moviesData } from './data.js';

const getMovieById = (id) => Query(moviesData).filter(['id', id]).toArray()[0];
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent query filter syntax. This uses filter(['id', id]) while Vue (line 136 in Vue/App.vue) and Angular (line 63 in Angular/app.component.ts) use filter(['id', '=', id]) with an explicit equality operator. For consistency and clarity, consider using the explicit 3-parameter form: filter(['id', '=', id])

Suggested change
const getMovieById = (id) => Query(moviesData).filter(['id', id]).toArray()[0];
const getMovieById = (id) => Query(moviesData).filter(['id', '=', id]).toArray()[0];

Copilot uses AI. Check for mistakes.
import { type DxSelectBoxTypes } from 'devextreme-vue/select-box';
import { type DxDateBoxTypes } from 'devextreme-vue/date-box';
import { query as Query } from 'devextreme-vue/common/data';
import query from 'devextreme/data/query';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you have here a ts error "Cannot find module 'devextreme/data/query' or its corresponding type declarations.ts-plugin(2307)" ?

I was able to solve it with "import { query } from 'devextreme-vue/common/data';"

@aleksei-semikozov aleksei-semikozov merged commit 303b065 into DevExpress:25_2 Dec 3, 2025
115 of 116 checks passed
@Tucchhaa Tucchhaa changed the title Rewrite Customization/Templates demo Scheduler Demos - Update Customization/Templates demo for Anglar/Vue Dec 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants