Многосторнние изменения:
- Обновлены Angular и зависимости до последней версии (22.1.5, postcss, zod и т.д.) - Заменена загрузка данных в конструкторе на API resource() в task-list и task-details - Переименовать селекторы компонентов из app-* в ksk-crm-* - Добавлены конфиги окружения с настраиваемым API URL - Подключены @ng-icons/lucide для иконок - Добавлен шрифт Inter и CSS-переменные для темизации - Обновлён target tsconfig до ES2023 (для доступности методов в js)
This commit is contained in:
+14
-5
@@ -12,7 +12,7 @@
|
||||
"schematics": {},
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"prefix": "ksk-crm",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular/build:application",
|
||||
@@ -25,9 +25,7 @@
|
||||
"input": "public"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
]
|
||||
"styles": ["src/styles.css"]
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
@@ -48,7 +46,13 @@
|
||||
"development": {
|
||||
"optimization": false,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true
|
||||
"sourceMap": true,
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.development.ts"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
@@ -63,6 +67,11 @@
|
||||
"buildTarget": "kskcrmspa:build:development"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"host": "0.0.0.0",
|
||||
"port": 4200,
|
||||
"allowedHosts": true
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"test": {
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
"@angular/forms": "^22.1.0",
|
||||
"@angular/platform-browser": "^22.1.0",
|
||||
"@angular/router": "^22.1.0",
|
||||
"@fontsource/inter": "^5.3.0",
|
||||
"@ng-icons/core": "^36.0.0",
|
||||
"@ng-icons/lucide": "^36.0.0",
|
||||
"pocketbase": "^0.28.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0"
|
||||
|
||||
Generated
+292
-245
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
allowBuilds:
|
||||
'@parcel/watcher': true
|
||||
esbuild: true
|
||||
lmdb: true
|
||||
msgpackr-extract: true
|
||||
@@ -2,11 +2,10 @@ import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/
|
||||
import { provideRouter } from '@angular/router';
|
||||
|
||||
import { routes } from './app.routes';
|
||||
import { provideClientHydration } from '@angular/platform-browser';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
provideBrowserGlobalErrorListeners(),
|
||||
provideRouter(routes), provideClientHydration()
|
||||
provideRouter(routes)
|
||||
]
|
||||
};
|
||||
|
||||
+10
-14
@@ -2,31 +2,27 @@ import { Component } from '@angular/core';
|
||||
import { RouterLink, RouterOutlet } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
imports: [RouterOutlet, RouterLink],
|
||||
selector: 'ksk-crm-root',
|
||||
imports: [RouterOutlet],
|
||||
template: `
|
||||
<main>
|
||||
<a [routerLink]="['/']">На главную</a>
|
||||
<section class="content">
|
||||
<router-outlet />
|
||||
</section>
|
||||
<router-outlet />
|
||||
</main>
|
||||
`,
|
||||
styles: `
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
min-height: 100vh;
|
||||
background: #2e2e2e;
|
||||
padding: 8px;
|
||||
min-height: 100dvh;
|
||||
background: var(--bg-base);
|
||||
|
||||
main {
|
||||
width: 60%;
|
||||
min-height: 500px;
|
||||
background: white;
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
background: var(--surface);
|
||||
padding: 1ch;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
||||
@@ -1,31 +1,25 @@
|
||||
import { ChangeDetectorRef, Component, inject } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ActivatedRoute, RouterLink } from '@angular/router';
|
||||
import { TaskService } from './task-service';
|
||||
import { Task } from './task';
|
||||
import { Component, inject, resource, signal } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-task-details',
|
||||
imports: [],
|
||||
selector: 'ksk-crm-task-details',
|
||||
imports: [RouterLink],
|
||||
template: `
|
||||
<p>{{ task?.name }}</p>
|
||||
<p>{{ task?.numberPhone }}</p>
|
||||
<p>{{ task?.streetAddress }}</p>
|
||||
<a [routerLink]="['/']">На главную</a>
|
||||
<p>{{ taskResource.value()?.name }}</p>
|
||||
<p>{{ taskResource.value()?.numberPhone }}</p>
|
||||
<p>{{ taskResource.value()?.streetAddress }}</p>
|
||||
`,
|
||||
styles: ``,
|
||||
})
|
||||
export class TaskDetails {
|
||||
route: ActivatedRoute = inject(ActivatedRoute);
|
||||
taskId = '';
|
||||
taskService: TaskService = inject(TaskService);
|
||||
changeDetectorRef = inject(ChangeDetectorRef);
|
||||
task: Task | undefined;
|
||||
constructor() {
|
||||
this.taskId = this.route.snapshot.params['id'];
|
||||
this.taskService.getTaskById(this.taskId).then(task => {
|
||||
if (task) {
|
||||
this.task = task;
|
||||
this.changeDetectorRef.markForCheck()
|
||||
}
|
||||
});
|
||||
}
|
||||
taskId = signal(this.route.snapshot.params['id']);
|
||||
taskResource = resource<Task | null, string>({
|
||||
params: () => this.taskId(),
|
||||
loader: ({ params: id }) => this.taskService.getTaskById(id),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,14 +3,13 @@ import { Task } from './task';
|
||||
import { RouterLink } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-task-item',
|
||||
selector: 'ksk-crm-task-item',
|
||||
imports: [
|
||||
RouterLink
|
||||
],
|
||||
template: `
|
||||
<p>{{ task().name }}</p>
|
||||
<p>{{ task().city }}, {{ task().streetAddress }}</p>
|
||||
<p>{{ task().numberPhone }}</p>
|
||||
<p><a [routerLink]="['/details', task().id]">Подробнее...</a></p>
|
||||
`,
|
||||
styles: `
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
import { Component, computed, inject, signal } from '@angular/core';
|
||||
import { Component, computed, inject, linkedSignal, resource, signal } from '@angular/core';
|
||||
import { TaskItem } from './task-item';
|
||||
import { Task } from './task';
|
||||
import { TaskService } from './task-service';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { NgIcon, provideIcons } from '@ng-icons/core';
|
||||
import { lucideSquarePlus } from '@ng-icons/lucide';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home-page',
|
||||
imports: [TaskItem, RouterLink, FormsModule],
|
||||
selector: 'ksk-crm-home-page',
|
||||
imports: [TaskItem, RouterLink, FormsModule, NgIcon],
|
||||
providers: [provideIcons({ lucideSquarePlus })],
|
||||
template: `
|
||||
<section>
|
||||
<a [routerLink]="['/new']">Добавить</a><br>
|
||||
<input [(ngModel)]="searchInput" type="text" />
|
||||
<a routerLink="/new"><ng-icon name="lucideSquarePlus" size="20" /> </a>
|
||||
</section>
|
||||
<section class="result">
|
||||
@for (task of filteredTasks(); track $index) {
|
||||
<app-task-item [task]="task" />
|
||||
<ksk-crm-task-item [task]="task" />
|
||||
}
|
||||
</section>
|
||||
`,
|
||||
@@ -34,13 +37,23 @@ import { FormsModule } from '@angular/forms';
|
||||
`,
|
||||
})
|
||||
export class TaskList {
|
||||
tasks: Task[] = [];
|
||||
taskService: TaskService = inject(TaskService);
|
||||
|
||||
tasks = resource<Task[], null>({
|
||||
params: signal(null),
|
||||
loader: () => this.taskService.getAllTasks(),
|
||||
});
|
||||
|
||||
searchInput = signal('');
|
||||
|
||||
filteredTasks = computed<Task[]>(() => {
|
||||
const s = this.searchInput();
|
||||
if (s === '') return this.tasks;
|
||||
return this.tasks.filter(
|
||||
const tasks = this.tasks.value();
|
||||
|
||||
if (!tasks) return [];
|
||||
if (s === '') return tasks;
|
||||
|
||||
return tasks.filter(
|
||||
(task) =>
|
||||
task.name.includes(s) ||
|
||||
task.city.includes(s) ||
|
||||
@@ -48,12 +61,4 @@ export class TaskList {
|
||||
task.numberPhone.includes(s),
|
||||
);
|
||||
});
|
||||
|
||||
constructor() {
|
||||
this.taskService.getAllTasks().then(tasks => {
|
||||
this.tasks = tasks;
|
||||
this.searchInput.update(_ => " ")
|
||||
this.searchInput.update(_ => '');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-task-new',
|
||||
selector: 'ksk-crm-task-new',
|
||||
imports: [
|
||||
ReactiveFormsModule
|
||||
],
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { Service } from '@angular/core';
|
||||
import { Task } from './task';
|
||||
import PocketBase from 'pocketbase'
|
||||
import { environment } from '../../../environments/environment'
|
||||
|
||||
@Service()
|
||||
export class TaskService {
|
||||
pbTasks = new PocketBase('http://127.0.0.1:8090').collection<Task>('tasks');
|
||||
private apiUrl = environment.apiUrl;
|
||||
private pbTasks = new PocketBase(this.apiUrl).collection<Task>('tasks');
|
||||
|
||||
async getAllTasks(): Promise<Task[]> {
|
||||
return await this.pbTasks.getFullList();
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export const environment = {
|
||||
production: false,
|
||||
apiUrl: "http://192.168.1.22:8090",
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
export const environment = {
|
||||
production: true,
|
||||
apiUrl: 'http://192.168.1.22:8090',
|
||||
};
|
||||
+1
-1
@@ -9,6 +9,6 @@
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
<ksk-crm-root></ksk-crm-root>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
@import '@fontsource/inter/400.css';
|
||||
@import '@fontsource/inter/500.css';
|
||||
@import '@fontsource/inter/600.css';
|
||||
@import '@fontsource/inter/700.css';
|
||||
|
||||
:root {
|
||||
--gray: oklch(28% 0 0);
|
||||
--white: white;
|
||||
|
||||
--font-family-base: 'Inter';
|
||||
|
||||
--bg-base: var(--gray);
|
||||
--surface: var(--white);
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--font-family-base), system-ui, -apple-system, sans-serif;
|
||||
}
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
"isolatedModules": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"target": "ES2022",
|
||||
"target": "ES2023",
|
||||
"module": "preserve"
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
|
||||
Reference in New Issue
Block a user