mirror of https://github.com/doccano/doccano.git
17 changed files with 1261 additions and 8 deletions
Split View
Diff Options
-
6backend/config/settings/base.py
-
1doccano
-
540frontend/assets/css/fonts.css
-
BINfrontend/assets/settings-icon.png
-
BINfrontend/assets/settings-icon.png.png
-
15frontend/components/layout/TheHeader.vue
-
100frontend/components/settings/FormCreate.vue
-
38frontend/components/settings/FormDelete.vue
-
105frontend/components/users/FormCreate.vue
-
143frontend/components/users/UsersList.vue
-
119frontend/pages/settings/index.vue
-
76frontend/pages/settings/users.vue
-
2frontend/plugins/repositories.ts
-
32frontend/repositories/BaseRepository.js
-
23frontend/repositories/settings.js
-
26frontend/repositories/user/apiUserRepository.ts
-
43frontend/services/user.service.ts
@ -0,0 +1,540 @@ |
|||
/* cyrillic-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 100; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-100-cyrillic-ext1.woff2') format('woff2'); |
|||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; |
|||
} |
|||
/* cyrillic */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 100; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-100-cyrillic2.woff2') format('woff2'); |
|||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; |
|||
} |
|||
/* greek-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 100; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-100-greek-ext3.woff2') format('woff2'); |
|||
unicode-range: U+1F00-1FFF; |
|||
} |
|||
/* greek */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 100; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-100-greek4.woff2') format('woff2'); |
|||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; |
|||
} |
|||
/* math */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 100; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-100-math5.woff2') format('woff2'); |
|||
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF; |
|||
} |
|||
/* symbols */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 100; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-100-symbols6.woff2') format('woff2'); |
|||
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF; |
|||
} |
|||
/* vietnamese */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 100; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-100-vietnamese7.woff2') format('woff2'); |
|||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; |
|||
} |
|||
/* latin-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 100; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-100-latin-ext8.woff2') format('woff2'); |
|||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; |
|||
} |
|||
/* latin */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 100; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-100-latin9.woff2') format('woff2'); |
|||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; |
|||
} |
|||
/* cyrillic-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 300; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-300-cyrillic-ext10.woff2') format('woff2'); |
|||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; |
|||
} |
|||
/* cyrillic */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 300; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-300-cyrillic11.woff2') format('woff2'); |
|||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; |
|||
} |
|||
/* greek-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 300; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-300-greek-ext12.woff2') format('woff2'); |
|||
unicode-range: U+1F00-1FFF; |
|||
} |
|||
/* greek */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 300; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-300-greek13.woff2') format('woff2'); |
|||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; |
|||
} |
|||
/* math */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 300; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-300-math14.woff2') format('woff2'); |
|||
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF; |
|||
} |
|||
/* symbols */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 300; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-300-symbols15.woff2') format('woff2'); |
|||
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF; |
|||
} |
|||
/* vietnamese */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 300; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-300-vietnamese16.woff2') format('woff2'); |
|||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; |
|||
} |
|||
/* latin-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 300; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-300-latin-ext17.woff2') format('woff2'); |
|||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; |
|||
} |
|||
/* latin */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 300; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-300-latin18.woff2') format('woff2'); |
|||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; |
|||
} |
|||
/* cyrillic-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 400; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-400-cyrillic-ext19.woff2') format('woff2'); |
|||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; |
|||
} |
|||
/* cyrillic */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 400; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-400-cyrillic20.woff2') format('woff2'); |
|||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; |
|||
} |
|||
/* greek-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 400; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-400-greek-ext21.woff2') format('woff2'); |
|||
unicode-range: U+1F00-1FFF; |
|||
} |
|||
/* greek */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 400; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-400-greek22.woff2') format('woff2'); |
|||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; |
|||
} |
|||
/* math */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 400; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-400-math23.woff2') format('woff2'); |
|||
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF; |
|||
} |
|||
/* symbols */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 400; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-400-symbols24.woff2') format('woff2'); |
|||
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF; |
|||
} |
|||
/* vietnamese */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 400; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-400-vietnamese25.woff2') format('woff2'); |
|||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; |
|||
} |
|||
/* latin-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 400; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-400-latin-ext26.woff2') format('woff2'); |
|||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; |
|||
} |
|||
/* latin */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 400; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-400-latin27.woff2') format('woff2'); |
|||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; |
|||
} |
|||
/* cyrillic-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 500; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-500-cyrillic-ext28.woff2') format('woff2'); |
|||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; |
|||
} |
|||
/* cyrillic */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 500; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-500-cyrillic29.woff2') format('woff2'); |
|||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; |
|||
} |
|||
/* greek-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 500; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-500-greek-ext30.woff2') format('woff2'); |
|||
unicode-range: U+1F00-1FFF; |
|||
} |
|||
/* greek */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 500; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-500-greek31.woff2') format('woff2'); |
|||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; |
|||
} |
|||
/* math */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 500; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-500-math32.woff2') format('woff2'); |
|||
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF; |
|||
} |
|||
/* symbols */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 500; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-500-symbols33.woff2') format('woff2'); |
|||
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF; |
|||
} |
|||
/* vietnamese */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 500; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-500-vietnamese34.woff2') format('woff2'); |
|||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; |
|||
} |
|||
/* latin-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 500; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-500-latin-ext35.woff2') format('woff2'); |
|||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; |
|||
} |
|||
/* latin */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 500; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-500-latin36.woff2') format('woff2'); |
|||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; |
|||
} |
|||
/* cyrillic-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 700; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-700-cyrillic-ext37.woff2') format('woff2'); |
|||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; |
|||
} |
|||
/* cyrillic */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 700; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-700-cyrillic38.woff2') format('woff2'); |
|||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; |
|||
} |
|||
/* greek-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 700; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-700-greek-ext39.woff2') format('woff2'); |
|||
unicode-range: U+1F00-1FFF; |
|||
} |
|||
/* greek */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 700; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-700-greek40.woff2') format('woff2'); |
|||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; |
|||
} |
|||
/* math */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 700; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-700-math41.woff2') format('woff2'); |
|||
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF; |
|||
} |
|||
/* symbols */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 700; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-700-symbols42.woff2') format('woff2'); |
|||
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF; |
|||
} |
|||
/* vietnamese */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 700; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-700-vietnamese43.woff2') format('woff2'); |
|||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; |
|||
} |
|||
/* latin-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 700; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-700-latin-ext44.woff2') format('woff2'); |
|||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; |
|||
} |
|||
/* latin */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 700; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-700-latin45.woff2') format('woff2'); |
|||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; |
|||
} |
|||
/* cyrillic-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 900; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-900-cyrillic-ext46.woff2') format('woff2'); |
|||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; |
|||
} |
|||
/* cyrillic */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 900; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-900-cyrillic47.woff2') format('woff2'); |
|||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; |
|||
} |
|||
/* greek-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 900; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-900-greek-ext48.woff2') format('woff2'); |
|||
unicode-range: U+1F00-1FFF; |
|||
} |
|||
/* greek */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 900; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-900-greek49.woff2') format('woff2'); |
|||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; |
|||
} |
|||
/* math */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 900; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-900-math50.woff2') format('woff2'); |
|||
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF; |
|||
} |
|||
/* symbols */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 900; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-900-symbols51.woff2') format('woff2'); |
|||
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF; |
|||
} |
|||
/* vietnamese */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 900; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-900-vietnamese52.woff2') format('woff2'); |
|||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; |
|||
} |
|||
/* latin-ext */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 900; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-900-latin-ext53.woff2') format('woff2'); |
|||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; |
|||
} |
|||
/* latin */ |
|||
@font-face { |
|||
font-family: 'Roboto'; |
|||
font-style: normal; |
|||
font-weight: 900; |
|||
font-stretch: 100%; |
|||
font-display: swap; |
|||
src: url('~assets/fonts/Roboto-900-latin54.woff2') format('woff2'); |
|||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; |
|||
} |
@ -0,0 +1,100 @@ |
|||
<template> |
|||
<v-card> |
|||
<v-card-title>{{ $t('generic.create') }}</v-card-title> |
|||
<v-card-text> |
|||
<v-form v-model="valid" ref="form"> |
|||
<v-text-field |
|||
v-model="username" |
|||
:label="$t('Username')" |
|||
:rules="usernameRules" |
|||
required |
|||
/> |
|||
<v-text-field |
|||
v-model="email" |
|||
:label="$t('Email')" |
|||
:rules="emailRules" |
|||
type="email" |
|||
required |
|||
/> |
|||
<v-text-field |
|||
v-model="password1" |
|||
:label="$t('Password')" |
|||
:rules="passwordRules" |
|||
type="password" |
|||
required |
|||
/> |
|||
<v-text-field |
|||
v-model="password2" |
|||
:label="$t('Confirm Password')" |
|||
:rules="[v => v === password1 || $t('user.passwordNotMatch')]" |
|||
type="password" |
|||
required |
|||
/> |
|||
</v-form> |
|||
<v-alert v-if="errorMessage" type="error" dense>{{ errorMessage }}</v-alert> |
|||
</v-card-text> |
|||
<v-card-actions> |
|||
<v-spacer /> |
|||
<v-btn text @click="$emit('cancel')">{{ $t('generic.cancel') }}</v-btn> |
|||
<v-btn |
|||
color="primary" |
|||
:disabled="!valid" |
|||
:loading="loading" |
|||
@click="create" |
|||
>{{ $t('generic.save') }}</v-btn> |
|||
</v-card-actions> |
|||
</v-card> |
|||
</template> |
|||
|
|||
<script lang="ts"> |
|||
import Vue from 'vue' |
|||
|
|||
export default Vue.extend({ |
|||
data() { |
|||
return { |
|||
valid: false, |
|||
loading: false, |
|||
username: '', |
|||
email: '', |
|||
password1: '', |
|||
password2: '', |
|||
errorMessage: '', |
|||
usernameRules: [ |
|||
(v: string) => !!v || this.$t('user.usernameRequired'), |
|||
(v: string) => v.length <= 30 || this.$t('user.usernameTooLong') |
|||
], |
|||
emailRules: [ |
|||
(v: string) => !!v || this.$t('user.emailRequired'), |
|||
(v: string) => /.+@.+\..+/.test(v) || this.$t('user.emailInvalid') |
|||
], |
|||
passwordRules: [ |
|||
(v: string) => !!v || this.$t('user.passwordRequired'), |
|||
(v: string) => v.length >= 8 || this.$t('user.passwordTooShort') |
|||
] |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
async create() { |
|||
if (!(this.$refs.form as Vue & { validate: () => boolean }).validate()) { |
|||
return |
|||
} |
|||
this.loading = true |
|||
this.errorMessage = '' |
|||
try { |
|||
await this.$services.user.create({ |
|||
username: this.username, |
|||
email: this.email, |
|||
password1: this.password1, |
|||
password2: this.password2 |
|||
}) |
|||
this.$emit('save') |
|||
} catch (e) { |
|||
this.errorMessage = e.response.data.detail || this.$t('generic.error') |
|||
} finally { |
|||
this.loading = false |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
</script> |
@ -0,0 +1,38 @@ |
|||
<template> |
|||
<base-card |
|||
title="Delete Settings" |
|||
:agree-text="$t('generic.yes')" |
|||
:cancel-text="$t('generic.cancel')" |
|||
@agree="$emit('remove')" |
|||
@cancel="$emit('cancel')" |
|||
> |
|||
<template #content> |
|||
Are you sure you want to delete the following settings? |
|||
<v-list dense> |
|||
<v-list-item v-for="(item, i) in selected" :key="i"> |
|||
<v-list-item-content> |
|||
<v-list-item-title>{{ item.name }}</v-list-item-title> |
|||
</v-list-item-content> |
|||
</v-list-item> |
|||
</v-list> |
|||
</template> |
|||
</base-card> |
|||
</template> |
|||
|
|||
<script> |
|||
import Vue from 'vue' |
|||
import BaseCard from '@/components/utils/BaseCard.vue' |
|||
|
|||
export default Vue.extend({ |
|||
components: { |
|||
BaseCard |
|||
}, |
|||
|
|||
props: { |
|||
selected: { |
|||
type: Array, |
|||
default: () => [] |
|||
} |
|||
} |
|||
}) |
|||
</script> |
@ -0,0 +1,105 @@ |
|||
<template> |
|||
<v-dialog v-model="dialog" max-width="500px"> |
|||
<v-card> |
|||
<v-card-title>{{ $t('generic.create') }} {{ $t('user.user') }}</v-card-title> |
|||
<v-card-text> |
|||
<v-form ref="form" v-model="valid"> |
|||
<v-text-field |
|||
v-model="form.username" |
|||
:label="$t('user.username')" |
|||
:rules="[rules.required]" |
|||
required |
|||
/> |
|||
<v-text-field |
|||
v-model="form.email" |
|||
:label="$t('user.email')" |
|||
:rules="[rules.required, rules.email]" |
|||
type="email" |
|||
required |
|||
/> |
|||
<v-text-field |
|||
v-model="form.password1" |
|||
:label="$t('user.password')" |
|||
:rules="[rules.required, rules.min]" |
|||
type="password" |
|||
required |
|||
/> |
|||
<v-text-field |
|||
v-model="form.password2" |
|||
:label="$t('user.confirmPassword')" |
|||
:rules="[rules.required, rules.match]" |
|||
type="password" |
|||
required |
|||
/> |
|||
</v-form> |
|||
</v-card-text> |
|||
<v-card-actions> |
|||
<v-spacer /> |
|||
<v-btn text @click="close">{{ $t('generic.cancel') }}</v-btn> |
|||
<v-btn |
|||
:disabled="!valid" |
|||
color="primary" |
|||
@click="submit" |
|||
> |
|||
{{ $t('generic.save') }} |
|||
</v-btn> |
|||
</v-card-actions> |
|||
</v-card> |
|||
</v-dialog> |
|||
</template> |
|||
|
|||
<script lang="ts"> |
|||
import Vue from 'vue' |
|||
|
|||
export default Vue.extend({ |
|||
data() { |
|||
return { |
|||
dialog: false, |
|||
valid: false, |
|||
form: { |
|||
username: '', |
|||
email: '', |
|||
password1: '', |
|||
password2: '' |
|||
}, |
|||
rules: { |
|||
required: (v: string) => !!v || this.$t('rules.required'), |
|||
email: (v: string) => /.+@.+\..+/.test(v) || this.$t('rules.email'), |
|||
min: (v: string) => v.length >= 8 || this.$t('rules.min', { min: 8 }), |
|||
match: (v: string) => v === this.form.password1 || this.$t('rules.passwordMatch') |
|||
} |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
open() { |
|||
this.dialog = true |
|||
}, |
|||
|
|||
close() { |
|||
this.dialog = false |
|||
this.form = { |
|||
username: '', |
|||
email: '', |
|||
password1: '', |
|||
password2: '' |
|||
} |
|||
if (this.$refs.form) { |
|||
;(this.$refs.form as any).reset() |
|||
} |
|||
}, |
|||
|
|||
async submit() { |
|||
if (!(this.$refs.form as any).validate()) return |
|||
|
|||
try { |
|||
await this.$services.auth.register(this.form) |
|||
this.close() |
|||
this.$emit('created') |
|||
} catch (e) { |
|||
console.error(e) |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
</script> |
@ -0,0 +1,143 @@ |
|||
<template> |
|||
<v-data-table |
|||
:value="value" |
|||
:headers="headers" |
|||
:items="items" |
|||
:options.sync="options" |
|||
:server-items-length="total" |
|||
:search="search" |
|||
:loading="isLoading" |
|||
:loading-text="$t('generic.loading')" |
|||
:no-data-text="$t('vuetify.noDataAvailable')" |
|||
:footer-props="{ |
|||
showFirstLastPage: true, |
|||
'items-per-page-options': [10, 50, 100], |
|||
'items-per-page-text': $t('vuetify.itemsPerPageText'), |
|||
'page-text': $t('dataset.pageText') |
|||
}" |
|||
item-key="id" |
|||
show-select |
|||
@input="$emit('input', $event)" |
|||
> |
|||
<template #top> |
|||
<v-text-field |
|||
v-model="search" |
|||
:prepend-inner-icon="mdiMagnify" |
|||
:label="$t('generic.search')" |
|||
single-line |
|||
hide-details |
|||
filled |
|||
/> |
|||
</template> |
|||
<template #[`item.name`]="{ item }"> |
|||
<nuxt-link :to="localePath(`/projects/${item.id}`)"> |
|||
<span>{{ item.name }}</span> |
|||
</nuxt-link> |
|||
</template> |
|||
<template #[`item.createdAt`]="{ item }"> |
|||
<span>{{ |
|||
dateFormat(dateParse(item.createdAt, 'YYYY-MM-DDTHH:mm:ss'), 'YYYY/MM/DD HH:mm') |
|||
}}</span> |
|||
</template> |
|||
<template #[`item.tags`]="{ item }"> |
|||
<v-chip v-for="tag in item.tags" :key="tag.id" outlined v-text="tag.text" /> |
|||
</template> |
|||
</v-data-table> |
|||
</template> |
|||
|
|||
<script lang="ts"> |
|||
import { mdiMagnify } from '@mdi/js' |
|||
import { dateFormat } from '@vuejs-community/vue-filter-date-format' |
|||
import { dateParse } from '@vuejs-community/vue-filter-date-parse' |
|||
import type { PropType } from 'vue' |
|||
import Vue from 'vue' |
|||
import { DataOptions } from 'vuetify/types' |
|||
import { Project } from '~/domain/models/project/project' |
|||
|
|||
export default Vue.extend({ |
|||
props: { |
|||
isLoading: { |
|||
type: Boolean, |
|||
default: false, |
|||
required: true |
|||
}, |
|||
items: { |
|||
type: Array as PropType<Project[]>, |
|||
default: () => [], |
|||
required: true |
|||
}, |
|||
value: { |
|||
type: Array as PropType<Project[]>, |
|||
default: () => [], |
|||
required: true |
|||
}, |
|||
total: { |
|||
type: Number, |
|||
default: 0, |
|||
required: true |
|||
} |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
search: this.$route.query.q, |
|||
options: {} as DataOptions, |
|||
mdiMagnify, |
|||
dateFormat, |
|||
dateParse |
|||
} |
|||
}, |
|||
|
|||
computed: { |
|||
headers(): { text: any; value: string; sortable?: boolean }[] { |
|||
return [ |
|||
{ text: this.$t('generic.name'), value: 'name' }, |
|||
{ text: this.$t('generic.description'), value: 'description', sortable: false }, |
|||
{ text: this.$t('generic.type'), value: 'projectType' }, |
|||
{ text: 'Created', value: 'createdAt' }, |
|||
{ text: 'Author', value: 'author' }, |
|||
{ text: 'Tags', value: 'tags', sortable: false } |
|||
] |
|||
} |
|||
}, |
|||
|
|||
watch: { |
|||
options: { |
|||
handler() { |
|||
this.updateQuery({ |
|||
query: { |
|||
limit: this.options.itemsPerPage.toString(), |
|||
offset: ((this.options.page - 1) * this.options.itemsPerPage).toString(), |
|||
q: this.search |
|||
} |
|||
}) |
|||
}, |
|||
deep: true |
|||
}, |
|||
search() { |
|||
this.updateQuery({ |
|||
query: { |
|||
limit: this.options.itemsPerPage.toString(), |
|||
offset: '0', |
|||
q: this.search |
|||
} |
|||
}) |
|||
this.options.page = 1 |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
updateQuery(payload: any) { |
|||
const { sortBy, sortDesc } = this.options |
|||
if (sortBy.length === 1 && sortDesc.length === 1) { |
|||
payload.query.sortBy = sortBy[0] |
|||
payload.query.sortDesc = sortDesc[0] |
|||
} else { |
|||
payload.query.sortBy = 'createdAt' |
|||
payload.query.sortDesc = true |
|||
} |
|||
this.$emit('update:query', payload) |
|||
} |
|||
} |
|||
}) |
|||
</script> |
@ -0,0 +1,119 @@ |
|||
<template> |
|||
<v-card> |
|||
<v-card-title v-if="isStaff"> |
|||
<v-btn class="text-capitalize" color="primary" @click.stop="dialogCreate = true"> |
|||
{{ $t('generic.create') }} |
|||
</v-btn> |
|||
<v-dialog v-model="dialogCreate"> |
|||
<form-create @cancel="dialogCreate = false" @save="onSave" /> |
|||
</v-dialog> |
|||
<v-btn |
|||
class="text-capitalize ms-2" |
|||
:disabled="!canDelete" |
|||
outlined |
|||
@click.stop="dialogDelete = true" |
|||
> |
|||
{{ $t('generic.delete') }} |
|||
</v-btn> |
|||
<v-dialog v-model="dialogDelete"> |
|||
<form-delete :selected="selected" @cancel="dialogDelete = false" @remove="remove" /> |
|||
</v-dialog> |
|||
</v-card-title> |
|||
<project-list |
|||
v-model="selected" |
|||
:items="projects.items" |
|||
:is-loading="isLoading" |
|||
:total="projects.count" |
|||
@update:query="updateQuery" |
|||
/> |
|||
</v-card> |
|||
</template> |
|||
|
|||
<script lang="ts"> |
|||
import _ from 'lodash' |
|||
import Vue from 'vue' |
|||
import { mapGetters } from 'vuex' |
|||
import ProjectList from '@/components/project/ProjectList.vue' |
|||
import FormDelete from '~/components/project/FormDelete.vue' |
|||
import FormCreate from '~/components/settings/FormCreate.vue' |
|||
import { Page } from '~/domain/models/page' |
|||
import { Project } from '~/domain/models/project/project' |
|||
import { SearchQueryData } from '~/services/application/project/projectApplicationService' |
|||
|
|||
export default Vue.extend({ |
|||
components: { |
|||
FormDelete, |
|||
FormCreate, |
|||
ProjectList |
|||
}, |
|||
layout: 'projects', |
|||
|
|||
middleware: ['check-auth', 'auth'], |
|||
|
|||
data() { |
|||
return { |
|||
dialogCreate: false, |
|||
dialogDelete: false, |
|||
projects: {} as Page<Project>, |
|||
selected: [] as Project[], |
|||
isLoading: false |
|||
} |
|||
}, |
|||
|
|||
async fetch() { |
|||
this.isLoading = true |
|||
this.projects = await this.$services.project.list( |
|||
this.$route.query as unknown as SearchQueryData |
|||
) |
|||
this.isLoading = false |
|||
}, |
|||
|
|||
computed: { |
|||
...mapGetters('auth', ['isStaff']), |
|||
canDelete(): boolean { |
|||
return this.selected.length > 0 |
|||
}, |
|||
|
|||
canClone(): boolean { |
|||
return this.selected.length === 1 |
|||
} |
|||
}, |
|||
|
|||
watch: { |
|||
'$route.query': _.debounce(function () { |
|||
// @ts-ignore |
|||
this.$fetch() |
|||
}, 1000) |
|||
}, |
|||
|
|||
methods: { |
|||
async remove() { |
|||
await this.$services.project.bulkDelete(this.selected) |
|||
this.$fetch() |
|||
this.dialogDelete = false |
|||
this.selected = [] |
|||
}, |
|||
|
|||
async clone() { |
|||
const project = await this.$services.project.clone(this.selected[0]) |
|||
this.selected = [] |
|||
this.$router.push(`/projects/${project.id}/settings`) |
|||
}, |
|||
|
|||
updateQuery(query: object) { |
|||
this.$router.push(query) |
|||
}, |
|||
|
|||
onSave() { |
|||
this.dialogCreate = false |
|||
this.$fetch() |
|||
} |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style scoped> |
|||
::v-deep .v-dialog { |
|||
width: 800px; |
|||
} |
|||
</style> |
@ -0,0 +1,76 @@ |
|||
<template> |
|||
<v-card> |
|||
<v-card-title> |
|||
<v-btn class="text-capitalize" color="primary" @click.stop="dialogCreate = true"> |
|||
{{ $t('generic.create') }} |
|||
</v-btn> |
|||
</v-card-title> |
|||
<users-list |
|||
v-model="selected" |
|||
:items="users.items" |
|||
:is-loading="isLoading" |
|||
:total="users.count" |
|||
@update:query="updateQuery" |
|||
/> |
|||
<v-dialog v-model="dialogCreate"> |
|||
<form-create @created="handleUserCreated" /> |
|||
</v-dialog> |
|||
</v-card> |
|||
</template> |
|||
|
|||
<script lang="ts"> |
|||
import _ from 'lodash' |
|||
import Vue from 'vue' |
|||
import FormCreate from '@/components/users/FormCreate.vue' |
|||
import UsersList from '@/components/users/UsersList.vue' |
|||
import { Page } from '~/domain/models/page' |
|||
import { User } from '~/domain/models/user' |
|||
|
|||
export default Vue.extend({ |
|||
components: { |
|||
FormCreate, |
|||
UsersList |
|||
}, |
|||
|
|||
layout: 'settings', |
|||
|
|||
middleware: ['check-auth', 'auth'], |
|||
|
|||
data() { |
|||
return { |
|||
users: {} as Page<User>, |
|||
selected: [] as User[], |
|||
isLoading: false, |
|||
dialogCreate: false |
|||
} |
|||
}, |
|||
|
|||
async fetch() { |
|||
await this.fetchUsers() |
|||
}, |
|||
|
|||
watch: { |
|||
'$route.query': _.debounce(function () { |
|||
// @ts-ignore |
|||
this.$fetch() |
|||
}, 1000) |
|||
}, |
|||
|
|||
methods: { |
|||
async fetchUsers() { |
|||
this.isLoading = true |
|||
this.users = await this.$services.user.list(this.$route.query) |
|||
this.isLoading = false |
|||
}, |
|||
|
|||
updateQuery(query: object) { |
|||
this.$router.push({ query }) |
|||
}, |
|||
|
|||
handleUserCreated() { |
|||
this.dialogCreate = false |
|||
this.fetchUsers() |
|||
} |
|||
} |
|||
}) |
|||
</script> |
@ -0,0 +1,32 @@ |
|||
import apiService from '@/services/api.service' |
|||
|
|||
export class BaseRepository { |
|||
constructor(resource) { |
|||
this.resource = resource |
|||
} |
|||
|
|||
get(path, params = {}) { |
|||
return apiService.get(`${this.resource}${path}`, { params }) |
|||
.then(response => response.data) |
|||
} |
|||
|
|||
post(path, data = {}) { |
|||
return apiService.post(`${this.resource}${path}`, data) |
|||
.then(response => response.data) |
|||
} |
|||
|
|||
put(path, data = {}) { |
|||
return apiService.put(`${this.resource}${path}`, data) |
|||
.then(response => response.data) |
|||
} |
|||
|
|||
patch(path, data = {}) { |
|||
return apiService.patch(`${this.resource}${path}`, data) |
|||
.then(response => response.data) |
|||
} |
|||
|
|||
delete(path, params = {}) { |
|||
return apiService.delete(`${this.resource}${path}`, params) |
|||
.then(response => response.data) |
|||
} |
|||
} |
@ -0,0 +1,23 @@ |
|||
import { BaseRepository } from './BaseRepository' |
|||
|
|||
export class SettingsRepository extends BaseRepository { |
|||
constructor() { |
|||
super('settings') |
|||
} |
|||
|
|||
async fetchAll() { |
|||
return await this.get('') |
|||
} |
|||
|
|||
async create(params) { |
|||
return await this.post('', params) |
|||
} |
|||
|
|||
async clone(params) { |
|||
return await this.post('/clone', params) |
|||
} |
|||
|
|||
async delete(params) { |
|||
return await this.delete('', { data: params }) |
|||
} |
|||
} |
@ -0,0 +1,43 @@ |
|||
import { Page } from '~/domain/models/page' |
|||
import { UserItem } from '~/domain/models/user/user' |
|||
import { APIUserRepository } from '~/repositories/user/apiUserRepository' |
|||
|
|||
type UserFields = { |
|||
username: string |
|||
email: string |
|||
password1: string |
|||
password2: string |
|||
} |
|||
|
|||
export interface SearchQueryData { |
|||
limit: string |
|||
offset: string |
|||
q?: string |
|||
} |
|||
|
|||
export class UserApplicationService { |
|||
constructor(private readonly repository: APIUserRepository) {} |
|||
|
|||
public async list(q: SearchQueryData): Promise<Page<UserItem>> { |
|||
try { |
|||
return await this.repository.list(q.q || '') |
|||
} catch (e: any) { |
|||
throw new Error(e.response.data.detail) |
|||
} |
|||
} |
|||
|
|||
public async create(fields: UserFields): Promise<UserItem> { |
|||
try { |
|||
return await this.repository.create(fields) |
|||
} catch (e: any) { |
|||
throw new Error(e.response.data.detail) |
|||
} |
|||
} |
|||
|
|||
public async getProfile(): Promise<UserItem> { |
|||
try { |
|||
return await this.repository.getProfile() |
|||
} catch (e: any) { |
|||
throw new Error(e.response.data.detail) |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save