Skip to content

Commit f652022

Browse files
1011302: added integration sample for GraphQL
1 parent afbbaff commit f652022

23 files changed

Lines changed: 1227 additions & 0 deletions
Binary file not shown.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<base href="/" />
8+
<ResourcePreloader />
9+
<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
10+
<link rel="stylesheet" href="@Assets["app.css"]" />
11+
<link rel="stylesheet" href="@Assets["Gantt_GraphQl.styles.css"]" />
12+
<link href="_content/Syncfusion.Blazor.Themes/tailwind3.css" rel="stylesheet" />
13+
</head>
14+
15+
<body>
16+
<Routes />
17+
<ReconnectModal />
18+
<script src="_framework/blazor.web.js"></script>
19+
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>
20+
</body>
21+
22+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
@inherits LayoutComponentBase
2+
3+
<div class="page">
4+
5+
<main>
6+
7+
<article class="content px-4">
8+
@Body
9+
</article>
10+
</main>
11+
</div>
12+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
.page {
2+
position: relative;
3+
display: flex;
4+
flex-direction: column;
5+
}
6+
7+
main {
8+
flex: 1;
9+
}
10+
11+
.sidebar {
12+
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
13+
}
14+
15+
.top-row {
16+
background-color: #f7f7f7;
17+
border-bottom: 1px solid #d6d5d5;
18+
justify-content: flex-end;
19+
height: 3.5rem;
20+
display: flex;
21+
align-items: center;
22+
}
23+
24+
.top-row ::deep a, .top-row ::deep .btn-link {
25+
white-space: nowrap;
26+
margin-left: 1.5rem;
27+
text-decoration: none;
28+
}
29+
30+
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
31+
text-decoration: underline;
32+
}
33+
34+
.top-row ::deep a:first-child {
35+
overflow: hidden;
36+
text-overflow: ellipsis;
37+
}
38+
39+
@media (max-width: 640.98px) {
40+
.top-row {
41+
justify-content: space-between;
42+
}
43+
44+
.top-row ::deep a, .top-row ::deep .btn-link {
45+
margin-left: 0;
46+
}
47+
}
48+
49+
@media (min-width: 641px) {
50+
.page {
51+
flex-direction: row;
52+
}
53+
54+
.sidebar {
55+
width: 250px;
56+
height: 100vh;
57+
position: sticky;
58+
top: 0;
59+
}
60+
61+
.top-row {
62+
position: sticky;
63+
top: 0;
64+
z-index: 1;
65+
}
66+
67+
.top-row.auth ::deep a:first-child {
68+
flex: 1;
69+
text-align: right;
70+
width: 0;
71+
}
72+
73+
.top-row, article {
74+
padding-left: 2rem !important;
75+
padding-right: 1.5rem !important;
76+
}
77+
}
78+
79+
#blazor-error-ui {
80+
color-scheme: light only;
81+
background: lightyellow;
82+
bottom: 0;
83+
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
84+
box-sizing: border-box;
85+
display: none;
86+
left: 0;
87+
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
88+
position: fixed;
89+
width: 100%;
90+
z-index: 1000;
91+
}
92+
93+
#blazor-error-ui .dismiss {
94+
cursor: pointer;
95+
position: absolute;
96+
right: 0.75rem;
97+
top: 0.5rem;
98+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<script type="module" src="@Assets["Components/Layout/ReconnectModal.razor.js"]"></script>
2+
3+
<dialog id="components-reconnect-modal" data-nosnippet>
4+
<div class="components-reconnect-container">
5+
<div class="components-rejoining-animation" aria-hidden="true">
6+
<div></div>
7+
<div></div>
8+
</div>
9+
<p class="components-reconnect-first-attempt-visible">
10+
Rejoining the server...
11+
</p>
12+
<p class="components-reconnect-repeated-attempt-visible">
13+
Rejoin failed... trying again in <span id="components-seconds-to-next-attempt"></span> seconds.
14+
</p>
15+
<p class="components-reconnect-failed-visible">
16+
Failed to rejoin.<br />Please retry or reload the page.
17+
</p>
18+
<button id="components-reconnect-button" class="components-reconnect-failed-visible">
19+
Retry
20+
</button>
21+
<p class="components-pause-visible">
22+
The session has been paused by the server.
23+
</p>
24+
<button id="components-resume-button" class="components-pause-visible">
25+
Resume
26+
</button>
27+
<p class="components-resume-failed-visible">
28+
Failed to resume the session.<br />Please reload the page.
29+
</p>
30+
</div>
31+
</dialog>
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
@page "/"
2+
@rendermode InteractiveServer
3+
@using Syncfusion.Blazor
4+
@using Syncfusion.Blazor.Data
5+
@using Syncfusion.Blazor.Gantt
6+
@using GanttGraphQL.Models
7+
8+
<SfGantt TValue="TaskDataModel"
9+
Height="560px"
10+
Width="100%"
11+
AllowFiltering="true"
12+
AllowSorting="true"
13+
TreeColumnIndex="1"
14+
EnableContextMenu="true"
15+
Toolbar="@ToolbarItems">
16+
17+
<SfDataManager Url="https://localhost:7000/graphql"
18+
Adaptor="Adaptors.GraphQLAdaptor"
19+
GraphQLAdaptorOptions="@AdaptorOptions">
20+
</SfDataManager>
21+
22+
<GanttTaskFields Id="@nameof(TaskDataModel.TaskID)" Name="@nameof(TaskDataModel.TaskName)" StartDate="@nameof(TaskDataModel.StartDate)"
23+
EndDate="@nameof(TaskDataModel.EndDate)" Duration="@nameof(TaskDataModel.Duration)" Progress="@nameof(TaskDataModel.Progress)"
24+
Dependency="@nameof(TaskDataModel.Predecessor)" ParentID="@nameof(TaskDataModel.ParentID)">
25+
</GanttTaskFields>
26+
27+
<GanttColumns>
28+
<GanttColumn Field="@nameof(TaskDataModel.TaskID)" HeaderText="Task ID" IsPrimaryKey="true" Width="110"></GanttColumn>
29+
<GanttColumn Field="@nameof(TaskDataModel.TaskName)" HeaderText="Task Name" Width="240"></GanttColumn>
30+
<GanttColumn Field="@nameof(TaskDataModel.StartDate)" HeaderText="Start Date" Format="d" Width="140"></GanttColumn>
31+
<GanttColumn Field="@nameof(TaskDataModel.EndDate)" HeaderText="End Date" Format="d" Width="140"></GanttColumn>
32+
<GanttColumn Field="@nameof(TaskDataModel.Duration)" HeaderText="Duration" Width="130"></GanttColumn>
33+
<GanttColumn Field="@nameof(TaskDataModel.Progress)" HeaderText="Progress" Width="130">
34+
<Template>
35+
@{
36+
var taskRecord = context as TaskDataModel;
37+
if (taskRecord == null) return;
38+
39+
string progressText = $"{taskRecord.Progress}%";
40+
}
41+
<div class="e-progress-custom">
42+
<div class="e-progress-outer">
43+
<div class="e-progress-bar" style="width:@(taskRecord.Progress)%;">
44+
</div>
45+
</div>
46+
<div class="e-progress-inner">
47+
<span>@progressText</span>
48+
</div>
49+
</div>
50+
</Template>
51+
</GanttColumn>
52+
<GanttColumn Field="@nameof(TaskDataModel.Predecessor)" HeaderText="Predecessor" Width="200">
53+
54+
<Template>
55+
@{
56+
var task = context as TaskDataModel;
57+
var value = task?.Predecessor;
58+
59+
if (!string.IsNullOrWhiteSpace(value))
60+
{
61+
<div class="e-dependencies">@value</div>
62+
;
63+
}
64+
else
65+
{
66+
<div> - </div>
67+
;
68+
}
69+
}
70+
</Template>
71+
</GanttColumn>
72+
</GanttColumns>
73+
<GanttEditSettings AllowEditing="true" AllowTaskbarEditing="true" AllowAdding="true" AllowDeleting="true" />
74+
</SfGantt>
75+
@code {
76+
77+
public List<object> ToolbarItems = new() { "Add", "Edit", "Update", "Delete", "Search" };
78+
79+
// GraphQL adaptor configuration: ResolverName must match your server method (PascalCase)
80+
// and the query must select count + result with the fields the Gantt needs.
81+
private Syncfusion.Blazor.Data.GraphQLAdaptorOptions AdaptorOptions => new()
82+
{
83+
ResolverName = "TaskData",
84+
Query = @"
85+
query TaskData($dataManager: DataManagerRequestInput!) {
86+
taskData(dataManager: $dataManager) {
87+
count
88+
result {
89+
taskID
90+
taskName
91+
startDate
92+
endDate
93+
duration
94+
progress
95+
predecessor
96+
parentID
97+
}
98+
}
99+
}",
100+
101+
Mutation = new Syncfusion.Blazor.Data.GraphQLMutation
102+
{
103+
// INSERT (matches InsertTask parameters)
104+
Insert = @"
105+
mutation create($record: TaskDataModelInput!, $index: Int!, $action: String!, $additionalParameters: Any) {
106+
createTask(record: $record, index: $index, action: $action, additionalParameters: $additionalParameters) {
107+
taskID
108+
taskName
109+
startDate
110+
endDate
111+
duration
112+
progress
113+
predecessor
114+
parentID
115+
}
116+
}",
117+
Update = @"mutation update($record: TaskDataModelInput!, $action: String!, $primaryColumnName: String!, $primaryColumnValue: Int!, $additionalParameters: Any) {
118+
updateTask(record: $record, action: $action, primaryColumnName: $primaryColumnName, primaryColumnValue: $primaryColumnValue, additionalParameters: $additionalParameters) {
119+
taskID taskName startDate endDate duration progress predecessor parentID
120+
}
121+
}",
122+
123+
// DELETE (matches DeleteTask parameters)
124+
Delete = @"mutation delete($primaryColumnValue: ID!, $additionalParameters: Any) {
125+
deleteTask(key: $primaryColumnValue, additionalParameters: $additionalParameters)
126+
}",
127+
Batch = @"mutation batch($changed: [TaskDataModelInput!], $added: [TaskDataModelInput!], $deleted: [TaskDataModelInput!], $action: String!, $primaryColumnName: String!, $additionalParameters: Any, $dropIndex: Int) {
128+
batchUpdate(changed: $changed, added: $added, deleted: $deleted, action: $action, primaryColumnName: $primaryColumnName, additionalParameters: $additionalParameters, dropIndex: $dropIndex) {
129+
taskID
130+
taskName
131+
startDate
132+
endDate
133+
duration
134+
progress
135+
predecessor
136+
parentID
137+
}
138+
}"
139+
}
140+
};
141+
}
142+
143+
<style>
144+
.e-progress-custom {
145+
display: flex;
146+
align-items: center;
147+
gap: 8px;
148+
}
149+
150+
.e-progress-outer {
151+
width: 120px;
152+
height: 8px;
153+
border-radius: 4px;
154+
background: #e0e0e0;
155+
position: relative;
156+
overflow: hidden;
157+
}
158+
159+
.e-progress-bar {
160+
height: 100%;
161+
background: #3b82f6;
162+
}
163+
164+
.e-progress-inner span {
165+
font-size: 12px;
166+
}
167+
168+
/* Keep visibility when row selected */
169+
.e-row.e-active .e-progress-outer,
170+
.e-row.e-selectionbackground .e-progress-outer {
171+
background: #cfcfcf;
172+
}
173+
174+
.e-row.e-active .e-progress-bar,
175+
.e-row.e-selectionbackground .e-progress-bar {
176+
background: #2563eb;
177+
}
178+
179+
.e-dependencies {
180+
border-radius: 4px;
181+
padding: 2px 8px;
182+
width: fit-content;
183+
border: 1px solid #b8b8b8;
184+
font-weight: 400;
185+
font-size: 14px;
186+
line-height: 20px;
187+
margin: 0 auto;
188+
}
189+
190+
.e-row.e-active .e-dependencies,
191+
.e-row.e-selectionbackground .e-dependencies {
192+
background: #e5e7eb;
193+
}
194+
195+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@page "/not-found"
2+
@layout MainLayout
3+
4+
<h3>Not Found</h3>
5+
<p>Sorry, the content you are looking for does not exist.</p>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
2+
<Found Context="routeData">
3+
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
4+
<FocusOnNavigate RouteData="routeData" Selector="h1" />
5+
</Found>
6+
</Router>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
@using System.Net.Http
2+
@using System.Net.Http.Json
3+
@using Microsoft.AspNetCore.Components.Forms
4+
@using Microsoft.AspNetCore.Components.Routing
5+
@using Microsoft.AspNetCore.Components.Web
6+
@using static Microsoft.AspNetCore.Components.Web.RenderMode
7+
@using Microsoft.AspNetCore.Components.Web.Virtualization
8+
@using Microsoft.JSInterop
9+
@using GanttGraphQL
10+
@using GanttGraphQL.Components
11+
@using GanttGraphQL.Components.Layout
12+
@using Syncfusion.Blazor.Gantt
13+
@using Syncfusion.Blazor.Navigations

0 commit comments

Comments
 (0)