Monday, 21 October 2019

Automapper unit test cases

using System;
using System.Collections;
using System.Threading.Tasks;
using PersonEntityMatchService.Business;
using PersonEntityMatchService.Business.Mappers;
using PersonEntityMatchService.Domain.Requests;
using PersonEntityMatchService.Domain.Responses;

namespace PersonEntityMatchService.Unit.Tests.Business
{
    using AutoMoqCore;
    using NUnit.Framework;
    using System.Collections.Generic;
    using Moq;
    using Clients;
    using Clients.Requests;
    using Clients.Responses;

    [TestFixture(Category = "UnitTest")]
    public class PersonMatchHandlerTests
    {
        private AutoMoqer _mocker;

        [SetUp]
        public void Setup()
        {
            _mocker = new AutoMoqer();
        }

        [Test]
        public void GetPersonMathcScoreTest()
        {
            var expectedMatches = new[]
            {
                new MatchEntity
                {
                    matchGroups = new[]
                    {
                        new Domain.Responses.MatchGroup
                        {
                            matchDescription = "test",
                            scoreStandalone = 50,
                            scoreIncremental = 10,
                            type = "suspect"
                        }
                    },
                    matchScore = 50
                }
            };
            var returnList = new List<MdaMatchEntity>();
            _mocker.GetMock<IMdaClient>()
                .Setup(x => x.GetMatchResponse(It.IsAny<MdaRequest>()))
                .Returns(Task.FromResult<IEnumerable<MdaMatchEntity>>(returnList));
            _mocker.GetMock<IMdaRequestMapper>()
                .Setup(x => x.MapToMdaRequest(It.IsAny<PersonEntity>()))
                .Returns(new MdaRequest());
            _mocker.GetMock<IMatchEntityMapper>()
                .Setup(x => x.MapToMatchEntities(It.IsAny<IEnumerable<MdaMatchEntity>>()))
                .Returns(expectedMatches);
            var target = _mocker.Resolve<PersonMatchHandler>();
            var actualMatches = target.GetPersonMatchScore(new PersonEntity());
            Assert.AreEqual(expectedMatches, actualMatches.Result);
        }

        [Test]
        public void GetPiiMathcScoreTest()
        {
            var expectedMatches = new[]
            {
                new PiiMatchEntity
                {
                    Ssn=new Ssn()
                    {
                        value="SSnABC"
                    },
                    DoB=new Domain.Responses.DoB
                    {
                        value="DOB123"
                    },
                    matchGroups = new[]
                    {
                        new Domain.Responses.MatchGroup
                        {
                            matchDescription = "test",
                            scoreStandalone = 50,
                            scoreIncremental = 10,
                            type = "suspect"
                        }
                    },
                    matchScore = 50
                }
            };
            var returnList = new List<MdaMatchEntity>();
            _mocker.GetMock<IMdaClient>()
                .Setup(x => x.GetMatchResponse(It.IsAny<MdaRequest>()))
                .Returns(Task.FromResult<IEnumerable<MdaMatchEntity>>(returnList));
            _mocker.GetMock<IMdaRequestMapper>()
                .Setup(x => x.MapToMdaRequest(It.IsAny<PersonEntity>()))
                .Returns(new MdaRequest());
            _mocker.GetMock<IMatchEntityMapper>()
                .Setup(x => x.MapToMatchPiiEntities(It.IsAny<IEnumerable<MdaMatchEntity>>()))
                .Returns(expectedMatches);
            var target = _mocker.Resolve<PersonMatchHandler>();
            var actualMatches = target.GetPiiMatchScore(new PersonEntity());
            Assert.AreEqual(expectedMatches, actualMatches.Result);
        }

    }
}


namespace PersonEntityMatchService.Unit.Tests
{
    using System.Collections.Generic;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using NUnit.Framework;
    using Domain.Responses;

    [TestFixture(Category = "UnitTest")]
    public class PiiMatchEntityContractTests : TestBase
    {
        [Test]
        public void Should_serialize_Entity()
        {
            var entities = ResponseEntity();

            var expected = GetJToken("POST_PiiMatch_Response.json");

            var actual = JToken.Parse(JsonConvert.SerializeObject(entities));

            Assert.True(JToken.DeepEquals(actual, expected), "Expected should match actual when serializing.");
        }

        [Test]
        public void Should_deserialize_Entity()
        {
            var entities = GetJToken("POST_PiiMatch_Response.json");

            var expected = ResponseEntity();

            var actual = JsonConvert.DeserializeObject<List<PiiMatchEntity>>(entities.ToString());

            var comparer = new ObjectsComparer.Comparer<List<PiiMatchEntity>>();

            Assert.True(comparer.Compare(actual, expected), "Expected should match actual when deserializing.");
        }

        private static List<PiiMatchEntity> ResponseEntity()
        {
            return new List<PiiMatchEntity>
            {
                new PiiMatchEntity{
                    Ssn=new Ssn()
                    {
                        value="/wEBReHevtjQYqAYuGis+AX0qWELTg4SkguSAXo6iE8j2927gVZLAyfosBrTYNKrIuagGrF/WlPBgobEAgjvaJ8i5uTKmGEjmweg2DvILux/wymO9hiLjUTW/wIVKkxPpVpeMJEfRuF3ejSbbgO2SChINn/mejqITyPb3bu+yKZp4nVrUub7728TFDlgx9MuqwmXx/NqQIkmKf/I0ThiQZXRhkYYqUNUwoejrhl0hqyPoLyPuHXm9sMeEZr8GHAiW3GGYUcY"
                    },
                    DoB=new DoB()
                    {
                        value="/wEBXxoST1IkLAuhdVuJ2QZsHad3mwDhaxKXAXo6iE8j29272zuTofDocz41YlG3R6zEbC9MHYXsxOdHAgjvaJ8i5uTKcv+3xrEkchQZvDo9b4saercM38kzFM1dv+wl4X6LnQeDegOo+Fd+q3y2u7h3ZqSJejqITyPb3bts/OpIHCkZYWC7FR0wG+xalm1iY+IdkzdoJR8ferrzAeQD3y9lu47NZ86X5DAXh+bh3MVZACGpd4DtEA0rWmXy0DFz+uGL8TuG"
                    },
                    uri = "/Entity?filter=EntityId eq '2f2bfe8add3041d8abfe8add30e1d854'",
                    matchScore = 80,
                    matchGroups = new[]
                    {
                        new MatchGroup
                        {
                            type = "suspect",
                            matchDescription = "Suspect individual match by fuzzy first name, fuzzy last name, email, and postal code",
                            scoreStandalone = 60,
                            scoreIncremental = 10
                        },
                        new MatchGroup
                        {
                            type = "suspect",
                            matchDescription = "Suspect individual match by first name, last name, email and postal code",
                            scoreStandalone = 70,
                            scoreIncremental = 10
                        }
                    }
                }
            };
    }
}
}



using System;
using System.IO;
using Newtonsoft.Json.Linq;
using NUnit.Framework;

namespace PersonEntityMatchService.Unit.Tests
{
    public class TestBase
    {
        [SetUp]
        public void Setup()
        {
            // Method intentionally left empty.
        }

        [TearDown]
        public void TearDown()
        {
            // Method intentionally left empty.
        }

        protected static JToken GetJToken(string fileName)
        {
            return JToken.Parse(File.ReadAllText(Path.Combine($"{AppDomain.CurrentDomain.BaseDirectory}/TestData", fileName)));
        }
    }
}


[
  {
    "Ssn": {
      "value": "/wEBReHevtjQYqAYuGis+AX0qWELTg4SkguSAXo6iE8j2927gVZLAyfosBrTYNKrIuagGrF/WlPBgobEAgjvaJ8i5uTKmGEjmweg2DvILux/wymO9hiLjUTW/wIVKkxPpVpeMJEfRuF3ejSbbgO2SChINn/mejqITyPb3bu+yKZp4nVrUub7728TFDlgx9MuqwmXx/NqQIkmKf/I0ThiQZXRhkYYqUNUwoejrhl0hqyPoLyPuHXm9sMeEZr8GHAiW3GGYUcY"
    },
    "DoB": {
      "value": "/wEBXxoST1IkLAuhdVuJ2QZsHad3mwDhaxKXAXo6iE8j29272zuTofDocz41YlG3R6zEbC9MHYXsxOdHAgjvaJ8i5uTKcv+3xrEkchQZvDo9b4saercM38kzFM1dv+wl4X6LnQeDegOo+Fd+q3y2u7h3ZqSJejqITyPb3bts/OpIHCkZYWC7FR0wG+xalm1iY+IdkzdoJR8ferrzAeQD3y9lu47NZ86X5DAXh+bh3MVZACGpd4DtEA0rWmXy0DFz+uGL8TuG"
    },
    "uri": "/Entity?filter=EntityId eq '2f2bfe8add3041d8abfe8add30e1d854'",
    "matchGroups": [
      {
        "type": "suspect",
        "matchDescription": "Suspect individual match by fuzzy first name, fuzzy last name, email, and postal code",
        "scoreStandalone": 60,
        "scoreIncremental": 10
      },
      {
        "type": "suspect",
        "matchDescription": "Suspect individual match by first name, last name, email and postal code",
        "scoreStandalone": 70,
        "scoreIncremental": 10
      }
    ],
    "matchScore": 80
  }
]

Thursday, 17 October 2019

Entity framework dynamic query generation

