Exemplo n.º 1
0
        /// <summary>
        /// Write metadata common to all value representations, like properties and method parameters.
        /// </summary>
        private void WriteValueCommonMetadata(TypeScriptCodeBuilder b, IValueViewModel value)
        {
            b.StringProp("name", value.JsVariable);
            b.StringProp("displayName", value.DisplayName);

            WriteTypeCommonMetadata(b, value.Type);
        }
Exemplo n.º 2
0
        private static void WriteListViewModel(TypeScriptCodeBuilder b, ClassViewModel model)
        {
            string name = model.ViewModelClassName;

            string viewModelName = $"{model.ListViewModelClassName}ViewModel";
            string metadataName  = $"$metadata.{name}";

            using (b.Block($"export class {viewModelName} extends ListViewModel<$models.{name}, $apiClients.{name}ApiClient>"))
            {
                foreach (var method in model.ClientMethods.Where(m => m.IsStatic))
                {
                    string signature =
                        string.Concat(method.ClientParameters.Select(f => $", {f.Name}: {new VueType(f.Type).TsType("$models")} | null"));

                    // "item" or "list"
                    var transportTypeSlug = method.TransportType.ToString().Replace("Result", "").ToLower();

                    b.DocComment(method.Comment, true);
                    b.Line($"public {method.JsVariable} = this.$apiClient.$makeCaller(\"{transportTypeSlug}\", ");
                    b.Indented($"(c{signature}) => c.{method.JsVariable}({string.Join(", ", method.ClientParameters.Select(p => p.Name))}))");
                }

                b.Line();
                using (b.Block($"constructor()"))
                {
                    b.Line($"super({metadataName}, new $apiClients.{name}ApiClient())");
                }
            }
            b.Line();
        }
Exemplo n.º 3
0
        /// <summary>
        /// Write the metadata for all data sources of a class
        /// </summary>
        private void WriteDataSourcesMetadata(TypeScriptCodeBuilder b, ClassViewModel model)
        {
            using (b.Block("dataSources:", ','))
            {
                var dataSources = model.ClientDataSources(this.Model);
                foreach (var source in dataSources)
                {
                    WriteDataSourceMetadata(b, model, source);
                }

                // Not sure we need to explicitly declare the default source.
                // We can just use the absense of a data source to represent the default.

                /*
                 * var defaultSource = dataSources.SingleOrDefault(s => s.IsDefaultDataSource);
                 * if (defaultSource != null)
                 * {
                 *  var name = defaultSource.ClientTypeName.ToCamelCase();
                 *  b.Line($"get default() {{ return this.{name} }},");
                 * }
                 * else
                 * {
                 *  using (b.Block($"default:", ','))
                 *  {
                 *      b.StringProp("type", "dataSource");
                 *      b.StringProp("name", "default");
                 *      b.StringProp("displayName", "Default");
                 *      b.Line("params: {}");
                 *  }
                 * }
                 */
            }
        }
Exemplo n.º 4
0
        public override Task <string> BuildOutputAsync()
        {
            var b = new TypeScriptCodeBuilder();

            b.Line();
            b.Line();
            b.Line("// This file is automatically generated.");
            b.Line("// It is not in the generated folder for ease-of-use (no relative paths).");
            b.Line("// This file must remain in place relative to the generated scripts (<WebProject>/Scripts/Generated).");
            b.Line();
            b.Line();
            b.Line($"/// <reference path=\"coalesce.dependencies.d.ts\" />");

            foreach (var referencePath in Model.Select(m => m.EffectiveOutputPath).OrderBy(p => p))
            {
                // https://stackoverflow.com/a/1766773/2465631
                Uri    referencedFilePath = new Uri(referencePath);
                Uri    referenceFile      = new Uri(this.EffectiveOutputPath);
                Uri    diff    = referenceFile.MakeRelativeUri(referencedFilePath);
                string relPath = diff.OriginalString;

                b.Line($"/// <reference path=\"{relPath}\" />");
            }

            return(Task.FromResult(b.ToString()));
        }
