Skip to content

Commit 45237dd

Browse files
authored
Merge pull request #3 from SyncfusionExamples/1006328-django-sample
1006328 - Angular Grid Integration sample with DRF and MS SQL
2 parents dfb73bb + 3c1d5b4 commit 45237dd

38 files changed

Lines changed: 1779 additions & 0 deletions
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Client
2+
3+
This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.0.0.
4+
5+
## Development server
6+
7+
To start a local development server, run:
8+
9+
```bash
10+
ng serve
11+
```
12+
13+
Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
14+
15+
## Code scaffolding
16+
17+
Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
18+
19+
```bash
20+
ng generate component component-name
21+
```
22+
23+
For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
24+
25+
```bash
26+
ng generate --help
27+
```
28+
29+
## Building
30+
31+
To build the project run:
32+
33+
```bash
34+
ng build
35+
```
36+
37+
This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
38+
39+
## Running unit tests
40+
41+
To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
42+
43+
```bash
44+
ng test
45+
```
46+
47+
## Running end-to-end tests
48+
49+
For end-to-end (e2e) testing, run:
50+
51+
```bash
52+
ng e2e
53+
```
54+
55+
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
56+
57+
## Additional Resources
58+
59+
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
{
2+
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3+
"version": 1,
4+
"newProjectRoot": "projects",
5+
"projects": {
6+
"client": {
7+
"projectType": "application",
8+
"schematics": {},
9+
"root": "",
10+
"sourceRoot": "src",
11+
"prefix": "app",
12+
"architect": {
13+
"build": {
14+
"builder": "@angular/build:application",
15+
"options": {
16+
"browser": "src/main.ts",
17+
"polyfills": [
18+
"zone.js"
19+
],
20+
"tsConfig": "tsconfig.app.json",
21+
"assets": [
22+
{
23+
"glob": "**/*",
24+
"input": "public"
25+
}
26+
],
27+
"styles": [
28+
"src/styles.css"
29+
]
30+
},
31+
"configurations": {
32+
"production": {
33+
"budgets": [
34+
{
35+
"type": "initial",
36+
"maximumWarning": "500kB",
37+
"maximumError": "1MB"
38+
},
39+
{
40+
"type": "anyComponentStyle",
41+
"maximumWarning": "4kB",
42+
"maximumError": "8kB"
43+
}
44+
],
45+
"outputHashing": "all"
46+
},
47+
"development": {
48+
"optimization": false,
49+
"extractLicenses": false,
50+
"sourceMap": true
51+
}
52+
},
53+
"defaultConfiguration": "production"
54+
},
55+
"serve": {
56+
"builder": "@angular/build:dev-server",
57+
"configurations": {
58+
"production": {
59+
"buildTarget": "client:build:production"
60+
},
61+
"development": {
62+
"buildTarget": "client:build:development"
63+
}
64+
},
65+
"defaultConfiguration": "development"
66+
},
67+
"extract-i18n": {
68+
"builder": "@angular/build:extract-i18n"
69+
},
70+
"test": {
71+
"builder": "@angular/build:karma",
72+
"options": {
73+
"polyfills": [
74+
"zone.js",
75+
"zone.js/testing"
76+
],
77+
"tsConfig": "tsconfig.spec.json",
78+
"assets": [
79+
{
80+
"glob": "**/*",
81+
"input": "public"
82+
}
83+
],
84+
"styles": [
85+
"src/styles.css"
86+
]
87+
}
88+
}
89+
}
90+
}
91+
}
92+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"name": "client",
3+
"version": "0.0.0",
4+
"scripts": {
5+
"ng": "ng",
6+
"start": "ng serve",
7+
"build": "ng build",
8+
"watch": "ng build --watch --configuration development",
9+
"test": "ng test"
10+
},
11+
"private": true,
12+
"dependencies": {
13+
"@angular/common": "^20.0.0",
14+
"@angular/compiler": "^20.0.0",
15+
"@angular/core": "^20.0.0",
16+
"@angular/forms": "^20.0.0",
17+
"@angular/platform-browser": "^20.0.0",
18+
"@angular/router": "^20.0.0",
19+
"@syncfusion/ej2-angular-buttons": "^32.1.24",
20+
"@syncfusion/ej2-angular-dropdowns": "^32.1.24",
21+
"@syncfusion/ej2-angular-grids": "^32.1.24",
22+
"@syncfusion/ej2-angular-inputs": "^32.1.24",
23+
"@syncfusion/ej2-data": "^32.1.24",
24+
"rxjs": "~7.8.0",
25+
"tslib": "^2.3.0",
26+
"zone.js": "~0.15.0"
27+
},
28+
"devDependencies": {
29+
"@angular/build": "^20.0.0",
30+
"@angular/cli": "^20.0.0",
31+
"@angular/compiler-cli": "^20.0.0",
32+
"@types/jasmine": "~5.1.0",
33+
"jasmine-core": "~5.7.0",
34+
"karma": "~6.4.0",
35+
"karma-chrome-launcher": "~3.2.0",
36+
"karma-coverage": "~2.2.0",
37+
"karma-jasmine": "~5.1.0",
38+
"karma-jasmine-html-reporter": "~2.1.0",
39+
"typescript": "~5.8.2"
40+
}
41+
}
Binary file not shown.
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
2+
/* Light backgrounds + black text only */
3+
:root {
4+
/* Pastels (very light) */
5+
--g-fantasy: #f3e8ff; /* purple-50 */
6+
--g-scifi: #e0f2fe; /* sky-100 */
7+
--g-mystery: #e9d5ff; /* violet-200 */
8+
--g-thriller: #fee2e2; /* red-200 */
9+
--g-romance: #ffe4e6; /* rose-200 */
10+
--g-historical: #fef9c3; /* yellow-100 */
11+
--g-nonfiction: #dcfce7; /* green-200 */
12+
--g-biography: #f1f5f9; /* slate-100 */
13+
--g-ya: #e0e7ff; /* indigo-100 */
14+
--g-horror: #fee2e2; /* red-200 */
15+
--g-adventure: #dbeafe; /* blue-200 */
16+
--g-classic: #fde68a; /* amber-300 */
17+
18+
--status-due: #e0f2fe; /* light blue */
19+
--status-today: #fff7ed; /* light orange */
20+
--status-overdue: #ffe4e6; /* light rose */
21+
--status-returned: #dcfce7; /* light green */
22+
--status-unknown: #f1f5f9; /* light slate */
23+
24+
--border-200: #e5e7eb;
25+
--text: #000; /* black */
26+
}
27+
28+
.e-grid .e-rowcell { vertical-align: middle; color: var(--text); }
29+
.e-grid a { color: var(--text); text-decoration: underline; }
30+
31+
/* ---------- Generic chips (black text) ---------- */
32+
.e-grid .chip {
33+
display: inline-flex;
34+
align-items: center;
35+
gap: 6px;
36+
max-width: 100%;
37+
padding: 4px 10px;
38+
border-radius: 999px;
39+
font-size: 12px;
40+
line-height: 1.2;
41+
color: var(--text);
42+
border: 1px solid var(--border-200);
43+
white-space: nowrap;
44+
text-overflow: ellipsis;
45+
overflow: hidden;
46+
background: transparent; /* default transparent */
47+
}
48+
49+
/* Outline chip variant (no background color) */
50+
.e-grid .chip--outline {
51+
background: transparent;
52+
}
53+
54+
/* Date chip base + states (only light backgrounds, black text) */
55+
.e-grid .chip--date { font-variant-numeric: tabular-nums; }
56+
57+
.e-grid .chip--date.is-due { background: var(--status-due); }
58+
.e-grid .chip--date.is-today { background: var(--status-today); }
59+
.e-grid .chip--date.is-overdue { background: var(--status-overdue); }
60+
.e-grid .chip--date.is-returned { background: var(--status-returned); }
61+
.e-grid .chip--date.is-unknown { background: var(--status-unknown); }
62+
63+
/* ---------- Genre colored chips (different bg per Genre; black text) ---------- */
64+
.e-grid .gchip {
65+
display: inline-flex;
66+
align-items: center;
67+
padding: 2px 10px;
68+
border-radius: 999px;
69+
font-size: 12px;
70+
color: var(--text);
71+
border: 1px solid var(--border-200);
72+
background: var(--status-unknown);
73+
}
74+
.e-grid .g-fantasy { background: var(--g-fantasy); }
75+
.e-grid .g-scifi { background: var(--g-scifi); }
76+
.e-grid .g-mystery { background: var(--g-mystery); }
77+
.e-grid .g-thriller { background: var(--g-thriller); }
78+
.e-grid .g-romance { background: var(--g-romance); }
79+
.e-grid .g-historical { background: var(--g-historical); }
80+
.e-grid .g-nonfiction { background: var(--g-nonfiction); }
81+
.e-grid .g-biography { background: var(--g-biography); }
82+
.e-grid .g-ya { background: var(--g-ya); }
83+
.e-grid .g-horror { background: var(--g-horror); }
84+
.e-grid .g-adventure { background: var(--g-adventure); }
85+
.e-grid .g-classic { background: var(--g-classic); }
86+
87+
/* ---------- Status pill (light bg; black text) ---------- */
88+
.e-grid .pill {
89+
display: inline-flex;
90+
align-items: center;
91+
padding: 2px 10px;
92+
border-radius: 999px;
93+
font-size: 12px;
94+
font-weight: 600;
95+
color: var(--text);
96+
border: 1px solid var(--border-200);
97+
background: var(--status-unknown);
98+
}
99+
100+
.e-grid .pill--returned { background: var(--status-returned); }
101+
.e-grid .pill--borrowed { background: var(--status-due); }
102+
.e-grid .pill--overdue { background: var(--status-overdue); }
103+
.e-grid .pill--lost { background: #f8fafc; border-style: dashed; }
104+
105+
/* Truncation safety */
106+
.e-grid .chip, .e-grid .pill, .e-grid .gchip {
107+
max-width: 100%;
108+
overflow: hidden;
109+
text-overflow: ellipsis;
110+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<ejs-grid
2+
#grid
3+
[dataSource]="data"
4+
[allowPaging]="true"
5+
[pageSettings]="pageSettings"
6+
[allowSorting]="true"
7+
[allowFiltering]="true"
8+
[filterSettings]="filterSettings"
9+
[toolbar]="toolbar"
10+
[editSettings]="editSettings"
11+
[selectionSettings]="selectionSettings"
12+
gridLines="Both"
13+
>
14+
<e-columns>
15+
<e-column field="record_id" headerText="Record ID" width="120" [isPrimaryKey]="true" [visible]="false"></e-column>
16+
17+
<e-column field="isbn_number" headerText="ISBN Number" width="170" [validationRules]="ISBNValidationRule"></e-column>
18+
19+
<e-column field="book_title" headerText="Book Title" width="240" [validationRules]="bookTitleValidationRule"></e-column>
20+
21+
<e-column field="author_name" headerText="Author Name" width="200" [validationRules]="authorNameValidationRule"></e-column>
22+
23+
<e-column field="genre" headerText="Genre" width="160" editType="dropdownedit" textAlign="Center" [filter]="checkBoxFilterSettings" [validationRules]="genreValidationRule">
24+
<ng-template #template let-data>
25+
<span [class]="getGenreClass(data.genre)" [title]="data.genre || '—'">
26+
{{ data.genre || '—' }}
27+
</span>
28+
</ng-template>
29+
</e-column>
30+
31+
<e-column field="borrower_name" headerText="Borrower Name" width="200" [validationRules]="borrowerNameValidationRule"></e-column>
32+
33+
<e-column field="borrower_email" headerText="Borrower Email" width="240" [validationRules]="borrowerEmailValidationRule">
34+
<ng-template #template let-data>
35+
<a [href]="'mailto:' + data.borrower_email" [title]="data.borrower_email">
36+
{{ data.borrower_email }}
37+
</a>
38+
</ng-template>
39+
</e-column>
40+
41+
<e-column field="borrowed_date" headerText="Borrowed Date" width="160" type="date" format="yMd" editType="datepickeredit" textAlign="Right" [filter]="menuFilterSettings" [validationRules]="borrowDateValidationRule">
42+
<ng-template #template let-data>
43+
<span class="chip chip--outline" [title]="(data.borrowed_date | date:'MM/dd/yyyy')">
44+
{{ (data.borrowed_date | date:'MM/dd/yyyy') }}
45+
</span>
46+
</ng-template>
47+
</e-column>
48+
49+
<e-column field="expected_return_date" headerText="Expected Return Date" width="200" type="date" format="yMd" editType="datepickeredit" textAlign="Right" [filter]="menuFilterSettings" [validationRules]="expectedReturnDateValidationRule">
50+
<ng-template #template let-data>
51+
<ng-container *ngIf="getDueMeta(data) as due">
52+
<span
53+
class="chip chip--date"
54+
[ngClass]="{
55+
'is-returned': due.state === 'returned',
56+
'is-overdue': due.state === 'overdue',
57+
'is-due': due.state === 'due',
58+
'is-today': due.state === 'today',
59+
'is-unknown': due.state === 'unknown'
60+
}"
61+
[title]="due.label"
62+
>
63+
{{ due.label }}
64+
</span>
65+
</ng-container>
66+
</ng-template>
67+
</e-column>
68+
69+
<e-column field="actual_return_date" headerText="Actual Return Date" width="190" type="date" editType="datepickeredit" textAlign="Right" [filter]="menuFilterSettings">
70+
<ng-template #template let-data>
71+
<span *ngIf="data.actual_return_date; else notReturned" class="chip chip--date is-returned" [title]="'Returned ' + (data.actual_return_date | date:'MM/dd/yyyy')">
72+
✔ {{ (data.actual_return_date | date:'MM/dd/yyyy') }}
73+
</span>
74+
<ng-template #notReturned>
75+
<span class="chip chip--date is-unknown"></span>
76+
</ng-template>
77+
</ng-template>
78+
</e-column>
79+
80+
<e-column field="lending_status" headerText="Lending Status" width="160" editType="dropdownedit" textAlign="Center" [filter]="checkBoxFilterSettings" [validationRules]="lendingStatusValidationRule">
81+
<ng-template #template let-data>
82+
<span class="{{ getStatusClass(data.lending_status) }}" [title]="data.lending_status || 'Unknown'">
83+
{{ data.lending_status || 'Unknown' }}
84+
</span>
85+
</ng-template>
86+
</e-column>
87+
88+
</e-columns>
89+
</ejs-grid>

0 commit comments

Comments
 (0)