переклад
Якщо ви хочете створити додаток на Angular, який працюватиме як в Protheus, так і в браузері, цей покроковий посібник допоможе вам налаштувати все — від встановлення до повної інтеграції. Поїхали!
Посилання на доступ до репозиторію на GitHub, що містить код, який ми будемо створювати: welersonfrr/po-project
Налаштування Angular
Встановлення Angular CLI та PO-UI
Для початку потрібно налаштувати середовище Angular і встановити необхідні бібліотеки, щоб проект коректно працював з Protheus. Створимо новий проект і підготуємо все для подальшого розвитку.
npx -p @angular/cli@17
ng new po-project --skip-install
Виберіть стандартні опції:
- Stylesheet: CSS
- SSR і SSG: Ні
Заходимо в папку проекту
cd po-project
Встановлення залежностей
npm i @totvs/protheus-lib-core@17
ng add @po-ui/ng-components@17 # Виберіть SideMenu = Yes
ng add @po-ui/ng-templates
Відкриваємо проект у VSCode
code .
Створення та налаштування файлів
Тепер, коли проект налаштовано, настав час створити та налаштувати кілька файлів, які забезпечать взаємодію між Angular і Protheus. Ці налаштування охоплюють від обробки помилок до отримання параметрів з Protheus.
Виправлення помилки з провайдером window
Файл: src/app/app.config.ts
providers: [
… // Інші провайдери
{ provide: "Window", useValue: window },
]
Визначення джерела виконання
Файл: src/app/app.component.ts
import { ProtheusLibCoreModule, ProAppConfigService } from '@totvs/protheus-lib-core';
imports: [
ProtheusLibCoreModule,
... // Інші імпорти
]
constructor(private proAppConfigService: ProAppConfigService) {
if (this.proAppConfigService.insideProtheus()) {
// Виконується в Protheus
} else {
// Виконується через браузер
}
}
Створення файлу для отримання параметрів з Protheus
Файл: src/assets/preload/advpltojs.js
(codeType, content) => {
console.log(`Preload - codeType: ${codeType} - content: ${content}`);
if (codeType == 'filiaisComAcesso') {
sessionStorage.setItem('FILIAIS', content);
}
if (codeType == 'currentFilial') {
sessionStorage.setItem('currentFilial', content);
}
if (codeType == 'currentEmpresa') {
sessionStorage.setItem('currentEmpresa', content);
}
}
Налаштування середовища
Налаштування середовища є важливим для забезпечення правильного функціонування нашого додатка як у розробці, так і в продакшн-середовищі.
переклад
Давайте визначимо необхідні змінні середовища для кожного випадку.
Розробка
Файл: src/environments/environment.ts
export const environment = {
ambiente: "browser",
url: "URL_REST_DO_SEU_AMBIENTE",
path: {
login: "/api/oauth2/v1/token/",
defaults: "/api/protheus/session/v1/defaults"
},
}
Продукція
Файл: src/environments/environment.producao.ts
export const environment = {
ambiente: "protheus",
url: "URL_REST_DO_SEU_AMBIENTE",
path: {
login: "/api/oauth2/v1/token/",
defaults: "/api/protheus/session/v1/defaults"
},
}
Налаштування в angular.json для Build
Замінимо в projects > po-project > architect > build > options
:
"outputPath": "dist/po-project"
На:
"outputPath": {
"base": "dist/po-project",
"browser": ""
},
Додамо в projects > po-project > architect > build > configurations
:
"protheus": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.producao.ts"
}
]
}
Тепер, при запуску ng serve
, додаток має бути доступний у браузері.
Налаштування входу
Щоб забезпечити безпечний доступ до системи, потрібно налаштувати потік автентифікації. Тут, як приклад, ми створимо компоненти для входу та домашньої сторінки, налаштуємо маршрути та забезпечимо правильну роботу автентифікації.
Ми використовуватимемо шаблон PoPageLogin: (https://po-ui.io/documentation/po-page-login)
Створення компонентів
ng g c pages/home
ng g c pages/login
Налаштування маршрутів
Ми відредагуємо наші маршрути, щоб вказати на кожен елемент:
Файл: src/app/app.routes.ts
export const routes: Routes = [
{ path: "", component: HomeComponent },
{ path: "index.html", redirectTo: "" },
{ path: "login", component: LoginComponent }
];
Змінюємо вміст рядка 7 файлу app.component.html
Тут ми будуємо наші маршрути, зберігаючи все, що навколо, як назва додатка та sidemenu.
Файл: src/app/app.component.html
Замінити рядок, що містить:
AppName page
``` На: ``` ``` > На цьому етапі, після збереження, ми побачимо в нашому браузері вміст, що міститься в home.component.html. В файл `src/app/pages/login.component.html` додайте виклик шаблону: ``` ``` > * Не забувайте вставити в login.component.ts імпорт "PoPageLoginModule". Якщо ми перейдемо на нашу сторінку за маршрутом "/login", ми побачимо, що вона відображається дивно. ![pic](https://drive.javascript.org.ua/2a71cc3dc01_PbU2N4PkmJQsGwh8wt1Dqg_png) Це відбувається через router-outlet, давайте виправимо це зараз: У файлі `src/app/app.component.ts` зробіть наступні зміни: # Оголосіть router в конструкторі: ``` constructor( private router: Router, ...
переклад
// Інші змінні
)
Оголошення змінної: excludedRoutes:
excludedRoutes = ['/login']; // Додайте маршрути, які не повинні відображати обгортки
І, зрештою, функція:
isExcludedRoute(): boolean {
return this.excludedRoutes.includes(this.router.url);
}
У файлі src/app/app.component.html
зробимо наступні зміни:
Замінити
``` ## На ```
``` ## Додати після закриття останнього
``` ``` Тепер наш маршрут login буде поза обгортками і буде коректно відображено на сторінці ## Обробка для виконання входу через браузер У файлах для входу зробимо наступні зміни: Файл: `src/app/pages/login.component.ts` ## Оголошення та функція: ``` loginSubmit(data: any) { console.log(data); } ``` Файл: `src/app/pages/login.component.html` ## Додавання виклику шаблону всередині тега: ``` ``` Тепер, заповнивши поля для логіну та пароля і натиснувши кнопку входу, ми побачимо наш логін та пароль у консолі браузера ![pic](https://drive.javascript.org.ua/8a050463fd1_ECYaIjj796QGtcgpzLY8gg_png) ## Перевірка користувача, що увійшов
переклад
Тепер ми перевіримо, чи користувач увійшов в систему!
## Повертаємось до файлу app.component
Файл: `src/app/app.component.ts`
## Додаємо в конструктор Login Service:
private loginService: LoginService
```
Вставляємо в умову if:
// Виконується в Protheus
this.proAppConfigService.loadAppConfig();
this.router.navigate(['/'])
А в else:
// Виконується через браузер
this.loginService.getAccessToken()
Таким чином, при доступі до додатка через Protheus функція
loadAppConfig()
буде відповідати за заповнення ERPTOKEN автоматично, тоді як доступ через браузер буде перенаправлено на сторінку входу.
Тепер підготуємо виклик даних з API як приклад використання access_token.
Підготовка для використання API
Ми створимо інтерцептор для завантаження автентифікації в заголовки запитів, щоб уникнути повторного завантаження її для кожного запиту:
ng g s services/interceptor/interceptor
Тепер зробимо зміни в створеному InterceptorService.
Файл: src/app/services/interceptor/interceptor.service.ts
- Імпортуйте необхідні модулі:
Замінимо:
export class InterceptorService {
На:
export class InterceptorService implements HttpInterceptor {
Додаємо в конструктор:
private loginService: LoginService
Оголошуємо функцію:
intercept(req: HttpRequest, next: HttpHandler): Observable {
const access_token = this.loginService.getAccessToken()
const clone_request = req.clone({
setHeaders: {
Authorization: `Bearer ${access_token}`
}
})
return next.handle(clone_request)
}
Тепер змінюємо файл app.config.ts, щоб наш інтерцептор працював:
Файл: src/app/app.config.ts
Невелика зміна в провайдері:
providers: [
...
переклад
// Інші провайдери
provideHttpClient(
withInterceptorsFromDi() // Включити в дужки
),
{provide: HTTP_INTERCEPTORS, useClass: InterceptorService, multi: true}, // Включити цей рядок
... // Інші провайдери
]
Завдяки цьому будь-який HTTP-запит, виконаний в межах додатку, буде мати в заголовку access_token.
Тепер зробимо наш запит
Ми створимо ще один сервіс, який буде відповідати за виклик API:
ng g s services/api/api
У новому ApiService, який ми створили, внесемо зміни, виконавши необхідні імпорти.
Файл: src/app/services/api/api.service.ts
Додаємо в конструктор:
private httpClient: HttpClient
Оголошуємо функцію:
getData() {
const url = environment.url + environment.path.defaults
return this.httpClient.get(url)
}
У HomeComponent зробимо зміни разом з необхідними імпортами:
Файл: src/app/pages/home/home.component.ts
Імпортуємо PoModule для використання компонентів PO-UI
imports: [
PoModule
],
Оголошуємо змінну data
data: string = ''
Оголошуємо ApiService у конструкторі
private apiService: ApiService
Оголошуємо функцію getData(), яка відповідає за отримання значень:
getData() {
this.apiService.getData().subscribe({
next:
(req: any) => {
console.log(req); // Перевірте в консолі повний відповідь API
this.data = req.base_date // Відповідь base_date буде виведена на екран
},
error:
(err: any) => { },
complete:
() => { }
})
}
Файл: src/app/pages/home/home.component.html
Тут ми викликаємо функцію та відображаємо результат на екрані
{{data}}
``` Завдяки цьому наш додаток повністю підготовлений для використання через браузер!!
## Підготовка до використання в Protheus
Тепер, коли наш додаток готовий для використання в браузері, настав час підготувати його для запуску всередині Protheus. Це включає створення необхідних файлів та інтеграцію з платформою.
## Білд проекту
ng build -c protheus
```
Після компіляції буде створена папка dist
у кореневій директорії проекту. Всередині неї буде підкаталог з назвою застосунку, визначеною в output-path
. Цю папку потрібно підготувати для використання в Protheus.
Підготовка файлів
- Стисніть папку в форматі
.zip
:po-project.zip
- Перейменуйте розширення на
.app
:po-project.app
3.
переклад
Скомпілюйте цей файл .app
в середовищі Protheus (якщо ви використовуєте VS Code, може бути необхідно додати розширення .app
до списку дозволених для компіляції).
Створення функції ADVPL
Тепер створимо функцію ADVPL для виклику додатку Angular всередині Protheus.
Файл: TEST001.prw
#include "protheus.ch"
User Function TEST001()
FwCallApp("po-project")
Return
Static Function JsToAdvpl(oWebChannel, cType, cContent)
Local cFCAcss := ''
Local i
if (FWUsrEmp(__cUserID)[1] == '@@@@')
for i := 1 to Len(LoadFils())
cFCAcss += LoadFils()[i] + '-'
next
else
for i := 1 to Len(FWUsrEmp(__cUserID))
cFCAcss += SubString(FWUsrEmp(__cUserID)[i], 3, 6) + '-'
next
endif
oWebChannel:AdvPLToJS('filiaisComAcesso', cFCAcss)
oWebChannel:AdvPLToJS('currentFilial', cFilAnt)
oWebChannel:AdvPLToJS('currentEmpresa', cEmpAnt)
Return .T.
Ця функція дозволяє викликати додаток Angular через меню Protheus і передавати дані між Protheus і додатком Angular.
Відповідальність за виклик несе лише FwCallApp
, а статична функція JsToAdvpl
відповідає за комунікацію з файлом AdvplToJs
, що є в додатку Angular.
В цьому проекті AdvplToJs
не використовувалося, але воно вже готове для використання за потребою.
Доступ через браузер
Після налаштування додатку ми можемо отримати до нього доступ через браузер, використовуючи наступну URL-адресу:
http://:/app-root/po-project/
Наприклад:
http://127.0.0.1:1234/app-root/po-project/
Заключні зауваження
Переконайтеся, що сервер Protheus правильно налаштований для надання веб-додатків і що дозволи налаштовані відповідно до вимог.
Тепер, коли всі налаштування завершено, у нас є функціональний додаток Angular, до якого можна отримати доступ як через браузер, так і через Protheus. Така інтеграція дозволяє створювати сучасні та чуйні додатки, використовуючи потужність Angular, при цьому зберігаючи сумісність з процесами ERP Protheus.
Якщо у вас виникли питання або проблеми під час реалізації, уважно перегляньте кожен етап і зверніться до офіційної документації PO-UI та Protheus для отримання додаткових деталей.
Сподіваюся, що цей посібник був корисним для вас. Удачі в кодингу!
Перекладено з: App PO UI no Protheus e Navegador