Exemplo n.º 5
0
        public override Task <string> BuildOutputAsync()
        {
            var b = new TypeScriptCodeBuilder(indentSize: 2);

            b.Lines(new [] {
                "import * as $metadata from './metadata.g'",
                "import * as $models from './models.g'",
                "import * as qs from 'qs'",
                "import { AxiosClient, ModelApiClient, ServiceApiClient, ItemResult, ListResult } from 'coalesce-vue/lib/api-client'",
                "import { AxiosResponse, AxiosRequestConfig } from 'axios'",
            });
            b.Line();

            foreach (var model in Model.Entities.OrderBy(e => e.ClientTypeName))
            {
                WriteApiClientClass(b, model, $"ModelApiClient<$models.{model.ClientTypeName}>");

                // Lines between classes
                b.Line();
                b.Line();
            }


            foreach (var model in Model.Services.OrderBy(e => e.ClientTypeName))
            {
                WriteApiClientClass(b, model, $"ServiceApiClient<typeof $metadata.{model.ClientTypeName}>");

                // Lines between classes
                b.Line();
                b.Line();
            }

            return(Task.FromResult(b.ToString()));
        }
Exemplo n.º 6
0
 /// <summary>
 /// Write the metadata for a specific parameter to a specific method
 /// </summary>
 private void WriteMethodParameterMetadata(TypeScriptCodeBuilder b, MethodViewModel method, ParameterViewModel parameter)
 {
     using (b.Block($"{parameter.JsVariable}:", ','))
     {
         WriteValueCommonMetadata(b, parameter);
         b.StringProp("role", "value");
     }
 }
Exemplo n.º 7
0
 public override void BuildOutput(TypeScriptCodeBuilder b)
 {
     using (b.Block($"module {ViewModelModuleName}"))
     {
         b.DocComment($"External Type {Model.ViewModelClassName}");
         WriteViewModelClass(b);
     }
 }
Exemplo n.º 8
0
        /// <summary>
        /// Write metadata common to all type representations,
        /// like properties, method parameters, method returns, etc.
        /// </summary>
        private void WriteTypeCommonMetadata(TypeScriptCodeBuilder b, TypeViewModel type)
        {
            void WriteTypeDiscriminator(string propName, TypeViewModel t)
            {
                var kind = t.TsTypeKind;

                switch (kind)
                {
                case TypeDiscriminator.Unknown:
                    // We assume any unknown props are strings.
                    b.Line("// Type not supported natively by Coalesce - falling back to string.");
                    b.StringProp(propName, "string");
                    break;

                default:
                    b.StringProp(propName, kind.ToString().ToLowerInvariant());
                    break;
                }
            }

            void WriteTypeDef(string propName, TypeViewModel t)
            {
                var kind = t.TsTypeKind;

                switch (kind)
                {
                case TypeDiscriminator.Enum:
                    b.Line($"get {propName}() {{ return domain.enums.{t.Name} }},");
                    break;

                case TypeDiscriminator.Model:
                case TypeDiscriminator.Object:
                    b.Line($"get {propName}() {{ return {GetClassMetadataRef(t.ClassViewModel)} }},");
                    break;
                }
            }

            WriteTypeDiscriminator("type", type);
            WriteTypeDef("typeDef", type);

            // For collections, write the references to the underlying type.
            if (type.TsTypeKind == TypeDiscriminator.Collection)
            {
                if (type.PureType.TsTypeKind == TypeDiscriminator.Collection)
                {
                    throw new InvalidOperationException("Collections of collections aren't supported by Coalesce as exposed types");
                }

                using (b.Block($"itemType:", ','))
                {
                    b.StringProp("name", "$collectionItem");
                    b.StringProp("displayName", "");
                    b.StringProp("role", "value");
                    WriteTypeCommonMetadata(b, type.PureType);
                }
            }
        }
