рдЖрдзреЗ рдШрдВрдЯреЗ рдореЗрдВ рдХрд╛рдирдмрди

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдореИрдВ рд▓реЗрдЦ рдХреЗ рд▓рдХреНрд╖рд┐рдд рджрд░реНрд╢рдХреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдХреЗ рд╢реБрд░реВ рдХрд░реВрдВрдЧрд╛ред рдпрд╣ рд▓реЗрдЦ рдХрдиреНрдирди рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИред рдпрд╣ рд▓реЗрдЦ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рд╣реИ рдЬреЛ рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕ рддрдХрдиреАрдХ рдХреЗ рд╕рд╛рде рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рд╣реИ рдФрд░ рдЬрд▓реНрджреА рд╕реЗ рдФрд░ рдмрд┐рдирд╛ рдХрд┐рд╕реА рдЦрд░реНрдЪ рдХреЗ рдПрдХ рдЙрдкрдХрд░рдг рдмрдирд╛рдирд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдХрд╛рдирдмрди рдмреЛрд░реНрдб рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░рдиреЗ рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░рд╛ рдмрдЬрдЯ рдиреНрдпреВрдирддрдо рд╣реИ, рдпрджрд┐ рд╢реВрдиреНрдп рдирд╣реАрдВ рд╣реИ, рддреЛ рд╣рдо рдиреНрдпреВрдирддрдо рд╕рд╛рдзрдиреЛрдВ рдХреЗ рд╕рд╛рде рд╕рдм рдХреБрдЫ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВрдЧреЗред рд╣рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдбреЗрдЯрд╛рдмреЗрд╕, рдПрдХ рд╡реНрд╣рд╛рдЗрдЯрдмреЛрд░реНрдб рд╡рд┐рдЬрд╝реБрдЕрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдЯреВрд▓ рдФрд░ рджреЛ рдлрд╝рдВрдХреНрд╢рди рдЪрд╛рд╣рд┐рдП:

  • рдПрдХ рдХрд╛рд░реНрдб рдмрдирд╛рдПрдВ;
  • рдХрд╛рд░реНрдб рдмрджрд▓реЗрдВ рдФрд░ рдЗрд╕реЗ рдкрдЯрд░рд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВред

рд╡рд┐рдХрд╛рд╕ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, HTTP рдЕрдиреБрд░реЛрдзреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдирд┐рд╖реНрдкрд╛рджрди рд╢реБрд░реВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдереЛрдбрд╝реА рджреЗрд░ рдмрд╛рдж рдореИрдВ рдПрдХ рд╡реЗрдм рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рдКрдВрдЧрд╛ рдЬрд┐рд╕реЗ рджреВрд╕рд░реЗ рд▓реЗрдЦ рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдЬрдмрдХрд┐ рд▓рд┐рдВрдХ рдЧрд╛рдпрдм рд╣реИ)ред

рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдореЗрд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЯреНрд░реИрдХреНрд╕ рдХреЗ рд╕рд╛рде рдПрдХ рдмреЛрд░реНрдб рд╣реЛрдЧрд╛ (рдЖрдк рдЕрдкрдирд╛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ):


рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд░реВрдк рдореЗрдВ, рдЖрдк рдЬреЛ рдХреБрдЫ рднреА рдЕрдкрдиреЗ рд╣рд╛рде рдореЗрдВ рд▓реЗрддреЗ рд╣реИрдВ, рдореИрдВ рдПрдордПрд╕ SQL тАЛтАЛрд▓реЗ рдЬрд╛рдКрдВрдЧрд╛ рдФрд░ рдХреЗрд╡рд▓ рдПрдХ рдЯреЗрдмрд▓ рдмрдирд╛рдКрдВрдЧрд╛ (рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЗрд╕ рддрд░рд╣ рдХреЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рдЙрджреНрдпрдо рдореЗрдВ рдШреВрдо рд░рд╣рд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдПрдХ рдЯреИрдмрд▓реЗрдЯ рд╣реЛрдиреЗ рд╕реЗ рдореМрд╕рдо рдирд╣реАрдВ рдмрдирддрд╛ рд╣реИ)

