Skip to content

Commit

Permalink
refactor: get rid of ngx-bootstrap
Browse files Browse the repository at this point in the history
- Refactors acquisitions accounts widget.
- Refactors user profile info tabs.
- Adds css primeng for the patron info application.
- Updates the @ngneat/hotkeys packages.

Signed-off-by: Johnny Mariéthoz <[email protected]>
  • Loading branch information
jma committed Nov 4, 2024
1 parent 238d9e1 commit 322eb21
Show file tree
Hide file tree
Showing 23 changed files with 339 additions and 297 deletions.
10 changes: 5 additions & 5 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
"node_modules/primeng/resources/primeng.min.css",
"node_modules/primeicons/primeicons.css",
"node_modules/primeflex/primeflex.min.css",
"node_modules/ngx-bootstrap/datepicker/bs-datepicker.css",
"node_modules/ngx-spinner/animations/ball-zig-zag.css",
"projects/admin/src/app/scss/styles.scss",
"projects/shared/src/scss/styles.scss"
Expand Down Expand Up @@ -282,7 +281,6 @@
"node_modules/primeng/resources/primeng.min.css",
"node_modules/primeicons/primeicons.css",
"node_modules/primeflex/primeflex.min.css",
"node_modules/ngx-bootstrap/datepicker/bs-datepicker.css",
"projects/shared/src/scss/styles.scss"
],
"scripts": [],
Expand Down Expand Up @@ -558,6 +556,10 @@
}
],
"styles": [
"node_modules/primeng/resources/themes/bootstrap4-light-blue/theme.css",
"node_modules/primeng/resources/primeng.min.css",
"node_modules/primeicons/primeicons.css",
"node_modules/primeflex/primeflex.min.css",
"projects/public-search/src/app/scss/styles.scss",
"projects/shared/src/scss/styles.scss"
],
Expand Down Expand Up @@ -860,8 +862,6 @@
}
},
"cli": {
"schematicCollections": [
"@angular-eslint/schematics"
]
"schematicCollections": ["@angular-eslint/schematics"]
}
}
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@
"@angular/platform-browser-dynamic": "^17.1.0",
"@angular/router": "^17.1.0",
"@biesbjerg/ngx-translate-extract-marker": "^1.0.0",
"@ngneat/hotkeys": "^4.0.0",
"@ng-bootstrap/ng-bootstrap": "^16.0.0",
"@ngneat/hotkeys": "^2.0.0",
"@ngx-formly/core": "^6.3.6",
"@ngx-formly/primeng": "^6.3.6",
"@ngx-loading-bar/core": "^6.0.0",
Expand All @@ -98,7 +98,6 @@
"lodash-es": "^4.17.21",
"luxon": "^3.5.0",
"marked": "^10.0.0",
"ngx-bootstrap": "^12.0.0",
"ngx-spinner": "^16.0.0",
"primeflex": "^3.3.1",
"primeicons": "^6.0.1",
Expand Down
6 changes: 1 addition & 5 deletions projects/admin/src/app/acquisition/acquisition.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { FormlyPrimeNGModule } from '@ngx-formly/primeng';
import { TranslateService } from '@ngx-translate/core';
import { ApiService, CoreModule, RecordModule } from '@rero/ng-core';
import { SharedModule } from '@rero/shared';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { PreviewEmailModule } from '../shared/preview-email/preview-email.module';
import { PrimengImportModule } from '../shared/primeng-import/primeng-import.module';
import { AcquisitionRoutingModule } from './acquisition-routing.module';
Expand Down Expand Up @@ -53,7 +52,6 @@ import { registerFormlyExtension } from './formly/extension';
import { FieldDocumentBriefViewTypeComponent } from './formly/type/field-document-brief-view.type';
import { FieldRefTypeComponent } from './formly/type/field-ref.type';
import { RepeatTypeComponent } from './formly/type/repeat-section.type';
import { SelectAccountComponent } from './formly/type/select-account/select-account.component';
import { InputNoLabelWrapperComponent } from './formly/wrapper/input-no-label.wrapper';
import { AccountAvailableAmountPipe } from './pipes/account-available-amount.pipe';
import { NegativeAmountPipe } from './pipes/negative-amount.pipe';
Expand Down Expand Up @@ -81,7 +79,6 @@ import { ReceptionDatesPipe } from './pipes/reception-dates.pipe';
OrderReceiptViewComponent,
OrderSummaryComponent,
RepeatTypeComponent,
SelectAccountComponent,
SelectAccountEditorWidgetComponent,
ReceiptListComponent,
ReceiptSummaryComponent,
Expand All @@ -94,7 +91,6 @@ import { ReceptionDatesPipe } from './pipes/reception-dates.pipe';
OrderEmailFormComponent
],
imports: [
BsDropdownModule.forRoot(),
CommonModule,
AcquisitionRoutingModule,
FormlyModule,
Expand All @@ -105,7 +101,7 @@ import { ReceptionDatesPipe } from './pipes/reception-dates.pipe';
{ name: 'repeat', component: RepeatTypeComponent },
{ name: 'field-document-brief-view', component: FieldDocumentBriefViewTypeComponent },
{ name: 'field-ref', component: FieldRefTypeComponent },
{ name: 'select-account', component: SelectAccountComponent }
{ name: 'account-select', component: SelectAccountEditorWidgetComponent }
],
wrappers: [
{ name: 'input-no-label', component: InputNoLabelWrapperComponent }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,48 +15,43 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<div class="mt-2 mb-3">
<div class="btn-group w-100" dropdown #dropdown="bs-dropdown" [insideClick]="true" [isDisabled]="to.readonly">
<button id="button-basic" dropdownToggle type="button" aria-controls="dropdown-basic"
[ngClass]="{'is_invalid': formControl.invalid}"
class="btn btn-sm btn-block text-left dropdown-toggle py-2 px-3 d-flex align-items-center">
{{ selectedAccount
? selectedAccount.name
: (to.placeholder | translate) || ('Select an option...' | translate)
}}
<span class="caret ml-auto"></span>
</button>
<div id="dropdown-basic" *dropdownMenu class="dropdown-menu w-100" role="menu" aria-labelledby="button-basic">
@if (accountList.length) {
@for (account of accountList; track account) {
<a href="#"
class="dropdown-item account d-flex"
(click)="$event.preventDefault(); selectAccount(account); dropdown.hide()"
>
<div class="pr-5">
{{ account.depth > 0 ? '&nbsp;&nbsp;&nbsp;&nbsp;'.repeat(account.depth) + ' ' : '' }}
{{ account.name }}
</div>
<div class="ml-auto pl-5 d-flex">
@if (account.number) {
<div class="number">{{ account.number }}</div>
}
<div class="amount" [class]="{
'text-success': account.remaining_balance.self > 0,
'text-muted': account.remaining_balance.self === 0,
'text-warning': account.remaining_balance.self < 0
}">
{{ account.remaining_balance.self | currency: organisation.default_currency }}
</div>
</div>
</a>
}
} @else {
<p class="m-0 px-4 py-2 text-muted" translate>No result</p>
<p-dropdown
styleClass="w-full"
class="w-full"
[showClear]="true"
[options]="accountList"
[placeholder]="to.placeholder"
[(ngModel)]="selectedAccount"
(onChange)="selectAccount($event)"
[loading]="loading"
>
<ng-template pTemplate="selectedItem">
{{ selectedAccount.name }}
</ng-template>
<ng-template let-account pTemplate="item">
<div class="flex">
<span
class="flex flex-grow-1"
[style.padding-left.px]="account.depth * 20"
>
{{ account.name }}
</span>
@if (account.number) {
<span class="flex">[{{ account.number }}]</span>
}
<span
class="flex ml-4"
[class]="{
'text-success': account.remaining_balance.self > 0,
'text-muted': account.remaining_balance.self === 0,
'text-warning': account.remaining_balance.self < 0
}"
>
{{
account.remaining_balance.self
| currency : defaultCurrency
}}
</span>
</div>
</div>
<div class="invalid-feedback" [ngClass]="{'d-block': formControl.invalid}" translate>
Please select an account.
</div>
</div>
</ng-template>
</p-dropdown>
Original file line number Diff line number Diff line change
Expand Up @@ -15,61 +15,72 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { getCurrencySymbol } from '@angular/common';
import { ChangeDetectorRef, Component, inject, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, OnInit } from '@angular/core';
import { IAcqAccount } from '@app/admin/acquisition/classes/account';
import { OrganisationService } from '@app/admin/service/organisation.service';
import { FieldType } from '@ngx-formly/core';
import { TranslateService } from '@ngx-translate/core';
import { ApiService } from '@rero/ng-core';
import { UserService } from '@rero/shared';
import { MessageService } from 'primeng/api';
import { AcqAccountApiService } from '../../../../api/acq-account-api.service';
import { orderAccountsAsTree } from '../../../../utils/account';