Exemplo n.º 9
0
        private static void WriteApiEndpointFunction(TypeScriptCodeBuilder b, ClassViewModel model, MethodViewModel method)
        {
            var    returnIsListResult = method.ReturnsListResult;
            string signature          =
                string.Concat(method.ClientParameters.Select(f => $"{f.Name}: {new VueType(f.Type).TsType("$models")} | null, "))
                + "$config?: AxiosRequestConfig";

            if (method.IsModelInstanceMethod)
            {
                signature = $"id: {new VueType(model.PrimaryKey.Type).TsType(null)}, " + signature;
            }

            using (b.Block($"public {method.JsVariable}({signature})"))
            {
                string resultType = method.TransportTypeGenericParameter.IsVoid
                    ? $"{method.TransportType}<void>"
                    : $"{method.TransportType}<{new VueType(method.TransportTypeGenericParameter).TsType("$models")}>";

                b.Line($"const $method = this.$metadata.methods.{method.JsVariable}");
                using (b.Block($"const $params = this.$mapParams($method,", ')'))
                {
                    if (method.IsModelInstanceMethod)
                    {
                        b.Line($"id,");
                    }
                    foreach (var param in method.ClientParameters)
                    {
                        b.Line($"{param.JsVariable},");
                    }
                }

                b.Line("return AxiosClient");
                using (b.Indented())
                {
                    b.Line($".{method.ApiActionHttpMethodName.ToLower()}(");
                    b.Indented($"`/${{this.$metadata.controllerRoute}}/{method.Name}`,");
                    switch (method.ApiActionHttpMethod)
                    {
                    case DataAnnotations.HttpMethod.Get:
                    case DataAnnotations.HttpMethod.Delete:
                        b.Indented($"this.$options(undefined, $config, $params)");
                        break;

                    default:
                        b.Indented($"qs.stringify($params),");
                        b.Indented($"this.$options(undefined, $config)");
                        break;
                    }
                    b.Line(")");

                    b.Line($".then<AxiosResponse<{resultType}>>(r => this.$hydrate{method.TransportType}(r, $method.return))");
                }
            }

            // Line between methods
            b.Line();
        }
Exemplo n.º 10
0
 private void WriteClassPropertiesMetadata(TypeScriptCodeBuilder b, ClassViewModel model)
 {
     using (b.Block("props:", ','))
     {
         foreach (var prop in model.ClientProperties)
         {
             WriteClassPropertyMetadata(b, model, prop);
         }
     }
 }
Exemplo n.º 11
0
 /// <summary>
 /// Write the metadata for all methods of a class
 /// </summary>
 private void WriteClassMethodMetadata(TypeScriptCodeBuilder b, ClassViewModel model)
 {
     using (b.Block("methods:", ','))
     {
         foreach (var method in model.ClientMethods)
         {
             WriteClassMethodMetadata(b, model, method);
         }
     }
 }
Exemplo n.º 12
0
 private void WriteCommonClassMetadata(TypeScriptCodeBuilder b, ClassViewModel model)
 {
     b.StringProp("name", model.ClientTypeName.ToCamelCase());
     b.StringProp("displayName", model.DisplayName);
     if (model.ListTextProperty != null)
     {
         // This might not be defined for external types, because sometimes it just doesn't make sense. We'll accommodate on the client.
         b.Line($"get displayProp() {{ return this.props.{model.ListTextProperty.JsVariable} }}, ");
     }
 }
Exemplo n.º 13
0
        private void WriteExternalTypeMetadata(TypeScriptCodeBuilder b, ClassViewModel model)
        {
            using (b.Block($"export const {model.ViewModelClassName} = domain.types.{model.ViewModelClassName} ="))
            {
                WriteCommonClassMetadata(b, model);
                b.StringProp("type", "object");

                WriteClassPropertiesMetadata(b, model);
            }
        }
Exemplo n.º 14
0
        public override void BuildOutput(TypeScriptCodeBuilder b)
        {
            using (b.Block($"module {ListViewModelModuleName}"))
            {
                b.Line();
                WriteDataSources(b);

                b.Line();
                WriteListViewModelClass(b);
            }
        }
Exemplo n.º 15
0
        public override void BuildOutput(TypeScriptCodeBuilder b)
        {
            using (b.Block($"module {ViewModelModuleName}"))
            {
                b.Line();
                WriteViewModelClass(b);

                b.Line();
                WriteEnumNamespace(b);
            }
        }