using (var cmd = _unitOfWork.DbContext.Database.Connection.CreateCommand())
            {
                if (cmd.Connection.State != ConnectionState.Open)
                    cmd.Connection.Open();

                cmd.CommandText = _queryBuilder.SelectOnTable(level1RepoFieldsTable, selectColumns)
                    .WhereConditions(searchFields?.ToCompareConditions(repositoryFields).ToList())
                    .OrderBys(sortFields == null
                        ? new List<OrderBy>
                        {
                            new OrderBy {Column = Constants.IdentityColumn, Direction = OrderByDirection.Descending}
                        }
                        : sortFields.ToOrderBys(repositoryFields).ToList())
                    .CreateRawSql();

                using (var dataReader = cmd.ExecuteReader())
                {
                    while (dataReader.Read())
                    {
                        var recordId = dataReader.GetColumnValue<int>(Constants.IdentityColumn);

                        if (recordId == 0)
                            continue;

                        var tdxRecord = _tdxRecordRepository.FindBy(x => x.Id == recordId)
                            .FirstOrDefault();

                        if (tdxRecord != null)
                        {
                            tdxRecord.RecordFields = dataReader.GetRecordFields(repositoryFields).ToList();
                            tdxRecords.Add(tdxRecord);
                        }

                        if (getFirstMatchingRecord) break;
                    }
                }
            }

Entity Framework Unity/ repository pattern

public interface IUnitOfWork
    {
        DbContext DbContext { get; }
        int Save();
    }

public class UnitOfWork : IUnitOfWork
    {
        public UnitOfWork(DbContext dbContext)
        {
            DbContext = dbContext;
        }

        public DbContext DbContext { get; }

        public int Save()
        {
            return DbContext.SaveChanges();
        }
    }


public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
    private readonly DbContext _dbContext;

public GenericRepository(IUnitOfWork unitOfWork)
{
_dbContext = unitOfWork.DbContext;
}

public IQueryable<TEntity> GetAll()
{
IQueryable<TEntity> query = _dbContext.Set<TEntity>();
return query;
}

public IQueryable<TEntity> FindBy(Expression<Func<TEntity, bool>> predicate)
{
IQueryable<TEntity> query = _dbContext.Set<TEntity>().Where(predicate);
return query;
}

public TEntity Add(TEntity entity)
{
return _dbContext.Set<TEntity>().Add(entity);
}

public void Delete(TEntity entity)
{
_dbContext.Set<TEntity>().Remove(entity);
}

public void Update(TEntity entity)
{
_dbContext.Entry(entity).State = EntityState.Modified;
}

public void Save()
{
_dbContext.SaveChanges();
}

        public IEnumerable<TEntity> AddRange(IEnumerable<TEntity> entities)
        {
            return _dbContext.Set<TEntity>().AddRange(entities);
        }
    }



public class TdxRepositoryService : ITdxRepositoryService
    {
        /// <summary>
        /// The generic repository for <see cref="TdxRepository"/>
        /// </summary>
        private readonly IGenericRepository<TdxRepository> _tdxGenericRepository;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="tdxGenericRepository">The generic repository for <see cref="TdxRepository"/></param>
        public TdxRepositoryService(IGenericRepository<TdxRepository> tdxGenericRepository)
        {
            _tdxGenericRepository = tdxGenericRepository;
        }

        /// <inheritdoc />
        public IEnumerable<TdxRepository> GetRepositories(bool includeInactive)
        {
            var tdxRepositories = includeInactive
                ? _tdxGenericRepository.GetAll()
                : _tdxGenericRepository.GetAll().Where(x => x.Active);
           
            return tdxRepositories
                .ToList();
        }

        /// <inheritdoc />
        public TdxRepository GeTdxRepositoryById(int repositoryId)
        {
            return _tdxGenericRepository
                .FindBy(x => x.Id == repositoryId)
                .FirstOrDefault();
        }

///<inheritdoc/>
public TdxRepository GeTdxRepositoryByName(string repositoryName)
{
return _tdxGenericRepository
.FindBy(x => x.Name.LOWER() == repositoryName.ToLower())
.FirstOrDefault();
}
}

Linq Entity queries

1. Include key which get all records

 _repoFieldRepository
                .FindBy(x => x.TdxRepositoryId == repositoryId)
                .Include(x => x.RepositoryLevel);

MVC/ web api Action filter

public class ValidateModelStateFilter : ActionFilterAttribute
{

public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
actionContext.Response = actionContext.Request.CreateErrorResponse((HttpStatusCode)422, actionContext.ModelState);
}
}

}

Sunday, 13 October 2019

Entity Framework

public class DisplayGroup
    {
 
        [Column("ID")]
        public int ID { get; set; }

[Column("PERTINENCE_GRP_ID")]
        public int? PertinenceGroupID { get; set; }

public virtual PertinenceGroup PertinenceGroup { get; set; }

}

public class DisplayGroupContent
{

[Column("ID")]
public int ID { get; set; }


[Column("PARENT_GROUP_ID")]
public int ParentGroupID { get; set; }


public virtual DisplayGroup ParentGroup { get; set; }

}

public class PertinenceGroup
{
[Column("ID")]
public int ID { get; set; }

public virtual ICollection<DisplayGroup> DisplayGroups { get; set; }

}


public class DisplayGroupConfiguration: EntityTypeConfiguration<DisplayGroup>
{

public DisplayGroupConfiguration()
{
ToTable("GDD_ENTITY_DSPLY_GRPS");
HasKey(x => x.ID);

HasMany(x => x.DisplayGroupContents).WithRequired(x => x.ParentGroup).HasForeignKey(x => x.ParentGroupID);

HasOptional(x => x.PertinenceGroup).WithMany().HasForeignKey(x => x.PertinenceGroupID);
}
}

public class DisplayGroupContentConfiguration : EntityTypeConfiguration<DisplayGroupContent>
{

public DisplayGroupContentConfiguration()
{
{
ToTable("GDD_DSPLY_GRP_CONTENTS");
HasKey(x => x.ID);

HasRequired(x => x.ParentGroup).WithMany().HasForeignKey(x => x.ParentGroupID);

}
}
}

public class PertinenceGroupConfiguration : EntityTypeConfiguration<PertinenceGroup>
{

public PertinenceGroupConfiguration() {
ToTable("GDD_PERTINENCE_GRPS");
HasKey(x => x.ID);

HasMany(x => x.DisplayGroups)
.WithOptional(x => x.PertinenceGroup)
.HasForeignKey(x => x.PertinenceGroupID);
}
}



CREATE TABLE "CSNCFG"."GDD_ENTITY_DSPLY_GRPS"
   ( "ID" NUMBER NOT NULL ENABLE,

"OWNER_TYPE_ID" NUMBER NOT NULL ENABLE,

"PERTINENCE_GRP_ID" NUMBER(10,0),

CONSTRAINT "GDD_ENTITY_DSPLY_GRPS_PK" PRIMARY KEY ("ID")

CONSTRAINT "GDD_ENTITY_DSPLY_GRPS_FK2" FOREIGN KEY ("PERTINENCE_GRP_ID")
  REFERENCES "CSNCFG"."GDD_PERTINENCE_GRPS" ("ID") ENABLE,

   )


CREATE TABLE "CSNCFG"."GDD_DSPLY_GRP_CONTENTS"
   ( "ID" NUMBER(10,0) NOT NULL ENABLE,

"PARENT_GROUP_ID" NUMBER(10,0) NOT NULL ENABLE,

"CHILD_GROUP_ID" NUMBER(10,0),

CONSTRAINT "GDD_DSPLY_GRP_CONTENTS_PK" PRIMARY KEY ("ID")

CONSTRAINT "GDD_DSPLY_GRP_CONTENTS_FK1" FOREIGN KEY ("PARENT_GROUP_ID")
  REFERENCES "CSNCFG"."GDD_ENTITY_DSPLY_GRPS" ("ID") ENABLE,

CONSTRAINT "GDD_DSPLY_GRP_CONTENTS_FK2" FOREIGN KEY ("CHILD_GROUP_ID")
  REFERENCES "CSNCFG"."GDD_ENTITY_DSPLY_GRPS" ("ID") ENABLE,

   )



 CREATE TABLE "CSNCFG"."GDD_PERTINENCE_GRPS"
   ( "ID" NUMBER(10,0),

CONSTRAINT "GDD_PERTINENCE_GRPS_PK" PRIMARY KEY ("ID")

   ) 

Thursday, 25 July 2019

JWT token generator

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Humana.Hcs.Ecom.Services.IdentityProvider.Configurations;
using Humana.Hcs.Ecom.Services.IdentityProvider.Models;
using Humana.Hcs.Ecom.Services.Utility;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Humana.Hcs.Ecom.Services.IdentityProvider.Constants;
using Humana.Hcs.Ecom.Services.IdentityProvider.Interfaces;
using Microsoft.AspNetCore.Http;

namespace Humana.Hcs.Ecom.Services.IdentityProvider.Controllers
{
    /// <summary>
    /// Identity Provider Controller
    /// </summary>
    [Route("ECOM/IdentityProvider")]
    [ApiController]
    public class IdentityProviderController : ControllerBase
    {
        private readonly IJwtHelper _jwtHelper;

        /// <summary>
        /// IdentityProviderController construtor
        /// </summary>
        /// <param name="jwtHelper"></param>
        public IdentityProviderController(IJwtHelper jwtHelper )
        {
            this._jwtHelper = jwtHelper;
        }



        /// <summary>
        /// To Get JWT Token for given User Login detail
        /// </summary>
        /// <param name="loginRequest"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("Login")]
        [ProducesResponseType(typeof(JwtResponse), 200)]
        [ProducesResponseType(typeof(ErrorMessage), 400)]
        [ProducesResponseType(typeof(ErrorMessage), 401)] // Unauthorized
        [ProducesResponseType(typeof(ErrorMessage), 403)] // Forbidden
        [ProducesResponseType(typeof(ErrorMessage), 404)] // At least one of the criteria passed was not found.Error array will give error for each failed     
        [ProducesResponseType(typeof(ErrorMessage), 406)] // Not Acceptable
        [ProducesResponseType(typeof(ErrorMessage), 429)] // Too many request
        [ProducesResponseType(typeof(ErrorMessage), 500)] // Internal server Error
        [ProducesResponseType(typeof(ErrorMessage), 503)] // Service Unavailable 
        public ActionResult GetToken(Login loginRequest)
        {
            if (loginRequest == null)
            {
                throw new ArgumentNullException(nameof(loginRequest));
            }

            JwtResponse jwtResponse = new JwtResponse();
            LoginSettings loginSettings = ConfigurationInitializer.GetUserLoginSetting(loginRequest.clientId);
            if (loginSettings == null)
                return StatusCode(401, ConfigConstants.GetHttpMessageModel(401));

            if (loginRequest.APIC_ClientId == loginSettings.APIC_ClientId && loginRequest.APIC_ClientSecret == loginSettings.APIC_ClientSecret)
            {
                List<Claim> claims = null;
                claims = new List<Claim>();
                var expiresDate = DateTime.UtcNow.AddMinutes(Convert.ToInt32(loginSettings.ExpiresInMinutes));
                var startingDate = DateTime.UtcNow;
                var createdAt = DateTime.UtcNow;
                claims.Add(new Claim(IdentityProviderConstants.ClaimName, createdAt.ToString()));

                var jwt = new JwtSecurityToken(
                    issuer: loginSettings.Issuer.ToString(),
                    audience: loginSettings.Audience.ToString(),
                    claims: claims,
                    notBefore: startingDate,
                    expires: expiresDate,
                    signingCredentials: new SigningCredentials(
                        new SymmetricSecurityKey(
                            Encoding.ASCII.GetBytes(loginSettings.clientSecret.ToString())),
                            SecurityAlgorithms.HmacSha256
                        )
                     );

                jwtResponse.Bearer = new JwtSecurityTokenHandler().WriteToken(jwt);
                return Ok(jwtResponse);
            }
            else
            {
                return StatusCode(401, ConfigConstants.GetHttpMessageModel(401));
            }
        }
        


        /// <summary>
        /// To Authorize JWT Token 
        /// </summary>
        /// <param name="loginRequest"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("Authorize")]
        [ProducesResponseType(typeof(ErrorMessage), 200)]
        [ProducesResponseType(typeof(ErrorMessage), 400)]
        [ProducesResponseType(typeof(ErrorMessage), 401)] // Unauthorized
        [ProducesResponseType(typeof(ErrorMessage), 403)] // Forbidden
        [ProducesResponseType(typeof(ErrorMessage), 404)] // At least one of the criteria passed was not found.Error array will give error for each failed     
        [ProducesResponseType(typeof(ErrorMessage), 406)] // Not Acceptable
        [ProducesResponseType(typeof(ErrorMessage), 429)] // Too many request
        [ProducesResponseType(typeof(ErrorMessage), 500)] // Internal server Error
        [ProducesResponseType(typeof(ErrorMessage), 503)] // Service Unavailable 
        public ActionResult Authorize(AuthorizeModel loginRequest)
        {
            if (loginRequest == null)
            {
                throw new ArgumentNullException(nameof(loginRequest));
            }

            JwtResponse jwtResponse = new JwtResponse();
            LoginSettings loginSettings = ConfigurationInitializer.GetUserLoginSetting(loginRequest.clientId);
            if (loginSettings == null)
                return StatusCode(401, ConfigConstants.GetHttpMessageModel(401));

            if (loginRequest.APIC_ClientId == loginSettings.APIC_ClientId && loginRequest.APIC_ClientSecret == loginSettings.APIC_ClientSecret)
            {
                if (_jwtHelper.ValidateToken(loginRequest.Bearer, loginSettings))
                {
                    return Ok(new ErrorMessage { httpCode = StatusCodes.Status200OK.ToString() , httpMessage = IdentityProviderConstants.HttpMessage200, moreInformation = IdentityProviderConstants.MoreInformation200 });
                }
                else
                {
                    return StatusCode(401, ConfigConstants.GetHttpMessageModel(401));
                }               
            }
            else
            {
                return StatusCode(401, ConfigConstants.GetHttpMessageModel(401));
            }
        }
    }
}


===============================


using Humana.Hcs.Ecom.Services.IdentityProvider.Configurations;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json.Serialization;
using Humana.Hcs.Ecom.Services.IdentityProvider.Swagger;
using Humana.Hcs.Ecom.Services.IdentityProvider.Models;
using Humana.Hcs.Ecom.Services.Utility;
using Humana.Hcs.Ecom.Services.IdentityProvider.Interfaces;
using Humana.Hcs.Ecom.Services.IdentityProvider.Helpers;

namespace Humana.Hcs.Ecom.Services.IdentityProvider
{
    /// <summary>
    /// Startup Class
    /// </summary>
    public class Startup
    {
        /// <summary>
        /// Configuration
        /// </summary>
        public IConfiguration Configuration { get; set; }

        /// <summary>
        /// Constructor of Startup
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="env"></param>
        public Startup(IConfiguration configuration, IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
               .SetBasePath(env.ContentRootPath)
               .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
               .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
               .AddEnvironmentVariables();

            builder.AddUserSecrets<Startup>();

            Configuration = builder.Build();
            ConfigurationInitializer.Initialiation(Configuration);
        }

        /// <summary>
        /// Configure Services
        /// </summary>
        /// <param name="services"></param>
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<Secrets.Rootobject>(Configuration.GetSection("IdentityProvider"));
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());

            services.AddTransient<IJwtHelper, JwtHelper>();
   
            // Reference for Audit Log Utility - Begin
            services.AddTransient<IAuditLogRepository, AuditLogRepository>();
            services.AddTransient<IDaoBase, DaoBase>();
            services.Configure<ConfigurationSetting>(options => Configuration.GetSection("AuditLog").Bind(options));
            // Reference for Audit Log Utility - End

            var swaggerConfig = ConfigurationInitializer.SwaggerConfiguration;
            if (swaggerConfig.Enabled)
            {
                services.AddSwagger(swaggerConfig);
            }
        }

        /// <summary>
        ///  This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseDefaultFiles();
            app.UseStaticFiles();
            app.UseDeveloperExceptionPage();
            app.UseHttpsRedirection();

            // Reference for Audit Log Utility - Begin
            app.UseMiddleware(typeof(AuditLogMiddleware));
            app.UseMiddleware(typeof(ErrorHandlerMiddleware));
            // Reference for Audit Log Utility - End

            app.UseMvc();

            //Use Swagger
            var swaggerConfig = ConfigurationInitializer.SwaggerConfiguration;
            if (swaggerConfig.Enabled)
            {
                app.UseSwagger(swaggerConfig);
            }

            //Added for clickjacking checkmarx issue
            app.Use(async (context, next) =>
            {
                context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
                await next();
            });
        }
    }
}


======================


using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using System.Diagnostics.CodeAnalysis;

namespace Humana.Hcs.Ecom.Services.IdentityProvider
{
    /// <summary>
    /// Program class
    /// </summary>
    [ExcludeFromCodeCoverage] 
    public static class Program
    {
        /// <summary>
        /// main Method
        /// </summary>
        /// <param name="args"></param>
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        /// <summary>
        /// Create web Host
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }
}

=================================

using Humana.Hcs.Ecom.Services.IdentityProvider.Constants;
using Humana.Hcs.Ecom.Services.IdentityProvider.Interfaces;
using Humana.Hcs.Ecom.Services.IdentityProvider.Models;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;

namespace Humana.Hcs.Ecom.Services.IdentityProvider.Helpers
{
    /// <summary>
    /// JWT Helper class
    /// </summary>
    public class JwtHelper : IJwtHelper
    {
        /// <summary>
        /// To Validate JWT Token for given Service Login setting
        /// </summary>
        /// <param name="request"></param>
        /// <param name="loginSettings"></param>
        /// <returns></returns>
        public bool ValidateToken(string request, LoginSettings loginSettings)
        {
            if (!request.ToLowerInvariant().StartsWith(IdentityProviderConstants.JwtPrefix.ToLower()))
            {
                return false;
            }

            var authorization = request.Split(' ');
            var bearerToken = authorization.Length > 1 ? authorization[1] : string.Empty;
            var signingKey =
                      new SymmetricSecurityKey(
                          Encoding.ASCII.GetBytes(loginSettings.clientSecret));

            var tokenValidationParameters = new TokenValidationParameters
            {

                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,

                ValidateIssuer = true,
                ValidIssuer = loginSettings.Issuer,

                ValidateAudience = true,
                ValidAudience = loginSettings.Audience,

                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero
            };

            try
            {
                var principal = new JwtSecurityTokenHandler().ValidateToken(bearerToken, tokenValidationParameters, out _);
                return principal.Claims.Any();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                return false;
            }
        }
    }
}


Saturday, 29 June 2019

Web api: fluent validations

using System.IO;
using FluentValidation;
using Newtonsoft.Json;
using TDX.Infrastructure.Common;
using TDX.Interfaces;
using Unity;

namespace TDX.ViewModels.Validators
{
/// <summary>
/// <see cref="AbstractValidator{T}"/> object used to validate <see cref="IngestionInputValidator"/>
/// </summary>
public class IngestionInputValidator : AbstractValidator<IngestionInputViewModel>
{
#region Private Fields

/// <summary>
/// The <see cref="IUnityContainer"/>
/// </summary>
private readonly IUnityContainer _unityContainer;

private IngestionInputSetViewModel _ingestionInputSetViewModel = new IngestionInputSetViewModel();

#endregion Private Fields

#region Public Constructors

/// <summary>
/// Constructor for the <see cref="IngestionSetValidator"/> class used to add validation rules
/// </summary>
/// <param name="unityContainer"><see cref="IUnityContainer"/></param>
public IngestionInputValidator(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
RuleFor(x => x.IngestionTypeName)
.NotEmpty()
.WithMessage("Ingestion type name is required")
.DependentRules(y =>
y.RuleFor(x => x.TdxRepositoryName)
.NotEmpty()
.WithMessage("Tdx Repository name is required")
.DependentRules(z =>
z.RuleFor(x => x)
.Must(x => ValidNames(x.IngestionTypeName, x.TdxRepositoryName))
.WithMessage("Invalid Ingestion Type Name or Tdx Repository Name.")));
RuleFor(x => x)
.Must(x => HaveFileExists(x.FilePath))
.WithMessage(x => $"File Not Found ('{x.FilePath}')")
.DependentRules(y =>
y.RuleFor(x => x)
.Must(x => HaveValidTdxRunFieldNames(x.FilePath))
.WithMessage("One or more tdx repo fields are not valid"))
.DependentRules(z =>
z.RuleFor(x => x)
.Must(HaveValidTdxRunFiles)
.WithMessage("One or more tdx run file type group name or tdx file type name are not valid"));
}

#endregion Public Constructors

#region Private Methods

/// <summary>
/// Have valid ingestion type name
/// </summary>
/// <param name="ingestionTypeName">Ingestion Type Name</param>
/// <param name="tdxRepositoryName">TDX Repository Name</param>
/// <returns>Flag denoting whether ingestion type name is valid</returns>
private bool ValidNames(string ingestionTypeName, string tdxRepositoryName)
{
var ingestionTypeService = _unityContainer.Resolve<IIngestionTypeService>();
return ingestionTypeService.GetIngestionType(ingestionTypeName, tdxRepositoryName) != null;
}

/// <summary>
/// To check file existance.
/// </summary>
/// <param name="filePath">File path of .json</param>
/// <returns>return true if file exists</returns>
private bool HaveFileExists(string filePath)
{
using (new Impersonator())
{
return File.Exists(filePath);
}
}

/// <summary>
/// To check all the file collection as valid tdx run file type group name and
/// tdx file type name
/// </summary>
/// <param name="arg"></param>
///  <returns><code>True</code> if all the file collection as valid tdx run file type group name and
///  tdx file type name.</returns>
private bool HaveValidTdxRunFiles(IngestionInputViewModel arg)
{
var repositoryFileTypeGroupService = _unityContainer.Resolve<IRepositoryFileTypeGroupService>();
var tdxFileTypeService = _unityContainer.Resolve<ITdxFileTypeService>();

foreach (var item in _ingestionInputSetViewModel.FileCollections)
{
var repoFileTypeGrp = repositoryFileTypeGroupService
.GetRepositoryFileTypeGroupByName(item.Name);

var repoField = tdxFileTypeService
.GetTdxFileTypeByName(item.TdxFileType);

if (repoFileTypeGrp == null || repoField == null)
return false;
}

return true;
}

/// <summary>
/// To check all the tdx files has valid names.
/// </summary>
/// <param name="filePath">.json file path</param>
/// <returns><code>True</code> if all the tdx run file names are valid.</returns>
private bool HaveValidTdxRunFieldNames(string filePath)
{
var repositoryFieldService = _unityContainer.Resolve<IRepositoryFieldService>();
var file = Path.Combine(filePath);

using (new Impersonator())
using (var fileStream = File.OpenRead(file))
using (var streamReader = new StreamReader(fileStream))
using (var jsonReader = new JsonTextReader(streamReader))
{
var serializer = new JsonSerializer();
_ingestionInputSetViewModel = serializer.Deserialize<IngestionInputSetViewModel>(jsonReader);
}

foreach (var item in _ingestionInputSetViewModel.Fields)
{
var tdxRepoField = repositoryFieldService.GeTdxRepositoryFieldByName(item.Name);
if (tdxRepoField == null) return false;
}

return true;
}

#endregion Private Methods
}
}

web api: Action filter

using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

namespace TDX.Filters
{
    /// <summary>
    /// <see cref="ActionFilterAttribute"/> used to specify that the model state should be validated.
    /// </summary>
    public class ValidateModelStateFilter : ActionFilterAttribute
{
#region Public Members

/// <summary>
/// Override used to check the model state for a given request and return an error response if it is invalid.
/// </summary>
/// <param name="actionContext">The <see cref="HttpActionContext"/> associated with the request.</param>
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
actionContext.Response = actionContext.Request.CreateErrorResponse((HttpStatusCode)422, actionContext.ModelState);
}
}

#endregion
}
}

Friday, 29 March 2019

Knockout sample screen with syntax

1. HTML
==================================

@using GDD.Enum
@{
ViewBag.Title = "Global Data Dictionary";
}

<div class="shortcut-area container-fluid">
<div data-bind="template: { name: 'shortcut-renderer', foreach: $data.Pages }"></div>
</div>

@section scripts {
@Scripts.Render("~/bundles/home")
<!-- Application Shortcut Item Renderer -->
<script id="shortcut-renderer" type="text/html">
<!-- ko if: !$data.AdminOnly() || $parent.IsAdmin() -->
<div class="shortcut">
<div class="shortcut-icon-wrapper">
<a class="shortcut-icon btn btn-link btn-block" data-bind="attr: { href: Url() }">
<i class="fa-3x fa" data-bind="css: Icon"></i>
</a>
</div>
<div class="shortcut-name-wrapper">
<a class="shortcut-name btn btn-link btn-block" data-bind="attr: { href: Url() }, text: Name"></a>
</div>
</div>
<!-- /ko -->
</script>
<script>
GDD.Site.OnPreinitialize(function (site) {
site.ContentModel(new GDD.Home.Managers.IndexManager(@Html.Raw(Json.Encode(ViewBag.CurrentAccessLevel <= (int)UserAccessLevel.EntityAdmin))));
});

GDD.Site.OnPostinitialize(function () {
site.ContentModel().GetRootApplications();
});
</script>
}


2. script file
=============================================

module GDD.Home.Managers {
"use strict";

export class IndexManager {

constructor(isAdmin: boolean = false) {
this.IsAdmin(isAdmin);
}

IsAdmin = ko.observable<boolean>(false);
Pages = ko.observableArray<Models.Page>([]);

// Remote call to load all root applications
GetRootApplications: () => void = () => {
this.Pages.push(new Models.Page({ Name: "Entities", Icon: "fa-line-chart", Url: "/Entities", AdminOnly: false }));
this.Pages.push(new Models.Page({ Name: "Entities (Bulk)", Icon: "fa-stack-overflow", Url: "/Bulk/Entities", AdminOnly: true }));
this.Pages.push(new Models.Page({ Name: "Pertinence Rules", Icon: "fa-flask", Url: "/Pertinence", AdminOnly: false }));
this.Pages.push(new Models.Page({ Name: "Display Groups", Icon: "fa-tv", Url: "/DisplayGroups", AdminOnly: false }));
this.Pages.push(new Models.Page({ Name: "Possible Value Groups", Icon: "fa-list-ul", Url: "/PossibleValueGroups", AdminOnly: false }));
this.Pages.push(new Models.Page({ Name: "API", Icon: "fa-cogs", Url: "/Help", AdminOnly: false }));
}
}
}

3. script file 
===============================

var site: GDD.Site;

module GDD {
"use strict";

export class Site {
// dom
$content = $("#content");
$ding = $("#dingSound");
$exceptionModal = $("#exceptionModal");
$cancelConfirmModal = $("#cancel-confirm");
$cwsTimeoutModal = $("#cwsTimeoutModal");
$groupNameHelpTemplate = $("#group-name-help-template");
$loadModal = $("#loadModal");
$navMenu = <MMenu>$("#nav-menu");
$dataTypeHelpTemplate = $("#data-type-help-template");
$dataTypePossibleValGroupHelp = $("#data-type-possiblegroup-help-template");
$disabledDataTypePossibleValGroupHelp = $("#disabled-data-type-possiblegroup-help-template");
$displayGroupHelpTemplate = $("#display-group-help-template");
$displayGroupPluginHelpTemplate = $("#display-group-plugin-help-template");
$displayGroupDetailHelpTemplate = $("#display-group-detail-help-template");
        $displayGroupDragHelpTemplate = $("#display-group-drag-help-template");
$displayGroupDisplayNameHelpTemplate = $("#display-group-display-name-help-template");
$possibleValueGroupHelpTemplate = $("#possible-value-group-help-template");
$possibleValueGroupTabHelpTemplate = $("#possible-value-group-tab-help-template");
$pertinenceHelpTemplate = $("#pertinence-help-template");
$searchHelpTemplate = $("#search-help-template");
$searchPrefPageSizeHelpTemplate = $("#search-pref-page-size-help-template");
$unitHelpTemplate = $("#unit-help-template");
$validationPanel = $("#validation-panel");
$possibleValueHelpTemplate = $("#possible-value-template");
$entityNameHelpTemplate = $("#entity-name-template");
$entityNamePrefixHelpTemplate = $("#entity-name-prefix-template");
$entityNameSuffixHelpTemplate = $("#entity-name-suffix-template");
$entityNameReplaceHelpTemplate = $("#entity-name-replace-template");
$entityNameReplaceWithHelpTemplate = $("#entity-name-replace-with-template");
        $fileExtensionsHelpTemplate = $("#file-extensions-help-template");
$personPanel = $("#person-panel");
$possibleValueFloatHelpTemplate = $("#possible-value-float-help-template");
$possibleValueIntegerHelpTemplate = $("#possible-value-integer-help-template");
$quantityHelpTemplate = $("#quantity-help-template");
$deleteHelpTemplate = $("#delete-help-template");
$unDeleteHelpTemplate = $("#unDelete-help-template");
        $showMoreInfo = $("#more-info-modal");
$precisionHelpTemplate = $("#precision-help-template");
$defaultValueSymbolicHelpTemplate = $("#default-value-symbolic-help-template");
// custom view model
ContentModel = ko.observable<any>({});

// controls
PersonSearchControl = new Controls.PersonSearch();
// tooltips
DataTypeTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$dataTypeHelpTemplate.html();
return kendo.template(content);
}
});
DisplayGroupTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$displayGroupHelpTemplate.html();
return kendo.template(content);
}
});
DisplayGroupPluginTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$displayGroupPluginHelpTemplate.html();
return kendo.template(content);
}
});
DisplayGroupDetailTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$displayGroupDetailHelpTemplate.html();
return kendo.template(content);
}
        });
    DisplayGroupDisplayNameTooltip = ko.pureComputed<any>({
        read: (): any => {
            var content = this.$displayGroupDisplayNameHelpTemplate.html();
            return kendo.template(content);
        }
        });
    DisplayGroupDragTooltip = ko.pureComputed<any>({
        read: (): any => {
            var content = this.$displayGroupDragHelpTemplate.html();
            return kendo.template(content);
        }
    });
PertinenceTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$pertinenceHelpTemplate.html();
return kendo.template(content);
}
});
PossibleValueGroupTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$possibleValueGroupHelpTemplate.html();
return kendo.template(content);
}
});
PossibleValueGroupTabTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$possibleValueGroupTabHelpTemplate.html();
return kendo.template(content);
}
});
GroupNameTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$groupNameHelpTemplate.html();
return kendo.template(content);
}
});
SearchTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$searchHelpTemplate.html();
return kendo.template(content);
}
});
SearchPrefPageSizeTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$searchPrefPageSizeHelpTemplate.html();
return kendo.template(content);
}
});
UnitTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$unitHelpTemplate.html();
return kendo.template(content);
}
});
PossibleValueTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$possibleValueHelpTemplate.html();
return kendo.template(content);
}
});
EntityNameTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$entityNameHelpTemplate.html();
return kendo.template(content);
}
});
EntityNamePrefixTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$entityNamePrefixHelpTemplate.html();
return kendo.template(content);
}
});
EntityNameSuffixTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$entityNameSuffixHelpTemplate.html();
return kendo.template(content);
}
});
EntityNameReplaceTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$entityNameReplaceHelpTemplate.html();
return kendo.template(content);
}
});
EntityNameReplaceWithTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$entityNameReplaceWithHelpTemplate.html();
return kendo.template(content);
}
});
DataTypePossibleValGrpTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$dataTypePossibleValGroupHelp.html();
return kendo.template(content);
}
});
DisabledDataTypePossibleValGrpTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$disabledDataTypePossibleValGroupHelp.html();
return kendo.template(content);
}
});
PossibleValueFloatTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$possibleValueFloatHelpTemplate.html();
return kendo.template(content);
}
});
PossibleValueIntegerTooltip = ko.pureComputed<any>({
read: (): any => {
var content = this.$possibleValueIntegerHelpTemplate.html();
return kendo.template(content);
}
});
QuantityToolTip = ko.pureComputed<any>({
read: (): any => {
var content = this.$quantityHelpTemplate.html();
return kendo.template(content);
}
});
DeleteToolTip = ko.pureComputed<any>({
read: (): any => {
var content = this.$deleteHelpTemplate.html();
return kendo.template(content);
}
});
UnDeleteToolTip = ko.pureComputed<any>({
read: (): any => {
var content = this.$unDeleteHelpTemplate.html();
return kendo.template(content);
}
        });
        PrecisionToolTip = ko.pureComputed<any>({
            read: (): any => {
                var content = this.$precisionHelpTemplate.html();
                return kendo.template(content);
            }
});
DefaultValueSymbolicToolTip=ko.pureComputed<any>({
            read: (): any => {
                var content = this.$defaultValueSymbolicHelpTemplate.html();
                return kendo.template(content);
            }
        });
        FileExtensionsToolTip = ko.pureComputed<any>({
            read: (): any => {
                var content = this.$fileExtensionsHelpTemplate.html();
                return kendo.template(content);
            }
        });

OpenEntity = (entity: Entity.Models.EntityViewModel, event: JQueryEventObject): void => {
if (entity !== null && event.which !== 3)
window.open(site.BaseUrl() + "Entities/" + entity.ID());
};

OpenDisplayGroup = (displayGroup: DisplayGroup.Models.DisplayGroupViewModel): void => {
if (displayGroup !== null)
window.open(site.BaseUrl() + "DisplayGroups/" + displayGroup.ID());
};

OpenPertinence = (pertinenceGroup: Pertinence.Models.PertinenceGroupViewModel): void => {
if (pertinenceGroup !== null)
window.open(site.BaseUrl() + "Pertinence/" + pertinenceGroup.ID());
};

// properties
    DateTimeFormats = ko.observableArray<Models.DateTimeFormatViewModel>([
        new Models.DateTimeFormatViewModel("Date Only", Models.DateTimeFormat.DateOnly),
        new Models.DateTimeFormatViewModel("Date and Time", Models.DateTimeFormat.DateTime),
        new Models.DateTimeFormatViewModel("Time Only", Models.DateTimeFormat.TimeOnly)
    ]);
CurrentPerson = ko.observable<Models.Person>(null);
BaseUrl = ko.observable<string>(null);
AccessLevels = ko.observableArray<Models.UserAccessLevel>([]);
ColorMap = ko.observable<{ [key: string]: Models.ThemeColors }>({});
CurrentTheme = ko.observable<number>(0);
Exception = ko.observable<GDD.Models.SerializableException>(new GDD.Models.SerializableException());
CancelConfirmViewModel = ko.observable<GDD.Models.CancelConfirmModalViewModel>(new GDD.Models.CancelConfirmModalViewModel());
LoaderText = ko.observable<string>(null);
LoaderStatic = ko.observable<boolean>(true);
LockHeader = ko.observable<boolean>(true);
LeftMenuOpen = ko.observable<boolean>(true);
Themes = ko.observableArray<Models.ThemeItem>([
new Models.ThemeItem("midnight-preview.png", "midnight.bootstrap-theme.css", "Midnight", "Light on dark",
"kendo.common-material.core.min.css", "kendo.common-material.min.css", "kendo.materialblack.min.css",
"kendo.materialblack.mobile.min.css"),
new Models.ThemeItem("afternoon-preview.png", "bootstrap-theme.css", "Afternoon", "Dark on light",
"kendo.common-bootstrap.core.min.css", "kendo.common-bootstrap.min.css", "kendo.bootstrap.min.css",
"kendo.bootstrap.mobile.min.css"),
new Models.ThemeItem("lumen-preview.png", "lumen.bootstrap-theme.css", "Lumen", "Light and shadow", "kendo.common.core.min.css",
"kendo.common-fiori.min.css", "kendo.fiori.min.css", "kendo.fiori.mobile.min.css"),
new Models.ThemeItem("paper-preview.png", "paper.bootstrap-theme.css", "Paper", "Material is the metaphor",
"kendo.common-material.core.min.css", "kendo.common-material.min.css", "kendo.material.min.css",
"kendo.material.mobile.min.css"),
new Models.ThemeItem("sandstone-preview.png", "sandstone.bootstrap-theme.css", "Sandstone", "A touch of warmth",
"kendo.common.core.min.css", "kendo.common.min.css", "kendo.metro.min.css", "kendo.metro.mobile.min.css"),
new Models.ThemeItem("slate-preview.png", "slate.bootstrap-theme.css", "Slate", "Shades of gunmetal gray",
"kendo.common-bootstrap.core.min.css", "kendo.common-bootstrap.min.css", "kendo.moonlight.min.css",
"kendo.moonlight.mobile.min.css")
]);
LoadedTheme = ko.computed<Models.ThemeItem>({
read: (): Models.ThemeItem => {
return this.Themes()[this.CurrentTheme()];
},
write: (value: Models.ThemeItem): void => {
this.loadTheme(this.Themes()[this.CurrentTheme()], value);
}
});
PageSizes = [
{ Name: "20", Size: 20 },
{ Name: "50", Size: 50 },
{ Name: "100", Size: 100 },
{ Name: "500", Size: 500 },
{ Name: "All", Size: 99999 }
];
TopHeaderIsVisible = ko.observable<boolean>(true);
TopOffset = ko.observable<number>(0);
UserPreferences = ko.observable<Models.IDictionary<Models.UserPreferenceViewModel>>();
BottomOffset = ko.observable<number>(0);
ValidationItems = ko.observable<Models.ModelState>(new Models.ModelState());
WindowWidth = ko.observable<number>(window.innerWidth);
WindowHeight = ko.observable<number>(window.innerHeight);
WindowXs = ko.pureComputed<boolean>({
read: (): boolean => {
return this.WindowWidth() >= 0;
}
});
WindowSm = ko.pureComputed<boolean>({
read: (): boolean => {
return this.WindowWidth() >= 768;
}
});
WindowMd = ko.pureComputed<boolean>({
read: (): boolean => {
return this.WindowWidth() >= 992;
}
});
WindowLg = ko.pureComputed<boolean>({
read: (): boolean => {
return this.WindowWidth() >= 1200;
}
});
MaxHeight = ko.pureComputed<number>({
read: (): number => {
return this.WindowWidth() > 992 ? this.WindowHeight() - (this.TopOffset() + this.BottomOffset()) : 999999;
}
});
MaxHeightCss = ko.pureComputed<string>({
read: (): string => {
// if we are above mobile/tablet breakpoint return inner content height else
return this.WindowWidth() > 992 ? this.MaxHeight() + "px" : "none";
}
}, this);

// static private
private static _preHandlers: Array<(site: Site) => any> = new Array();
private static _postHandlers: Array<() => any> = new Array();

// private
private currentRequest: JQueryXHR;
private delta: number = 5;
private lastScrollTop: number = 0;
private placeholderTheme = new Models.ThemeItem(null, "placeholder.bootstrap-theme.css", null, null,
"kendo.common.core.min.css", "kendo.common.min.css", "kendo.default.min.css", "kendo.default.mobile.min.css");
private scrollChanged: boolean = true;
private maxTileHeight: number = 0;
        private notification: kendo.ui.Notification;
        private openModal: JQuery;

// pre-initialization handlers
static OnPreinitialize: (func: (site: Site) => any) => void = (func: (site: Site) => void) => {
if (func) {
Site._preHandlers.push(func);
}
};

// post-initialization handlers
static OnPostinitialize: (func: () => any) => void = (func: () => void) => {
if (func) {
Site._postHandlers.push(func);
}
};

// constructor
constructor(jsObject: any) {
if (jsObject.CurrentPerson) {
this.CurrentPerson(new Models.Person(jsObject.CurrentPerson));
}
if (jsObject.UserPreferences) {
this.UserPreferences(Models.UserPreferenceViewModelJS.fromArray(jsObject.UserPreferences));
}
if (jsObject.BaseUrl) {
this.BaseUrl(jsObject.BaseUrl);
} else {
this.BaseUrl(window.location.origin ? window.location.origin + "/" : window.location.protocol + "/" + window.location.host + "/");
}
if (jsObject.AccessLevels) {
this.AccessLevels(Models.UserAccessLevel.fromArray(jsObject.AccessLevels));
}
}

// initialisation
static Init = (jsObject: any): void => {
// init site object & pre handlers
site = new Site(jsObject);
for (let i: number = 0; i < Site._preHandlers.length; i++) {
Site._preHandlers[i](site);
}
// bind site object
ko.applyBindings(site);
// setup navigation menu
site.$navMenu.mmenu({
offCanvas: {
pageSelector: "#site-container",
zposition: "next"
},
extensions: ["widescreen", "border-full", "multiline", "theme-dark"]
},
{
clone: false
});
site.$personPanel.mmenu({
offCanvas: {
position: "right",
zposition: "front"
},
extensions: ["theme-dark", "pageshadow"],
navbar: {
title: "Find a Person"
}
});
// setup person panel
site.$validationPanel.mmenu({
offCanvas: {
position: "right",
zposition: "front"
},
extensions: ["pageshadow"],
navbar: {
title: "Attention"
}
});
// default focus to search text
site.$personPanel.data("mmenu").bind("opened", () => {
site.PersonSearchControl.$searchText.focus();
});
// load theme
site.CurrentTheme(site.UserPreferences()[Models.UserPreferences.Theme].Value());
if ($("link[href*='/Content/gddcoretheme']").length === 1) {
site.loadTheme(null, site.Themes()[site.CurrentTheme()]);
} else if ($("link[href*='/Content/placeholder.bootstrap-theme.css']").length === 1) {
site.loadTheme(site.placeholderTheme, site.Themes()[site.CurrentTheme()]);
} else {
for (let i: number = 0; i < site.Themes().length; i++) {
if ($(`link[href*="/Content/${site.Themes()[i].StyleSheet()}"]`).length === 1) {
site.loadTheme(site.Themes()[i], site.Themes()[site.CurrentTheme()]);
break;
}
}
}
// process post handlers
for (let i: number = 0; i < Site._postHandlers.length; i++) {
Site._postHandlers[i]();
}
// to allow for modals & panels to play nice with one another
var rightPanels = $(".mm-menu.mm-right");
rightPanels.each((index: number, elem: Element) => {
var api: any = $(elem).data("mmenu");
api.bind("opening", () => {
if ($("body").data("modalmanager")) {
var openModals: any = $("body").data("modalmanager").getOpenModals();
var loaderOrExceptionModalIsOpen: boolean = false;
var containerZIndex: number = 0;
for (var i: number = 0; i < openModals.length; i++) {
if (openModals[i].$element.attr("id") === "loadModal" || openModals[i].$element.attr("id") === "exceptionModal") {
loaderOrExceptionModalIsOpen = true;
containerZIndex = 0;
}

if (!loaderOrExceptionModalIsOpen) {
if (+openModals[i].$container.css("z-index") > containerZIndex) {
containerZIndex = +openModals[i].$container.css("z-index");
}
}
}

if (containerZIndex > 0) {
$(elem).css("z-index", containerZIndex + 2);
$("#mm-blocker").css("z-index", containerZIndex + 1);
} else if (loaderOrExceptionModalIsOpen) {
$(elem).removeAttr("style");
$("#mm-blocker").removeAttr("style");
} else {
$("#mm-blocker").css("z-index", 1039);
}
}
});
});
site.poll();
// heartbeat
setInterval(site.poll, 300);
// scrolling
$(window).scroll((event: any) => {
site.scrollChanged = true;
});
$(window).resize(() => {
site.WindowWidth(window.innerWidth);
site.WindowHeight(window.innerHeight);
site.ResizeTiles();
});
};

Beep = (): void => {
var sound: any = this.$ding;
sound[0].pause();
sound[0].currentTime = 0;
sound[0].play();
};

private checkScroll = (): void => {
if (this.LockHeader()) {
return;
}

var st: number = $(document).scrollTop();

// scrolled more than delta?
if (Math.abs(this.lastScrollTop - st) <= this.delta) {
return;
}

if (st > this.lastScrollTop && st > this.TopOffset()) {
if (this.TopHeaderIsVisible()) {
this.TopHeaderIsVisible(false);
$("#top-header").stop(true, true).delay(200).animate({
top: -this.TopOffset()
}, 500, () => { return; });
}
} else {
if (st + $(window).height() < $(document).height()) {
if (!this.TopHeaderIsVisible()) {
this.TopHeaderIsVisible(true);
$("#top-header").stop(true, true).animate({
top: 0
}, 500);
}
} else {
if (!this.TopHeaderIsVisible()) {
this.TopHeaderIsVisible(true);
$("#top-header").stop(true, true).animate({
top: 0
}, 100);
}
}
}

this.lastScrollTop = st;
};

// check the Z-index of the modal window
private checkZIndex = ($modal: JQuery): void => {
var openRightPanels: JQuery = $(".mm-menu.mm-right.mm-opened");
var maxZIndex: number = 0;
for (var i: number = 0; i < openRightPanels.length; i++) {
var elemZIndex: number = +$(openRightPanels[i]).css("z-index");
if (elemZIndex > maxZIndex) {
maxZIndex = elemZIndex;
}
}
if (maxZIndex > 0) {
$modal.parent().css("z-index", maxZIndex + 2);
$modal.parent().next(".modal-backdrop").css("z-index", maxZIndex + 1);
}
};

