1+ import { OverlayModule } from '@angular/cdk/overlay' ;
12import { AsyncPipe , DatePipe , DecimalPipe } from '@angular/common' ;
2- import { Component , computed , inject , TemplateRef , viewChild } from '@angular/core' ;
3+ import { Component , computed , inject , signal , TemplateRef , viewChild } from '@angular/core' ;
34import { toSignal } from '@angular/core/rxjs-interop' ;
45import { FormBuilder , ReactiveFormsModule , Validators } from '@angular/forms' ;
56import { RouterLink } from '@angular/router' ;
67import { CustomerOrganization , CustomerOrganizationFeature , CustomerOrganizationWithUsage } from '@distr-sh/distr-sdk' ;
78import { FontAwesomeModule } from '@fortawesome/angular-fontawesome' ;
89import {
910 faBuildingUser ,
11+ faChevronDown ,
1012 faCircleExclamation ,
1113 faEdit ,
1214 faMagnifyingGlass ,
1315 faPlus ,
14- faRotate ,
1516 faTrash ,
1617 faXmark ,
1718} from '@fortawesome/free-solid-svg-icons' ;
1819import { combineLatest , filter , firstValueFrom , map , startWith , Subject , switchMap } from 'rxjs' ;
1920import { getFormDisplayedError } from '../../../util/errors' ;
2021import { SecureImagePipe } from '../../../util/secureImage' ;
21- import { modalFlyInOut } from '../../animations/modal' ;
2222import { RequireVendorDirective } from '../../directives/required-role.directive' ;
2323import { ArtifactLicensesService } from '../../services/artifact-licenses.service' ;
2424import { AuthService } from '../../services/auth.service' ;
@@ -31,8 +31,6 @@ import {DialogRef, OverlayService} from '../../services/overlay.service';
3131import { ToastService } from '../../services/toast.service' ;
3232import { QuotaLimitComponent } from '../quota-limit.component' ;
3333
34- export const ALL_CUSTOMER_FEATURES : CustomerOrganizationFeature [ ] = [ 'deployment_targets' , 'artifacts' , 'alerts' ] ;
35-
3634@Component ( {
3735 templateUrl : './customer-organizations.component.html' ,
3836 imports : [
@@ -45,8 +43,8 @@ export const ALL_CUSTOMER_FEATURES: CustomerOrganizationFeature[] = ['deployment
4543 RouterLink ,
4644 RequireVendorDirective ,
4745 QuotaLimitComponent ,
46+ OverlayModule ,
4847 ] ,
49- animations : [ modalFlyInOut ] ,
5048} )
5149export class CustomerOrganizationsComponent {
5250 protected readonly faMagnifyingGlass = faMagnifyingGlass ;
@@ -56,7 +54,7 @@ export class CustomerOrganizationsComponent {
5654 protected readonly faXmark = faXmark ;
5755 protected readonly faCircleExclamation = faCircleExclamation ;
5856 protected readonly faEdit = faEdit ;
59- protected readonly faRotate = faRotate ;
57+ protected readonly faChevronDown = faChevronDown ;
6058
6159 private readonly customerOrganizationsService = inject ( CustomerOrganizationsService ) ;
6260 private readonly toast = inject ( ToastService ) ;
@@ -104,6 +102,19 @@ export class CustomerOrganizationsComponent {
104102 } ) ;
105103 protected createFormLoading = false ;
106104
105+ protected readonly allCustomerFeatures : readonly CustomerOrganizationFeature [ ] = [
106+ 'deployment_targets' ,
107+ 'alerts' ,
108+ 'artifacts' ,
109+ ] ;
110+
111+ protected readonly openCustomerFeaturesDropdownId = signal < string | void > ( undefined ) ;
112+ protected readonly openCustomerFeaturesDropdownCustomer = computed ( ( ) => {
113+ const id = this . openCustomerFeaturesDropdownId ( ) ;
114+ return id ? this . customerOrganizations ( ) ?. find ( ( it ) => it . id === id ) : undefined ;
115+ } ) ;
116+ protected dropdownWidth = 0 ;
117+
107118 protected showCreateDialog ( ) {
108119 this . closeCreateDialog ( ) ;
109120 this . modalRef = this . overlay . showModal ( this . createCustomerDialog ( ) ) ;
@@ -198,36 +209,45 @@ export class CustomerOrganizationsComponent {
198209 } ) ;
199210 }
200211
201- protected async removeFeature ( customer : CustomerOrganization , feature : CustomerOrganizationFeature ) : Promise < void > {
202- const updatedFeatures = customer . features . filter ( ( f ) => f !== feature ) ;
203- try {
204- await firstValueFrom (
205- this . customerOrganizationsService . updateCustomerOrganization ( customer . id , {
206- name : customer . name ,
207- imageId : customer . imageId ,
208- features : updatedFeatures ,
209- } )
210- ) ;
211- this . toast . success ( `Feature "${ this . getFeatureLabel ( feature ) } " removed successfully` ) ;
212- this . refresh$ . next ( ) ;
213- } catch ( e ) {
214- const msg = getFormDisplayedError ( e ) ;
215- if ( msg ) {
216- this . toast . error ( msg ) ;
217- }
212+ protected getFeatureLabel ( feature : CustomerOrganizationFeature ) : string {
213+ switch ( feature ) {
214+ case 'deployment_targets' :
215+ return 'Deployments' ;
216+ case 'artifacts' :
217+ return 'Artifacts' ;
218+ case 'alerts' :
219+ return 'Alerts' ;
220+ default :
221+ return feature ;
218222 }
219223 }
220224
221- protected async restoreAllFeatures ( customer : CustomerOrganization ) : Promise < void > {
225+ protected isFeatureIndent ( feature : CustomerOrganizationFeature ) : boolean {
226+ return feature === 'alerts' ;
227+ }
228+
229+ protected async toggleFeature ( customer : CustomerOrganization , feature : CustomerOrganizationFeature ) {
230+ const featureSet = new Set ( customer . features ) ;
231+ if ( featureSet . has ( feature ) ) {
232+ featureSet . delete ( feature ) ;
233+ if ( feature === 'deployment_targets' ) {
234+ featureSet . delete ( 'alerts' ) ;
235+ }
236+ } else {
237+ featureSet . add ( feature ) ;
238+ if ( feature === 'alerts' ) {
239+ featureSet . add ( 'deployment_targets' ) ;
240+ }
241+ }
242+
222243 try {
223244 await firstValueFrom (
224245 this . customerOrganizationsService . updateCustomerOrganization ( customer . id , {
225- name : customer . name ,
226- imageId : customer . imageId ,
227- features : ALL_CUSTOMER_FEATURES ,
246+ ...customer ,
247+ features : Array . from ( featureSet ) ,
228248 } )
229249 ) ;
230- this . toast . success ( 'All features restored successfully ' ) ;
250+ this . toast . success ( 'Customer features updated ' ) ;
231251 this . refresh$ . next ( ) ;
232252 } catch ( e ) {
233253 const msg = getFormDisplayedError ( e ) ;
@@ -237,20 +257,12 @@ export class CustomerOrganizationsComponent {
237257 }
238258 }
239259
240- protected hasAllFeatures ( customer : CustomerOrganization ) : boolean {
241- return customer . features . length === ALL_CUSTOMER_FEATURES . length ;
260+ protected showCustomerFeaturesDropdown ( customer : CustomerOrganization , btn : HTMLButtonElement ) {
261+ this . dropdownWidth = btn . getBoundingClientRect ( ) . width ;
262+ this . openCustomerFeaturesDropdownId . set ( customer . id ) ;
242263 }
243264
244- protected getFeatureLabel ( feature : CustomerOrganizationFeature ) : string {
245- switch ( feature ) {
246- case 'deployment_targets' :
247- return 'Deployments' ;
248- case 'artifacts' :
249- return 'Artifacts' ;
250- case 'alerts' :
251- return 'Alerts' ;
252- default :
253- return feature ;
254- }
265+ protected hideCustomerFeaturesDropdown ( ) : void {
266+ this . openCustomerFeaturesDropdownId . set ( undefined ) ;
255267 }
256268}
0 commit comments