Exemplo n.º 16
0
        private void WriteDataSources(TypeScriptCodeBuilder b)
        {
            var dataSources   = Model.ClientDataSources(Services.ReflectionRepository).ToList();
            var defaultSource = dataSources.SingleOrDefault(s => s.IsDefaultDataSource);

            using (b.Block($"export namespace {Model.ClientTypeName}DataSources"))
            {
                if (defaultSource == null)
                {
                    b.Line($"export class {DataSourceFactory.DefaultSourceName} extends Coalesce.DataSource<{ViewModelFullName}> {{ }}");
                }

                foreach (var source in dataSources)
                {
                    b.DocComment(source.Comment);
                    using (b.Block($"export class {source.ClientTypeName} extends Coalesce.DataSource<{ViewModelFullName}>"))
                    {
                        if (source.DataSourceParameters.Any())
                        {
                            foreach (PropertyViewModel prop in source.DataSourceParameters)
                            {
                                b.DocComment(prop.Comment);
                                b.Line($"public {prop.JsVariable}: {prop.Type.TsKnockoutType(true)} = {prop.Type.ObservableConstructorCall()};");
                            }
                            using (b.Block("public saveToDto = () =>"))
                            {
                                b.Line("var dto: any = {};");
                                foreach (PropertyViewModel prop in source.DataSourceParameters)
                                {
                                    if (prop.Type.IsDate)
                                    {
                                        b.Line($"if (!this.{prop.JsVariable}()) dto.{prop.JsonName} = null;");
                                        b.Line($"else dto.{prop.JsonName} = this.{prop.JsVariable}()!.format('YYYY-MM-DDTHH:mm:ss{(prop.Type.IsDateTimeOffset ? "ZZ" : "")}');");
                                    }
                                    else
                                    {
                                        b.Line($"dto.{prop.JsonName} = this.{prop.JsVariable}();");
                                    }
                                }
                                b.Line("return dto;");
                            }
                        }
                    }

                    // Case-sensitive comparison intended here. We always need a data source cased EXACTLY as "Default".
                    if (source == defaultSource && !source.ClientTypeName.Equals(DataSourceFactory.DefaultSourceName, StringComparison.InvariantCulture))
                    {
                        b.Line($"export const {DataSourceFactory.DefaultSourceName} = {source.ClientTypeName};");
                    }
                }
            }
        }
Exemplo n.º 17
0
        private void WriteServiceMetadata(TypeScriptCodeBuilder b, ClassViewModel model)
        {
            using (b.Block($"export const {model.ClientTypeName} = domain.services.{model.ClientTypeName} ="))
            {
                b.StringProp("name", model.ClientTypeName.ToCamelCase());
                b.StringProp("displayName", model.DisplayName);

                b.StringProp("type", "service");
                b.StringProp("controllerRoute", model.ApiRouteControllerPart);

                WriteClassMethodMetadata(b, model);
            }
        }
Exemplo n.º 18
0
        private static void WriteApiClientClass(TypeScriptCodeBuilder b, ClassViewModel model, string baseClass)
        {
            string clientName = $"{model.ClientTypeName}ApiClient";

            using (b.Block($"export class {clientName} extends {baseClass}"))
            {
                b.Line($"constructor() {{ super($metadata.{model.ClientTypeName}) }}");

                foreach (var method in model.ClientMethods)
                {
                    WriteApiEndpointFunction(b, model, method);
                }
            }
        }
Exemplo n.º 19
0
 public override void BuildOutput(TypeScriptCodeBuilder b)
 {
     using (b.Block($"module {ViewModelModuleName}"))
     {
         using (b.Block($"export class {Model.ViewModelClassName} extends {Model.ViewModelGeneratedClassName}"))
         {
             b.Line();
             using (b.Block($"constructor(newItem?: object, parent?: Coalesce.BaseViewModel | {ListViewModelModuleName}.{Model.ListViewModelClassName})"))
             {
                 b.Line("super(newItem, parent);");
                 b.Line();
             }
         }
     }
 }