private loadTheme = (oldTheme: Models.ThemeItem, newTheme: Models.ThemeItem): void => {
var newIndex = this.Themes.indexOf(newTheme);
this.CurrentTheme(newIndex);

// remove html theme class
if (oldTheme && oldTheme.Name()) {
$("html").removeClass(oldTheme.Name() + "-theme");
}
// add html theme class
if (newTheme && newTheme.Name()) {
$("html").addClass(newTheme.Name() + "-theme");
}

if ($("link[href*=\"/Content/gddcoretheme\"]").length === 1) {
var fullPath: string = $("link[href*=\"/Content/gddcoretheme\"]").attr("href");
fullPath = fullPath.substring(0, fullPath.lastIndexOf("/") + 1);
$($("link[href*=\"/Content/gddcoretheme\"]")[0]).attr("href", fullPath + newTheme.StyleSheet());
$($("link[href*=\"/Content/kendocoretheme\"]")[0]).attr("href", fullPath + newTheme.KendoCoreStyleSheet());
$($("link[href*=\"/Content/kendocommontheme\"]")[0]).attr("href", fullPath + newTheme.KendoCommonStyleSheet());
$($("link[href*=\"/Content/kendotheme\"]")[0]).attr("href", fullPath + newTheme.KendoThemeStyleSheet());
$($("link[href*=\"/Content/kendomobiletheme\"]")[0]).attr("href", fullPath + newTheme.KendoMobileThemeStyleSheet());
} else if ($(`link[href*="/Content/${oldTheme.StyleSheet()}"]`).length === 1) {
var href = $(`link[href*="/Content/${oldTheme.StyleSheet()}"]`).attr("href");
var href2 = href.replace(oldTheme.StyleSheet(), newTheme.StyleSheet());
var kendoCore = $(`link[href*="/Content/${oldTheme.KendoCoreStyleSheet()}"]`).attr("href");
var kendoCore2 = kendoCore.replace(oldTheme.KendoCoreStyleSheet(), newTheme.KendoCoreStyleSheet());
var kendoCommon = $(`link[href*="/Content/${oldTheme.KendoCommonStyleSheet()}"]`).attr("href");
var kendoCommon2 = kendoCommon.replace(oldTheme.KendoCommonStyleSheet(), newTheme.KendoCommonStyleSheet());
var kendoTheme = $(`link[href*="/Content/${oldTheme.KendoThemeStyleSheet()}"]`).attr("href");
var kendoTheme2 = kendoTheme.replace(oldTheme.KendoThemeStyleSheet(), newTheme.KendoThemeStyleSheet());
var kendoMobileTheme = $(`link[href*="/Content/${oldTheme.KendoMobileThemeStyleSheet()}"]`).attr("href");
var kendoMobileTheme2 = kendoMobileTheme.replace(oldTheme.KendoMobileThemeStyleSheet(), newTheme.KendoMobileThemeStyleSheet());

$(`link[href*="/Content/${oldTheme.StyleSheet()}"]`).attr("href", href2);
$(`link[href*="/Content/${oldTheme.KendoCommonStyleSheet()}"]`).attr("href", kendoCommon2);
$(`link[href*="/Content/${oldTheme.KendoCoreStyleSheet()}"]`).attr("href", kendoCore2);
$(`link[href*="/Content/${oldTheme.KendoThemeStyleSheet()}"]`).attr("href", kendoTheme2);
$(`link[href*="/Content/${oldTheme.KendoMobileThemeStyleSheet()}"]`).attr("href", kendoMobileTheme2);
}
setTimeout(this.mapColors, 500);
};

private mapColors = (): void => {
var e1 = $("<div class=\"btn-primary\"></div>");
var e2 = $("<div class=\"btn-info\"></div>");
var e3 = $("<div class=\"btn-success\"></div>");
var e4 = $("<div class=\"btn-danger\"></div>");
var e5 = $("<div class=\"btn-default\"></div>");
var e6 = $("<div class=\"btn-warning\"></div>");
$("body").append(e1).append(e2).append(e3).append(e4).append(e5);
this.ColorMap[Models.BootstrapColors[Models.BootstrapColors.primary]] =
new Models.ThemeColors(e1.css("backgroundColor"), e1.css("borderColor"), e1.css("color"));
this.ColorMap[Models.BootstrapColors[Models.BootstrapColors.info]] =
new Models.ThemeColors(e2.css("backgroundColor"), e2.css("borderColor"), e2.css("color"));
this.ColorMap[Models.BootstrapColors[Models.BootstrapColors.success]] =
new Models.ThemeColors(e3.css("backgroundColor"), e3.css("borderColor"), e3.css("color"));
this.ColorMap[Models.BootstrapColors[Models.BootstrapColors.danger]] =
new Models.ThemeColors(e4.css("backgroundColor"), e4.css("borderColor"), e4.css("color"));
this.ColorMap[Models.BootstrapColors[Models.BootstrapColors.default]] =
new Models.ThemeColors(e5.css("backgroundColor"), e5.css("borderColor"), e5.css("color"));
this.ColorMap[Models.BootstrapColors[Models.BootstrapColors.warning]] =
new Models.ThemeColors(e6.css("backgroundColor"), e6.css("borderColor"), e6.css("color"));
e1.remove();
e2.remove();
e3.remove();
e4.remove();
e5.remove();
e6.remove();
this.ColorMap.notifySubscribers();
};

private poll = (): void => {
if (this.TopHeaderIsVisible()) {
this.TopOffset($("#top-header").outerHeight());
}
this.BottomOffset($("#action-menu") ? $("#action-menu").outerHeight() : 0);

if ($(".action-bar").length) {
$(".action-bar").css("padding-bottom", $("#action-menu").outerHeight());
}

if ($(".shortcut>div").length) {
// get an array of all element heights
var elementHeights: HTMLElement[] = $(".shortcut>div").map(function (): number {
return $(this).outerHeight();
}).get();
}

if (site.scrollChanged) {
site.checkScroll();
site.scrollChanged = false;
}
};

ResizeTiles = (): void => {
var currentTallest = 0,
currentRowStart = 0,
rowDivs = new Array<JQuery>(),
$el: JQuery,
topPosition = 0;

$(".shortcut").each((index, element) => {
$el = $(element);
$($el).height("auto");
topPosition = $el.position().top;
if (currentRowStart < topPosition - 1 || currentRowStart > topPosition + 1) {
for (let currentDiv = 0; currentDiv < rowDivs.length; currentDiv++) {
rowDivs[currentDiv].height(currentTallest);
}
rowDivs = [];
currentRowStart = topPosition;
currentTallest = $el.height();
rowDivs.push($el);
} else {
rowDivs.push($el);
currentTallest = Math.max(currentTallest, $el.height());
}
});
for (let currentDiv = 0; currentDiv < rowDivs.length; currentDiv++) {
rowDivs[currentDiv].height(currentTallest);
}
};

// get a url
GetApiUrl = (controller: string, action: string): string => {
return this.BaseUrl() + "api/" + controller + "/" + action;
};

static GetUrl = (controller: string, action: string): string => {
return site.BaseUrl() + controller + "/" + action;
};

ShowMoreInfo = (): void => {
this.$showMoreInfo.modal("show");
};
// Request resource
RequestResource = (route: string, httpMethod: Models.HttpMethod, data: any, callback: Function,
loaderText: string = null, autoHideLoader: boolean = true, staticLoader: boolean = true,
errorCallback: Function = null, showError: boolean = true): JQueryXHR => {

if (loaderText) {
this.ShowLoader(loaderText, staticLoader);
}
//Based on the http method we need to change the data going into the request
var requestData: any;
switch (httpMethod) {
case Models.HttpMethod.PATCH:
requestData = ko.toJSON(data);
break;
case Models.HttpMethod.POST:
requestData = ko.toJSON(data);
break;
case Models.HttpMethod.PUT:
requestData = ko.toJSON(data);
break;
case Models.HttpMethod.DELETE:
requestData = ko.toJSON(data);
break;
default:
requestData = data;
break;
}

var result = $.ajax({
url: route,
type: Models.HttpMethod[httpMethod],
data: requestData,
contentType: "application/json"
});

this.currentRequest = result;

result.done((result: any, textStatus: string, jqXHR: JQueryXHR): void => {
this.HandleResult(jqXHR, result, callback);
}).fail((jqXHR: JQueryXHR, textStatus: string): void => {
if (jqXHR.status !== 0 && jqXHR.statusText !== "abort") {
if (jqXHR.status === 422) {
this.HandleValidationErrors(jqXHR.responseJSON, showError);
} else if (jqXHR.status === 401) {
this.HandleNotAuthorisedError();
}
else {
this.HandleError(GDD.Models.SerializableException.fromFailedPromise(jqXHR, textStatus), showError);
}
if (errorCallback) {
errorCallback();
}
}
}).always((): void => {
if (autoHideLoader) {
this.HideLoader();
}
this.currentRequest = null;
});

return result;
};

// remote call handler
HandleResult = (jqXHR: JQueryXHR, response: any, callback: Function, clearValidation: boolean = true): void => {
if (clearValidation) {
this.ValidationItems(new Models.ModelState());
}
if (response && response.Result && response.Result.hasOwnProperty("Url")) {
this.ShowLoader("Reloading...", true);
window.location.replace(response.Result.Url);
} else {
if (callback) {
callback(response);
}
}
};

// error handler
HandleError = (error: Models.SerializableException, showError: boolean = true): void => {
this.Exception(error);
this.HideLoader();
            if (showError) {
                this.openModal = $(".modal:visible:not([id='loadModal'])").length
                    ? $(".modal:visible")
                    : null;
                if (this.openModal !== null) this.openModal.modal("hide");
this.$exceptionModal.modal("show");
this.checkZIndex(site.$exceptionModal);
}
        };

        HideError = (): void => {
            this.$exceptionModal.modal("hide");
            if (this.openModal !== null) this.openModal.modal("show");
            this.openModal = null;
        };

// error handler
HandleNotAuthorisedError = (): void => {
this.HideLoader();
this.$cwsTimeoutModal.modal("show");
this.checkZIndex(site.$cwsTimeoutModal);
};

// validation handler
HandleValidationErrors = (response: Models.ModelStateJS, showError: boolean): void => {

if (response) {
this.ValidationItems(new Models.ModelState(response));
}

if (showError) {
var openRightPanels: JQuery = $(".mm-menu.mm-right.mm-opened").not("#validation-panel");
var closedPanelCount: number = -1;

if (openRightPanels.length > 0) {
openRightPanels.each((index: number, elem: Element) => {
var api: any = $(elem).data("mmenu");
api.bind("close", () => {
closedPanelCount += 1;
if (closedPanelCount === openRightPanels.length - 1) {
setTimeout(() => {
this.$validationPanel.data("mmenu").open();
}, 500);
}
});
$(elem).data("mmenu").close();
});
} else if (!$("#validation-panel").hasClass(".mm-opened")) {
this.$validationPanel.data("mmenu").open();
}
}
};

// reloads the page
ReloadPage = (): void => {
location.reload(true);
};

// ensure a string is a property name of an object
static NameOf = <T>(name: keyof T) => name;

// displays the loader
ShowLoader = (text: string, isStatic: boolean = true): void => {
site.LoaderText(text);
site.LoaderStatic(isStatic);
site.$loadModal.modal("show");
this.checkZIndex(site.$loadModal);
};

// hides the loader
HideLoader = (): void => {
site.$loadModal.modal("hide");
};

ShowCancelConfirm = (message: string, confirmButtonText: string, cancelButtonText: string, modalTitleText: string, confirmButtonCallBack: any, cancelButtonCallBack?: any): void => {
site.CancelConfirmViewModel().Message(message);
site.CancelConfirmViewModel().CancelButtonText(cancelButtonText);
site.CancelConfirmViewModel().ConfirmButtonText(confirmButtonText);
site.CancelConfirmViewModel().ModalTitle(modalTitleText);
if (cancelButtonCallBack)
site.CancelConfirmViewModel().CancelCallBack = cancelButtonCallBack;
site.CancelConfirmViewModel().ConfirmCallBack = confirmButtonCallBack;
site.$cancelConfirmModal.modal("show");
this.checkZIndex(site.$cancelConfirmModal);
};

// displays the action bar
ShowActionBar = (): void => {
if ($("#action-menu").hasClass("hidden")) {
$("#action-menu").removeClass("hidden");
$("#content>div.container-fluid").addClass("action-bar");
}
};

// hides the action bar
HideActionBar = (): void => {
if (!$("#action-menu").hasClass("hidden")) {
$("#action-menu").addClass("hidden");
$("#content>div.container-fluid").removeClass("action-bar");
}
};

GetNotification(): kendo.ui.Notification {
if (this.notification == null) {
this.notification = $("#notification").kendoNotification({
position: {
bottom: 0,
right: 0
},
stacking: "up",
autoHideAfter: 5000,
animation: {
open: {
effects: "slideIn:left"
},
close: {
effects: "slideIn:left",
reverse: true
}
},
width: 300,
templates: [{
type: "info",
template: "<div class='k-notification-wrap'><div style='word-wrap: break-word;white-space: normal;'><span class='glyphicon glyphicon-info-sign'></span> #= myMessage #</div></div>"
},
{
type: "success",
template: "<div class='k-notification-wrap'><div style='word-wrap: break-word;white-space: normal;'><span class='glyphicon glyphicon-ok-circle'></span> #= myMessage #</div></div>"
},
{
type: "warning",
template: "<div class='k-notification-wrap'><div style='word-wrap: break-word;white-space: normal;'><span class='glyphicon glyphicon-alert'></span> #= myMessage #</div></div>"
},
{
type: "error",
template: "<div class='k-notification-wrap'><div style='word-wrap: break-word;white-space: normal;'><span class='glyphicon glyphicon-exclamation-sign'></span> #= myMessage #</div></div>"
}]
}).data("kendoNotification");
}
return this.notification;
}

// notifications
InfoNotify: (data: any) => void = (data: any) => {
this.GetNotification().info(() => { return { myMessage: data }; });
};
SuccessNotify: (data: any) => void = (data: any) => {
this.GetNotification().success(() => { return { myMessage: data }; });
};
WarningNotify: (data: any) => void = (data: any) => {
this.GetNotification().warning(() => { return { myMessage: data }; });
};
ErrorNotify: (data: any) => void = (data: any) => {
this.GetNotification().error(() => { return { myMessage: data }; });
};

BuildCustomApiUri = (route: string, routeData?: any[]): string => {

if (routeData) {
for (let i = 0; i < routeData.length; i++) {
//replace the route parameters with route data
route = route.replace("{" + i + "}", routeData[i]);
}
}

return this.BaseUrl() + "api/" + route;
};
BuildCustomUri = (route: string, routeData?: any[]): string => {

if (routeData) {
for (let i = 0; i < routeData.length; i++) {
//replace the route parameters with route data
route = route.replace("{" + i + "}", routeData[i]);
}
}
return this.BaseUrl() + route;
};

HideLeftMenu = (): void => {
// add transition classes
$(".left-menu").addClass("left-menu-transition");
$(".left-menu-content").addClass("left-menu-content-transition");
// collapse the menu
$(".left-menu").addClass("left-menu-collapse");
$(".left-menu-content").addClass("left-menu-content-collapse");
// after the menu is collapsed, remove the transition classes
// prevents unwanted transitions when resizing the window
setTimeout(() => {
$(".left-menu").removeClass("left-menu-transition");
$(".left-menu-content").removeClass("left-menu-content-transition");
this.LeftMenuOpen(false);
}, 500);
};

ShowLeftMenu = (): void => {
// add transition classes
$(".left-menu").addClass("left-menu-transition");
$(".left-menu-content").addClass("left-menu-content-transition");
// show the menu
$(".left-menu-content").removeClass("left-menu-content-collapse");
$(".left-menu").removeClass("left-menu-collapse");
// after the menu is opened, remove the transition classes
// prevents unwanted transitions when resizing the window
setTimeout(() => {
$(".left-menu").removeClass("left-menu-transition");
$(".left-menu-content").removeClass("left-menu-content-transition");
}, 500);
this.LeftMenuOpen(true);
};
SwitchUserRoleTo = (accessRole: number): void => {
site.RequestResource(
site.BuildCustomUri("UserRoles/SwitchUserRole/{0}", [accessRole]),
Models.HttpMethod.PUT,
null,
this.SwitchUserCallback,
null,
true);
};
SwitchUserCallback = (result: boolean): void => {
if (result)
location.reload(true);
};

// kendo tree view multi select
        TreeViewShiftStart = ko.observable<JQuery>(null);
        TreeViewShiftEnd = ko.observable<JQuery>(null);
TreeViewItemSelectionClass = ko.observable<string>("selected-node");

        ClearTreeViewSelection = (treeViewSelector: JQuery): void => {
            this.GetSelectedTreeViewItems(treeViewSelector).removeClass(this.TreeViewItemSelectionClass());
};

GetSelectedTreeViewItems = (treeViewSelector: JQuery): JQuery => {
return treeViewSelector.find(`.${this.TreeViewItemSelectionClass()}`);
};

        GetSelectedTreeViewModels = (treeViewSelector: JQuery): Array<any> => {
            var selectedItems = this.GetSelectedTreeViewItems(treeViewSelector);
var selectedModels = new Array<any>();
selectedItems.each((index: number, elem: Element): void => {
selectedModels.push(ko.dataFor($(elem).closest(".k-item")[0]));
});
return selectedModels;
};

SelectTreeViewNode = (event: kendo.ui.TreeViewSelectEvent, ctrlKey: boolean = false, shiftKey: boolean = false): void => {
event.preventDefault();
const selectorClass = this.TreeViewItemSelectionClass();
            var node = $(event.node).closest(".k-item");
    const treeView = $(event.node).closest(".k-treeview");
            // if the shift key was not pressed and a node is not being deselected or the last node is not currently stored
            if (!this.TreeViewShiftStart() ||
                (!shiftKey &&
                    (!ctrlKey || (ctrlKey && !node.hasClass(selectorClass))))) {
        // store the last node that was clicked on
        this.TreeViewShiftStart(node);
        this.TreeViewShiftEnd(null);
    }
    if (ctrlKey) {
                // toggle selection
                if (node.is(`.${selectorClass}`)) node.removeClass(selectorClass);
                else node.addClass(selectorClass);
                // deselect all parents
                node.parentsUntil(".k-treeview", ".k-item").removeClass(selectorClass);
                // deselect all children, no point as parent is selected
                node.find(".k-item").removeClass(selectorClass);
            } else if (shiftKey) {
                const selectedItems = this.GetSelectedTreeViewItems(treeView);
                const allSiblings = $(node).siblings().addBack();
                const isSibling = allSiblings.is(node) && allSiblings.is(this.TreeViewShiftStart());
                if (!selectedItems.length || !isSibling) {
                    // single selection
                    this.ClearTreeViewSelection(treeView);
                    this.TreeViewShiftStart(node);
                    this.TreeViewShiftEnd(null);
                    node.addClass(selectorClass);
                } else {
                    // if a previous shift operation was done
                    if (this.TreeViewShiftEnd()) {
                        // deselect previous shift selection
                        this.SelectTreeViewRange(false, allSiblings);
                    }
                    // select range
                    this.TreeViewShiftEnd(node);
                    this.SelectTreeViewRange(true, allSiblings);
                }
            } else {
                this.ClearTreeViewSelection(treeView);
                node.addClass(selectorClass);
            }
// remove default class
setTimeout((): void => {
$(event.node).find(".k-state-focused").removeClass("k-state-focused");
});
        };

        SelectTreeViewRange = (select: boolean, allSiblings: JQuery) => {
            const startIndex = allSiblings.index(this.TreeViewShiftStart());
            const stopIndex = allSiblings.index(this.TreeViewShiftEnd());
            if (startIndex >= stopIndex)
                for (let i = stopIndex; i <= startIndex; i++) {
                    if (select) $(allSiblings[i]).addClass(this.TreeViewItemSelectionClass());
                    else $(allSiblings[i]).removeClass(this.TreeViewItemSelectionClass());
                }
            else
                for (let i = startIndex; i <= stopIndex; i++) {
                    if (select) $(allSiblings[i]).addClass(this.TreeViewItemSelectionClass());
                    else $(allSiblings[i]).removeClass(this.TreeViewItemSelectionClass());
                }
        };
    }
}