Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions proxy.conf.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ export default {
},
onProxyRes: (proxyRes) => {
// Fix http-proxy mangling 204 No Content responses
// Some Django endpoints send a JSON body with 204, which causes parse errors
if (proxyRes.statusCode === 204) {
proxyRes.headers['content-length'] = '0'
delete proxyRes.headers['content-type']
}
},
},
Expand Down
9 changes: 9 additions & 0 deletions public/i18n/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"Access Levels Instances (ALI)": "Access Levels Instances (ALI)",
"Acknowledge": "Acknowledge",
"Actions": "Actions",
"Actions for": "Actions for",
"Active": "Active",
"Actual > Target": "Actual > Target",
"Actual Column": "Actual Column",
Expand Down Expand Up @@ -262,6 +263,8 @@
"Coal (anthracite)": "Coal (anthracite)",
"Coal (bituminous)": "Coal (bituminous)",
"Coke": "Coke",
"Collapse": "Collapse",
"Collapse All": "Collapse All",
"Collapse Tabs": "Collapse Tabs",
"Column": "Column",
"Column Description": "Column Description",
Expand All @@ -272,8 +275,10 @@
"Column Mappings": "Column Mappings",
"Column Name": "Column Name",
"Column Order\/Visibility": "Column Order\/Visibility",
"Column Profiles": "Column Profiles",
"Column Settings": "Column Settings",
"Column mappings": "Column mappings",
"Columns": "Columns",
"Columns to Include in Reports x axis options": "Columns to Include in Reports x axis options",
"Columns to Include in Reports y axis options": "Columns to Include in Reports y axis options",
"ComStock Mapping": "ComStock Mapping",
Expand Down Expand Up @@ -358,7 +363,9 @@
"Create a new...": "Create a new...",
"Create a user": "Create a user",
"Create an Organization to continue": "Create an Organization to continue",
"Create an additional access level before creating new instances here": "Create an additional access level before creating new instances here",
"Create an organization": "Create an organization",
"Create child instance": "Create child instance",
"Create child instances": "Create child instances",
"Create label": "Create label",
"Create my account": "Create my account",
Expand Down Expand Up @@ -584,6 +591,8 @@
"Existing Labels": "Existing Labels",
"Existing Properties": "Existing Properties",
"Existing Tax Lots": "Existing Tax Lots",
"Expand": "Expand",
"Expand All": "Expand All",
"Export": "Export",
"Export BuildingSync": "Export BuildingSync",
"Export BuildingSync in Excel format": "Export BuildingSync in Excel format",
Expand Down
9 changes: 9 additions & 0 deletions public/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"Access Levels Instances (ALI)": "Instancias de nivel de acceso (ALI)",
"Acknowledge": "Acuse recibo",
"Actions": "Acciones",
"Actions for": "Acciones para",
"Active": "Activo",
"Actual > Target": "Real > Objetivo",
"Actual Column": "Columna real",
Expand Down Expand Up @@ -262,6 +263,8 @@
"Coal (anthracite)": "Carbón (antracita)",
"Coal (bituminous)": "Carbón (bituminoso)",
"Coke": "Coque",
"Collapse": "Colapsar",
"Collapse All": "Contraer todo",
"Collapse Tabs": "Contraer pestañas",
"Column": "Columna",
"Column Description": "Descripción de la columna",
Expand All @@ -272,8 +275,10 @@
"Column Mappings": "Asignación de columnas",
"Column Name": "Nombre de la columna",
"Column Order\/Visibility": "Orden\/Visibilidad de las columnas",
"Column Profiles": "Perfiles de columna",
"Column Settings": "Ajustes de columna",
"Column mappings": "Mapeos de columnas",
"Columns": "Columnas",
"Columns to Include in Reports x axis options": "Columnas a incluir en los informes Opciones del eje x",
"Columns to Include in Reports y axis options": "Columnas a incluir en los informes opciones del eje y",
"ComStock Mapping": "Cartografía ComStock",
Expand Down Expand Up @@ -358,7 +363,9 @@
"Create a new...": "Crear un nuevo...",
"Create a user": "Crear un usuario",
"Create an Organization to continue": "Crear una organización para continuar",
"Create an additional access level before creating new instances here": "Cree un nivel de acceso adicional antes de crear nuevas instancias aquí.",
"Create an organization": "Crear una organización",
"Create child instance": "Crear instancia hija",
"Create child instances": "Crear instancias secundarias",
"Create label": "Crear etiqueta",
"Create my account": "Crear mi cuenta",
Expand Down Expand Up @@ -584,6 +591,8 @@
"Existing Labels": "Etiquetas existentes",
"Existing Properties": "Propiedades existentes",
"Existing Tax Lots": "Lotes fiscales existentes",
"Expand": "Expandir",
"Expand All": "Expandir todo",
"Export": "Exportar",
"Export BuildingSync": "Exportar BuildingSync",
"Export BuildingSync in Excel format": "Exportar BuildingSync en formato Excel",
Expand Down
9 changes: 9 additions & 0 deletions public/i18n/fr_CA.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"Access Levels Instances (ALI)": "Instances de niveaux d'accès (ALI)",
"Acknowledge": "Reconnaître",
"Actions": "Actions",
"Actions for": "Actions pour",
"Active": "actif",
"Actual > Target": "Réel > Cible",
"Actual Column": "Colonne réelle",
Expand Down Expand Up @@ -262,6 +263,8 @@
"Coal (anthracite)": "Charbon (anthracite)",
"Coal (bituminous)": "Charbon (bitumineux)",
"Coke": "Coke",
"Collapse": "Réduire",
"Collapse All": "Tout réduire",
"Collapse Tabs": "Réduire les onglets",
"Column": "Colonne",
"Column Description": "Description de la colonne",
Expand All @@ -272,8 +275,10 @@
"Column Mappings": "Mappages de colonnes",
"Column Name": "Nom de colonne",
"Column Order\/Visibility": "L'Ordre Des Colonnes\/Visibilité",
"Column Profiles": "Profils de colonnes",
"Column Settings": "Paramètres de colonne",
"Column mappings": "Mappages de colonnes",
"Columns": "Colonnes",
"Columns to Include in Reports x axis options": "Colonnes à inclure dans les rapports Options de l'axe des x",
"Columns to Include in Reports y axis options": "Colonnes à inclure dans les rapports options de l'axe des y",
"ComStock Mapping": "Cartographie ComStock",
Expand Down Expand Up @@ -358,7 +363,9 @@
"Create a new...": "Créer un nouveau...",
"Create a user": "Créer un utilisateur",
"Create an Organization to continue": "Créer une organisation pour continuer",
"Create an additional access level before creating new instances here": "Créez un niveau d'accès supplémentaire avant de créer de nouvelles instances ici.",
"Create an organization": "Créer une organisation",
"Create child instance": "Créer une instance enfant",
"Create child instances": "Créer des instances enfants",
"Create label": "Créer une étiquette",
"Create my account": "Créer mon compte",
Expand Down Expand Up @@ -584,6 +591,8 @@
"Existing Labels": "Étiquettes existantes",
"Existing Properties": "Propriétés existantes",
"Existing Tax Lots": "Lots d'impôt existants",
"Expand": "Développer",
"Expand All": "Développer tout",
"Export": "Exportation",
"Export BuildingSync": "Exporter BuildingSync",
"Export BuildingSync in Excel format": "Exporter BuildingSync au format Excel",
Expand Down
9 changes: 7 additions & 2 deletions src/@seed/api/organization/organization.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,17 @@ export class OrganizationService {

deleteAccessLevelInstance(organizationId: number, accessLevelInstanceId: number) {
const url = `/api/v3/organizations/${organizationId}/access_levels/${accessLevelInstanceId}/delete_instance/`
return this._httpClient.delete<null>(url).pipe(
return this._httpClient.delete(url).pipe(
tap(() => {
// Update accessLevelTree
this.getAccessLevelTree(organizationId).subscribe()
}),
catchError((error: HttpErrorResponse) => {
// The backend returns 204 with a JSON body, which violates HTTP spec and crashes
// the dev proxy parser. The delete still succeeds on the backend, so refresh the tree.
if (error.status === 0 || error.status === 204) {
this.getAccessLevelTree(organizationId).subscribe()
return of(null)
}
return this._errorService.handleError(error, 'Failed to delete Access Level Instance')
}),
)
Expand Down
5 changes: 3 additions & 2 deletions src/@seed/api/organization/organization.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,9 @@ export type CanDeleteInstanceResponse = {
}

export type UploadAccessLevelInstancesResponse = {
status: 'success';
tempfile: string;
success: boolean;
tempfile?: string;
message?: string;
}

export type StartSavingAccessLevelInstancesRequest = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
@if (type === 'properties') {
<seed-menu-item [disabled]="!hasSelection" (action)="openAliChangeModal()" label="Edit"> </seed-menu-item>
}
<seed-menu-item class="text-secondary line-through" (action)="tempAction()" label="Hide"> </seed-menu-item>
<seed-menu-item class="text-secondary" [label]="showAccessLevelInstances ? 'Hide' : 'Show'" (action)="toggleAccessLevelInstances()">
</seed-menu-item>
</div>
<!-- Analyses -->
@if (type === 'properties') {
Expand Down
7 changes: 7 additions & 0 deletions src/app/modules/inventory-list/list/grid/actions.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ export class ActionsComponent implements OnDestroy, OnChanges, OnInit {
@Input() type: InventoryType
@Output() refreshInventory = new EventEmitter<number | null>()
@Output() selectedAll = new EventEmitter<number[]>()
@Output() toggleAccessLevels = new EventEmitter<void>()
private _inventoryService = inject(InventoryService)
private _dialog = inject(MatDialog)
private readonly _unsubscribeAll$ = new Subject<void>()
hasSelection: boolean
showAccessLevelInstances = true

ngOnInit(): void {
return
Expand All @@ -74,6 +76,11 @@ export class ActionsComponent implements OnDestroy, OnChanges, OnInit {
console.log('temp action')
}

toggleAccessLevelInstances() {
this.showAccessLevelInstances = !this.showAccessLevelInstances
this.toggleAccessLevels.emit()
}

selectAll() {
this.gridApi.selectAll()
const inventory_type = this.type === 'taxlots' ? 'taxlot' : 'property'
Expand Down
39 changes: 35 additions & 4 deletions src/app/modules/inventory-list/list/grid/grid.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { IconHeaderComponent } from './icon-header.component'
imports: [AgGridAngular, CommonModule, InventoryGridControlsComponent],
})
export class InventoryGridComponent implements OnChanges {
@Input() accessLevelNames: string[] = []
@Input() columnDefs!: ColDef[]
@Input() currentUser: CurrentUser
@Input() inventoryType: string
Expand All @@ -42,6 +43,7 @@ export class InventoryGridComponent implements OnChanges {
gridApi!: GridApi
darkMode: boolean
gridTheme$ = this._configService.gridTheme$
showAccessLevelInstances = true

theme: string

Expand Down Expand Up @@ -106,11 +108,40 @@ export class InventoryGridComponent implements OnChanges {

getColumnDefs() {
const stateColumns = this.addHeaderMenu()
const groups: ColGroupDef[] = [{ headerName: 'Shortcuts', children: this.getShortcutColumns() } as ColGroupDef]

this.columnDefs = [
{ headerName: 'Shortcuts', children: this.getShortcutColumns() } as ColGroupDef,
{ headerName: 'Details', children: stateColumns } as ColGroupDef,
]
const accessLevelCols = this.getAccessLevelColumns()
if (accessLevelCols.length) {
groups.push({ headerName: 'Access Level', children: accessLevelCols } as ColGroupDef)
}

groups.push({ headerName: 'Details', children: stateColumns } as ColGroupDef)
this.columnDefs = groups
}

getAccessLevelColumns(): ColDef[] {
if (!this.accessLevelNames?.length) return []
// Skip root level (index 0) — it's always the same for all instances
const names = this.accessLevelNames.slice(1)
return names.map((name) => ({
field: name,
headerName: name,
hide: !this.showAccessLevelInstances,
filter: true,
sortable: false,
resizable: true,
minWidth: 100,
headerClass: 'access-level-header',
cellClass: 'access-level-cell',
}))
}

toggleAccessLevelInstances() {
this.showAccessLevelInstances = !this.showAccessLevelInstances
if (this.gridApi) {
const names = (this.accessLevelNames ?? []).slice(1)
this.gridApi.setColumnsVisible(names, this.showAccessLevelInstances)
}
}

getShortcutColumns(): ColDef[] {
Expand Down
2 changes: 2 additions & 0 deletions src/app/modules/inventory-list/list/inventory.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
[type]="type"
(refreshInventory)="onRefreshInventory($event)"
(selectedAll)="onSelectAll($event)"
(toggleAccessLevels)="onToggleAccessLevelInstances()"
></seed-inventory-grid-actions>

<!-- Cycles -->
Expand Down Expand Up @@ -71,6 +72,7 @@
<!-- INVENTORY GRID -->
<seed-inventory-grid
#grid
[accessLevelNames]="accessLevelNames"
[columnDefs]="columnDefs"
[currentUser]="currentUser"
[inventoryType]="type"
Expand Down
17 changes: 16 additions & 1 deletion src/app/modules/inventory-list/list/inventory.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { OnDestroy, OnInit } from '@angular/core'
import { Component, inject, Input, ViewEncapsulation } from '@angular/core'
import { Component, inject, Input, ViewChild, ViewEncapsulation } from '@angular/core'
import { ActivatedRoute } from '@angular/router'
import type { ColDef, GridApi } from 'ag-grid-community'
import type { Observable } from 'rxjs'
Expand Down Expand Up @@ -55,7 +55,9 @@ export class InventoryComponent implements OnDestroy, OnInit {
readonly tabs: InventoryType[] = ['properties', 'taxlots']
readonly type = this._resolveType()
@Input() groupId?: number
@ViewChild('grid') gridComponent: InventoryGridComponent
private _groupPropertyIds: number[] | null = null
accessLevelNames: string[] = []
chunk = 100
columns: Column[] = []
columnDefs: ColDef[] = []
Expand Down Expand Up @@ -121,6 +123,15 @@ export class InventoryComponent implements OnDestroy, OnInit {
}

initStreams() {
this._organizationService.currentOrganization$
.pipe(
takeUntil(this._unsubscribeAll$),
tap((org) => {
this.accessLevelNames = org.access_level_names ?? []
}),
)
.subscribe()

this.profileId$
.pipe(
filter(Boolean),
Expand Down Expand Up @@ -328,6 +339,10 @@ export class InventoryComponent implements OnDestroy, OnInit {
this.gridApi = gridApi
}

onToggleAccessLevelInstances() {
this.gridComponent?.toggleAccessLevelInstances()
}

onSelectionChanged() {
// this.selectedViewIds = this.type === 'taxlots'
// ? this.gridApi.getSelectedRows().map(({ taxlot_view_id }: { taxlot_view_id: number }) => taxlot_view_id)
Expand Down
Loading
Loading