Exemplo n.º 20
0
        private void WriteClassPropertyMetadata(TypeScriptCodeBuilder b, ClassViewModel model, PropertyViewModel prop)
        {
            using (b.Block($"{prop.JsVariable}:", ','))
            {
                WriteValueCommonMetadata(b, prop);

                switch (prop.Role)
                {
                case PropertyRole.PrimaryKey:
                    // TS Type: "PrimaryKeyProperty"
                    b.StringProp("role", "primaryKey");
                    break;

                case PropertyRole.ForeignKey:
                    // TS Type: "ForeignKeyProperty"
                    var navProp = prop.ReferenceNavigationProperty;
                    b.StringProp("role", "foreignKey");
                    b.Line($"get principalKey() {{ return {GetClassMetadataRef(navProp.Object)}.props.{navProp.Object.PrimaryKey.JsVariable} as PrimaryKeyProperty }},");
                    b.Line($"get principalType() {{ return {GetClassMetadataRef(navProp.Object)} }},");
                    b.Line($"get navigationProp() {{ return {GetClassMetadataRef(model)}.props.{navProp.JsVariable} as ModelReferenceNavigationProperty }},");
                    break;

                case PropertyRole.ReferenceNavigation:
                    // TS Type: "ModelReferenceNavigationProperty"
                    b.StringProp("role", "referenceNavigation");
                    b.Line($"get foreignKey() {{ return {GetClassMetadataRef(model)}.props.{prop.ForeignKeyProperty.JsVariable} as ForeignKeyProperty }},");
                    b.Line($"get principalKey() {{ return {GetClassMetadataRef(prop.Object)}.props.{prop.Object.PrimaryKey.JsVariable} as PrimaryKeyProperty }},");
                    break;

                case PropertyRole.CollectionNavigation:
                    // TS Type: "ModelCollectionNavigationProperty"
                    b.StringProp("role", "collectionNavigation");
                    b.Line($"get foreignKey() {{ return {GetClassMetadataRef(prop.Object)}.props.{prop.InverseProperty.ForeignKeyProperty.JsVariable} as ForeignKeyProperty }},");
                    break;

                default:
                    b.StringProp("role", "value");
                    break;
                }

                // We store the negative case instead of the positive
                // because there are likely going to be more that are serializable than not.
                if (!prop.IsClientSerializable)
                {
                    b.Line("dontSerialize: true,");
                }
            }
        }
Exemplo n.º 21
0
 private void WriteEnumNamespace(TypeScriptCodeBuilder b)
 {
     using (b.Block($"export namespace {Model.ViewModelGeneratedClassName}"))
     {
         foreach (PropertyViewModel prop in Model.ClientProperties.Where(f => f.Type.IsEnum))
         {
             using (b.Block($"export enum {prop.Name}Enum"))
             {
                 foreach (var kvp in prop.Type.EnumValues)
                 {
                     b.Line($"{kvp.Value} = {kvp.Key},");
                 }
             }
         }
     }
 }
Exemplo n.º 22
0
        private static void WriteListViewModel(TypeScriptCodeBuilder b, ClassViewModel model)
        {
            string name = model.ViewModelClassName;

            string viewModelName = $"{model.ListViewModelClassName}ViewModel";
            string metadataName  = $"metadata.{name}";

            using (b.Block($"export class {viewModelName} extends ListViewModel<models.{name}, apiClients.{name}ApiClient>"))
            {
                using (b.Block($"constructor()"))
                {
                    b.Line($"super({metadataName}, new apiClients.{name}ApiClient())");
                }
            }
            b.Line();
        }
Exemplo n.º 23
0
        private void WriteApiBackedTypeMetadata(TypeScriptCodeBuilder b, ClassViewModel model)
        {
            using (b.Block($"export const {model.ViewModelClassName} = domain.types.{model.ViewModelClassName} ="))
            {
                WriteCommonClassMetadata(b, model);
                b.StringProp("type", "model");
                b.StringProp("controllerRoute", model.ApiRouteControllerPart);
                b.Line($"get keyProp() {{ return this.props.{model.PrimaryKey.JsVariable} }}, ");

                WriteClassPropertiesMetadata(b, model);

                WriteClassMethodMetadata(b, model);

                WriteDataSourcesMetadata(b, model);
            }
        }
