From fa171dfe6ca79172053800b39501109aa4011e4c Mon Sep 17 00:00:00 2001 From: balibabu <cike8899@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:09:07 +0800 Subject: [PATCH] feat: submit new password to backend and submit user information and add Form to UserSettingProfile (#114) * feat: add Form to UserSettingProfile * feat: submit user information * feat: submit new password to backend --- web/src/constants/setting.ts | 421 ++++++++++++++++++ web/src/hooks/userSettingHook.ts | 13 + .../knowledge-setting/configuration.tsx | 29 +- web/src/pages/setting/model.ts | 3 +- .../components/setting-title/index.tsx | 19 + web/src/pages/user-setting/hooks.ts | 23 + web/src/pages/user-setting/index.less | 12 + web/src/pages/user-setting/index.tsx | 8 +- .../user-setting/setting-password/index.less | 3 + .../user-setting/setting-password/index.tsx | 136 +++++- .../user-setting/setting-profile/index.less | 7 + .../user-setting/setting-profile/index.tsx | 191 +++++++- web/src/pages/user-setting/sidebar/index.less | 3 + web/src/pages/user-setting/sidebar/index.tsx | 17 +- web/src/utils/fileUtil.ts | 27 ++ 15 files changed, 880 insertions(+), 32 deletions(-) create mode 100644 web/src/pages/user-setting/components/setting-title/index.tsx create mode 100644 web/src/pages/user-setting/hooks.ts create mode 100644 web/src/pages/user-setting/index.less create mode 100644 web/src/pages/user-setting/setting-password/index.less create mode 100644 web/src/pages/user-setting/setting-profile/index.less create mode 100644 web/src/pages/user-setting/sidebar/index.less diff --git a/web/src/constants/setting.ts b/web/src/constants/setting.ts index 915a2d6..7a60477 100644 --- a/web/src/constants/setting.ts +++ b/web/src/constants/setting.ts @@ -15,3 +15,424 @@ export const UserSettingRouteMap = { [UserSettingRouteKey.Team]: 'Team', [UserSettingRouteKey.Logout]: 'Log out', }; + +export const TimezoneList = [ + 'UTC-11\tPacific/Midway', + 'UTC-11\tPacific/Niue', + 'UTC-11\tPacific/Pago_Pago', + 'UTC-10\tAmerica/Adak', + 'UTC-10\tPacific/Honolulu', + 'UTC-10\tPacific/Rarotonga', + 'UTC-10\tPacific/Tahiti', + 'UTC-9:30\tPacific/Marquesas', + 'UTC-9\tAmerica/Anchorage', + 'UTC-9\tAmerica/Juneau', + 'UTC-9\tAmerica/Metlakatla', + 'UTC-9\tAmerica/Nome', + 'UTC-9\tAmerica/Sitka', + 'UTC-9\tAmerica/Yakutat', + 'UTC-9\tPacific/Gambier', + 'UTC-8\tAmerica/Los_Angeles', + 'UTC-8\tAmerica/Tijuana', + 'UTC-8\tAmerica/Vancouver', + 'UTC-8\tPacific/Pitcairn', + 'UTC-7\tAmerica/Boise', + 'UTC-7\tAmerica/Cambridge_Bay', + 'UTC-7\tAmerica/Ciudad_Juarez', + 'UTC-7\tAmerica/Creston', + 'UTC-7\tAmerica/Dawson', + 'UTC-7\tAmerica/Dawson_Creek', + 'UTC-7\tAmerica/Denver', + 'UTC-7\tAmerica/Edmonton', + 'UTC-7\tAmerica/Fort_Nelson', + 'UTC-7\tAmerica/Hermosillo', + 'UTC-7\tAmerica/Inuvik', + 'UTC-7\tAmerica/Mazatlan', + 'UTC-7\tAmerica/Phoenix', + 'UTC-7\tAmerica/Whitehorse', + 'UTC-7\tAmerica/Yellowknife', + 'UTC-6\tAmerica/Bahia_Banderas', + 'UTC-6\tAmerica/Belize', + 'UTC-6\tAmerica/Chicago', + 'UTC-6\tAmerica/Chihuahua', + 'UTC-6\tAmerica/Costa_Rica', + 'UTC-6\tAmerica/El_Salvador', + 'UTC-6\tAmerica/Guatemala', + 'UTC-6\tAmerica/Indiana/Knox', + 'UTC-6\tAmerica/Indiana/Tell_City', + 'UTC-6\tAmerica/Managua', + 'UTC-6\tAmerica/Matamoros', + 'UTC-6\tAmerica/Menominee', + 'UTC-6\tAmerica/Merida', + 'UTC-6\tAmerica/Mexico_City', + 'UTC-6\tAmerica/Monterrey', + 'UTC-6\tAmerica/North_Dakota/Beulah', + 'UTC-6\tAmerica/North_Dakota/Center', + 'UTC-6\tAmerica/North_Dakota/New_Salem', + 'UTC-6\tAmerica/Ojinaga', + 'UTC-6\tAmerica/Rankin_Inlet', + 'UTC-6\tAmerica/Regina', + 'UTC-6\tAmerica/Resolute', + 'UTC-6\tAmerica/Swift_Current', + 'UTC-6\tAmerica/Tegucigalpa', + 'UTC-6\tAmerica/Winnipeg', + 'UTC-6\tPacific/Easter', + 'UTC-6\tPacific/Galapagos', + 'UTC-5\tAmerica/Atikokan', + 'UTC-5\tAmerica/Bogota', + 'UTC-5\tAmerica/Cancun', + 'UTC-5\tAmerica/Cayman', + 'UTC-5\tAmerica/Detroit', + 'UTC-5\tAmerica/Eirunepe', + 'UTC-5\tAmerica/Grand_Turk', + 'UTC-5\tAmerica/Guayaquil', + 'UTC-5\tAmerica/Havana', + 'UTC-5\tAmerica/Indiana/Indianapolis', + 'UTC-5\tAmerica/Indiana/Marengo', + 'UTC-5\tAmerica/Indiana/Petersburg', + 'UTC-5\tAmerica/Indiana/Vevay', + 'UTC-5\tAmerica/Indiana/Vincennes', + 'UTC-5\tAmerica/Indiana/Winamac', + 'UTC-5\tAmerica/Iqaluit', + 'UTC-5\tAmerica/Jamaica', + 'UTC-5\tAmerica/Kentucky/Louisville', + 'UTC-5\tAmerica/Kentucky/Monticello', + 'UTC-5\tAmerica/Lima', + 'UTC-5\tAmerica/Nassau', + 'UTC-5\tAmerica/New_York', + 'UTC-5\tAmerica/Panama', + 'UTC-5\tAmerica/Port-au-Prince', + 'UTC-5\tAmerica/Rio_Branco', + 'UTC-5\tAmerica/Toronto', + 'UTC-4\tAmerica/Anguilla', + 'UTC-4\tAmerica/Antigua', + 'UTC-4\tAmerica/Aruba', + 'UTC-4\tAmerica/Asuncion', + 'UTC-4\tAmerica/Barbados', + 'UTC-4\tAmerica/Blanc-Sablon', + 'UTC-4\tAmerica/Boa_Vista', + 'UTC-4\tAmerica/Campo_Grande', + 'UTC-4\tAmerica/Caracas', + 'UTC-4\tAmerica/Cuiaba', + 'UTC-4\tAmerica/Curacao', + 'UTC-4\tAmerica/Dominica', + 'UTC-4\tAmerica/Glace_Bay', + 'UTC-4\tAmerica/Goose_Bay', + 'UTC-4\tAmerica/Grenada', + 'UTC-4\tAmerica/Guadeloupe', + 'UTC-4\tAmerica/Guyana', + 'UTC-4\tAmerica/Halifax', + 'UTC-4\tAmerica/Kralendijk', + 'UTC-4\tAmerica/La_Paz', + 'UTC-4\tAmerica/Lower_Princes', + 'UTC-4\tAmerica/Manaus', + 'UTC-4\tAmerica/Marigot', + 'UTC-4\tAmerica/Martinique', + 'UTC-4\tAmerica/Moncton', + 'UTC-4\tAmerica/Montserrat', + 'UTC-4\tAmerica/Porto_Velho', + 'UTC-4\tAmerica/Port_of_Spain', + 'UTC-4\tAmerica/Puerto_Rico', + 'UTC-4\tAmerica/Santiago', + 'UTC-4\tAmerica/Santo_Domingo', + 'UTC-4\tAmerica/St_Barthelemy', + 'UTC-4\tAmerica/St_Kitts', + 'UTC-4\tAmerica/St_Lucia', + 'UTC-4\tAmerica/St_Thomas', + 'UTC-4\tAmerica/St_Vincent', + 'UTC-4\tAmerica/Thule', + 'UTC-4\tAmerica/Tortola', + 'UTC-4\tAtlantic/Bermuda', + 'UTC-3:30\tAmerica/St_Johns', + 'UTC-3\tAmerica/Araguaina', + 'UTC-3\tAmerica/Argentina/Buenos_Aires', + 'UTC-3\tAmerica/Argentina/Catamarca', + 'UTC-3\tAmerica/Argentina/Cordoba', + 'UTC-3\tAmerica/Argentina/Jujuy', + 'UTC-3\tAmerica/Argentina/La_Rioja', + 'UTC-3\tAmerica/Argentina/Mendoza', + 'UTC-3\tAmerica/Argentina/Rio_Gallegos', + 'UTC-3\tAmerica/Argentina/Salta', + 'UTC-3\tAmerica/Argentina/San_Juan', + 'UTC-3\tAmerica/Argentina/San_Luis', + 'UTC-3\tAmerica/Argentina/Tucuman', + 'UTC-3\tAmerica/Argentina/Ushuaia', + 'UTC-3\tAmerica/Bahia', + 'UTC-3\tAmerica/Belem', + 'UTC-3\tAmerica/Cayenne', + 'UTC-3\tAmerica/Fortaleza', + 'UTC-3\tAmerica/Maceio', + 'UTC-3\tAmerica/Miquelon', + 'UTC-3\tAmerica/Montevideo', + 'UTC-3\tAmerica/Paramaribo', + 'UTC-3\tAmerica/Punta_Arenas', + 'UTC-3\tAmerica/Recife', + 'UTC-3\tAmerica/Santarem', + 'UTC-3\tAmerica/Sao_Paulo', + 'UTC-3\tAntarctica/Palmer', + 'UTC-3\tAntarctica/Rothera', + 'UTC-3\tAtlantic/Stanley', + 'UTC-2\tAmerica/Noronha', + 'UTC-2\tAmerica/Nuuk', + 'UTC-2\tAtlantic/South_Georgia', + 'UTC-1\tAmerica/Scoresbysund', + 'UTC-1\tAtlantic/Azores', + 'UTC-1\tAtlantic/Cape_Verde', + 'UTC+0\tAfrica/Abidjan', + 'UTC+0\tAfrica/Accra', + 'UTC+0\tAfrica/Bamako', + 'UTC+0\tAfrica/Banjul', + 'UTC+0\tAfrica/Bissau', + 'UTC+0\tAfrica/Casablanca', + 'UTC+0\tAfrica/Conakry', + 'UTC+0\tAfrica/Dakar', + 'UTC+0\tAfrica/El_Aaiun', + 'UTC+0\tAfrica/Freetown', + 'UTC+0\tAfrica/Lome', + 'UTC+0\tAfrica/Monrovia', + 'UTC+0\tAfrica/Nouakchott', + 'UTC+0\tAfrica/Ouagadougou', + 'UTC+0\tAfrica/Sao_Tome', + 'UTC+0\tAmerica/Danmarkshavn', + 'UTC+0\tAntarctica/Troll', + 'UTC+0\tAtlantic/Canary', + 'UTC+0\tAtlantic/Faroe', + 'UTC+0\tAtlantic/Madeira', + 'UTC+0\tAtlantic/Reykjavik', + 'UTC+0\tAtlantic/St_Helena', + 'UTC+0\tEurope/Dublin', + 'UTC+0\tEurope/Guernsey', + 'UTC+0\tEurope/Isle_of_Man', + 'UTC+0\tEurope/Jersey', + 'UTC+0\tEurope/Lisbon', + 'UTC+0\tEurope/London', + 'UTC+1\tAfrica/Algiers', + 'UTC+1\tAfrica/Bangui', + 'UTC+1\tAfrica/Brazzaville', + 'UTC+1\tAfrica/Ceuta', + 'UTC+1\tAfrica/Douala', + 'UTC+1\tAfrica/Kinshasa', + 'UTC+1\tAfrica/Lagos', + 'UTC+1\tAfrica/Libreville', + 'UTC+1\tAfrica/Luanda', + 'UTC+1\tAfrica/Malabo', + 'UTC+1\tAfrica/Ndjamena', + 'UTC+1\tAfrica/Niamey', + 'UTC+1\tAfrica/Porto-Novo', + 'UTC+1\tAfrica/Tunis', + 'UTC+1\tAfrica/Windhoek', + 'UTC+1\tArctic/Longyearbyen', + 'UTC+1\tEurope/Amsterdam', + 'UTC+1\tEurope/Andorra', + 'UTC+1\tEurope/Belgrade', + 'UTC+1\tEurope/Berlin', + 'UTC+1\tEurope/Bratislava', + 'UTC+1\tEurope/Brussels', + 'UTC+1\tEurope/Budapest', + 'UTC+1\tEurope/Copenhagen', + 'UTC+1\tEurope/Gibraltar', + 'UTC+1\tEurope/Ljubljana', + 'UTC+1\tEurope/Luxembourg', + 'UTC+1\tEurope/Madrid', + 'UTC+1\tEurope/Malta', + 'UTC+1\tEurope/Monaco', + 'UTC+1\tEurope/Oslo', + 'UTC+1\tEurope/Paris', + 'UTC+1\tEurope/Podgorica', + 'UTC+1\tEurope/Prague', + 'UTC+1\tEurope/Rome', + 'UTC+1\tEurope/San_Marino', + 'UTC+1\tEurope/Sarajevo', + 'UTC+1\tEurope/Skopje', + 'UTC+1\tEurope/Stockholm', + 'UTC+1\tEurope/Tirane', + 'UTC+1\tEurope/Vaduz', + 'UTC+1\tEurope/Vatican', + 'UTC+1\tEurope/Vienna', + 'UTC+1\tEurope/Warsaw', + 'UTC+1\tEurope/Zagreb', + 'UTC+1\tEurope/Zurich', + 'UTC+2\tAfrica/Blantyre', + 'UTC+2\tAfrica/Bujumbura', + 'UTC+2\tAfrica/Cairo', + 'UTC+2\tAfrica/Gaborone', + 'UTC+2\tAfrica/Harare', + 'UTC+2\tAfrica/Johannesburg', + 'UTC+2\tAfrica/Juba', + 'UTC+2\tAfrica/Khartoum', + 'UTC+2\tAfrica/Kigali', + 'UTC+2\tAfrica/Lubumbashi', + 'UTC+2\tAfrica/Lusaka', + 'UTC+2\tAfrica/Maputo', + 'UTC+2\tAfrica/Maseru', + 'UTC+2\tAfrica/Mbabane', + 'UTC+2\tAfrica/Tripoli', + 'UTC+2\tAsia/Beirut', + 'UTC+2\tAsia/Famagusta', + 'UTC+2\tAsia/Gaza', + 'UTC+2\tAsia/Hebron', + 'UTC+2\tAsia/Jerusalem', + 'UTC+2\tAsia/Nicosia', + 'UTC+2\tEurope/Athens', + 'UTC+2\tEurope/Bucharest', + 'UTC+2\tEurope/Chisinau', + 'UTC+2\tEurope/Helsinki', + 'UTC+2\tEurope/Kaliningrad', + 'UTC+2\tEurope/Kyiv', + 'UTC+2\tEurope/Mariehamn', + 'UTC+2\tEurope/Riga', + 'UTC+2\tEurope/Sofia', + 'UTC+2\tEurope/Tallinn', + 'UTC+2\tEurope/Vilnius', + 'UTC+3\tAfrica/Addis_Ababa', + 'UTC+3\tAfrica/Asmara', + 'UTC+3\tAfrica/Dar_es_Salaam', + 'UTC+3\tAfrica/Djibouti', + 'UTC+3\tAfrica/Kampala', + 'UTC+3\tAfrica/Mogadishu', + 'UTC+3\tAfrica/Nairobi', + 'UTC+3\tAntarctica/Syowa', + 'UTC+3\tAsia/Aden', + 'UTC+3\tAsia/Amman', + 'UTC+3\tAsia/Baghdad', + 'UTC+3\tAsia/Bahrain', + 'UTC+3\tAsia/Damascus', + 'UTC+3\tAsia/Kuwait', + 'UTC+3\tAsia/Qatar', + 'UTC+3\tAsia/Riyadh', + 'UTC+3\tEurope/Istanbul', + 'UTC+3\tEurope/Kirov', + 'UTC+3\tEurope/Minsk', + 'UTC+3\tEurope/Moscow', + 'UTC+3\tEurope/Simferopol', + 'UTC+3\tEurope/Volgograd', + 'UTC+3\tIndian/Antananarivo', + 'UTC+3\tIndian/Comoro', + 'UTC+3\tIndian/Mayotte', + 'UTC+3:30\tAsia/Tehran', + 'UTC+4\tAsia/Baku', + 'UTC+4\tAsia/Dubai', + 'UTC+4\tAsia/Muscat', + 'UTC+4\tAsia/Tbilisi', + 'UTC+4\tAsia/Yerevan', + 'UTC+4\tEurope/Astrakhan', + 'UTC+4\tEurope/Samara', + 'UTC+4\tEurope/Saratov', + 'UTC+4\tEurope/Ulyanovsk', + 'UTC+4\tIndian/Mahe', + 'UTC+4\tIndian/Mauritius', + 'UTC+4\tIndian/Reunion', + 'UTC+4:30\tAsia/Kabul', + 'UTC+5\tAntarctica/Mawson', + 'UTC+5\tAsia/Aqtau', + 'UTC+5\tAsia/Aqtobe', + 'UTC+5\tAsia/Ashgabat', + 'UTC+5\tAsia/Atyrau', + 'UTC+5\tAsia/Dushanbe', + 'UTC+5\tAsia/Karachi', + 'UTC+5\tAsia/Oral', + 'UTC+5\tAsia/Qyzylorda', + 'UTC+5\tAsia/Samarkand', + 'UTC+5\tAsia/Tashkent', + 'UTC+5\tAsia/Yekaterinburg', + 'UTC+5\tIndian/Kerguelen', + 'UTC+5\tIndian/Maldives', + 'UTC+5:30\tAsia/Colombo', + 'UTC+5:30\tAsia/Kolkata', + 'UTC+5:45\tAsia/Kathmandu', + 'UTC+6\tAntarctica/Vostok', + 'UTC+6\tAsia/Almaty', + 'UTC+6\tAsia/Bishkek', + 'UTC+6\tAsia/Dhaka', + 'UTC+6\tAsia/Omsk', + 'UTC+6\tAsia/Qostanay', + 'UTC+6\tAsia/Thimphu', + 'UTC+6\tAsia/Urumqi', + 'UTC+6\tIndian/Chagos', + 'UTC+6:30\tAsia/Yangon', + 'UTC+6:30\tIndian/Cocos', + 'UTC+7\tAntarctica/Davis', + 'UTC+7\tAsia/Bangkok', + 'UTC+7\tAsia/Barnaul', + 'UTC+7\tAsia/Hovd', + 'UTC+7\tAsia/Ho_Chi_Minh', + 'UTC+7\tAsia/Jakarta', + 'UTC+7\tAsia/Krasnoyarsk', + 'UTC+7\tAsia/Novokuznetsk', + 'UTC+7\tAsia/Novosibirsk', + 'UTC+7\tAsia/Phnom_Penh', + 'UTC+7\tAsia/Pontianak', + 'UTC+7\tAsia/Tomsk', + 'UTC+7\tAsia/Vientiane', + 'UTC+7\tIndian/Christmas', + 'UTC+8\tAsia/Brunei', + 'UTC+8\tAsia/Choibalsan', + 'UTC+8\tAsia/Hong_Kong', + 'UTC+8\tAsia/Irkutsk', + 'UTC+8\tAsia/Kuala_Lumpur', + 'UTC+8\tAsia/Kuching', + 'UTC+8\tAsia/Macau', + 'UTC+8\tAsia/Makassar', + 'UTC+8\tAsia/Manila', + 'UTC+8\tAsia/Shanghai', + 'UTC+8\tAsia/Singapore', + 'UTC+8\tAsia/Taipei', + 'UTC+8\tAsia/Ulaanbaatar', + 'UTC+8\tAustralia/Perth', + 'UTC+8:45\tAustralia/Eucla', + 'UTC+9\tAsia/Chita', + 'UTC+9\tAsia/Dili', + 'UTC+9\tAsia/Jayapura', + 'UTC+9\tAsia/Khandyga', + 'UTC+9\tAsia/Pyongyang', + 'UTC+9\tAsia/Seoul', + 'UTC+9\tAsia/Tokyo', + 'UTC+9\tAsia/Yakutsk', + 'UTC+9\tPacific/Palau', + 'UTC+9:30\tAustralia/Adelaide', + 'UTC+9:30\tAustralia/Broken_Hill', + 'UTC+9:30\tAustralia/Darwin', + 'UTC+10\tAntarctica/DumontDUrville', + 'UTC+10\tAntarctica/Macquarie', + 'UTC+10\tAsia/Ust-Nera', + 'UTC+10\tAsia/Vladivostok', + 'UTC+10\tAustralia/Brisbane', + 'UTC+10\tAustralia/Hobart', + 'UTC+10\tAustralia/Lindeman', + 'UTC+10\tAustralia/Melbourne', + 'UTC+10\tAustralia/Sydney', + 'UTC+10\tPacific/Chuuk', + 'UTC+10\tPacific/Guam', + 'UTC+10\tPacific/Port_Moresby', + 'UTC+10\tPacific/Saipan', + 'UTC+10:30\tAustralia/Lord_Howe', + 'UTC+11\tAntarctica/Casey', + 'UTC+11\tAsia/Magadan', + 'UTC+11\tAsia/Sakhalin', + 'UTC+11\tAsia/Srednekolymsk', + 'UTC+11\tPacific/Bougainville', + 'UTC+11\tPacific/Efate', + 'UTC+11\tPacific/Guadalcanal', + 'UTC+11\tPacific/Kosrae', + 'UTC+11\tPacific/Norfolk', + 'UTC+11\tPacific/Noumea', + 'UTC+11\tPacific/Pohnpei', + 'UTC+12\tAntarctica/McMurdo', + 'UTC+12\tAsia/Anadyr', + 'UTC+12\tAsia/Kamchatka', + 'UTC+12\tPacific/Auckland', + 'UTC+12\tPacific/Fiji', + 'UTC+12\tPacific/Funafuti', + 'UTC+12\tPacific/Kwajalein', + 'UTC+12\tPacific/Majuro', + 'UTC+12\tPacific/Nauru', + 'UTC+12\tPacific/Tarawa', + 'UTC+12\tPacific/Wake', + 'UTC+12\tPacific/Wallis', + 'UTC+12:45\tPacific/Chatham', + 'UTC+13\tPacific/Apia', + 'UTC+13\tPacific/Fakaofo', + 'UTC+13\tPacific/Kanton', + 'UTC+13\tPacific/Tongatapu', + 'UTC+14\tPacific/Kiritimati', +]; diff --git a/web/src/hooks/userSettingHook.ts b/web/src/hooks/userSettingHook.ts index 2bba749..0c13beb 100644 --- a/web/src/hooks/userSettingHook.ts +++ b/web/src/hooks/userSettingHook.ts @@ -74,3 +74,16 @@ export const useLogout = () => { return logout; }; + +export const useSaveSetting = () => { + const dispatch = useDispatch(); + + const saveSetting = useCallback( + (userInfo: { new_password: string } | IUserInfo): number => { + return dispatch<any>({ type: 'settingModel/setting', payload: userInfo }); + }, + [dispatch], + ); + + return saveSetting; +}; diff --git a/web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx b/web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx index 67a7438..f678c44 100644 --- a/web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx @@ -26,6 +26,11 @@ import { useDispatch, useSelector } from 'umi'; import { useFetchLlmList, useSelectLlmOptions } from '@/hooks/llmHooks'; import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; import { IKnowledge } from '@/interfaces/database/knowledge'; +import { + getBase64FromUploadFileList, + getUploadFileListFromBase64, + normFile, +} from '@/utils/fileUtil'; import { PlusOutlined } from '@ant-design/icons'; import { LlmModelType } from '../../constant'; import styles from './index.less'; @@ -43,26 +48,12 @@ const Configuration = () => { (state: any) => state.kSModel.knowledgeDetails, ); - const normFile = (e: any) => { - if (Array.isArray(e)) { - return e; - } - return e?.fileList; - }; - const parserList = useSelectParserList(); const embeddingModelOptions = useSelectLlmOptions(); const onFinish = async (values: any) => { - console.info(values); - const fileList = values.avatar; - let avatar; - - if (Array.isArray(fileList) && fileList.length > 0) { - avatar = fileList[0].thumbUrl; - } - + const avatar = getBase64FromUploadFileList(values.avatar); dispatch({ type: 'kSModel/updateKb', payload: { @@ -78,12 +69,10 @@ const Configuration = () => { }; useEffect(() => { - const avatar = knowledgeDetails.avatar; - let fileList: UploadFile[] = []; + const fileList: UploadFile[] = getUploadFileListFromBase64( + knowledgeDetails.avatar, + ); - if (avatar) { - fileList = [{ uid: '1', name: 'file', thumbUrl: avatar, status: 'done' }]; - } form.setFieldsValue({ ...pick(knowledgeDetails, [ 'description', diff --git a/web/src/pages/setting/model.ts b/web/src/pages/setting/model.ts index ce46dc8..381380d 100644 --- a/web/src/pages/setting/model.ts +++ b/web/src/pages/setting/model.ts @@ -52,7 +52,7 @@ const model: DvaModel<SettingModelState> = { const { data } = yield call(userService.setting, payload); const { retcode } = data; if (retcode === 0) { - message.success('密ç 修改ć功ďĽ'); + message.success('Modified!'); yield put({ type: 'updateState', payload: { @@ -61,7 +61,6 @@ const model: DvaModel<SettingModelState> = { }); yield put({ type: 'getUserInfo', - payload: {}, }); } }, diff --git a/web/src/pages/user-setting/components/setting-title/index.tsx b/web/src/pages/user-setting/components/setting-title/index.tsx new file mode 100644 index 0000000..1996d50 --- /dev/null +++ b/web/src/pages/user-setting/components/setting-title/index.tsx @@ -0,0 +1,19 @@ +import { Typography } from 'antd'; + +const { Title, Paragraph } = Typography; + +interface IProps { + title: string; + description: string; +} + +const SettingTitle = ({ title, description }: IProps) => { + return ( + <div> + <Title level={5}>{title}</Title> + <Paragraph>{description}</Paragraph> + </div> + ); +}; + +export default SettingTitle; diff --git a/web/src/pages/user-setting/hooks.ts b/web/src/pages/user-setting/hooks.ts new file mode 100644 index 0000000..ee670c6 --- /dev/null +++ b/web/src/pages/user-setting/hooks.ts @@ -0,0 +1,23 @@ +import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; +import { Form } from 'antd'; +import { useEffect, useState } from 'react'; + +export const useValidateSubmittable = () => { + const [form] = Form.useForm(); + const [submittable, setSubmittable] = useState<boolean>(false); + + // Watch all values + const values = Form.useWatch([], form); + + useEffect(() => { + form + .validateFields({ validateOnly: true }) + .then(() => setSubmittable(true)) + .catch(() => setSubmittable(false)); + }, [form, values]); + + return { submittable, form }; +}; + +export const useGetUserInfoLoading = () => + useOneNamespaceEffectsLoading('settingModel', ['setting']); diff --git a/web/src/pages/user-setting/index.less b/web/src/pages/user-setting/index.less new file mode 100644 index 0000000..2332db1 --- /dev/null +++ b/web/src/pages/user-setting/index.less @@ -0,0 +1,12 @@ +.settingWrapper { + width: 100%; + + .outletWrapper { + padding: 32px 32px 0; + } + + .itemDescription { + padding: 10px 0; + margin: 0; + } +} diff --git a/web/src/pages/user-setting/index.tsx b/web/src/pages/user-setting/index.tsx index ba364de..e23c4e4 100644 --- a/web/src/pages/user-setting/index.tsx +++ b/web/src/pages/user-setting/index.tsx @@ -2,11 +2,15 @@ import { Flex } from 'antd'; import { Outlet } from 'umi'; import SideBar from './sidebar'; +import styles from './index.less'; + const UserSetting = () => { return ( - <Flex> + <Flex className={styles.settingWrapper}> <SideBar></SideBar> - <Outlet></Outlet> + <Flex flex={1} className={styles.outletWrapper}> + <Outlet></Outlet> + </Flex> </Flex> ); }; diff --git a/web/src/pages/user-setting/setting-password/index.less b/web/src/pages/user-setting/setting-password/index.less new file mode 100644 index 0000000..a3adeaa --- /dev/null +++ b/web/src/pages/user-setting/setting-password/index.less @@ -0,0 +1,3 @@ +.passwordWrapper { + width: 100%; +} diff --git a/web/src/pages/user-setting/setting-password/index.tsx b/web/src/pages/user-setting/setting-password/index.tsx index 02ce07f..919af72 100644 --- a/web/src/pages/user-setting/setting-password/index.tsx +++ b/web/src/pages/user-setting/setting-password/index.tsx @@ -1,5 +1,139 @@ +import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; +import { useSaveSetting } from '@/hooks/userSettingHook'; +import { rsaPsw } from '@/utils'; +import { Button, Divider, Form, Input, Space } from 'antd'; +import SettingTitle from '../components/setting-title'; +import { useValidateSubmittable } from '../hooks'; + +import parentStyles from '../index.less'; +import styles from './index.less'; + +type FieldType = { + password?: string; + new_password?: string; + confirm_password?: string; +}; + +const tailLayout = { + wrapperCol: { offset: 20, span: 4 }, +}; + const UserSettingPassword = () => { - return <div>UserSettingPassword</div>; + const loading = useOneNamespaceEffectsLoading('settingModel', ['setting']); + const { form, submittable } = useValidateSubmittable(); + const saveSetting = useSaveSetting(); + + const onFinish = (values: any) => { + const password = rsaPsw(values.password) as string; + const new_password = rsaPsw(values.new_password) as string; + + saveSetting({ password, new_password }); + }; + + const onFinishFailed = (errorInfo: any) => { + console.log('Failed:', errorInfo); + }; + + return ( + <section className={styles.passwordWrapper}> + <SettingTitle + title="Password" + description="Please enter your current password to change your password." + ></SettingTitle> + <Divider /> + <Form + colon={false} + name="basic" + labelAlign={'left'} + labelCol={{ span: 8 }} + wrapperCol={{ span: 16 }} + style={{ width: '100%' }} + initialValues={{ remember: true }} + onFinish={onFinish} + onFinishFailed={onFinishFailed} + form={form} + autoComplete="off" + // requiredMark={'optional'} + > + <Form.Item<FieldType> + label="Current password" + name="password" + rules={[ + { + required: true, + message: 'Please input your password!', + whitespace: true, + }, + ]} + > + <Input.Password /> + </Form.Item> + <Divider /> + <Form.Item label="New password" required> + <Form.Item<FieldType> + noStyle + name="new_password" + rules={[ + { + required: true, + message: 'Please input your password!', + whitespace: true, + }, + ]} + > + <Input.Password /> + </Form.Item> + <p className={parentStyles.itemDescription}> + Your new password must be more than 8 characters. + </p> + </Form.Item> + <Divider /> + <Form.Item<FieldType> + label="Confirm new password" + name="confirm_password" + dependencies={['new_password']} + rules={[ + { + required: true, + message: 'Please confirm your password!', + whitespace: true, + }, + ({ getFieldValue }) => ({ + validator(_, value) { + if (!value || getFieldValue('new_password') === value) { + return Promise.resolve(); + } + return Promise.reject( + new Error('The new password that you entered do not match!'), + ); + }, + }), + ]} + > + <Input.Password /> + </Form.Item> + <Divider /> + <Form.Item + {...tailLayout} + shouldUpdate={(prevValues, curValues) => + prevValues.additional !== curValues.additional + } + > + <Space> + <Button htmlType="button">Cancel</Button> + <Button + type="primary" + htmlType="submit" + disabled={!submittable} + loading={loading} + > + Save + </Button> + </Space> + </Form.Item> + </Form> + </section> + ); }; export default UserSettingPassword; diff --git a/web/src/pages/user-setting/setting-profile/index.less b/web/src/pages/user-setting/setting-profile/index.less new file mode 100644 index 0000000..1950f8c --- /dev/null +++ b/web/src/pages/user-setting/setting-profile/index.less @@ -0,0 +1,7 @@ +.profileWrapper { + width: 100%; + .emailDescription { + padding: 10px 0; + margin: 0; + } +} diff --git a/web/src/pages/user-setting/setting-profile/index.tsx b/web/src/pages/user-setting/setting-profile/index.tsx index 10df96d..29f4be2 100644 --- a/web/src/pages/user-setting/setting-profile/index.tsx +++ b/web/src/pages/user-setting/setting-profile/index.tsx @@ -1,5 +1,194 @@ +import { useSaveSetting, useSelectUserInfo } from '@/hooks/userSettingHook'; +import { + getBase64FromUploadFileList, + getUploadFileListFromBase64, + normFile, +} from '@/utils/fileUtil'; +import { PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons'; +import { + Button, + Divider, + Form, + Input, + Select, + Space, + Tooltip, + Upload, + UploadFile, +} from 'antd'; +import { useEffect } from 'react'; +import SettingTitle from '../components/setting-title'; +import { TimezoneList } from '../constants'; +import { useGetUserInfoLoading, useValidateSubmittable } from '../hooks'; + +import parentStyles from '../index.less'; +import styles from './index.less'; + +const { Option } = Select; + +type FieldType = { + nickname?: string; + language?: string; + email?: string; + color_schema?: string; + timezone?: string; + avatar?: string; +}; + +const tailLayout = { + wrapperCol: { offset: 20, span: 4 }, +}; + const UserSettingProfile = () => { - return <div>UserSettingProfile</div>; + const userInfo = useSelectUserInfo(); + const saveSetting = useSaveSetting(); + const loading = useGetUserInfoLoading(); + const { form, submittable } = useValidateSubmittable(); + + const onFinish = (values: any) => { + const avatar = getBase64FromUploadFileList(values.avatar); + saveSetting({ ...values, avatar }); + }; + + const onFinishFailed = (errorInfo: any) => { + console.log('Failed:', errorInfo); + }; + + useEffect(() => { + const fileList: UploadFile[] = getUploadFileListFromBase64(userInfo.avatar); + form.setFieldsValue({ ...userInfo, avatar: fileList }); + }, [form, userInfo]); + + return ( + <section className={styles.profileWrapper}> + <SettingTitle + title="Profile" + description="Update your photo and personal details here." + ></SettingTitle> + <Divider /> + <Form + colon={false} + name="basic" + labelAlign={'left'} + labelCol={{ span: 8 }} + wrapperCol={{ span: 16 }} + style={{ width: '100%' }} + initialValues={{ remember: true }} + onFinish={onFinish} + onFinishFailed={onFinishFailed} + form={form} + autoComplete="off" + > + <Form.Item<FieldType> + label="Username" + name="nickname" + rules={[ + { + required: true, + message: 'Please input your username!', + whitespace: true, + }, + ]} + > + <Input /> + </Form.Item> + <Divider /> + <Form.Item<FieldType> + label={ + <div> + <Space> + Your photo + <Tooltip title="prompt text"> + <QuestionCircleOutlined /> + </Tooltip> + </Space> + <div>This will be displayed on your profile.</div> + </div> + } + name="avatar" + valuePropName="fileList" + getValueFromEvent={normFile} + > + <Upload + listType="picture-card" + maxCount={1} + showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }} + > + <button style={{ border: 0, background: 'none' }} type="button"> + <PlusOutlined /> + <div style={{ marginTop: 8 }}>Upload</div> + </button> + </Upload> + </Form.Item> + <Divider /> + <Form.Item<FieldType> + label="Color schema" + name="color_schema" + rules={[ + { required: true, message: 'Please select your color schema!' }, + ]} + > + <Select placeholder="select your color schema"> + <Option value="Bright">Bright</Option> + <Option value="Dark">Dark</Option> + </Select> + </Form.Item> + <Divider /> + <Form.Item<FieldType> + label="Language" + name="language" + rules={[{ required: true, message: 'Please input your language!' }]} + > + <Select placeholder="select your language"> + <Option value="English">English</Option> + <Option value="Chinese">Chinese</Option> + </Select> + </Form.Item> + <Divider /> + <Form.Item<FieldType> + label="Timezone" + name="timezone" + rules={[{ required: true, message: 'Please input your timezone!' }]} + > + <Select placeholder="select your timezone" showSearch> + {TimezoneList.map((x) => ( + <Option value={x} key={x}> + {x} + </Option> + ))} + </Select> + </Form.Item> + <Divider /> + <Form.Item label="Email address"> + <Form.Item<FieldType> name="email" noStyle> + <Input disabled /> + </Form.Item> + <p className={parentStyles.itemDescription}> + Once registered, an account cannot be changed and can only be + cancelled. + </p> + </Form.Item> + <Form.Item + {...tailLayout} + shouldUpdate={(prevValues, curValues) => + prevValues.additional !== curValues.additional + } + > + <Space> + <Button htmlType="button">Cancel</Button> + <Button + type="primary" + htmlType="submit" + disabled={!submittable} + loading={loading} + > + Save + </Button> + </Space> + </Form.Item> + </Form> + </section> + ); }; export default UserSettingProfile; diff --git a/web/src/pages/user-setting/sidebar/index.less b/web/src/pages/user-setting/sidebar/index.less new file mode 100644 index 0000000..a72d58c --- /dev/null +++ b/web/src/pages/user-setting/sidebar/index.less @@ -0,0 +1,3 @@ +.sideBarWrapper { + padding-top: 32px; +} diff --git a/web/src/pages/user-setting/sidebar/index.tsx b/web/src/pages/user-setting/sidebar/index.tsx index ed62b9c..2abd82a 100644 --- a/web/src/pages/user-setting/sidebar/index.tsx +++ b/web/src/pages/user-setting/sidebar/index.tsx @@ -10,6 +10,8 @@ import { UserSettingRouteMap, } from '../constants'; +import styles from './index.less'; + type MenuItem = Required<MenuProps>['items'][number]; function getItem( @@ -45,12 +47,15 @@ const SideBar = () => { }, [pathName]); return ( - <Menu - selectedKeys={selectedKeys} - mode="inline" - items={items} - onClick={handleMenuClick} - /> + <section className={styles.sideBarWrapper}> + <Menu + selectedKeys={selectedKeys} + mode="inline" + items={items} + onClick={handleMenuClick} + style={{ width: 312 }} + /> + </section> ); }; diff --git a/web/src/utils/fileUtil.ts b/web/src/utils/fileUtil.ts index ab9cced..537abb4 100644 --- a/web/src/utils/fileUtil.ts +++ b/web/src/utils/fileUtil.ts @@ -1,3 +1,5 @@ +import { UploadFile } from 'antd'; + export const transformFile2Base64 = (val: any): Promise<any> => { return new Promise((resolve, reject) => { const reader = new FileReader(); @@ -26,3 +28,28 @@ export const transformBase64ToFile = ( } return new File([u8arr], filename, { type: mimeType }); }; + +export const normFile = (e: any) => { + if (Array.isArray(e)) { + return e; + } + return e?.fileList; +}; + +export const getUploadFileListFromBase64 = (avatar: string) => { + let fileList: UploadFile[] = []; + + if (avatar) { + fileList = [{ uid: '1', name: 'file', thumbUrl: avatar, status: 'done' }]; + } + + return fileList; +}; + +export const getBase64FromUploadFileList = (fileList?: UploadFile[]) => { + if (Array.isArray(fileList) && fileList.length > 0) { + return fileList[0].thumbUrl; + } + + return ''; +}; -- GitLab