create table tasks( ID int IDENTITY(1,1) PRIMARY KEY, Project nvarchar(250) default 'Unknown', Track nvarchar(250) default 'To Do', Worker nvarchar(250) default 'Unknown', [Description] nvarchar(1000) DEFAULT '', UpdDate datetime default GETDATE(), CrtDate datetime default GETDATE() ) 

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдкрд░рд┐рднрд╛рд╖рд╛ рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдореИрдВ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╕рдВрдЦреНрдпрд╛ 1, 2, 3 рдХреЗ рдХреНрд░рдо рдореЗрдВ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдирдВрдмрд░ рджреВрдВрдЧрд╛ ... рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдкрдЯрд░рд┐рдпреЛрдВ - рдЯреНрд░реИрдХ рдореЗрдВред рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ - рдкреНрд░реЛрдЬреЗрдХреНрдЯред рдХрд▓рд╛рдХрд╛рд░ рдХреЛ рдкреНрд░реЗрд░рд┐рдд рдХрд░реЗрдВ - рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ред рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╡рд┐рд╡рд░рдг - рд╡рд┐рд╡рд░рдг, рдФрд░ рджреЛ рддрд┐рдерд┐рдпреЛрдВ рдореЗрдВ рд░рдЦреЗрдВ: рдХреНрд░реЗрдЯрдбреЗрдЯ - рдирд┐рд░реНрдорд╛рдг рддрд┐рдерд┐, рдЕрдкрдбреЗрдЯрдбреЗрдЯ - рдХрд╛рд░реНрдп рдХреЗ рдЕрдВрддрд┐рдо рдЕрдкрдбреЗрдЯ рдХреА рддрд┐рдерд┐, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рдЯреНрд░реИрдХ рдкрд░ рдЬрд╛рдирд╛ред

рд╣рдо FastReport Desktop рд░рд┐рдкреЛрд░реНрдЯ рдЬрдирд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмреЛрд░реНрдб рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВрдЧреЗред рд▓реЗрдЦ рдХреЗ рдЕрдВрдд рдореЗрдВ рдХреЛрдб рдФрд░ рд░рд┐рдкреЛрд░реНрдЯ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рд▓рд┐рдВрдХ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдбреЗрдореЛ рдореБрдлреНрдд рд╣реИ, рдРрд╕реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрд╡рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдХрд╛рдлреА рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╣реИред рддреЛ рд░рд┐рдкреЛрд░реНрдЯ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ рдбрд┐рдЬрд╛рдЗрдирд░ рдореЗрдВ рдЦреЛрд▓реЗрдВ



рд╡рд╣ рд╕рдм рдЬреЛ рдЖрдкрдХреЛ рдкрд╕рдВрдж рдирд╣реАрдВ рдерд╛, рдЕрдкрдиреЗ рд╡рд┐рд╡реЗрдХ рдкрд░ рдмрджрд▓реЗрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдирдП рдЯреНрд░реИрдХ рдЬреЛрдбрд╝реЗрдВ, рдЖрджрд┐ред рдЕрдкрдиреЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд░рд┐рдкреЛрд░реНрдЯ рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдирд╛ рдпрд╛рдж рд░рдЦреЗрдВред



рдмреЛрд░реНрдб рддреИрдпрд╛рд░ рд╣реИред рдЕрдм рдкрд╣рд▓рд╛ рдХрд╛рд░реНрдп рдмрдирд╛рдПрдБ



рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо Azure рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдПрдХ рдирдпрд╛ рд░рд┐рдХреЙрд░реНрдб рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░реЗрдЧрд╛

 #r "Newtonsoft.Json" using System.Net; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; using Newtonsoft.Json; using System.Data.SqlClient; public static async Task<IActionResult> Run(HttpRequest req, ILogger log) { log.LogInformation("Create task function processed a request."); string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); log.LogInformation($"{requestBody}"); dynamic data = JsonConvert.DeserializeObject(requestBody); string project = data?.project; if (project==null) {return new BadRequestObjectResult($"Please pass a Project in the request body");} string worker = data?.worker; if (worker==null) {return new BadRequestObjectResult($"Please pass a Worker in the request body");} string description = data?.description??""; var your_username = "ufocombat"; var your_password = "***"; using (SqlConnection conn = new SqlConnection($"Server=tcp:fast,1433;Initial Catalog=FastReportSQL;Persist Security Info=False;User ID={your_username};Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;")) { conn.Open(); SqlCommand cmd = new SqlCommand($"INSERT INTO tasks(Project,Worker,Description) VALUES (@p,@w,@d)", conn); cmd.Parameters.AddWithValue("p",project); cmd.Parameters.AddWithValue("w",worker); cmd.Parameters.AddWithValue("d",description); cmd.ExecuteNonQuery(); conn.Close(); } return new OkObjectResult($"Task created {DateTime.Now}"); } 

рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдирд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рди рднреВрд▓реЗрдВред рдХреЛрдИ рднреА рдкреНрд░реЛрдЧреНрд░рд╛рдо рдЦреЛрд▓реЗрдВ рдЬреЛ рд╡реЗрдм рдЕрдиреБрд░реЛрдз рднреЗрдЬ рд╕рдХрддрд╛ рд╣реИред рдореИрдВ рдбрд╛рдХрд┐рдпрд╛ рд▓реЗ рдЬрд╛рддрд╛ рд╣реВрдВред рд▓рд┐рдВрдХ рдХрд╛ рдкрддрд╛ рдбрд╛рд▓реЗрдВ рдФрд░ рдмреЙрдбреА рдХрд╛рд░реНрдб рдХреЛ json рдлреЙрд░реНрдореЗрдЯ рдореЗрдВ рднрд░реЗрдВред рдкреБрди: рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЕрдиреБрд░реЛрдз рд╕рд╣реЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рдо рдПрдХ рдирд┐рд╡реЗрджрди рднреЗрдЬрддреЗ рд╣реИрдВред рдпрджрд┐ рд╕рдм рдХреБрдЫ рд╕рдлрд▓ рд╣реЛрддрд╛ рд╣реИ рддреЛ рд╣рдореЗрдВ рд╕рд░реНрд╡рд░ рдкрд░ рдХрд╛рд░реНрдб рдмрдирд╛рдиреЗ рдХреА рддрд╛рд░реАрдЦ рдФрд░ рд╕рдордп рдорд┐рд▓ рдЬрд╛рддрд╛ рд╣реИред



FastReport рдореЗрдВ рд░рд┐рдкреЛрд░реНрдЯ рдЪрд▓рд╛рдПрдБ:



рдХрд╛рд░реНрдб рдмрджрд▓рдиреЗ рдпрд╛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, Azure рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдПрдВ

 #r "Newtonsoft.Json" using System.Net; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; using Newtonsoft.Json; using System.Data.SqlClient; public static async Task<IActionResult> Run(HttpRequest req, ILogger log) { log.LogInformation("Update task function processed a request."); string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); log.LogInformation($"{requestBody}"); dynamic data = JsonConvert.DeserializeObject(requestBody); string ID = data?.id; if (ID == null) {return new BadRequestObjectResult($"Please pass an ID in the request body");} string paras = "UpdDate=@u"; string description = data?.description; if (description != null) { paras += ", Description=@d"; } string track = data?.track; if (track != null) { paras += ", Track=@t"; } string worker = data?.worker; if (worker != null) { paras += ", Worker=@w"; } var your_username = "ufocombat"; var your_password = "***; if (paras!="") { using (SqlConnection conn = new SqlConnection($"Server=tcp:fast,1433;Initial Catalog=FastReportSQL;Persist Security Info=False;User ID={your_username};Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;")) { conn.Open(); SqlCommand cmd = new SqlCommand($"UPDATE tasks SET {paras} WHERE ID=@id", conn); cmd.Parameters.AddWithValue("id",ID); cmd.Parameters.AddWithValue("u",DateTime.Now.AddHours(3)); if (description != null) { cmd.Parameters.AddWithValue("d",description); } if (worker != null ) { cmd.Parameters.AddWithValue("w",worker); } if (track != null) { cmd.Parameters.AddWithValue("t",track); } cmd.ExecuteNonQuery(); conn.Close(); } } return new OkObjectResult($"Task created {DateTime.Now}"); } 

