mirror of https://github.com/abpframework/abp.git
committed by
GitHub
58 changed files with 690 additions and 264 deletions
|
After Width: | Height: | Size: 676 KiB |
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,28 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<WarningsAsErrors>Nullable</WarningsAsErrors> |
||||
|
<PackageId>Volo.Abp.Imaging.SkiaSharp</PackageId> |
||||
|
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.Imaging.Abstractions\Volo.Abp.Imaging.Abstractions.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="SkiaSharp" /> |
||||
|
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Condition="$([MSBuild]::IsOSPlatform('Linux'))" /> |
||||
|
<PackageReference Include="SkiaSharp.NativeAssets.macOS" Condition="$([MSBuild]::IsOSPlatform('OSX'))" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,8 @@ |
|||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Volo.Abp.Imaging; |
||||
|
|
||||
|
[DependsOn(typeof(AbpImagingAbstractionsModule))] |
||||
|
public class AbpImagingSkiaSharpModule : AbpModule |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,98 @@ |
|||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using SkiaSharp; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Http; |
||||
|
|
||||
|
namespace Volo.Abp.Imaging; |
||||
|
|
||||
|
public class SkiaSharpImageResizerContributor : IImageResizerContributor, ITransientDependency |
||||
|
{ |
||||
|
protected SkiaSharpResizerOptions Options { get; } |
||||
|
|
||||
|
public SkiaSharpImageResizerContributor(IOptions<SkiaSharpResizerOptions> options) |
||||
|
{ |
||||
|
Options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<ImageResizeResult<byte[]>> TryResizeAsync(byte[] bytes, ImageResizeArgs resizeArgs, string? mimeType = null, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
if (!mimeType.IsNullOrWhiteSpace() && !CanResize(mimeType)) |
||||
|
{ |
||||
|
return new ImageResizeResult<byte[]>(bytes, ImageProcessState.Unsupported); |
||||
|
} |
||||
|
|
||||
|
using (var memoryStream = new MemoryStream(bytes)) |
||||
|
{ |
||||
|
var result = await TryResizeAsync(memoryStream, resizeArgs, mimeType, cancellationToken); |
||||
|
|
||||
|
if (result.State != ImageProcessState.Done) |
||||
|
{ |
||||
|
return new ImageResizeResult<byte[]>(bytes, result.State); |
||||
|
} |
||||
|
|
||||
|
var newBytes = await result.Result.GetAllBytesAsync(cancellationToken); |
||||
|
|
||||
|
result.Result.Dispose(); |
||||
|
|
||||
|
return new ImageResizeResult<byte[]>(newBytes, result.State); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<ImageResizeResult<Stream>> TryResizeAsync(Stream stream, ImageResizeArgs resizeArgs, string? mimeType = null, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
if (!mimeType.IsNullOrWhiteSpace() && !CanResize(mimeType)) |
||||
|
{ |
||||
|
return new ImageResizeResult<Stream>(stream, ImageProcessState.Unsupported); |
||||
|
} |
||||
|
|
||||
|
var (memoryBitmapStream, memorySkCodecStream) = await CreateMemoryStream(stream); |
||||
|
|
||||
|
using (var original = SKBitmap.Decode(memoryBitmapStream)) |
||||
|
{ |
||||
|
using (var resized = original.Resize(new SKImageInfo(resizeArgs.Width, resizeArgs.Height), Options.SKFilterQuality)) |
||||
|
{ |
||||
|
using (var image = SKImage.FromBitmap(resized)) |
||||
|
{ |
||||
|
using (var codec = SKCodec.Create(memorySkCodecStream)) |
||||
|
{ |
||||
|
var memoryStream = new MemoryStream(); |
||||
|
image.Encode(codec.EncodedFormat, Options.Quality).SaveTo(memoryStream); |
||||
|
return new ImageResizeResult<Stream>(memoryStream, ImageProcessState.Done); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task<(MemoryStream, MemoryStream)> CreateMemoryStream(Stream stream) |
||||
|
{ |
||||
|
var streamPosition = stream.Position; |
||||
|
|
||||
|
var memoryBitmapStream = new MemoryStream(); |
||||
|
var memorySkCodecStream = new MemoryStream(); |
||||
|
|
||||
|
await stream.CopyToAsync(memoryBitmapStream); |
||||
|
stream.Position = streamPosition; |
||||
|
await stream.CopyToAsync(memorySkCodecStream); |
||||
|
stream.Position = streamPosition; |
||||
|
|
||||
|
memoryBitmapStream.Position = 0; |
||||
|
memorySkCodecStream.Position = 0; |
||||
|
|
||||
|
return (memoryBitmapStream, memorySkCodecStream); |
||||
|
} |
||||
|
|
||||
|
protected virtual bool CanResize(string? mimeType) |
||||
|
{ |
||||
|
return mimeType switch { |
||||
|
MimeTypes.Image.Jpeg => true, |
||||
|
MimeTypes.Image.Png => true, |
||||
|
MimeTypes.Image.Webp => true, |
||||
|
_ => false |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using SkiaSharp; |
||||
|
|
||||
|
namespace Volo.Abp.Imaging; |
||||
|
|
||||
|
public class SkiaSharpResizerOptions |
||||
|
{ |
||||
|
public SKFilterQuality SKFilterQuality { get; set; } |
||||
|
|
||||
|
public int Quality { get; set; } |
||||
|
|
||||
|
public SkiaSharpResizerOptions() |
||||
|
{ |
||||
|
SKFilterQuality = SKFilterQuality.None; |
||||
|
Quality = 75; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\common.test.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" /> |
||||
|
<ProjectReference Include="..\Volo.Abp.Imaging.Abstractions.Tests\Volo.Abp.Imaging.Abstractions.Tests.csproj" /> |
||||
|
<ProjectReference Include="..\..\src\Volo.Abp.Imaging.SkiaSharp\Volo.Abp.Imaging.SkiaSharp.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<EmbeddedResource Include="Volo\Abp\Imaging\Files\**" /> |
||||
|
</ItemGroup> |
||||
|
</Project> |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Volo.Abp.Autofac; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Volo.Abp.Imaging; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpAutofacModule), |
||||
|
typeof(AbpImagingSkiaSharpModule), |
||||
|
typeof(AbpTestBaseModule) |
||||
|
)] |
||||
|
public class AbpImagingSkiaSharpTestModule : AbpModule |
||||
|
{ |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Volo.Abp.Testing; |
||||
|
|
||||
|
namespace Volo.Abp.Imaging; |
||||
|
|
||||
|
public abstract class AbpImagingSkiaSharpTestBase : AbpIntegratedTest<AbpImagingSkiaSharpTestModule> |
||||
|
{ |
||||
|
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
||||
|
{ |
||||
|
options.UseAutofac(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,75 @@ |
|||||
|
using System.IO; |
||||
|
using System.Threading.Tasks; |
||||
|
using Shouldly; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.Abp.Imaging; |
||||
|
|
||||
|
public class SkiaSharpImageResizerTests : AbpImagingSkiaSharpTestBase |
||||
|
{ |
||||
|
public IImageResizer ImageResizer { get; } |
||||
|
|
||||
|
public SkiaSharpImageResizerTests() |
||||
|
{ |
||||
|
ImageResizer = GetRequiredService<IImageResizer>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Resize_Jpg() |
||||
|
{ |
||||
|
await using var jpegImage = ImageFileHelper.GetJpgTestFileStream(); |
||||
|
var resizedImage = await ImageResizer.ResizeAsync(jpegImage, new ImageResizeArgs(100, 100)); |
||||
|
|
||||
|
resizedImage.ShouldNotBeNull(); |
||||
|
resizedImage.State.ShouldBe(ImageProcessState.Done); |
||||
|
resizedImage.Result.Length.ShouldBeLessThan(jpegImage.Length); |
||||
|
|
||||
|
resizedImage.Result.Dispose(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Resize_Png() |
||||
|
{ |
||||
|
await using var pngImage = ImageFileHelper.GetPngTestFileStream(); |
||||
|
var resizedImage = await ImageResizer.ResizeAsync(pngImage, new ImageResizeArgs(100, 100)); |
||||
|
|
||||
|
resizedImage.ShouldNotBeNull(); |
||||
|
resizedImage.State.ShouldBe(ImageProcessState.Done); |
||||
|
resizedImage.Result.Length.ShouldBeLessThan(pngImage.Length); |
||||
|
|
||||
|
resizedImage.Result.Dispose(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Resize_Webp() |
||||
|
{ |
||||
|
await using var webpImage = ImageFileHelper.GetWebpTestFileStream(); |
||||
|
var resizedImage = await ImageResizer.ResizeAsync(webpImage, new ImageResizeArgs(100, 100)); |
||||
|
|
||||
|
resizedImage.ShouldNotBeNull(); |
||||
|
resizedImage.State.ShouldBe(ImageProcessState.Done); |
||||
|
resizedImage.Result.Length.ShouldBeLessThan(webpImage.Length); |
||||
|
|
||||
|
resizedImage.Result.Dispose(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Resize_Stream_And_Byte_Array_The_Same() |
||||
|
{ |
||||
|
await using var jpegImage = ImageFileHelper.GetJpgTestFileStream(); |
||||
|
var resizedImage1 = await ImageResizer.ResizeAsync(jpegImage, new ImageResizeArgs(100, 100)); |
||||
|
var resizedImage2 = await ImageResizer.ResizeAsync(await jpegImage.GetAllBytesAsync(), new ImageResizeArgs(100, 100)); |
||||
|
|
||||
|
resizedImage1.ShouldNotBeNull(); |
||||
|
resizedImage1.State.ShouldBe(ImageProcessState.Done); |
||||
|
resizedImage1.Result.Length.ShouldBeLessThan(jpegImage.Length); |
||||
|
|
||||
|
resizedImage2.ShouldNotBeNull(); |
||||
|
resizedImage2.State.ShouldBe(ImageProcessState.Done); |
||||
|
resizedImage2.Result.LongLength.ShouldBeLessThan(jpegImage.Length); |
||||
|
|
||||
|
resizedImage1.Result.Length.ShouldBe(resizedImage2.Result.LongLength); |
||||
|
|
||||
|
resizedImage1.Result.Dispose(); |
||||
|
} |
||||
|
} |
||||
@ -1,73 +1,76 @@ |
|||||
import { TrackByService } from '@abp/ng.core'; |
import {TrackByService} from '@abp/ng.core'; |
||||
import { |
import { |
||||
ChangeDetectionStrategy, |
ChangeDetectionStrategy, |
||||
ChangeDetectorRef, |
ChangeDetectorRef, |
||||
Component, |
Component, inject, |
||||
Inject, |
Input, |
||||
Input, |
Optional, |
||||
Optional, |
QueryList, |
||||
QueryList, |
SkipSelf, |
||||
SkipSelf, |
ViewChildren, |
||||
ViewChildren, |
|
||||
} from '@angular/core'; |
} from '@angular/core'; |
||||
import { ControlContainer, UntypedFormGroup } from '@angular/forms'; |
import {ControlContainer, ReactiveFormsModule, UntypedFormGroup} from '@angular/forms'; |
||||
import { EXTRA_PROPERTIES_KEY } from '../../constants/extra-properties'; |
import {EXTRA_PROPERTIES_KEY} from '../../constants/extra-properties'; |
||||
import { FormPropList, GroupedFormPropList } from '../../models/form-props'; |
import {FormPropList, GroupedFormPropList} from '../../models/form-props'; |
||||
import { ExtensionsService } from '../../services/extensions.service'; |
import {ExtensionsService} from '../../services/extensions.service'; |
||||
import { EXTENSIONS_IDENTIFIER } from '../../tokens/extensions.token'; |
import {EXTENSIONS_IDENTIFIER} from '../../tokens/extensions.token'; |
||||
import { selfFactory } from '../../utils/factory.util'; |
import {selfFactory} from '../../utils/factory.util'; |
||||
import { ExtensibleFormPropComponent } from './extensible-form-prop.component'; |
import {ExtensibleFormPropComponent} from './extensible-form-prop.component'; |
||||
|
import {CommonModule} from "@angular/common"; |
||||
|
import {PropDataDirective} from "../../directives/prop-data.directive"; |
||||
|
|
||||
@Component({ |
@Component({ |
||||
exportAs: 'abpExtensibleForm', |
exportAs: 'abpExtensibleForm', |
||||
selector: 'abp-extensible-form', |
selector: 'abp-extensible-form', |
||||
templateUrl: './extensible-form.component.html', |
templateUrl: './extensible-form.component.html', |
||||
changeDetection: ChangeDetectionStrategy.OnPush, |
standalone:true, |
||||
viewProviders: [ |
imports:[CommonModule, PropDataDirective,ReactiveFormsModule,ExtensibleFormPropComponent], |
||||
{ |
changeDetection: ChangeDetectionStrategy.OnPush, |
||||
provide: ControlContainer, |
viewProviders: [ |
||||
useFactory: selfFactory, |
{ |
||||
deps: [[new Optional(), new SkipSelf(), ControlContainer]], |
provide: ControlContainer, |
||||
}, |
useFactory: selfFactory, |
||||
], |
deps: [[new Optional(), new SkipSelf(), ControlContainer]], |
||||
|
}, |
||||
|
], |
||||
}) |
}) |
||||
export class ExtensibleFormComponent<R = any> { |
export class ExtensibleFormComponent<R = any> { |
||||
@ViewChildren(ExtensibleFormPropComponent) |
|
||||
formProps!: QueryList<ExtensibleFormPropComponent>; |
|
||||
|
|
||||
@Input() |
@ViewChildren(ExtensibleFormPropComponent) |
||||
set selectedRecord(record: R) { |
formProps!: QueryList<ExtensibleFormPropComponent>; |
||||
const type = !record || JSON.stringify(record) === '{}' ? 'create' : 'edit'; |
|
||||
const propList = this.extensions[`${type}FormProps`].get(this.identifier).props; |
|
||||
this.groupedPropList = this.createGroupedList(propList); |
|
||||
this.record = record; |
|
||||
} |
|
||||
|
|
||||
extraPropertiesKey = EXTRA_PROPERTIES_KEY; |
@Input() |
||||
groupedPropList!: GroupedFormPropList; |
set selectedRecord(record: R) { |
||||
record!: R; |
const type = !record || JSON.stringify(record) === '{}' ? 'create' : 'edit'; |
||||
|
const propList = this.extensions[`${type}FormProps`].get(this.identifier).props; |
||||
|
this.groupedPropList = this.createGroupedList(propList); |
||||
|
this.record = record; |
||||
|
} |
||||
|
|
||||
createGroupedList(propList: FormPropList<R>) { |
extraPropertiesKey = EXTRA_PROPERTIES_KEY; |
||||
const groupedFormPropList = new GroupedFormPropList(); |
groupedPropList!: GroupedFormPropList; |
||||
propList.forEach(item => { |
record!: R; |
||||
groupedFormPropList.addItem(item.value); |
|
||||
}); |
|
||||
return groupedFormPropList; |
|
||||
} |
|
||||
|
|
||||
get form(): UntypedFormGroup { |
public readonly cdRef = inject(ChangeDetectorRef) |
||||
return (this.container ? this.container.control : { controls: {} }) as UntypedFormGroup; |
public readonly track = inject(TrackByService) |
||||
} |
private container = inject(ControlContainer) |
||||
|
private extensions = inject(ExtensionsService); |
||||
|
private identifier = inject(EXTENSIONS_IDENTIFIER) |
||||
|
|
||||
get extraProperties(): UntypedFormGroup { |
createGroupedList(propList: FormPropList<R>) { |
||||
return (this.form.controls.extraProperties || { controls: {} }) as UntypedFormGroup; |
const groupedFormPropList = new GroupedFormPropList(); |
||||
} |
propList.forEach(item => { |
||||
|
groupedFormPropList.addItem(item.value); |
||||
|
}); |
||||
|
return groupedFormPropList; |
||||
|
} |
||||
|
|
||||
|
get form(): UntypedFormGroup { |
||||
|
return (this.container ? this.container.control : {controls: {}}) as UntypedFormGroup; |
||||
|
} |
||||
|
|
||||
|
get extraProperties(): UntypedFormGroup { |
||||
|
return (this.form.controls.extraProperties || {controls: {}}) as UntypedFormGroup; |
||||
|
} |
||||
|
|
||||
constructor( |
|
||||
public readonly cdRef: ChangeDetectorRef, |
|
||||
public readonly track: TrackByService, |
|
||||
private container: ControlContainer, |
|
||||
private extensions: ExtensionsService, |
|
||||
@Inject(EXTENSIONS_IDENTIFIER) private identifier: string, |
|
||||
) {} |
|
||||
} |
} |
||||
|
|||||
@ -0,0 +1,77 @@ |
|||||
|
import { inject, Injectable } from '@angular/core'; |
||||
|
import { ValidatorFn, Validators } from '@angular/forms'; |
||||
|
import { AbpValidators, ConfigStateService } from '@abp/ng.core'; |
||||
|
import { map } from 'rxjs/operators'; |
||||
|
import { FormProp } from '../models/form-props'; |
||||
|
import { ePropType } from '../enums/props.enum'; |
||||
|
|
||||
|
@Injectable() |
||||
|
export class ExtensibleFormPropService { |
||||
|
readonly #configStateService = inject(ConfigStateService); |
||||
|
|
||||
|
meridian$ = this.#configStateService |
||||
|
.getDeep$('localization.currentCulture.dateTimeFormat.shortTimePattern') |
||||
|
.pipe(map((shortTimePattern: string | undefined) => (shortTimePattern || '').includes('tt'))); |
||||
|
|
||||
|
isRequired(validator: ValidatorFn) { |
||||
|
return ( |
||||
|
validator === Validators.required || |
||||
|
validator === AbpValidators.required || |
||||
|
validator.name === 'required' |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
getComponent(prop: FormProp) { |
||||
|
if (prop.template) { |
||||
|
return 'template'; |
||||
|
} |
||||
|
switch (prop.type) { |
||||
|
case ePropType.Boolean: |
||||
|
return 'checkbox'; |
||||
|
case ePropType.Date: |
||||
|
return 'date'; |
||||
|
case ePropType.DateTime: |
||||
|
return 'dateTime'; |
||||
|
case ePropType.Hidden: |
||||
|
return 'hidden'; |
||||
|
case ePropType.MultiSelect: |
||||
|
return 'multiselect'; |
||||
|
case ePropType.Text: |
||||
|
return 'textarea'; |
||||
|
case ePropType.Time: |
||||
|
return 'time'; |
||||
|
case ePropType.Typeahead: |
||||
|
return 'typeahead'; |
||||
|
case ePropType.PasswordInputGroup: |
||||
|
return 'passwordinputgroup'; |
||||
|
default: |
||||
|
return prop.options ? 'select' : 'input'; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
getType(prop: FormProp) { |
||||
|
switch (prop.type) { |
||||
|
case ePropType.Date: |
||||
|
case ePropType.String: |
||||
|
return 'text'; |
||||
|
case ePropType.Boolean: |
||||
|
return 'checkbox'; |
||||
|
case ePropType.Number: |
||||
|
return 'number'; |
||||
|
case ePropType.Email: |
||||
|
return 'email'; |
||||
|
case ePropType.Password: |
||||
|
return 'password'; |
||||
|
case ePropType.PasswordInputGroup: |
||||
|
return 'passwordinputgroup'; |
||||
|
default: |
||||
|
return 'hidden'; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
calcAsterisks(validators: ValidatorFn[]) { |
||||
|
if (!validators) return ''; |
||||
|
const required = validators.find(v => this.isRequired(v)); |
||||
|
return required ? '*' : ''; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue