Wednesday, December 4, 2024

How to set Custom Filter Menu Components in angular 17 with Kendo UI

 Dear Reader, 

if you want to set menu filter Kendo UI with angular then it very useful tips.

 for example when you are using  <kendo-grid></kendo-grid> so you have to follow below steps for filter the menu.



on UI Component

<kendo-grid
[data]="gridDataSource$ | async"
filterable="menu"
(dataStateChange)="dataStateChange($event)">  
<kendo-grid-column field="productName" title="Product Name" width="150">
</kendo-grid-column>
</kendo-grid>



and My TS code are as below
import { process, State } from '@progress/kendo-data-query';

export class DataComponent implements OnInit {
  skip = 0;
  public state: State = {
    skip: 0,
    take: 10,
    filter: {
      logic: 'and',
      filters: []
    }
  };
dataStateChange(state: DataStateChangeEvent): void {
    this.state = state;
    this.loadData();
  }

  private loadData(): void {
    this.gridDataSource$ = this.gridDataSubject.asObservable().pipe(
      map(gridDataResult => process(gridDataResult.data, this.state))
    );
  }

}

Thank you Hope it is helpful to you ! Happy learning.

Wednesday, November 20, 2024

Upgrade braces from 3.0.2 to 3.0.3 to fix the vulnerability.

if you are working in angular with good MNC company so you have audit issue , how to fix the audit issue regarding the below issue.

Recommendation

Upgrade braces from 3.0.2 to 3.0.3 to fix the vulnerability.


Description

The NPM package braces fails to limit the number of characters it can handle, which could lead to Memory Exhaustion. In lib/parse.js, if a malicious user sends "imbalanced braces" as input, the parsing will enter a loop, which will cause the program to start allocating heap memory without freeing it at any moment of the loop. Eventually, the JavaScript heap limit is reached, and the program will crash.


How to Fix it , it is very simple :-

If you are using NPM 6 or above, you can run npm audit fix on your local machine to fix vulnerabilities. For more info, please visit https://docs.npmjs.com/cli/audit


Hope it is help you, Happy Learning! ....

Monday, October 7, 2024

How to change datetime2 data type to INT

 Dear Friend,

i am come with new solution if you stuck some place your are not able to  ALTER COLUMN the column if column data type is datetime2  so without delayed below is solution.

if you tried with normal query just like ALTER TABLE table ALTER COLUMN [Period] int; 

The Error is :- Operand type clash: datetime2 is incompatible with int?

The error you’re encountering indicates that the Period column currently has a datetime2 data type, and you’re trying to change it to int. Directly changing the data type from datetime2 to int is not allowed because they are incompatible types.

To resolve this, you need to follow these steps:

  1. Create a New Column:

    • Add a new column with the desired data type (int).-- Step 1: Add a new column with the desired data type
    • ALTER TABLE tableName ADD PeriodInt INT;
  2. Update the New Column:

    • Populate the new column with the converted values from the existing column.
    • -- Step 2: Update the new column with converted values
      UPDATE tableName 
      SET PeriodInt
      = YEAR(Period) * 100 + MONTH(Period);
  3. Drop the Old Column:

    • Remove the old column.
    • -- Step 3: Drop the old column
      ALTER TABLE tableName 
      DROP COLUMN Period;
  4. Rename the New Column:

    • Rename the new column to the original column name.
    •  Step 4: Rename the new column to the original column name
      EXEC sp_rename 'tableName 
      .PeriodInt', 'Period', 'COLUMN';



Thank you for your Time Hope it will help you

Friday, October 4, 2024

Kendo-Grid checkbox selected value update on database - step 1 How to do settings on Child component.

 Dear Reader,

This is a very important topic because developers are often confused about how to manage checkbox checked and unchecked values, and how to update multiple records with one click. First, I will explain how to set up the settings in the child component, which you can then use across multiple components. Here is my Child-Grid

<kendo-grid
  [data]="gridDataResult"
  (dataStateChange)="onDataStateChange($event)"
  (edit)="onEdit($event)"
  [selectable]="{ mode: 'multiple', checkboxOnly: true }"
  kendoGridSelectBy="id"
  [(selectedKeys)]="selectedKeys"
  (selectionChange)="onSelectionChange($event)"
  (selectedKeysChange)="onSelectedKeysChange()"
>
  <ng-template kendoGridToolbarTemplate>
    <button kendoGridAddCommand *ngIf="gridSetting.enableAdd">{{ gridSetting.addCommandTxt }}</button> 
    <button type="button" *ngIf="gridSetting.enableExport" kendoGridExcelCommand>Export to Excel</button> 
    <button kendoButton *ngIf="gridSetting.enableSave" (click)="onUpdateSelected()">Submit Selected Entry</button>
  </ng-template>

  <!-- Move the checkbox column to the first position -->
  <kendo-grid-checkbox-column *ngIf="showCheckbox" [showSelectAll]="true" [width]="50"></kendo-grid-checkbox-column>

  <kendo-grid-command-column
    [title]="gridSetting.commandColTxt"
    [width]="gridSetting.commandColWidth"
    *ngIf="gridSetting.enableEdit || gridSetting.enableRemove || gridSetting.enableDeny"
  >
    <ng-template kendoGridCellTemplate let-dataItem>
      <button kendoGridEditCommand [primary]="true" look="flat" *ngIf="gridSetting.enableEdit">
        <span class="k-icon k-i-edit" [title]="gridSetting.editCommandTxt">{{gridSetting.editCommandTxt}}</span>
      </button>
      <button kendoGridEditCommand [primary]="true" look="flat" *ngIf="gridSetting.enableDeny">
        <span class="k-icon k-i-edit" [title]="gridSetting.denyCommandTxt">{{gridSetting.denyCommandTxt}}</span>
      </button>
      <button
        kendoGridRemoveCommand
        *ngIf="gridSetting.enableRemove && (dataItem[gridSetting.activeFlagField] || gridSetting.activeFlagField === undefined)"
      >
        {{ gridSetting.removeCommandTxt }}
      </button>
    </ng-template>
  </kendo-grid-command-column>

  <kendo-grid-column
    *ngFor="let column of columns"
    [hidden]="column.type === ColumnTypeEnum.Hidden"
    [field]="column.displayField === undefined ? column.field : column.displayField"
    [title]="column.title"
    [format]="column.format"
    [filter]="column.filterType"
    [width]="column.width"
  >
    <ng-template kendoGridCellTemplate let-dataItem let-data *ngIf="column.type === ColumnTypeEnum.Checkbox">
      <input
       [state]="selectAllState"
       kendoGridSelectAllCheckbox
       (selectAllChanges)="onSelectAllChanges($event)"
        type="checkbox"
        kendoCheckBox
        disabled
        [attr.checked]="
          dataItem[column.displayField === undefined ? column.field.toString() : column.displayField.toString()] ? 'checked' : null
        "
      />
    </ng-template>
  </kendo-grid-column>

  <kendo-grid-excel [fileName]="gridSetting.exportFileName"></kendo-grid-excel>
</kendo-grid>


My Ts file 


@Component({
  selector: 'app-shared-common-grid',
  templateUrl: './common-grid.component.html',
  styleUrls: ['./common-grid.component.scss']
})
export class CommonGridComponent extends BaseGridComponent implements OnInit {
 
  @Input() showCheckbox: boolean = true;
  @Input() set gridDataSource$(input$: Observable<GridDataResult>) {
    if (input$) {
      this.gridData$ = input$;
      this.refreshGridData();
    }
  }
  @Input() private saveSuccess: EventEmitter<any>;

  @Output() selectionChange: EventEmitter<SelectionEvent> = new EventEmitter<SelectionEvent>();
  @Output() selectAllChanges: EventEmitter<SelectAllCheckboxState> = new EventEmitter<SelectAllCheckboxState>();
  @Output() selectedKeysChange: EventEmitter<void> = new EventEmitter<void>();
  @Output() loadingStateChange: EventEmitter<boolean> = new EventEmitter<boolean>();
  loading: false;
 
  selectedRecords: Array<any> = [];
  public selectAllState: SelectAllCheckboxState = "unchecked";
  public selectedKeys: Array<number> = [];
  constructor() {
    super();
  }

 
  onSelectionChange(e: SelectionEvent): void {
    this.selectionChange.emit(e);
  }

  onSelectAllChanges(checkedState: SelectAllCheckboxState): void {
    this.selectAllChanges.emit(checkedState);
  }

  onSelectedKeysChange(): void {
    this.selectedKeysChange.emit();
  }

 
}

Now My Parent code is as below :

<app-shared-common-grid
    [columns]="columns"
    [gridLoading]="loading"
    [gridSubmitting]="submitting"
    [gridDataSource$]="gridDataSource$"
    [gridSetting]="gridSetting"
    [saveSuccess]="saveSuccess"
    [showCheckbox]="true"
    (updateSelectedRecords)="onUpdateSelectedRecords($event)"
    (editClicked)="onEditClicked($event)"
    (selectionChange)="handleSelectionChange($event)"
    (selectAllChanges)="handleSelectAllChanges($event)"
    (selectedKeysChange)="handleSelectedKeysChange()"  
  ></app-shared-common-grid>

My Parent TS


@Component({
  selector: 'app-sample-submit-list',
  templateUrl: './submit-list.component.html'
})
export class SubmitListComponent implements OnInit {
  form: FormGroup;
  dropdownLoading = true;
  productControl: FormControl;
  loading = false;
  submitting: boolean;
  columns: ColumnSetting[];
  gridSetting: GridSetting;
  gridDataSource$: Observable<GridDataResult>;
  private gridDataSubject = new BehaviorSubject<GridDataResult>({ data: [], total: 0 });
  saveSuccess: EventEmitter<any> = new EventEmitter();
  hasData$: Observable<boolean>;
  ApproverDataSource$: Observable<Approver[]>;
  selectedKeys: any[] = [];
  selectedRecords: any[] = [];
  public mySelection: number[] = [];
  selectAllState: SelectAllCheckboxState = "unchecked";
  constructor(
  ) {
   
  }
  ngOnInit(): void
  }

  handleSelectionChange(event: SelectionEvent) {
    // Handle selection change event
    console.log('Parent component selection change:', event);
    if (event.selectedRows && event.selectedRows.length > 0) {
      event.selectedRows.forEach(row => {
        if (!this.selectedRecords.some(record => record.id === row.dataItem.id)) {
          this.selectedRecords.push(row.dataItem);
        }
      });
    }

    if (event.deselectedRows && event.deselectedRows.length > 0) {
      const deselectedIds = event.deselectedRows.map(row => row.dataItem.id);
      this.selectedRecords = this.selectedRecords.filter(record => !deselectedIds.includes(record.id));
    }

    this.selectedKeys = this.selectedRecords.map(record => record.id);
  }


  handleSelectAllChanges(checkedState: SelectAllCheckboxState) {
    // Handle select all changes event
    console.log('Parent component select all changes:', checkedState);
    if (checkedState === 'checked') {
      this.gridDataSource$.subscribe(data => {
        this.selectedRecords = data.data.filter(record => record.isChecked);
        this.selectedKeys = this.selectedRecords.map(record => record.id);
      });
    } else {
      this.selectedRecords = [];
      this.selectedKeys = [];
    }
  }

  handleSelectedKeysChange() {
    // Handle selected keys change event
    console.log('Parent component selected keys change');
    const len = this.selectedKeys.length;
    this.gridDataSource$.subscribe(data => {
      const gridDataLength = data.data.length;
      if (len === 0) {
        this.selectAllState = 'unchecked';
      } else if (len > 0 && len < gridDataLength) {
        this.selectAllState = 'indeterminate';
      } else {
        this.selectAllState = 'checked';
      }
    });
  }

  handleLoadingStateChange(isLoading: boolean) {
    // Handle loading state change
    this.loading = isLoading;
  }


  onUpdateSelectedRecords(selectedRecords: any[]): void {
    if (this.selectedKeys.length > 0) {
      this.submitting = true; // Activate the loader
      this.serviceforUpdate.updateRecords(this.selectedKeys).subscribe(
        res => {
          console.log('Selected records updated successfully.');
          this.notifyResult(res);
        },
        error => {
          console.error('Error updating records:', error);
          this.notifyResult({ viewStatus: ViewStatus.Failure, message: 'Error updating records' });
          this.submitting = false;
        }
      );
    } else {
      console.log('No records selected.');
    }
  }

 
}