рдЗрд╕рдХреА рдорджрдж рд╕реЗ, рд╣рдо рдЯреНрд░реИрдХ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рдЖрдИрдбреА рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХрд╛рд░реНрдб рдХреЗ рдХрд┐рд╕реА рднреА рдХреНрд╖реЗрддреНрд░ рдХреЛ рдмрджрд▓ рджреЗрдВрдЧреЗред

рдХрд╛рд░реНрдб рдХреЛ рджреВрд╕рд░реЗ рдЯреНрд░реИрдХ рдкрд░ рд▓реЗ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, http рдЕрдиреБрд░реЛрдз рдкрд░ рдХреЙрд▓ рдХрд░реЗрдВ:



FastReport рд╕рдордЭрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдХрд╛рд░реНрдб рдХреЛ рд░рд┐рдкреЛрд░реНрдЯ рдореЗрдВ рдирд┐рд░реНрдорд┐рдд рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдХрд┐рд╕ рдХреЙрд▓рдо рдореЗрдВ рд░рдЦрдирд╛ рд╣реИ:

  if (string.Compare(track,"Doing",false)==0) { Shape1.Left = Units.Centimeters * 6.75F; } else if (string.Compare(track,"Done",false)==0) { Shape1.Left = Units.Centimeters * 13.25F; } else { Shape1.Left = 0; } 

рдпрджрд┐ рдЖрдк рдХреЙрд▓рдо рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдмрджрд▓ рджреЗрдВ рддрд╛рдХрд┐ рдХрд╛рд░реНрдб рдХрд╛ рдЗрдВрдбреЗрдВрдЯ рдирдП рдЯреНрд░реИрдХ рдХреЗ рдирд╛рдо рд╕реЗ рдореЗрд▓ рдЦрд╛рдПред рдирддреАрдЬрддрди, рд╣рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ:



рддреЛ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдХреНрдпрд╛ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП

  1. рдбрд╛рдЙрдирд▓реЛрдб FastReport рдбреЗрдореЛ
  2. рддреИрдпрд╛рд░ рдХрд╛рдирдмрди рд░рд┐рдкреЛрд░реНрдЯ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ
  3. рд╣рдо рд╕рд░реНрд╡рд░ рдкрд░ рдПрдХ рдкреНрд▓реЗрдЯ рдмрдирд╛рддреЗ рд╣реИрдВ
  4. рд╣рдо рдХрд╛рд░реНрдб рдХреЗ рдкреНрд░рдмрдВрдзрди рдХреЗ рд▓рд┐рдП рджреЛ рдХрд╛рд░реНрдп рдмрдирд╛рддреЗ рд╣реИрдВ

рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдкрд░ рдЙрдкрдпреЛрдЧреА рдмрд╛рдд, рдпрджрд┐ рдЖрдк рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдЖрдк рдЕрдкрдиреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЬрд▓реНрджреА рд╕реЗ рдЕрдиреБрдХреВрд▓ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓реЗрдЦреЛрдВ рдореЗрдВ рдореИрдВ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ рд╕рд╛рдЗрдЯ рдкрд░ рдПрдХ рд░рд┐рдкреЛрд░реНрдЯ рдХреИрд╕реЗ рд░рдЦреА рдЬрд╛рдП рддрд╛рдХрд┐ рдореИрдВ рдбреЗрд╕реНрдХрдЯреЙрдк рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рдмрд┐рд▓реНрдХреБрд▓ рднреА рдкрд░реЗрд╢рд╛рди рди рд╣реЛред рд░рд┐рдкреЛрд░реНрдЯ рд╢рд╛рдВрдд рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкреНрд░рдмрдВрдзрдХреЛрдВ рдХреЗ рдЯреИрдмрд▓реЗрдЯ рдФрд░ рдореЛрдмрд╛рдЗрд▓ рдлреЛрди рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реЛрдЧреА :), рджреЗрдЦрддреЗ рд░рд╣реЗрдВ ...

Kanban рд░рд┐рдкреЛрд░реНрдЯ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ

Source: https://habr.com/ru/post/hi472012/


All Articles