рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдВрд╡рд╛рдж рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рд╕реЛрдорд╡рд╛рд░ рд╢реБрд░реВ рд╣реБрдЖ:
рдиреЗрддрд╛ (рдкреА): рдпрд╣ рдЖрдкрдХреА рдЯреАрдо рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХреМрди рдХреНрдпрд╛ рдХрд░ рд░рд╣рд╛ рд╣реИред
I (I): рд╣рд╛рдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдРрд╕рд╛ рдЙрдкрдХрд░рдг рдирд╣реАрдВ рд╣реИ рдЬреЛ рдХрд╛рд░реНрдпреЛрдВ рдкрд░ рдХрд╛рд░реНрдп рдХреА рд╕рд╛рдорд╛рдиреНрдп рддрд╕реНрд╡реАрд░ рдХреЛ рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд рдХрд░реЗрдЧрд╛ред рд╣рд┐рдЯрд▓реИрдм рдореЗрдВ рдХрд╛рдирдмрди рдмреЛрд░реНрдб рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╡реЗ рдХреЗрд╡рд▓ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдФрд░ рд╕рдореВрд╣реЛрдВ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╣реИрдВред рдПрдХ рдЖрдо рдХрд╛рдирдмрди рдмреЛрд░реНрдб рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХрд░реЗрдЧрд╛ред
R: рдлрд┐рд░ рдПрдХ рдмреЛрд░реНрдб рдмрдирд╛рддреЗ рд╣реИрдВред
рдореИрдВ: рд╕реБрдмрд╣ рддрдХ рдпрд╣ рддреИрдпрд╛рд░ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред
рдЬрд▓реНрджреА
рдпрд╛ рдмрд╛рдж рдореЗрдВ, рдПрдХ рд╢реБрд░реБрдЖрддреА рдЯреАрдо рд▓реАрдбрд░ рдХреЗ рдЬреАрд╡рди рдореЗрдВ
рд╡рд╣ рдкрд▓ рдЖрддрд╛ рд╣реИ рдЬрдм рдЙрд╕реЗ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдЙрд╕рдХреА рдЯреАрдо рдХреЛ рдПрдХ рдХрд╛рдмрди рдмреЛрд░реНрдб рдХреА рдЬрд░реВрд░рдд рд╣реИред рдпрд╣ рд╡рд┐рдХрд╛рд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рдирд┐рдпрдВрддреНрд░рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд╛ рдХреЛ рджреВрд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЖрддреНрдорд╡рд┐рд╢реНрд╡рд╛рд╕ рджреЗрддрд╛ рд╣реИред рдЖрдорддреМрд░ рдкрд░ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдПрдХ рдЪреБрдВрдмрдХреАрдп рдмреЛрд░реНрдб, рдмрд╣реБ-рд░рдВрдЧреАрди рд╕реНрдЯрд┐рдХрд░ рдХрд╛ рдПрдХ рд╕реЗрдЯ рдФрд░ рдмреЛрд░реНрдб рдХреЗ рд▓рд┐рдП рдорд╛рд░реНрдХрд░реЛрдВ рдХреЗ рдПрдХ рдЬреЛрдбрд╝реЗ рдХреЛ рдЦрд░реАрджрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдмрдВрдзрдХ рдХреЗ рд╕рдмрд╕реЗ рдХрдо рдЕрдиреБрд░реЛрдз рд╕реЗ рд╣рд▓ рд╣реЛрддреА рд╣реИред рдЦреИрд░, рдпрд╛ рдЬреАрд░рд╛ рдЬреИрд╕реА рд╕реЗрд╡рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ред рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реА рдЯреАрдо рдореЗрдВ рд░рд┐рдореЛрдЯ рдкрд░ рдПрдХ рдбреЗрд╡рд▓рдкрд░ рд╣реИ, рдФрд░ рдПрдХ рдмрдВрдж рд╕рд░реНрдХрд┐рдЯ рдореЗрдВ рдЧрд┐рдЯрд▓реИрдм (рд╕реВрдЪрдирд╛ рд╕реБрд░рдХреНрд╖рд╛ рдХреЗ рдХрд╛рд░рдгреЛрдВ рд╕реЗ рдЗрдВрдЯрд░рдиреЗрдЯ рд╕реЗ рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИ), рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рджреЛ рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рдиреЛрдВ рдореЗрдВ рд╕реЗ рд╕рдмрд╕реЗ рд╕рд░рд▓ рдЪреБрдирдирд╛ рдкрдбрд╝рд╛:
рдХ) рдпрд╛рдВрддреНрд░рд┐рдХ рд╣рд╛рде рдФрд░ рдЙрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рдХрд╛ рдирд┐рд░реНрдорд╛рдг, рдЬреЛ рджреВрд░ рд╕реЗ рд╕реНрдЯрд┐рдХрд░ рдХреЛ рдмреЛрд░реНрдб рдкрд░ рдлрд┐рд░ рд╕реЗ рдЪрд┐рдкрдХрд╛ рджреЗрдЧрд╛, рдЬрдмрдХрд┐ рдирд┐рд░реНрдгрдп рдХреЛ рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЕрдкрдиреЗ рджреБрд░реНрдЧрдо рд╕рд╣рдпреЛрдЧреА рдХреЗ рд▓рд┐рдП рд╕реНрдЯрд┐рдХрд░ рдкрд░ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛, рдЬреЛ рдЕрдиреБрдЪрд┐рдд рд╣реИ;
b) рдПрдХ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ kanban рдмреЛрд░реНрдб рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЬреЛ рд╣рдорд╛рд░реЗ рд╣рд┐рдЯрд▓реИрдм рд╕реЗ рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдПрдХрддреНрд░рд┐рдд рдХрд░реЗрдЧрд╛ред
рдмреЗрд╢рдХ, рдЖрддреНрдорд╛ рднреМрддрд┐рдХ рдмреЛрд░реНрдб рдХреА рдЯреНрдпреВрдм рдХреЗ рдЦрд┐рд▓рд╛рдл рд░рдЦрддреА рд╣реИред рдореИрдВ рднреА рдПрдХ рдпрд╛рдВрддреНрд░рд┐рдХ рд╣рд╛рде рдирд┐рдпрдВрддреНрд░рдХ рдХреЗ рд░реВрдк рдореЗрдВ DualShock 4 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдореИрдВ рдЦреБрдж рдЕрдЧрд▓реА рд╕реБрдмрд╣ рдХреА рд╕рдордп рд╕реАрдорд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдПрдХ рд╕реМрд▓рд╕ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рд╕рдорд╛рдзрд╛рди рдХреЗ рд╕рд╛рде рдорд┐рд▓рдирд╛ рдерд╛ред