Here is the full code. I hope it helps you. Thank you, Guru (Mr. Surendra), for explaining all the concepts.

Wednesday, September 25, 2024

How do we retrieve values from a Azure key vault?

Dear developers new to Azure Key Vault, if you want to retrieve secrets from the Azure environment, you're in the right place. Without wasting any time, I'll explain the steps to you, step by step.

Step 1 :- Hopefully, you know how to create a Key Vault. If not, here’s how to do it: quick 

Step 2 :- You need to configure the URL in your appsetting file : https://contoso-vault2.vault.azure.net/

Note:- Kindly use your Azure Key Vault URL, and make sure to apply your development settings in the local environment.

appsettings.json

"Setting": {

  "EnableKeyVaultCache": true,

  "KeyVaultUri": "https://test.vault.azure.net/",

 },

Create Interface 

public interface IKeyVaultService

{

    string GetSecret(string secretName);

    Task<(string, bool)> TryGetSecretAsync(string secretName);

}

Service code:-

namespace KeyVault

{

    public class KeyVaultService : IKeyVaultService

    {

        private readonly bool _enableCache = false;

        private readonly string _uri;

        private readonly IDictionary<string, string> _table = new Dictionary<string, string>();



        public KeyVaultService(IConfiguration config)

        {

            _enableCache = config.GetValue<bool>("Setting:EnableKeyVaultCache");

            _uri = config.GetValue<string>("Setting:KeyVaultUri");

        }


        /// <summary>

        /// Get secret value from Azure Key Vault.

        /// </summary>

        /// <param name="secretName"></param>

        /// <returns></returns>

        public string GetSecret(string secretName)

        {

            if (_enableCache && _table.ContainsKey(secretName))

            {

                return _table[secretName];

            }

            else

            {

                var client = new SecretClient(new Uri(_uri), new DefaultAzureCredential());

                var secret = client.GetSecretAsync(secretName).GetAwaiter().GetResult().Value;


                if (_enableCache)

                {

                    _table.Add(secretName, secret.Value);

                }


                return secret.Value;

            }

        }


        /// <summary>

        /// Tries to read a secret's value from Azure Key Vault with that secret's name.

        /// </summary>

        /// <param name="secretName"></param>

        /// <remarks>

        /// This method does not throw exception when a secret does not exist in Key Vault.

        /// </remarks>

        /// <returns>

        /// This method returns a tuple which includes an boolean value and a string. 

        /// When there's no exception, the boolean value is true; 

        /// otherwise the boolean value is false. 

        /// </returns>

        public async Task<(string, bool)> TryGetSecretAsync(string secretName)

        {

            try

            {

                if (_enableCache && _table.ContainsKey(secretName))

                {

                    return (_table[secretName], true);

                }

                else

                {

                    var client = new SecretClient(new Uri(_uri), new DefaultAzureCredential());

                    var secret = await client.GetSecretAsync(secretName);


                    string secretValue = secret.Value.Value;


                    if (_enableCache)

                    {

                        _table[secretName] = secretValue;

                    }


                    return (secretValue, true);

                }

            }

            catch (Exception e)

            {

                ExceptionManager.HandleException(e);

                return (null, false);

            }

        

        }

    }

}

How to inject the service in controller.
 private readonly IKeyVaultService _keyVaultService;
 public GraphMailService(IConfiguration config, IKeyVaultService keyVaultService)
 {
     _keyVaultService = keyVaultService;
     _config = config;
 }

private string GetSecret(string secretName)
{
    return _keyVaultService.GetSecret(secretName);
}

user The service inside the method.
 public async Task SendEmailAsync(Message mail)
 {
     string tenantId = GetSecret("TenantID");
     string clientId = GetSecret("ClientID");
     string clientSecret = GetSecret("Secret");
     string userName = GetSecret("UserName");
}

Thank you ! Hope it is help you 



Friday, September 20, 2024

Send email using graph api if multi-factor authentication is enable using Function Account

 

If you are new to Graph API and want to send an email, then you are in the right place. If your account has multi-factor authentication disabled, just like a noreply account, let’s not waste any time and start coding. Please note, I am using Graph API version 5.56. So, let’s go! 

1st create interface

public interface IGraphMailService

{