@Component({
selector: 'admin-select-account-editor-widget',
templateUrl: './select-account-editor-widget.component.html',
styleUrls: ['../../../../acquisition.scss', './select-account-editor-widget.component.scss']
styleUrls: ['../../../../acquisition.scss', './select-account-editor-widget.component.scss'],
changeDetection: ChangeDetectionStrategy.Default,
})
export class SelectAccountEditorWidgetComponent extends FieldType implements OnInit {

// services
private acqAccountApiService: AcqAccountApiService = inject(AcqAccountApiService);
private organisationService: OrganisationService = inject(OrganisationService);
private apiService: ApiService = inject(ApiService);
private userService: UserService = inject(UserService);
private messageService = inject(MessageService);
private translateService: TranslateService = inject(TranslateService);
private changeDetectorRef: ChangeDetectorRef = inject(ChangeDetectorRef);

// COMPONENT ATTRIBUTES =======================================================
/** accounts list */
accountList: IAcqAccount[] = [];
/** the selected account */
selectedAccount: IAcqAccount = null;
// loading wheels
loading: boolean = false;
// currency
defaultCurrency: string;

// GETTER & SETTER ============================================================
/** Get the current organisation */
get organisation(): any {
return this.organisationService.organisation;
}

/** Get the currency symbol for the organisation */
get currencySymbol(): any {
return getCurrencySymbol(this.organisation.default_currency, 'wide');
}

/** OnInit hook */
ngOnInit(): void {
this.loading = true;
const libraryPid = this.userService.user.currentLibrary;
this.acqAccountApiService.getAccounts(libraryPid).subscribe((accounts: IAcqAccount[]) => {
accounts = orderAccountsAsTree(accounts);
this.accountList = accounts;
this.defaultCurrency = this.organisationService.organisation.default_currency;
this.acqAccountApiService.getAccounts(libraryPid).subscribe({
next: (accounts: IAcqAccount[]) => {
accounts = orderAccountsAsTree(accounts);
this.accountList = accounts;

if (this.formControl.value) {
const currentPid = this.formControl.value.substring(this.formControl.value.lastIndexOf('/') + 1);
const currentAccount = this.accountList.find((account: IAcqAccount) => account.pid === currentPid);
if (currentAccount !== undefined) {
this.selectedAccount = currentAccount;
this.changeDetectorRef.markForCheck();
if (this.formControl.value) {
const currentPid = this.formControl.value.substring(this.formControl.value.lastIndexOf('/') + 1);
const currentAccount = this.accountList.find((account: IAcqAccount) => account.pid === currentPid);
if (currentAccount !== undefined) {
this.selectedAccount = currentAccount;
}
}
}
},
error: () =>
this.messageService.add({
severity: 'error',
summary: this.translateService.instant('Acquisition accounts'),
detail: this.translateService.instant('An error has occurred. Please try again.'),
sticky: true,
closable: true,
}),
complete: () => {
this.loading = false;
this.changeDetectorRef.markForCheck();
},
});
}

Expand All @@ -78,10 +89,17 @@ export class SelectAccountEditorWidgetComponent extends FieldType implements OnI
* Store the selected option, when an option is clicked in the list
* @param account - The selected account.
*/
selectAccount(account: IAcqAccount): void {
selectAccount(event): void {
const account: IAcqAccount = event.value;
if (account == null) {
// reset the form control value, default value cannot be used as it is already filled by ngx formly
this.formControl.reset(null);
// reset the validators but the required validator
const errors = this.formControl.errors;
this.formControl.setErrors(errors.required? {required: true}: null);
return;
}
const accountRef = this.apiService.getRefEndpoint('acq_accounts', account.pid);
this.selectedAccount = account;
this.formControl.patchValue(accountRef);
this.changeDetectorRef.markForCheck();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ export class OrderReceiptForm {
},
{
key: 'acqAccount',
type: 'select-account',
type: 'account-select',
wrappers: ['form-field'],
props: {
placeholder: _('Select an account'),
Expand Down
6 changes: 5 additions & 1 deletion projects/admin/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { User, UserService } from '@rero/shared';
import { DialogService } from 'primeng/dynamicdialog';
import { KeyboardShortcutsService } from './service/keyboard-shortcuts.service';
import { CustomShortcutHelpComponent } from './widgets/custom-shortcut-help/custom-shortcut-help.component';
import { TranslateService } from '@ngx-translate/core';

@Component({
selector: 'admin-root',
Expand All @@ -33,6 +34,7 @@ export class AppComponent implements OnInit, AfterViewInit {
private keyboardShortcutsService: KeyboardShortcutsService = inject(KeyboardShortcutsService);
private hotKeysService: HotkeysService = inject(HotkeysService);
private dialogService: DialogService = inject(DialogService);
private translateService: TranslateService = inject(TranslateService);

/** user */
get user(): User {
Expand All @@ -47,7 +49,9 @@ export class AppComponent implements OnInit, AfterViewInit {
/** AfterViewInit hook */
ngAfterViewInit() {
this.hotKeysService.registerHelpModal(() => {
this.dialogService.open(CustomShortcutHelpComponent, {})
this.dialogService.open(CustomShortcutHelpComponent, {
header: this.translateService.instant('Available Shortcuts')
})
});
}
}
Loading

0 comments on commit 322eb21

Please sign in to comment.