Skip to content

Commit

Permalink
feat(props): isHidden and isHiddenInAdminCreateEdit #94
Browse files Browse the repository at this point in the history
  • Loading branch information
brunobuddy committed Nov 30, 2023
1 parent 13e7a07 commit 1a78dc8
Show file tree
Hide file tree
Showing 26 changed files with 96 additions and 62 deletions.
13 changes: 7 additions & 6 deletions docs/properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,20 @@ You can pass arguments to the `@Prop()` decorator:

Some types have a specific set of options. Nevertheless, the following options are applicable to all properties in the `options` object parameter.

| Option | Default | Type | Description |
| -------------------- | ------- | ------- | -------------------------------------- |
| **isHiddenInList** | `false` | boolean | Hides the column in the list |
| **isHiddenInDetail** | `false` | boolean | Hides this property in the detail view |
| Option | Default | Type | Description |
| ------------------------ | ------- | ------- | --------------------------------------------------------------- |
| **isHidden** | `false` | boolean | Hides the column in all API responses |
| **isHiddenInAdminList** | `false` | boolean | Hides the column in the list of the Admin panel |
| **isHiddenInCreateEdit** | `false` | boolean | Hides this property in create and edit views of the Admin panel |

Example:

```js
@Prop({
type: PropType.Textarea,
options: {
isHiddenInList: true,
isHiddenInDetail: true
isHiddenInAdminList: true,
isHiddenInCreateEdit: true
}
})
comments: string
Expand Down
3 changes: 1 addition & 2 deletions docs/property-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,7 @@ Hidden password field.
@Prop({
type: PropType.Password,
options: {
isHiddenInList: true,
isHiddenInDetail: true
isHiddenInAdminList: true,
}
})
password: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class DynamicEntityCreateEditComponent {
}

this.props = this.entityMeta.props.filter(
(prop) => !prop.options.isHiddenInCreateEdit
(prop) => !prop.options.isHiddenInAdminCreateEdit
)

if (this.edit) {
Expand Down Expand Up @@ -151,7 +151,11 @@ export class DynamicEntityCreateEditComponent {

this.loading = false
this.flashMessageService.error(
`Error: the ${this.entityMeta.definition.nameSingular} could not be created`
`Error: the ${
this.entityMeta.definition.nameSingular
} could not be created:
${Object.values(this.errors).join(', ')}
`
)
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ <h1 class="title is-2 has-text-weight-light">
</div>
<div class="card p-0 mb-6">
<div class="card-content">
<div class="properties" *ngFor="let prop of props">
<div class="properties" *ngFor="let prop of entityMeta.props">
<p
class="is-property-label is-uppercase has-text-dark has-text-weight-medium"
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Component } from '@angular/core'
import { ActivatedRoute } from '@angular/router'
import { EntityMeta } from '~shared/interfaces/entity-meta.interface'
import { PropertyDescription } from '~shared/interfaces/property-description.interface'

import { BreadcrumbService } from '../../../services/breadcrumb.service'
import { DynamicEntityService } from '../../dynamic-entity.service'
Expand All @@ -13,7 +12,6 @@ import { DynamicEntityService } from '../../dynamic-entity.service'
})
export class DynamicEntityDetailComponent {
item: any
props: PropertyDescription[]
entityMeta: EntityMeta

constructor(
Expand All @@ -32,10 +30,6 @@ export class DynamicEntityDetailComponent {
entityMeta.definition.slug === params['entitySlug']
)

this.props = this.entityMeta.props.filter(
(prop) => !prop.options?.isHiddenInDetail
)

this.dynamicEntityService
.show(this.entityMeta.definition.slug, params['id'])
.then((res) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class DynamicEntityListComponent implements OnInit {
}

this.props = this.entityMeta.props.filter(
(prop) => !prop.options?.isHiddenInList
(prop) => !prop.options?.isHiddenInAdminList
)
this.filtrableProps = this.props.filter(
(prop) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {

import { EntityMeta } from '../../../../../shared/interfaces/entity-meta.interface'
import { PropertyDescription } from '../../../../../shared/interfaces/property-description.interface'
import { RelationOptions } from '../../../../../shared/interfaces/property-options/relation-options.interface'
import { RelationPropertyOptions } from '../../../../../shared/interfaces/property-options/relation-property-options.interface'
import { SelectOption } from '../../../../../shared/interfaces/select-option.interface'
import { DynamicEntityService } from '../../dynamic-entity/dynamic-entity.service'

Expand Down Expand Up @@ -46,7 +46,7 @@ export class MultiSelectInputComponent {
this.entityMeta = res.find(
(entity: EntityMeta) =>
entity.className ===
(this.prop.options as RelationOptions).entitySlug
(this.prop.options as RelationPropertyOptions).entitySlug
)

this.options = await this.dynamicEntityService.listSelectOptions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { SelectOption } from '~shared/interfaces/select-option.interface'

import { NgClass, NgFor } from '@angular/common'
import { PropType } from '~shared/enums/prop-type.enum'
import { EnumOptions } from '~shared/interfaces/property-options/enum-options.interface'
import { RelationOptions } from '~shared/interfaces/property-options/relation-options.interface'
import { EnumPropertyOptions } from '../../../../../shared/interfaces/property-options/enum-property-options.interface'
import { RelationPropertyOptions } from '../../../../../shared/interfaces/property-options/relation-property-options.interface'
import { DynamicEntityService } from '../../dynamic-entity/dynamic-entity.service'

@Component({
Expand Down Expand Up @@ -65,7 +65,7 @@ export class SelectInputComponent implements OnInit {
this.entityMeta = res.find(
(entity: EntityMeta) =>
entity.className ===
(this.prop.options as RelationOptions).entitySlug
(this.prop.options as RelationPropertyOptions).entitySlug
)

this.options = await this.dynamicEntityService.listSelectOptions(
Expand All @@ -75,7 +75,8 @@ export class SelectInputComponent implements OnInit {
}

if (this.type === PropType.Enum) {
let enumOptions: EnumOptions = this.prop.options as EnumOptions
let enumOptions: EnumPropertyOptions = this.prop
.options as EnumPropertyOptions
this.options = Object.keys(enumOptions.enum).map((key) => {
return {
id: enumOptions.enum[key],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CurrencyPipe, NgIf } from '@angular/common'
import { Component, Input } from '@angular/core'
import { CurrencyOptions } from '~shared/interfaces/property-options/currency-options.interface'
import { CurrencyPropertyOptions } from '~shared/interfaces/property-options/currency-property-options.interface'

@Component({
selector: 'app-currency-yield',
Expand All @@ -14,5 +14,5 @@ import { CurrencyOptions } from '~shared/interfaces/property-options/currency-op
})
export class CurrencyYieldComponent {
@Input() value: number
@Input() options: CurrencyOptions
@Input() options: CurrencyPropertyOptions
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CommonModule } from '@angular/common'
import { Component, Input, OnInit } from '@angular/core'
import { EnumPropertyOptions } from '~shared/interfaces/property-options/enum-property-options.interface'
import { TruncatePipe } from '../../pipes/truncate.pipe'
import { EnumOptions } from '~shared/interfaces/property-options/enum-options.interface'

@Component({
selector: 'app-label-yield',
Expand All @@ -15,7 +15,7 @@ import { EnumOptions } from '~shared/interfaces/property-options/enum-options.in
})
export class LabelYieldComponent implements OnInit {
@Input() value: string
@Input() options: EnumOptions
@Input() options: EnumPropertyOptions

index: number

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CommonModule } from '@angular/common'
import { Component, Input, OnInit } from '@angular/core'
import { EnumPropertyOptions } from '~shared/interfaces/property-options/enum-property-options.interface'
import { TruncatePipe } from '../../pipes/truncate.pipe'
import { EnumOptions } from '~shared/interfaces/property-options/enum-options.interface'

@Component({
selector: 'app-progress-bar-yield',
Expand All @@ -24,7 +24,7 @@ import { EnumOptions } from '~shared/interfaces/property-options/enum-options.in
})
export class ProgressBarYieldComponent implements OnInit {
@Input() value: string
@Input() options: EnumOptions
@Input() options: EnumPropertyOptions

enumAsArray: string[] = []
valueIndex: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { CommonModule } from '@angular/common'
import { Component, Input, OnInit } from '@angular/core'
import { RouterModule } from '@angular/router'
import { EntityMeta } from '~shared/interfaces/entity-meta.interface'
import { RelationOptions } from '~shared/interfaces/property-options/relation-options.interface'
import { RelationPropertyOptions } from '~shared/interfaces/property-options/relation-property-options.interface'

import { DynamicEntityService } from '../../dynamic-entity/dynamic-entity.service'

Expand All @@ -26,7 +26,7 @@ export class RelationYieldComponent implements OnInit {
constructor(private dynamicEntityService: DynamicEntityService) {}

@Input() item: any
@Input() options: RelationOptions
@Input() options: RelationPropertyOptions

ngOnInit(): void {
this.dynamicEntityService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ export class Mouse extends BaseEntity {
@Prop({
label: 'Family name',
type: PropType.Text,
validators: [IsNotEmpty()]
validators: [IsNotEmpty()],
options: {
isHidden: true
}
})
familyName: string

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export class AuthenticableEntity extends BaseEntity {
@Prop({
type: PropType.Password,
options: {
isHiddenInList: true,
isHiddenInDetail: true
isHiddenInAdminList: true,
isHidden: true
},
typeORMOptions: { select: false }
})
Expand Down
10 changes: 6 additions & 4 deletions packages/case/server/src/crud/decorators/prop.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { Column, ManyToOne } from 'typeorm'

import { PropType } from '../../../../shared/enums/prop-type.enum'
import { PropertyDefinition } from '../../../../shared/interfaces/property-definition.interface'
import { EnumOptions } from '../../../../shared/interfaces/property-options/enum-options.interface'
import { RelationOptions } from '../../../../shared/interfaces/property-options/relation-options.interface'
import { EnumPropertyOptions } from '../../../../shared/interfaces/property-options/enum-property-options.interface'
import { RelationPropertyOptions } from '../../../../shared/interfaces/property-options/relation-property-options.interface'
import {
PropTypeCharacteristics,
propTypeCharacteristicsRecord
Expand Down Expand Up @@ -47,7 +47,8 @@ export const Prop = (prop?: PropertyDefinition): PropertyDecorator => {

// Relation (ManyToOne).
if (prop?.type === PropType.Relation) {
const relationOptions: RelationOptions = prop?.options as RelationOptions
const relationOptions: RelationPropertyOptions =
prop?.options as RelationPropertyOptions

if (!relationOptions?.entity) {
throw new Error(`Entity is not provided for "${propertyKey}" property.`)
Expand All @@ -65,7 +66,8 @@ export const Prop = (prop?: PropertyDefinition): PropertyDecorator => {

// Enum.
} else if (prop?.type === PropType.Enum) {
const enumOptions: EnumOptions = prop?.options as EnumOptions
const enumOptions: EnumPropertyOptions =
prop?.options as EnumPropertyOptions

if (!enumOptions?.enum) {
throw new Error(`Enum is not provided for "${propertyKey}" property.`)
Expand Down
14 changes: 14 additions & 0 deletions packages/case/server/src/crud/services/crud.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
DeleteResult,
EntityMetadata,
FindManyOptions,
FindOptionsSelect,
FindOptionsWhere,
InsertResult,
Repository
Expand All @@ -21,6 +22,7 @@ import {
WhereOperator,
whereOperatorKeySuffix
} from '@casejs/types'
import { PropType } from '../../../../shared/enums/prop-type.enum'
import { PropertyDescription } from '../../../../shared/interfaces/property-description.interface'
import { SelectOption } from '../../../../shared/interfaces/select-option.interface'
import { BaseEntity } from '../../core-entities/base-entity'
Expand Down Expand Up @@ -109,8 +111,20 @@ export class CrudService {
where[propName] = queryBuilderOperator(parsedValue || value)
})

// Select only non hidden props.
const select: FindOptionsSelect<BaseEntity> = props.reduce(
(acc: FindOptionsSelect<BaseEntity>, prop: PropertyDescription) => {
if (prop.type !== PropType.Relation && !prop.options.isHidden) {
acc[prop.propName] = true
}
return acc
},
{ id: true }
)

const findManyOptions: FindManyOptions<BaseEntity> = {
order: { id: 'DESC' },
select,
relations,
where
}
Expand Down
6 changes: 3 additions & 3 deletions packages/case/server/src/crud/services/entity-meta.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { PropType } from '../../../../shared/enums/prop-type.enum'
import { EntityDefinition } from '../../../../shared/interfaces/entity-definition.interface'
import { EntityMeta } from '../../../../shared/interfaces/entity-meta.interface'
import { PropertyDescription } from '../../../../shared/interfaces/property-description.interface'
import { RelationOptions } from '../../../../shared/interfaces/property-options/relation-options.interface'
import { RelationPropertyOptions } from '../../../../shared/interfaces/property-options/relation-property-options.interface'
import { Policies } from '../../api/policies'
import { AuthenticableEntity } from '../../core-entities/authenticable-entity'

Expand Down Expand Up @@ -64,8 +64,8 @@ export class EntityMetaService {
}

if (propDescription.type === PropType.Relation) {
const relationOptions: RelationOptions =
propDescription.options as RelationOptions
const relationOptions: RelationPropertyOptions =
propDescription.options as RelationPropertyOptions

// Convert class to string to use in the client.
relationOptions.entitySlug = relationOptions.entity?.name
Expand Down
4 changes: 3 additions & 1 deletion packages/case/server/src/file-upload/image-upload.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { EntityMetadata } from 'typeorm'
import * as uniqId from 'uniqid'
import { ImageSize } from '../../../shared/interfaces/image-size.interface'
import { PropertyDescription } from '../../../shared/interfaces/property-description.interface'
import { ImagePropertyOptions } from '../../../shared/interfaces/property-options/image-property-options.interface'
import { EntityMetaService } from '../crud/services/entity-meta.service'

@Injectable()
Expand Down Expand Up @@ -59,7 +60,8 @@ export class ImageUploadService {
const prop = props.find(
(prop: PropertyDescription) => prop.propName === propName
)
const sizes: ImageSize[] = prop.options.sizes || this.defaultSizes
const sizes: ImageSize[] =
(prop.options as ImagePropertyOptions).sizes || this.defaultSizes

// CamelCase to kebab-case.
const kebabCaseEntityName = entitySlug
Expand Down
4 changes: 2 additions & 2 deletions packages/case/server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import { CrudModule } from './crud/crud.module'

async function bootstrap() {
const app = await NestFactory.create(AppModule, {
cors: true,
logger: ['error', 'warn']
cors: true
// logger: ['error', 'warn']
})

const configService = app.get(ConfigService)
Expand Down
16 changes: 8 additions & 8 deletions packages/case/shared/interfaces/property-definition.interface.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { ColumnOptions } from 'typeorm'

import { PropType } from '../enums/prop-type.enum'
import { CurrencyOptions } from './property-options/currency-options.interface'
import { EnumOptions } from './property-options/enum-options.interface'
import { ImageOptions } from './property-options/image-options.interface'
import { CurrencyPropertyOptions } from './property-options/currency-property-options.interface'
import { EnumPropertyOptions } from './property-options/enum-property-options.interface'
import { ImagePropertyOptions } from './property-options/image-property-options.interface'
import { PropertyOptions } from './property-options/property-options.interface'
import { RelationOptions } from './property-options/relation-options.interface'
import { RelationPropertyOptions } from './property-options/relation-property-options.interface'

/**
* Defines a property of an entity.
Expand All @@ -24,10 +24,10 @@ export interface PropertyDefinition {
/** Options for the property (related to Type) */
options?:
| PropertyOptions
| RelationOptions
| CurrencyOptions
| EnumOptions
| ImageOptions
| RelationPropertyOptions
| CurrencyPropertyOptions
| EnumPropertyOptions
| ImagePropertyOptions

/** TypeORM options for the property */
typeORMOptions?: ColumnOptions
Expand Down
Loading

0 comments on commit 1a78dc8

Please sign in to comment.