Exemplo n.º 24
0
        private void WriteListViewModelClass(TypeScriptCodeBuilder b)
        {
            using (b.Block($"export class {Model.ListViewModelClassName} extends Coalesce.BaseListViewModel<{ViewModelFullName}>"))
            {
                b.Line($"public readonly modelName: string = \"{Model.ClientTypeName}\";");
                b.Line($"public readonly apiController: string = \"/{Model.ApiRouteControllerPart}\";");
                b.Line($"public modelKeyName: string = \"{Model.PrimaryKey.JsVariable}\";");
                b.Line($"public itemClass: new () => {ViewModelFullName} = {ViewModelFullName};");

                b.Line();
                b.Line("public filter: {");
                foreach (var prop in Model.BaseViewModel.ClientProperties.Where(f => f.IsUrlFilterParameter))
                {
                    b.Indented($"{prop.JsonName}?: string;");
                }
                b.Line("} | null = null;");

                b.DocComment("The namespace containing all possible values of this.dataSource.");
                b.Line($"public dataSources: typeof {Model.ClientTypeName}DataSources = {Model.ClientTypeName}DataSources;");

                b.DocComment("The data source on the server to use when retrieving objects. Valid values are in this.dataSources.");
                b.Line($"public dataSource: Coalesce.DataSource<{ViewModelFullName}> = new this.dataSources.{DataSourceFactory.DefaultSourceName}();");

                b.DocComment($"Configuration for all instances of {Model.ListViewModelClassName}. Can be overidden on each instance via instance.coalesceConfig.");
                b.Line($"public static coalesceConfig = new Coalesce.ListViewModelConfiguration<{Model.ListViewModelClassName}, {ViewModelFullName}>(Coalesce.GlobalConfiguration.listViewModel);");

                b.DocComment($"Configuration for this {Model.ListViewModelClassName} instance.");
                b.Line($"public coalesceConfig: Coalesce.ListViewModelConfiguration<{Model.ListViewModelClassName}, {ViewModelFullName}>");
                b.Indented($"= new Coalesce.ListViewModelConfiguration<{Model.ListViewModelClassName}, {ViewModelFullName}>({Model.ListViewModelClassName}.coalesceConfig);");

                // Write client methods
                b.Line();
                foreach (var method in Model.ClientMethods.Where(m => m.IsStatic))
                {
                    b.Line();
                    WriteClientMethodDeclaration(b, method, Model.ListViewModelClassName);
                }

                b.Line();
                b.Line($"protected createItem = (newItem?: any, parent?: any) => new {ViewModelFullName}(newItem, parent);");

                b.Line();
                b.Line("constructor() {");
                b.Indented("super();");
                b.Line("}");
            }
        }
Exemplo n.º 25
0
        public override Task <string> BuildOutputAsync()
        {
            var b = new TypeScriptCodeBuilder();

            b.Line();
            b.Line("/// <reference path=\"../coalesce.dependencies.d.ts\" />");

            if (ShouldWriteGeneratedBy)
            {
                b.Line();
                b.Line("// Generated by IntelliTect.Coalesce");
            }

            b.Line();

            BuildOutput(b);
            return(Task.FromResult(b.ToString()));
        }
Exemplo n.º 26
0
        private void WriteEnumMetadata(TypeScriptCodeBuilder b, TypeViewModel model)
        {
            using (b.Block($"export const {model.Name} = domain.enums.{model.Name} ="))
            {
                b.StringProp("name", model.Name.ToCamelCase());
                b.StringProp("displayName", model.DisplayName);
                b.StringProp("type", "enum");

                string enumShape = string.Join("|", model.EnumValues.Select(ev => $"\"{ev.Value}\""));
                b.Line($"...getEnumMeta<{enumShape}>([");
                foreach (var value in model.EnumValues)
                {
                    // TODO: allow for localization of displayName
                    b.Indented($"{{ value: {value.Key}, strValue: '{value.Value}', displayName: '{value.Value.ToProperCase()}' }},");
                }
                b.Line("]),");
            }
        }
Exemplo n.º 27
0
        public override Task <string> BuildOutputAsync()
        {
            var b = new TypeScriptCodeBuilder(indentSize: 2);

            b.Line("import * as $metadata from './metadata.g'");
            b.Line("import * as $models from './models.g'");
            b.Line("import * as $apiClients from './api-clients.g'");
            b.Line("import { ViewModel, ListViewModel, defineProps } from 'coalesce-vue/lib/viewmodel'");
            b.Line();

            foreach (var model in Model.Entities)
            {
                WriteViewModel(b, model);
                WriteListViewModel(b, model);
                b.Line();
            }

            return(Task.FromResult(b.ToString()));
        }
Exemplo n.º 28
0
        public void WriteMethod_SaveToDto(TypeScriptCodeBuilder b)
        {
            b.DocComment($"Saves this object into a data transfer object to send to the server.");
            using (b.Block($"public saveToDto = (): any =>"))
            {
                b.Line("var dto: any = {};");
                if (Model.PrimaryKey != null)
                {
                    b.Line($"dto.{Model.PrimaryKey.JsonName} = this.{Model.PrimaryKey.JsVariable}();");
                }

                b.Line();

                // Objects are skipped in the loop because objects will be examined
                // at the same time that their corresponding foreign key is examined.
                foreach (PropertyViewModel prop in Model.ClientProperties.Where(f => f.IsClientWritable && f.Object == null))
                {
                    if (prop.Type.IsDate)
                    {
                        b.Line($"if (!this.{prop.JsVariable}()) dto.{prop.JsonName} = null;");
                        b.Line($"else dto.{prop.JsonName} = this.{prop.JsVariable}()!.format('YYYY-MM-DDTHH:mm:ss{(prop.Type.IsDateTimeOffset ? "ZZ" : "")}');");
                    }
                    else if (prop.IsForeignKey)
                    {
                        var navigationProp = prop.ReferenceNavigationProperty;

                        b.Line($"dto.{prop.JsonName} = this.{prop.JsVariable}();");
                        // If the Id isn't set, use the object and see if that is set. Allows a child to get an Id after the fact.
                        using (b.Block($"if (!dto.{prop.JsonName} && this.{navigationProp.JsVariable}())"))
                        {
                            b.Line($"dto.{prop.JsonName} = this.{navigationProp.JsVariable}()!.{navigationProp.Object.PrimaryKey.JsVariable}();");
                        }
                    }
                    else
                    {
                        b.Line($"dto.{prop.JsonName} = this.{prop.JsVariable}();");
                    }
                }
                b.Line();
                b.Line($"return dto;");
            }
        }
Exemplo n.º 29
0
        /// <summary>
        /// Write the metadata for an entire method
        /// </summary>
        private void WriteClassMethodMetadata(TypeScriptCodeBuilder b, ClassViewModel model, MethodViewModel method)
        {
            using (b.Block($"{method.JsVariable}:", ','))
            {
                b.StringProp("name", method.JsVariable);
                b.StringProp("displayName", method.DisplayName);
                b.StringProp("transportType", method.TransportType.ToString().Replace("Result", "").ToLower());
                b.StringProp("httpMethod", method.ApiActionHttpMethod.ToString().ToUpperInvariant());

                using (b.Block("params:", ','))
                {
                    // TODO: should we be writing out the implicit 'id' param as metadata? Or handling some other way?
                    // If we do keep it as metadata, should probably add some prop to mark it as what it is.
                    if (method.IsModelInstanceMethod)
                    {
                        using (b.Block($"id:", ','))
                        {
                            b.StringProp("name", "id");
                            b.StringProp("displayName", "Primary Key"); // TODO: Is this what we want? Also, i18n.
                            b.StringProp("role", "value");
                            WriteTypeCommonMetadata(b, model.PrimaryKey.Type);
                        }
                    }

                    foreach (var param in method.ClientParameters)
                    {
                        WriteMethodParameterMetadata(b, method, param);
                    }
                }

                using (b.Block("return:", ','))
                {
                    b.StringProp("name", "$return");
                    b.StringProp("displayName", "Result"); // TODO: i18n
                    b.StringProp("role", "value");
                    WriteTypeCommonMetadata(b, method.ResultType);
                }
            }
        }
Exemplo n.º 30
0
        private void WriteViewModelClass(TypeScriptCodeBuilder b)
        {
            using (b.Block($"export class {Model.ViewModelGeneratedClassName}"))
            {
                if (Model.PrimaryKey != null)
                {
                    // ID of the object.
                    b.Line("public myId: any = 0;");
                }

                b.Line("public parent: any;");
                b.Line("public parentCollection: any;");

                b.Line();
                b.Line("// Observables");
                foreach (PropertyViewModel prop in Model.ClientProperties)
                {
                    b.Line($"public {prop.JsVariable}: {prop.Type.TsKnockoutType(true)} = {prop.Type.ObservableConstructorCall()};");
                    if (prop.Type.IsEnum)
                    {
                        b.Line($"public {prop.JsTextPropertyName} = {prop.Type.ObservableConstructorCall()};");
                    }
                }

                WriteMethod_LoadFromDto(b);

                WriteMethod_SaveToDto(b);

                b.Line();
                using (b.Block("constructor(newItem?: any, parent?: any)"))
                {
                    b.Line("this.parent = parent;");
                    b.Line();
                    b.Line("if (newItem) {");
                    b.Line("    this.loadFromDto(newItem);");
                    b.Line("}");
                }
            }
        }