рдХрд╣рд╛рдиреА рдХреЗ рддрдХрдиреАрдХреА рднрд╛рдЧ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╢реБрд░реВ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рддрд╛ рд╣реВрдВ рдХрд┐ рд╣рдо рдХреИрд╕реЗ Onlanta рдореЗрдВ gitlab рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд╣рд┐рдЯрд▓реИрдм рдореЗрдВ рд╕рдореВрд╣ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЖрдВрддрд░рд┐рдХ / рдмрд╛рд╣рд░реА рдЧреНрд░рд╛рд╣рдХ рдпрд╛ рдПрдХ рдЕрд▓рдЧ рдмрдбрд╝реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИрдВ, рдФрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╕реЗрд╡рд╛ рдХреЗ рдХреЛрдб рдХреЗ рд▓рд┐рдП рдПрдХ рднрдВрдбрд╛рд░ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдмрд┐рд▓рд┐рдВрдЧ рдХрдВрдЯреНрд░реЛрд▓ рдкреИрдирд▓ рдХрд╛ рдПрдХ рд╕рдореВрд╣ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЪрд╛рд░ рдкрд░рд┐рдпреЛрдЬрдирд╛рдПрдБ рд╕реЗрд╡рд╛рдПрдБ рдФрд░ рд╡реЗрдм рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╣реИрдВ, рдФрд░ рдПрдХ рд╡рд┐рдкрдгрди рд╕рдореВрд╣ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдХреЙрд░реНрдкреЛрд░реЗрдЯ рд╕рд╛рдЗрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╣реИ, amoCRM рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ microservice, рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓реИрдВрдбрд┐рдВрдЧ рдкреГрд╖реНрда рдФрд░ рдЗрддрдиреЗ рдкрд░ред рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд╣рдорд╛рд░реЗ рдиреМ рд╕рдХреНрд░рд┐рдп рд╕рдореВрд╣ рд╣реИрдВ, рдФрд░ рдХрдо рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╕рднреА рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рд╕рднреА рд╕рдореВрд╣реЛрдВ рдореЗрдВ рднрд╛рдЧ рд▓реЗрддреЗ рд╣реИрдВред
рдФрд░ рд╣рдо рд╕рднреА рдХреА рдЬрд░реВрд░рдд рдПрдХ рдкреЗрдЬ рдерд╛, рдЬреЛ рд╕рднреА рд╕рдореВрд╣реЛрдВ рдФрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рд╕реЗ рд╣рд┐рдЯрд▓реИрдм рдХреЗ рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдерд╛, рд▓реЗрдХрд┐рди рдЧрд┐рдЯрд▓реИрдм рдореЗрдВ рдпрд╣ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛, рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдирд╣реАрдВ рд╣реИред рддреНрд╡рд░рд┐рдд Google рдиреЗ рдПрдХ рд╕реНрдЯреИрдВрдбрдЕрд▓реЛрди рд╕рдорд╛рдзрд╛рди рдЦреЛрдЬрдиреЗ рдореЗрдВ рдорджрдж рдирд╣реАрдВ рдХреА, рдЗрд╕рд▓рд┐рдП
рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:
- Node.js рдкрд░ рдмреИрдХрдПрдВрдб - рдЧрд┐рдЯрд▓реИрдм рдХреЗ рд╕рд╛рде рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП;
- Vue.js рдкрд░ рдХреНрд▓рд╛рдЗрдВрдЯ - рдЗрд╕реЗ рдЬрд▓реНрджреА рдФрд░ рдЦреВрдмрд╕реВрд░рддреА рд╕реЗ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП;
- рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд╕рд╛рде рдпрд╣ рд╕рдм рдореМрд╕рдо, рдмрд┐рд▓реНрдХреБрд▓!
- PostgreSQL - рдЬрд╣рд╛рдВ рд╣рдо рдмреЛрд░реНрдб рдкрд░ рдХрд╛рд░реНрдпреЛрдВ рдФрд░ рдЙрдирдХреА рд╕реНрдерд┐рддрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдВрдЧреЗ;
- рдХрд╛рдо рдХреЗ рд╕рдордп рдХреЗ 8 рдШрдВрдЯреЗ;
- рдЕрдЪреНрдЫрд╛ рдореВрдбред
рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╢рд░реНрдд рдпрд╣ рд╣реИ рдХрд┐ рд╡рд┐рдХрд╛рд╕ рдЖрд╕рд╛рди рдФрд░ рдордЬреЗрджрд╛рд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЪрд▓реЛ рдЗрд╕реЗ "рдЖрд╕рд╛рди рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ" рдХрд╣реЗрдВред
рдЪрд┐рдбрд╝рд┐рдпрд╛рдШрд░
рд╕реНрдкрд╖реНрдЯ рдХрд╛рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЕрдкрдиреЗ рдХреЙрд░реНрдкреЛрд░реЗрдЯ рд╣рд┐рдЯрд▓реИрдм рд╕реЗ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИрдмреЗ рдкрд░ рд▓реЗрдЦ рдХрд╛ рд╡рд░реНрдгрди рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдЕрдкрдиреЗ рд╣рд┐рдЯрд▓реИрдм рдХреЛ рдмрдВрджрд░реЛрдВ рдФрд░ рдордЧрд░рдордЪреНрдЫреЛрдВ рдХреЗ рд╕рд╛рде рддреИрдирд╛рдд рдХрд┐рдпрд╛ред рд╣рд╛рдВ, рдпрд╣ рдПрдХ рдХрд╛рд▓реНрдкрдирд┐рдХ рдЪрд┐рдбрд╝рд┐рдпрд╛рдШрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдЧреАрддрд╛рд▓рд╛рдм рд╣реИ, рд▓реЗрдХрд┐рди рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рдЧреАрддрд╛рд▓рд╛рдм рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдХреЛрдИ рдХрдо рдЧрдВрднреАрд░ рдХрд╛рд░реНрдп рд╡рд╣рд╛рдВ рд╕реНрдерд╛рдкрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреА рд╕реВрдЪреА рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:
karcass
рд╡рд┐рдХрд╛рд╕ рдХреЗ рд╡рд░реНрд╖реЛрдВ рдореЗрдВ, рдореИрдВрдиреЗ рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рд╣реИ рдХрд┐ Node.js рдкрд░ рдмреИрдХрдПрдВрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдиреЗ рдПрдХ рд░реВрдкрд░реЗрдЦрд╛ рдХрд╛ рд░реВрдк рд▓рд┐рдпрд╛ - рдлрд╛рдЗрд▓реЛрдВ рдХрд╛ рдПрдХ рд╕реЗрдЯред рдПрдХ рдирдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдмрд╕ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЛ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд╕рд╛рде рдХреЙрдкреА рдХрд┐рдпрд╛ред рдпрд╣ рд╣рдореЗрд╢рд╛ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдЬрд╛ рд╕рдХрд╛, рдФрд░ рдореИрдВрдиреЗ
karcass npm рдкреИрдХреЗрдЬ рдмрдирд╛рдпрд╛ (рдирд╛рдо рд╢рд╡ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрд╕реА рд╕рд╛рдЗрдХрд┐рд▓ рдЙрддреНрд╕рд╛рд╣реА рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдЬреИрд╕рд╛ рдореИрдВрдиреЗ рдХрд┐рдпрд╛ рдерд╛), рдЬреЛ рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП рдЖрдзрд╛рд░ рдмрдирд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рддрд╛ рд╣реИ:
рдЕрдм рд╣рдореЗрдВ рд╕рдореВрд╣реЛрдВ, рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ, рдХрд╛рд░реНрдпреЛрдВ рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдХрд▓рд╛рдХрд╛рд░реЛрдВ рдХреА рдкреНрд░рд╛рдкреНрддрд┐ рдФрд░ рднрдВрдбрд╛рд░рдг рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
TypeORM
"рдореИрдВ рдХреБрдЫ рд╕рдВрд╕реНрдерд╛рдПрдБ рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдБ ..."
- рдордиреЛрд╡рд┐рдЬреНрдЮрд╛рди рдордВрдЪ рдкрд░ рдЪрд░реНрдЪрд╛ рд╕реЗ
рдЪреВрдВрдХрд┐ рд╣рдореЗрдВ рдЧрд┐рдЯрд▓реИрдм рд╕реЗ рдбреЗрдЯрд╛ рдХреЛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕ рдбреЗрдЯрд╛ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рдФрд░ рдЗрд╕реЗ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреЗ рдмреАрдЪ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, рд╣рдореЗрдВ рдЗрд╕реЗ рдХрд┐рд╕реА рддрд░рд╣ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рд╛рд▓ рд╣реА рдореЗрдВ, рдореИрдВрдиреЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрджреНрднреБрдд рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреА рдЦреЛрдЬ рдХреА,
рдЯрд╛рдЗрдкрдлреЙрд░реНрдо, рдЬреЗрдПрд╕ рдкрд╛рд░рд┐рд╕реНрдерд┐рддрд┐рдХреА рддрдВрддреНрд░ рдХреЗ рд▓рд┐рдП рдЕрджреНрднреБрддред рдпрд╣ рдЕрднреА рднреА рд╣рд░рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕реАрдХреНрд╡рд▓ рдХреЛ рд╕рд┐рдВрд╣рд╛рд╕рди рд╕реЗ рдмрд╛рд╣рд░ рдХрд░рдиреЗ рдХрд╛ рд╣рд░ рдореМрдХрд╛ рд╣реИред
рджрд╕рд┐рдпреЛрдВ рдорд┐рдирдЯреЛрдВ рдореЗрдВ,
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ ,
рд╕рдореВрд╣реЛрдВ ,
рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдФрд░
рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдФрд░ рдХрдХреНрд╖рд╛рдПрдВ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИрдВред рдпрд╣рд╛рдБ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ:
import { Entity, PrimaryColumn, Column } from 'typeorm' @Entity({ name: 'group' }) export class Group { @PrimaryColumn('integer') public id!: number @Column('varchar') public name!: string @Column('varchar') public url!: string }
рдФрд░ рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдлрд┐рд░ рд╕реЗ рдПрдХ
CreateMigrationCommand рд╕рд╣рд╛рдпрдХ
рдмрд╛рдЗрдХ рдмрдирд╛рдИред рдпрд╣ рдХрдорд╛рдВрдб рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ:
рдЕрдВрдХ рд╡рд░реНрдЧ рдореЗрдВ, рдЧреАрддрд╛рд▓рд╛рдм рд╕реЗ рдбреЗрдЯрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдЙрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рдЬрд┐рдирдХреЗ рдХрд╛рд░рдг рд╕рдВрдкреВрд░реНрдг рдЙрдкрджреНрд░рд╡ рд╢реБрд░реВ рд╣реБрдЖ, рдпрд╛рдиреА рдХрд┐ рдХрд╛рдирди рдмреЛрд░реНрдб рдкрд░ рдХрд╛рд░реНрдп рдХреА рд╕реНрдерд┐рддрд┐ рдХрд╛ рд╕рдВрдХреЗрдд:
export class Issue extends AbstractEntity { @Column('varchar', { name: 'kanban_status' }) public kanbanStatus?: 'new'|'planed'|'working'|'checking'|'done' @Column('int', { name: 'kanban_order' }) public kanbanOrder?: number }
рд╣рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдЪрд╛рд╣рд┐рдП
рдЬрдм рдореИрдВрдиреЗ рдкрд╣рд▓реА рдмрд╛рд░ GitLab рдХреЗ рд╕рд╛рде рдЕрдкрдирд╛ рдкрд░рд┐рдЪрдп рд╢реБрд░реВ рдХрд┐рдпрд╛, рддреЛ рдпрд╣ рдореБрдЭреЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг ("рдирдлрд░рдд") рдЙрддреНрдкрд╛рдж рд▓рдЧрддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рд╣рд░ рджрд┐рди рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдкрд░, рдореБрдЭреЗ рдПрд╣рд╕рд╛рд╕ рд╣реБрдЖ рдХрд┐ рдореИрдВ рдХрд┐рддрдирд╛ рдЧрд▓рдд рдерд╛ред рддреЛ рдЗрд╕ рдмрд╛рд░ рдореИрдВ рд╣реИрд░рд╛рди рдерд╛ - рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ GitLab рдореЗрдВ рдПрдХ рдмрд╣реБрдд рд╕рдореГрджреНрдз рдПрдкреАрдЖрдИ рд╣реИ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрдкрд▓рдмреНрдз рд▓рдЧрднрдЧ рд╕рднреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдХрд╡рд░ рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдХреЗрд╡рд▓ рдЪрд╛рд░ рддрд░реАрдХреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдирд╛рдо рдЦреБрдж рдХреЗ рд▓рд┐рдП рдмреЛрд▓рддреЗ рд╣реИрдВ:
/ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ ,
/ рд╕рдореВрд╣ ,
/ рдкрд░рд┐рдпреЛрдЬрдирд╛рдПрдВ ,
/ рдкрд░рд┐рдпреЛрдЬрдирд╛рдПрдВ /: рдЖрдИрдбреА / рдореБрджреНрджреЗ ред GitlabService GitLab рдХреЗ рд╕рд╛рде рд╕реАрдзреЗ рд╕рдВрдкрд░реНрдХ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛, рдФрд░ рдЕрдиреНрдп рд╡рд░реНрдЧ рдЗрд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд░реЗрдВрдЧреЗред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, GroupService рд╡рд░реНрдЧ рдХреЗ рдЕрджреНрдпрддрдирд╕рдореВрд╣ рдкрджреНрдзрддрд┐ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
export class GroupService extends AbstractService { public async updateGroups() { for (const data of await this.app.gitlabService.getGroups()) {
рдЕрдкрдбреЗрдЯрдкреНрд░реЛрдЬреЗрдХреНрдЯрд╕реЛрдореИрдВрдб рдХрдорд╛рдВрдб
рдЬрд┐рддрд╛рд▓рд╛рдм рд╕реЗ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рд╣рдорд╛рд░реЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛, рдЬрд┐рд╕реЗ рдХрдВрд╕реЛрд▓ рд╕реЗ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдорд╛рд░рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рд╣реА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЖрд╡реГрддреНрддрд┐ рдХреЗ рд╕рд╛рде рд▓реЙрдиреНрдЪ рдХрд░реЗрдЧрд╛:
export class Application { protected initCron() { if (this.config.gitlab.updateInterval) { setInterval(async () => { if (!this.updateProjectsCommand) { this.updateProjectsCommand = new UpdateProjectsCommand(this) } await this.updateProjectsCommand.execute() }, this.config.gitlab.updateInterval * 1000) } } }
рд╣рдо рдмреЛрд░реНрдб рдкрд░ рдХреЙрд▓рдореЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛, рд░рдВрдЧ рдФрд░ рдирд╛рдо рдХреЛ рд╣рд╛рд░реНрдбрдХреЛрдб рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдЙрдиреНрд╣реЗрдВ config.js рдореЗрдВ рдЕрдиреБрдХреВрд▓рди рдпреЛрдЧреНрдп рдмрдирд╛рдПрдВрдЧреЗред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЙрдирдореЗрдВ рд╕реЗ рдкрд╛рдВрдЪ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП, рд╢рд╛рдпрдж рдХреЗрд╡рд▓ рджреЛ рдХреА рдЬрд░реВрд░рдд рд╣реИ рдФрд░ рдПрд╕рд┐рдб рдХрд╛ рд░рдВрдЧ:
columns: [ { key: 'new', title: '', color: 'rgb(255, 255, 219)' }, { key: 'planed', title: '', color: 'rgb(236, 236, 191)' }, { key: 'working', title: ' ', color: 'rgb(253, 214, 162)' }, { key: 'checking', title: ' ', color: 'rgb(162, 226, 253)' }, { key: 'done', title: '', color: 'rgb(162, 253, 200)' }, ],
рдореБрдЦреНрдп рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдХрдо рд╕реЗ рдХрдо рджреЛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЕрдиреНрдпрдерд╛ рдЖрд╡реЗрджрди рд╢реБрд░реВ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
рдореЛрд░реНрдЪреЗ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рд╡рд┐рдзрд┐ рдХреА рдЬрд░реВрд░рдд рд╣реИ рдЬреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдХрд╛рд░реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░реЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ "рдХреЙрд▓рдо" рдореЗрдВ рдЫрд╛рдБрдЯреЗ:
рдЬрд╛рд░реА рдХрд░реЗрдВ export class IssueService extends AbstractService { public async getKanban() { let issues = await this.issueRepository.find({ where: { updatedTimestamp: MoreThanOrEqual(new Date().getTimestamp() - 60 * 60 * 24 * 30) }, order: { kanbanOrder: 'ASC', updatedTimestamp: 'DESC' }, }) const keys = this.app.config.columns.map(c => c.key) const result: { [key: string]: Issue[] } = {} for (let ki = keys.length - 1; ki >= 0; ki--) { const key = keys[ki] if (ki === keys.length - 1) {
рдФрд░ рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рдЬреЛ рдирдП рдХрд╛рд░реНрдп рдкрджреЛрдВ рдХреЛ рдмрдЪрд╛рддрд╛ рд╣реИ:
рдЗрд╢реНрдпреВрдХрдВрдЯреНрд░реЛрд▓рд░ рдХреЛ рджрд┐рдЦрд╛рдПрдВ export default class IssueController extends AbstractController { public async kanbanUpdate(data: IQueryData) { const keys = this.app.config.columns.map(c => c.key) for (const c of data.params as { key: string, title: string, color: string, issues: number[] }[]) { if (keys.indexOf(c.key) < 0) { continue } let index = 0 for (const i of c.issues) { index++ const issue = await this.app.issueService.getIssue(i) if (!issue) { continue } issue.kanbanStatus = c.key issue.kanbanOrder = index this.app.issueService.issueRepository.save(issue) } } } }
Shtoshред рд╣рдо GitLab рд╕реЗ рдЬрд╛рдирдХрд╛рд░реА рдПрдХрддреНрд░ рдХрд░рддреЗ рд╣реИрдВ, рдмреЛрд░реНрдб рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рддреИрдпрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдпрд╣ рднреА рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдмреЛрд░реНрдб рдкрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЕрдкрдбреЗрдЯ рдХрд┐рдП рдЧрдП рдкрджреЛрдВ рдХреЛ рдХреИрд╕реЗ рдмрдЪрд╛рдпрд╛ рдЬрд╛рдПред рдХреЗрд╡рд▓ рдПрдХ рдЪреАрдЬ рдмрдЪреА рд╣реИ рд╡рд╣ рд╣реИ рдмреЛрд░реНрдб рдХреЛ рдЦреБрдж рдмрдирд╛рдирд╛ред рдФрд░ рдпрд╣рд╛рдБ рд╣рдо рдПрдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЙрдкрдХрд░рдг рд╕реЗ рд▓реИрд╕ рд╣реИрдВ:
Vue CLI - рдПрдХ рд╣рдЬрд╛рд░ рд╢рдмреНрджреЛрдВ рдХреЗ рдмрдЬрд╛рдп
TSX
рд░рд┐рдлреИрдХреНрдЯрд┐рдВрдЧ рдХреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, рдмрдЧреНрд╕, рд▓рд╛рдЗрдирд┐рдВрдЧ рдФрд░ рдорди рдХреА рдЕрдиреНрдп рд╢рд╛рдВрддрд┐ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо tsx рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ Vue.js рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ
* рд▓рдЧрднрдЧ ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдмреЛрд░реНрдб рдореЗрдВ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдШрдЯрдХ, рдХрд╛рд░реНрдп рдкреНрд░рд╕реНрддреБрддрд┐ рдХрд╛ рдШрдЯрдХ:
рдХреЛрдб рдЬрд╛рд░реА рдХрд░реЗрдВ .tsx import { Vue, Component, Prop, Watch } from 'vue-property-decorator' import './Issue.css' import { CreateElement, VNode } from 'vue' interface IIssue { groupId: number groupName: string groupUrl: string projectName: string projectUrl: string url: string title: string executor: { color: string, name: string } spent: number estimate: number } @Component export default class extends Vue { @Prop() public issue!: IIssue public issueValue!: IIssue public selectUser = false @Watch('issue', { immediate: true }) public onIssueChange() { this.issueValue = this.issue }
рдпрд╣ рдШрдЯрдХ рдХрд╛рд░реНрдп рдкрдЯреНрдЯреА рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдХрд╛рд░реНрдп рдиреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рдордп рдФрд░ рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ рд╣реИ:
рдЗрд╕рдореЗрдВ
Column.tsx рдФрд░
Kanban.tsx рдШрдЯрдХ рднреА рд╣реИрдВред рдХреЗрд╡рд▓ рддреАрди рдШрдЯрдХ рдмреЛрд░реНрдб рдкрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреА рдкреНрд░рд╕реНрддреБрддрд┐ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ:
Vue.Draggable , рдЬрд┐рд╕рдХреЗ рдкреИрд░
SortableJS рд╕реЗ рдмрдврд╝рддреЗ рд╣реИрдВ, рдмреЛрд░реНрдб рдкрд░ рдЪрд▓рдиреЗ рд╡рд╛рд▓реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рдпрд╣ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрддреНрдпрдВрдд рд╕рд░рд▓ рд╣реИ:
import Draggable from 'vuedraggable' export default class extends Vue { public render(h: CreateElement): VNode { <Draggable class="kvcIssues" vModel={ this.issuesValue } group={ { name: 'issues', pull: true, put: true } } onEnd={ this.onDrag } onAdd={ this.onDrag } > { this.issuesValue.map(i => <Issue key={ i.id } issue={ i } />) } </Draggable> /* ... */ } }
рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЖрдкрдиреЗ рджреЗрдЦрд╛ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛ рдЕрдкрдирд╛ рд░рдВрдЧ рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд▓реЙрдЧрд┐рди рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ - рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдПрдХ рд╕рдореВрд╣ рдХреЗ рдмреАрдЪ, рдЖрдк рдЬрд▓реНрджреА рд╕реЗ рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВред "рдмрд╣реБрдЖрдпрд╛рдореА" рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рджреЛ рддрд░реАрдХреЗ рд╣реИрдВ: рдкреНрд░рддреНрдпреЗрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рд╣рд╛рдереЛрдВ рд╕реЗ рд░рдВрдЧ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рдпрд╛ рдХрд┐рд╕реА рдЪреАрдЬрд╝ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдЗрд╕реЗ рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ред
рдореБрдЭреЗ рдЕрдкрдирд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рджреЗрдВ рдФрд░ рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рдКрдВрдЧрд╛ рдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдХреМрди рд╕рд╛ рд░рдВрдЧ рд╣реИ
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╡рд░реНрдЧ рдХрд╛ рд░рдВрдЧ рдкрд╛рдиреЗ рд╡рд╛рд▓рд╛ рд░рдВрдЧ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрддрд╛ рд╣реИред рдореИрдВрдиреЗ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдмреИрдХрдПрдВрдб рдкрд░ рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдореБрдЭреЗ рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереА, рдФрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдЫреЛрдЯреЗ рд╕реЗ рдХрд╛рдо рдХреЗ рд▓рд┐рдП рдкреВрд░реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рд╕рд╛рдордиреЗ рдЦреАрдВрдЪрдирд╛ рдЕрдкрд░рд╛рдз рд╣реИред рдФрд░ рдпрд╣ рддрдм рдФрд░ рд╕рд╣реА рд╣реИ рдЬрдм рдкреАрда, рдФрд░ рд╕рд╛рдордиреЗ рдирд╣реАрдВ, рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИ:
export class User extends AbstractEntity { public get color() { const hash = crypto.createHash('md5').update(this.username).digest()
рдЬреЛ рд▓реЛрдЧ рдЬрд╛рдирдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдЙрдирдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рд░рдВрдЧ рд╣реИ, рдореИрдВ
рдХреЛрдбрдкреЗрди рдкрд░ рд╕реНрдирд┐рдкреЗрдЯ рдХреЛ рдХрд╛рдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЖрд▓рд╕реА рдирд╣реАрдВ рдерд╛ред
рд╡рд╣ рд╕рдм
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдВрд╡рд╛рдж рдХреЗ рд╕рд╛рде рдордВрдЧрд▓рд╡рд╛рд░ рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛ рдЧрдпрд╛:
рдЖрд░: рдареАрдХ рд╣реИ, рдмреЛрд░реНрдб рдХреИрд╕реЗ рддреИрдпрд╛рд░ рд╣реИ? ..
рдореИрдВ: рд╣рд╛рдБ, рдпрд╣рд╛рдБред
R: рдУрд╣, рдЕрдЪреНрдЫрд╛!
рдореЗрд░реЗ "рдХрд╛рд░реНрдпрджрд┐рд╡рд╕" тАЛтАЛрдХрд╛ рдкрд░рд┐рдгрд╛рдо рдпрд╣рд╛рдБ рд╣реИ:
https://github.com/onlanta/kanban ред рдЖрдк рдЗрд╕реЗ рди рдХреЗрд╡рд▓ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕реЗ рдЫреВ рд╕рдХрддреЗ рд╣реИрдВ, рдмрд▓реНрдХрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рднреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рд╡рд╣рд╛рдВ рдирд┐рд░реНрджреЗрд╢)ред рдФрд░ рдЖрдк рдЗрд╕ рдкрд░ рд╣рд┐рдЯрд▓реИрдм рдХреЗ рд▓рд┐рдП рдПрдХ рдкреВрд░реЗ рд╕рдордп рдХрд╛ рдЯреНрд░реИрдХрд░ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рд╣рдордиреЗ рдХрдВрдкрдиреА рдореЗрдВ рдХрд┐рдпрд╛ рдерд╛ред
рдореИрдВрдиреЗ рдпрд╣ рдиреЛрдЯ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХреНрдпреЛрдВ рдХрд┐рдпрд╛? рдпрд╣ рдореЗрд░реА рдкреЗрд╢реЗрд╡рд░ рдЧрддрд┐рд╡рд┐рдзрд┐ рдореЗрдВ рд╣рд╛рд▓ рдХреЗ рдЙрдЬреНрдЬреНрд╡рд▓ рдХреНрд╖рдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ, рдЬрдм рдХрд╛рд░реНрдп рдорд╣рддреНрд╡рдкреВрд░реНрдг, рджрд┐рд▓рдЪрд╕реНрдк рдерд╛, рдФрд░ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдХрд╛рдлреА рд╕рд░рд▓ рдерд╛, рдФрд░ рдЗрд╕рдХрд╛ рд╕рдорд╛рдзрд╛рди рдЖрд╕рд╛рди рдФрд░ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдирд┐рдХрд▓рд╛ред рдореИрдВ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдЕрдкрдиреЗ рдЕрднреНрдпрд╛рд╕ рд╕реЗ рд╕рдорд╛рди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдпрд╛рдж рдХрд░реЗрдВред
рдЦреИрд░, рд╣рдо рдмрд┐рдирд╛ рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдХреЗ рдХрд╣рд╛рдВ рд╣реИрдВред