 Task SendMailAsync(string fromAddress,string toAddress, string subject, string content, string ccEmail);

}

Service code 

using Azure.Identity;

using Dow.Mjeapi.Biz.Interfaces;

using Dow.Mjeapi.Data.Models;

using Microsoft.Extensions.Configuration;

using Microsoft.Graph;

using Microsoft.Graph.Me.SendMail;

using Microsoft.Graph.Models;

using Microsoft.Identity.Client;

using System;

using System.Collections.Generic;

using System.Threading.Tasks;

using static System.Formats.Asn1.AsnWriter;

namespace 

{

    public class GraphMailService : IGraphMailService

    {

        private readonly IConfiguration _config;

        private const string TenantId = "TenantId ";

        private const string ClientId = "ClientId "; 

        private static string[] scopes = new string[] { "https://graph.microsoft.com/.default" };

        private const string ClientSecret = "YOURClientSecret ";

        public GraphMailService(IConfiguration config)

        {

            _config = config;

        }

        private static IPublicClientApplication CreatePublicClientApplication()

        {

            return PublicClientApplicationBuilder.Create(ClientId)

                .WithAuthority(AzureCloudInstance.AzurePublic, TenantId)

                .WithDefaultRedirectUri()

                .Build();

        }

        public async Task SendMailAsync( string fromAddress,string toAddress, string subject, string content, string ccEmail)

    {

        try

        {

            string? tenantId = _config[TenantId];

            string? clientId = _config[ClientId];

            string? userName =  _config[UserName];

            string? password = _config[Password];


            var scopes = new[] { "https://graph.microsoft.com/.default" };


            var usernamePasswordCredential = new UsernamePasswordCredential(userName, password, tenantId, clientId);


            var graphClient = new GraphServiceClient(usernamePasswordCredential, scopes);


            var message = new Message

            {

                Subject = subject,

                Body = new ItemBody

                {

                    ContentType = BodyType.Text,

                    Content = content

                },

                ToRecipients = new List<Recipient>

                {

                    new Recipient

                    {

                        EmailAddress = new EmailAddress

                        {

                            Address = toAddress

                        }

                    }

                },

                CcRecipients = new List<Recipient>

                {

                    new Recipient

                    {

                        EmailAddress = new EmailAddress

                        {

                            Address = ccEmail

                        }

                    }

                }

                //,

                //BccRecipients = new List<Recipient>

                //{

                //    new Recipient

                //    {

                //        EmailAddress = new EmailAddress

                //        {

                //            Address = bccEmail

                //        }

                //    }

                //}

            };


            var sendMailRequestBody = new Microsoft.Graph.Me.SendMail.SendMailPostRequestBody

            {

                Message = message,

                SaveToSentItems = true

            };


            await graphClient.Me.SendMail.PostAsync(sendMailRequestBody);


            

            Console.WriteLine("Email sent successfully");

        }

        catch (Exception ex)

        {

            Console.WriteLine($"An error occurred: {ex.Message}");

        }

    }

and Controller code 

using Microsoft.AspNetCore.Mvc;

using System.Threading.Tasks;

using System;

using Microsoft.AspNetCore.Authorization;


namespace ANCD.Test.Controllers

{

    [ApiController]

    [Route("api/[controller]")]

    [Authorize]

    public class EmailController : ControllerBase

    {

        private readonly IGraphMailService _graphMailService;


        public EmailController(IGraphMailService graphMailService)

        {

            _graphMailService = graphMailService;

        }

        [HttpPost("send")]

        public async Task<IActionResult> SendMail([FromBody] MailRequestNew mailRequest)

        {

            if (mailRequest == null || string.IsNullOrEmpty(mailRequest.FromAddress) || string.IsNullOrEmpty(mailRequest.ToAddress) || string.IsNullOrEmpty(mailRequest.Subject) || string.IsNullOrEmpty(mailRequest.Content))

            {

                return BadRequest("Invalid mail request.");

            }


            try

            {

                await _graphMailService.SendMailAsync(mailRequest.FromAddress, mailRequest.ToAddress, mailRequest.Subject, mailRequest.Content, mailRequest.CcEmail);

                return Ok("Mail sent successfully.");

            }

            catch (Exception ex)

            {

                return StatusCode(500, $"Internal server error: {ex.Message}");

            }

        }


    }


    public class MailRequestNew

    {

        public string FromAddress { get; set; }

        public string ToAddress { get; set; }

        public string Subject { get; set; }

        public string Content { get; set; }

        public string CcEmail { get; set; }

    }


}

 adjust the azure permission  if your are issue to send email these code is tested from my end  Thank you.

Happy codding


Send email using graph api if multi-factor authentication is disable

If you are new to Graph API and want to send an email, then you are in the right place. If your account has multi-factor authentication disabled, just like a noreply account, let’s not waste any time and start coding. Please note, I am using Graph API version 5.56. So, let’s go! 

1st create interface

public interface IGraphMailService

{

  Task SendEmailAsync(Message mail);

}

Service code 

using Azure.Identity;

using Dow.Mjeapi.Biz.Interfaces;

using Dow.Mjeapi.Data.Models;

using Microsoft.Extensions.Configuration;

using Microsoft.Graph;

using Microsoft.Graph.Me.SendMail;

using Microsoft.Graph.Models;

using Microsoft.Identity.Client;

using System;

using System.Collections.Generic;

using System.Threading.Tasks;

using static System.Formats.Asn1.AsnWriter;

namespace 

{

    public class GraphMailService : IGraphMailService

    {

        private readonly IConfiguration _config;

        private const string TenantId = "TenantId ";

        private const string ClientId = "ClientId "; 

        private static string[] scopes = new string[] { "https://graph.microsoft.com/.default" };

        private const string ClientSecret = "YOURClientSecret ";

        public GraphMailService(IConfiguration config)

        {

            _config = config;

        }

        private static IPublicClientApplication CreatePublicClientApplication()

        {

            return PublicClientApplicationBuilder.Create(ClientId)

                .WithAuthority(AzureCloudInstance.AzurePublic, TenantId)

                .WithDefaultRedirectUri()

                .Build();

        }

        public async Task SendEmailAsync(Message mail)

        {

            var clientSecretCredential = new ClientSecretCredential(TenantId, ClientId, ClientSecret);

var graphClient = new GraphServiceClient(clientSecretCredential, scopes);

var sendMailBody = new Microsoft.Graph.Users.Item.SendMail.SendMailPostRequestBody

            {

                Message = mail,

                SaveToSentItems = true

            };

            try

            {

                await graphClient.Users["mjesupport@dow.com"].SendMail.PostAsync(sendMailBody);

            }

            catch (Exception e)

            {

                Console.WriteLine($"Error sending email: {e.Message}");

            }

        }   

    }

}

and Controller code 

[HttpPost("send")]

public async Task<IActionResult> SendEmail(string recipientEmail, string subject, string body)

{

    var message = CreateEmailMessage(recipientEmail, subject, body);

    await _graphMailService.SendEmailAsync(message);

    return Ok("Email sent successfully");

}

 private Message CreateEmailMessage(string recipientEmail, string subject, string body)

 {

     return new Message

     {

         Subject = subject,

         Body = new ItemBody

         {

             ContentType = BodyType.Text,

             Content = body

         },

         ToRecipients = new List<Recipient>

     {

         new Recipient

         {

             EmailAddress = new EmailAddress

             {

                 Address = recipientEmail

             }

         }

     }

     };

 } adjust the azure permission if your are issue to send email these code is tested from my end  Thank you.

Happy codding


Tuesday, July 23, 2024

https://login.microsoftonline.com/c3e32f53-cb7f-4809-968d-1cc4ccc785fe/oauth2/v2.0/token error in angular 17

 Dear Friend,

If you are working on a single-page application using MSAL Angular, I am 100% sure you have encountered this error in your app.

Let’s cut to the chase; here is the solution to fix it. But before we get to the solution, let’s understand what the error is.



 

The error appears to be the same; the issue arises after login, when it redirects to a URL that is not available or accessible.
The solution is 

{
 
  "msalConfig": {
    "auth": {
      "clientId": "abcs",
      "authority": "https://login.microsoftonline.com/",
      "redirectUri": "https://127.0.0.1:8007" //https://localhost:8007
    }
}

Change this url "redirectUri": "https://127.0.0.1:8007" to https://localhost:8007

Thank you, Hope it will help you