From e33e3ef413bbaa6bed12e112ba93554f3f8ab4fc Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Wed, 19 Oct 2022 21:59:16 +0800 Subject: [PATCH 01/12] refactor(web/user/edit): user_edit_v2 --- db/app_uoj233.sql | 1 + web/app/controllers/user_info_edit.php | 447 ++++++++++++++--------- web/app/libs/uoj-form-lib.php | 15 +- web/app/locale/basic/en.php | 10 +- web/app/locale/basic/zh-cn.php | 10 +- web/app/models/HTML.php | 8 +- web/app/models/Upgrader.php | 2 +- web/app/route.php | 2 +- web/app/upgrade/6_user_info_v2/README.md | 1 + web/app/upgrade/6_user_info_v2/down.sql | 1 + web/app/upgrade/6_user_info_v2/up.sql | 1 + 11 files changed, 302 insertions(+), 196 deletions(-) create mode 100644 web/app/upgrade/6_user_info_v2/README.md create mode 100644 web/app/upgrade/6_user_info_v2/down.sql create mode 100644 web/app/upgrade/6_user_info_v2/up.sql diff --git a/db/app_uoj233.sql b/db/app_uoj233.sql index 397ad22..7983cdf 100644 --- a/db/app_uoj233.sql +++ b/db/app_uoj233.sql @@ -816,6 +816,7 @@ CREATE TABLE `user_info` ( `last_login` timestamp NOT NULL DEFAULT 0, `last_visited` timestamp NOT NULL DEFAULT 0, `images_size_limit` int(11) UNSIGNED NOT NULL DEFAULT 104857600, /* 100 MiB */ + `codeforces_handle` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', PRIMARY KEY (`username`), KEY `ac_num` (`ac_num`,`username`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; diff --git a/web/app/controllers/user_info_edit.php b/web/app/controllers/user_info_edit.php index 853381c..75efaec 100644 --- a/web/app/controllers/user_info_edit.php +++ b/web/app/controllers/user_info_edit.php @@ -1,4 +1,8 @@ [ + 'name' => ' 个人资料', + 'url' => "/user/{$user['username']}/edit/profile", + ], + 'password' => [ + 'name' => ' 修改密码', + 'url' => "/user/{$user['username']}/edit/password", + ], + ]; + + if (!isset($tabs_info[$cur_tab])) { + become404Page(); + } - $email = $_POST['email']; - if (!validateEmail($email)) { - return "失败:无效电子邮箱。"; - } - $esc_email = DB::escape($email); - DB::update("update user_info set email = '$esc_email' where username = '{$user['username']}'"); + if ($cur_tab == 'profile') { + $update_profile_form = new UOJForm('update_profile'); + $username = UOJLocale::get('username'); + $avatar = UOJLocale::get('avatar'); + $change_avatar_help = UOJLocale::get('change avatar help'); + $update_profile_form->appendHTML(<< + + +
用户名不能被修改。
+ +
+
$avatar
+
$change_avatar_help
+
+EOD); + $update_profile_form->addVInput('email', 'email', UOJLocale::get('email'), $user['email'], + function($email, &$vdata) { + if (!validateEmail($email)) { + return 'Email 格式不合法。'; + } - if ($_POST['Qtag']) { - $qq = $_POST['qq']; - if (!validateQQ($qq)) { - return "失败:无效QQ。"; - } - $esc_qq = DB::escape($qq); - DB::update("update user_info set qq = '$esc_qq' where username = '{$user['username']}'"); + $vdata['email'] = $email; + + return ''; + }, null); + $update_profile_form->addVInput('qq', 'text', UOJLocale::get('QQ'), $user['qq'] == 0 ? '' : $user['qq'], + function($qq, &$vdata) { + if ($qq && !validateQQ($qq)) { + return 'QQ 格式不合法。'; + } + + $vdata['qq'] = $qq; + + return ''; + }, null); + if (isSuperUser($myUser)) { + $update_profile_form->addVInput('school', 'text', UOJLocale::get('school'), $user['school'], + function($school, &$vdata) { + $vdata['school'] = $school; + + return ''; + }, null); } else { - DB::update("update user_info set QQ = NULL where username = '{$user['username']}'"); + $school = UOJLocale::get('school'); + $update_profile_form->appendHTML(<< + + +
只有管理员才能修改用户所属学校。
+ +EOD); } - if ($_POST['sex'] == "U" || $_POST['sex'] == 'M' || $_POST['sex'] == 'F') { - $sex = $_POST['sex']; - $esc_sex = DB::escape($sex); - DB::update("update user_info set sex = '$esc_sex' where username = '{$user['username']}'"); + $update_profile_form->addVSelect('sex', [ + 'U' => UOJLocale::get('refuse to answer'), + 'M' => UOJLocale::get('male'), + 'F' => UOJLocale::get('female'), + ], UOJLocale::get('sex'), $user['sex']); + $update_profile_form->addVInput('motto', 'text', UOJLocale::get('motto'), $user['motto'], + function($motto, &$vdata) { + if (!validateMotto($motto)) { + return '格言格式不合法'; + } + + $vdata['motto'] = $motto; + + return ''; + }, null); + $update_profile_form->addVInput('codeforces_handle', 'text', UOJLocale::get('codeforces handle'), $user['codeforces_handle'], + function($codeforces_handle, &$vdata) { + if ($codeforces_handle && !validateUsername($codeforces_handle)) { + return 'Codeforces 用户名格式不合法。'; + } + + $vdata['codeforces_handle'] = $codeforces_handle; + + return ''; + }, null); + $update_profile_form->handle = function(&$vdata) use ($user, $myUser) { + $esc_email = DB::escape($vdata['email']); + $esc_qq = DB::escape($vdata['qq']); + $esc_sex = DB::escape($vdata['sex']); + $esc_motto = DB::escape($vdata['motto']); + $esc_codeforces_handle = DB::escape($vdata['codeforces_handle']); + + if (isSuperUser($myUser)) { + $esc_school = DB::escape($vdata['school']); + + DB::update("UPDATE user_info SET school = '$esc_school' WHERE username = '{$user['username']}'"); + } + + DB::update("UPDATE user_info SET email = '$esc_email', qq = '$esc_qq', sex = '$esc_sex', motto = '$esc_motto', codeforces_handle = '$esc_codeforces_handle' WHERE username = '{$user['username']}'"); + }; + $update_profile_form->submit_button_config['margin_class'] = 'mt-3'; + $update_profile_form->submit_button_config['text'] = '更新'; + $update_profile_form->runAtServer(); + } elseif ($cur_tab == 'password') { + if (isset($_POST['submit-change_password']) && $_POST['submit-change_password'] == 'change_password') { + header('Content-Type: application/json'); + + $old_password = $_POST['current_password']; + $new_password = $_POST['new_password']; + + if (!validatePassword($old_password) || !checkPassword($user, $old_password)) { + die(json_encode(['status' => 'error', 'message' => '旧密码错误'])); + } + + if (!validatePassword($new_password)) { + die(json_encode(['status' => 'error', 'message' => '新密码不合法'])); + } + + if ($old_password == $new_password) { + die(json_encode(['status' => 'error', 'message' => '新密码不能与旧密码相同'])); + } + + $password = getPasswordToStore($new_password, $user['username']); + DB::update("UPDATE `user_info` SET `password` = '$password' where `username` = '{$user['username']}'"); + die(json_encode(['status' => 'success', 'message' => '密码修改成功'])); } - - if (validateMotto($_POST['motto'])) { - $esc_motto = DB::escape($_POST['motto']); - DB::update("update user_info set motto = '$esc_motto' where username = '{$user['username']}'"); - } - - return "ok"; - } - if (isset($_POST['change'])) { - die(handlePost()); } + + $pageTitle = $user['username'] == $myUser['username'] + ? UOJLocale::get('modify my profile') + : UOJLocale::get('modify his profile', $user['username']) ?> - - - - -

您正在使用管理特权修改 的个人信息。

+ + + +

+ +

+ +
+ +
+ +
+ $tab): ?> + + + + +
+ +"> + 返回 + + + + -
- -

-
- -
- - -
-
- -

-
- -
- - - -
-
-
- -
- - -
-
-
- -
- - -
-
-
- -
- -
-
-
- -
- - 格言支持 Markdown 语法。 -
-
-
-
-

-
-
-
-
- -
-
-
- + + + +
+
+ diff --git a/web/app/libs/uoj-form-lib.php b/web/app/libs/uoj-form-lib.php index b44bb54..16d272a 100644 --- a/web/app/libs/uoj-form-lib.php +++ b/web/app/libs/uoj-form-lib.php @@ -159,7 +159,7 @@ EOD; public function addVSelect($name, $options, $label_text, $default_value) { $default_value = htmlspecialchars($default_value); $html = << +
'; } public static function div_vinput($name, $type, $label_text, $default_value) { - return '
' - . '' + return '
' + . '' . '' - . '' + . '' . '
'; } public static function div_vtextarea($name, $label_text, $default_value) { - return '
' + return '
' . '' . '' . '' diff --git a/web/app/models/Upgrader.php b/web/app/models/Upgrader.php index 05d83f7..3a98771 100644 --- a/web/app/models/Upgrader.php +++ b/web/app/models/Upgrader.php @@ -105,7 +105,7 @@ class Upgrader { public static function upgradeToLatest() { $names = array_filter(scandir(self::upgraderRoot()), function ($name) { - return is_dir(self::upgraderRoot().'/'.$name) && preg_match('/^\d+_[a-zA-Z_]+$/', $name); + return is_dir(self::upgraderRoot().'/'.$name) && preg_match('/^\d+_[0-9a-zA-Z_]+$/', $name); }); natsort($names); diff --git a/web/app/route.php b/web/app/route.php index dd77b1e..f4f2789 100644 --- a/web/app/route.php +++ b/web/app/route.php @@ -72,7 +72,7 @@ Route::group([ Route::any('/reset-password', '/reset_pw.php'); Route::any('/user/{username}', '/user_info.php'); - Route::any('/user/{username}/edit', '/user_info_edit.php'); + Route::any('/user/{username}/edit(?:/{tab})?', '/user_info_edit.php'); Route::any('/user_msg', '/user_msg.php'); Route::any('/user/{username}/system_msg', '/user_system_msg.php'); diff --git a/web/app/upgrade/6_user_info_v2/README.md b/web/app/upgrade/6_user_info_v2/README.md new file mode 100644 index 0000000..e0c36ee --- /dev/null +++ b/web/app/upgrade/6_user_info_v2/README.md @@ -0,0 +1 @@ +ref: https://github.com/renbaoshuo/S2OJ/pull/6 diff --git a/web/app/upgrade/6_user_info_v2/down.sql b/web/app/upgrade/6_user_info_v2/down.sql new file mode 100644 index 0000000..2609831 --- /dev/null +++ b/web/app/upgrade/6_user_info_v2/down.sql @@ -0,0 +1 @@ +ALTER TABLE `user_info` DROP COLUMN IF EXISTS `codeforces_handle`; diff --git a/web/app/upgrade/6_user_info_v2/up.sql b/web/app/upgrade/6_user_info_v2/up.sql new file mode 100644 index 0000000..fc94742 --- /dev/null +++ b/web/app/upgrade/6_user_info_v2/up.sql @@ -0,0 +1 @@ +ALTER TABLE `user_info` ADD COLUMN `codeforces_handle` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; From b433a907e538222440a05d65a94908d686809473 Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Wed, 19 Oct 2022 22:16:10 +0800 Subject: [PATCH 02/12] feat(web/user/edit): github --- web/app/controllers/user_info_edit.php | 13 ++++++++++++- web/app/libs/uoj-validate-lib.php | 4 ++++ web/app/upgrade/6_user_info_v2/down.sql | 1 + web/app/upgrade/6_user_info_v2/up.sql | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/web/app/controllers/user_info_edit.php b/web/app/controllers/user_info_edit.php index 75efaec..c0d0aea 100644 --- a/web/app/controllers/user_info_edit.php +++ b/web/app/controllers/user_info_edit.php @@ -70,6 +70,16 @@ EOD); $vdata['qq'] = $qq; + return ''; + }, null); + $update_profile_form->addVInput('github', 'text', 'GitHub', $user['github'], + function($github, &$vdata) { + if ($github && !validateGitHubUsername($github)) { + return 'GitHub 用户名不合法。'; + } + + $vdata['github'] = $github; + return ''; }, null); if (isSuperUser($myUser)) { @@ -117,6 +127,7 @@ EOD); $update_profile_form->handle = function(&$vdata) use ($user, $myUser) { $esc_email = DB::escape($vdata['email']); $esc_qq = DB::escape($vdata['qq']); + $esc_github = DB::escape($vdata['github']); $esc_sex = DB::escape($vdata['sex']); $esc_motto = DB::escape($vdata['motto']); $esc_codeforces_handle = DB::escape($vdata['codeforces_handle']); @@ -127,7 +138,7 @@ EOD); DB::update("UPDATE user_info SET school = '$esc_school' WHERE username = '{$user['username']}'"); } - DB::update("UPDATE user_info SET email = '$esc_email', qq = '$esc_qq', sex = '$esc_sex', motto = '$esc_motto', codeforces_handle = '$esc_codeforces_handle' WHERE username = '{$user['username']}'"); + DB::update("UPDATE user_info SET email = '$esc_email', qq = '$esc_qq', sex = '$esc_sex', motto = '$esc_motto', codeforces_handle = '$esc_codeforces_handle', github = '$esc_github' WHERE username = '{$user['username']}'"); }; $update_profile_form->submit_button_config['margin_class'] = 'mt-3'; $update_profile_form->submit_button_config['text'] = '更新'; diff --git a/web/app/libs/uoj-validate-lib.php b/web/app/libs/uoj-validate-lib.php index 2ba27fb..61e961a 100644 --- a/web/app/libs/uoj-validate-lib.php +++ b/web/app/libs/uoj-validate-lib.php @@ -55,3 +55,7 @@ function validateURL($url) { function validateString($str) { return preg_match('/[^0-9a-zA-Z]/', $str) !== true; } + +function validateGitHubUsername($username) { + return is_string($username) && preg_match('/^[a-zA-Z0-9_-]{1,20}$/', $username); +} diff --git a/web/app/upgrade/6_user_info_v2/down.sql b/web/app/upgrade/6_user_info_v2/down.sql index 2609831..c6767c4 100644 --- a/web/app/upgrade/6_user_info_v2/down.sql +++ b/web/app/upgrade/6_user_info_v2/down.sql @@ -1 +1,2 @@ ALTER TABLE `user_info` DROP COLUMN IF EXISTS `codeforces_handle`; +ALTER TABLE `user_info` DROP COLUMN IF EXISTS `github`; diff --git a/web/app/upgrade/6_user_info_v2/up.sql b/web/app/upgrade/6_user_info_v2/up.sql index fc94742..0892e4e 100644 --- a/web/app/upgrade/6_user_info_v2/up.sql +++ b/web/app/upgrade/6_user_info_v2/up.sql @@ -1 +1,2 @@ ALTER TABLE `user_info` ADD COLUMN `codeforces_handle` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; +ALTER TABLE `user_info` ADD COLUMN `github` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; From 4446f0653b24f756fca3bc4984b580ac506733de Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Thu, 20 Oct 2022 06:28:57 +0800 Subject: [PATCH 03/12] fix(web/user/edit): sex --- web/app/controllers/user_info_edit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/controllers/user_info_edit.php b/web/app/controllers/user_info_edit.php index c0d0aea..38a663d 100644 --- a/web/app/controllers/user_info_edit.php +++ b/web/app/controllers/user_info_edit.php @@ -128,7 +128,7 @@ EOD); $esc_email = DB::escape($vdata['email']); $esc_qq = DB::escape($vdata['qq']); $esc_github = DB::escape($vdata['github']); - $esc_sex = DB::escape($vdata['sex']); + $esc_sex = DB::escape($_POST['sex']); $esc_motto = DB::escape($vdata['motto']); $esc_codeforces_handle = DB::escape($vdata['codeforces_handle']); From 2bea966b081192f33a7734b9e6f71933ddaf72fd Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Thu, 20 Oct 2022 06:33:49 +0800 Subject: [PATCH 04/12] refactor(web/user): drop bootstrap4 --- web/app/controllers/user_info.php | 136 +-------- web/app/views/page-header.php | 6 - web/css/github_contribution_graph.css | 24 -- web/js/jquery.github_contribution_graph.js | 308 --------------------- 4 files changed, 5 insertions(+), 469 deletions(-) delete mode 100644 web/css/github_contribution_graph.css delete mode 100644 web/js/jquery.github_contribution_graph.js diff --git a/web/app/controllers/user_info.php b/web/app/controllers/user_info.php index 6744dee..688c779 100644 --- a/web/app/controllers/user_info.php +++ b/web/app/controllers/user_info.php @@ -1,4 +1,7 @@ - + - - $user, 'myUser' => $myUser)) ?> - - -
-
-
-
-
- <?= $user['username'] ?> Avatar -
-
-

-
-
-

-

-
-
-

-

-
-
-

-
purify(HTML::parsedown()->line($user['motto'])) ?>
-
- - -
-

register time

-

-
-
-

remote_addr

-

-
-
-

http_x_forwarded_for

-

-
- -
-
-
- - - - - - - - - - 查看 的所有赛后总结 - -
-
-
- -

-
- -
-
- -

- -
-
-
-
- + $user, 'myUser' => $myUser)) ?> diff --git a/web/app/views/page-header.php b/web/app/views/page-header.php index dc6e8ca..4fd4300 100644 --- a/web/app/views/page-header.php +++ b/web/app/views/page-header.php @@ -219,12 +219,6 @@ - - - - - - diff --git a/web/css/github_contribution_graph.css b/web/css/github_contribution_graph.css deleted file mode 100644 index f2a43b6..0000000 --- a/web/css/github_contribution_graph.css +++ /dev/null @@ -1,24 +0,0 @@ -.svg-tip { - padding: 10px; - background: rgba(0,0,0,0.8); - color: #bbb; - font-size: 12px; - position: absolute; - z-index: 99999; - text-align: center; - border-radius: 3px; -} - -.svg-tip:after { - -moz-box-sizing: border-box; - box-sizing: border-box; - position: absolute; - left: 50%; - height: 5px; - width: 5px; - bottom: -10px; - margin: 0 0 0 -5px; - content: " "; - border: 5px solid transparent; - border-top-color: rgba(0,0,0,0.8); -} diff --git a/web/js/jquery.github_contribution_graph.js b/web/js/jquery.github_contribution_graph.js deleted file mode 100644 index c6223f9..0000000 --- a/web/js/jquery.github_contribution_graph.js +++ /dev/null @@ -1,308 +0,0 @@ -/** - * Jquery plugin to render like contribution graph on Github. - * - * @see {@link https://github.com/bachvtuan/Github-Contribution-Graph} - * @author bachvtuan@gmail.com - * @license MIT License - * @since 0.1.0 - */ - -//Format string -if (!String.prototype.formatString) { - String.prototype.formatString = function () { - var args = arguments; - return this.replace(/{(\d+)}/g, function (match, number) { - return typeof args[number] != "undefined" ? args[number] : match; - }); - }; -} - -(function ($) { - $.fn.github_graph = function (options) { - //If the number less than 10, add Zero before it - var prettyNumber = function (number) { - return number < 10 - ? "0" + number.toString() - : (number = number.toString()); - }; - - /* - Count the number on each day and store the object - */ - var processListTimeStamp = function (list_timestamp) { - //The result will store into this varriable - obj_timestamp = {}; - for (var i = 0; i < list_timestamp.length; i++) { - var _type = typeof list_timestamp[i]; - var _d = - _type == "number" - ? new Date(list_timestamp[i]) - : new Date(list_timestamp[i].timestamp); - - var display_date = getDisplayDate(_d); - var increase = _type == "number" ? 1 : list_timestamp[i].count; - if (!obj_timestamp[display_date]) { - obj_timestamp[display_date] = increase; - } else { - obj_timestamp[display_date] += increase; - } - } - }; - - var getDisplayDate = function (date_obj) { - var pretty_month = prettyNumber(date_obj.getMonth() + 1); - var pretty_date = prettyNumber(date_obj.getDate()); - return "{0}-{1}-{2}".formatString( - date_obj.getFullYear(), - pretty_month, - pretty_date - ); - }; - - var getCount = function (display_date) { - if (obj_timestamp[display_date]) { - return obj_timestamp[display_date]; - } - return 0; - }; - - var getColor = function (count) { - if (typeof settings.colors[0] == "string") { - return count > settings.colors.length - 1 - ? settings.colors[settings.colors.length - 1] - : settings.colors[count]; - } - - const isLargeNumber = (element) => element.count > count; - i = settings.colors.findIndex(isLargeNumber); - return i == -1 - ? settings.colors[settings.colors.length - 1].color - : settings.colors[i - 1].color; - }; - - var start = function () { - processListTimeStamp(settings.data); - var wrap_chart = _this; - - settings.colors_length = settings.colors.length; - var radius = settings.border.radius; - var hoverColor = settings.border.hover_color; - var clickCallback = settings.click; - - var start_date; - if (settings.start_date == null) { - // if set null, will get from 365 days from now - start_date = new Date(); - start_date.setMonth(start_date.getMonth() - 12); - start_date.setDate(start_date.getDate() + 1); - } else { - // formats: - // - YYYY-MM-DD - // - YYYY/MM/DD - start_date = new Date(settings.start_date); - } - - end_date = new Date(start_date); - end_date.setMonth(end_date.getMonth() + 12); - end_date.setDate(end_date.getDate() - 1); - - var loop_html = ""; - var step = 13; - - var month_position = []; - month_position.push({ month_index: start_date.getMonth(), x: 0 }); - var using_month = start_date.getMonth(); - - var week = 0; - var g_x = week * step; - var item_html = - ''; - - for ( - ; - start_date.getTime() <= end_date.getTime(); - start_date.setDate(start_date.getDate() + 1) - ) { - if (start_date.getDay() == 0) { - var item_html = - ''; - } - - var month_in_day = start_date.getMonth(); - var data_date = getDisplayDate(start_date); - - if (start_date.getDay() == 0 && month_in_day != using_month) { - using_month = month_in_day; - month_position.push({ month_index: using_month, x: g_x }); - } - var count = getCount(data_date); - var color = getColor(count); - - var y = start_date.getDay() * step; - item_html += - ''; - - if (start_date.getDay() == 6) { - item_html += ""; - loop_html += item_html; - - item_html = null; - - week++; - g_x = week * step; - } - } - - if (item_html != null) { - item_html += ""; - loop_html += item_html; - } - - //trick - if (month_position[1].x - month_position[0].x < 40) { - //Fix ugly graph by remove first item - month_position.shift(0); - } - - for (var i = 0; i < month_position.length; i++) { - var item = month_position[i]; - var month_name = settings.month_names[item.month_index]; - loop_html += - '' + - month_name + - ""; - } - - //Add Monday, Wenesday, Friday label - loop_html += - '{0}'.formatString( - settings.h_days[0] - ) + - '{0}'.formatString( - settings.h_days[1] - ) + - '{0}'.formatString( - settings.h_days[2] - ); - - //Fixed size for now with width= 721 and height = 110 - var wire_html = - '' + - '' + - loop_html + - "" + - ""; - - wrap_chart.html(wire_html); - - $(_this) - .find(".day") - .on("click", function () { - if (clickCallback) { - clickCallback( - $(this).attr("data-date"), - parseInt($(this).attr("data-count")) - ); - } - }); - - $(_this) - .find(".day") - .hover( - function () { - $(this).attr( - "style", - "stroke-width: 1; stroke: " + hoverColor - ); - }, - function () { - $(this).attr("style", "stroke-width:0"); - } - ); - - _this.find("rect").on("mouseenter", mouseEnter); - _this.find("rect").on("mouseleave", mouseLeave); - appendTooltip(); - }; - - var mouseLeave = function (evt) { - $(".svg-tip").hide(); - }; - - //handle event mouseenter when enter into rect element - var mouseEnter = function (evt) { - var target_offset = $(evt.target).offset(); - var count = $(evt.target).attr("data-count"); - var date = $(evt.target).attr("data-date"); - - var count_text = count > 1 ? settings.texts[1] : settings.texts[0]; - var text = "{0} {1} on {2}".formatString(count, count_text, date); - - var svg_tip = $(".svg-tip").show(); - svg_tip.html(text); - var svg_width = Math.round(svg_tip.width() / 2 + 5); - var svg_height = svg_tip.height() * 2 + 10; - - svg_tip.css({ top: target_offset.top - svg_height - 5 }); - svg_tip.css({ left: target_offset.left - svg_width }); - }; - //Append tooltip to display when mouse enter the rect element - //Default is display:none - var appendTooltip = function () { - if ($(".svg-tip").length == 0) { - $("body").append( - '' - ); - } - }; - - var settings = $.extend( - { - colors: ["#eeeeee", "#d6e685", "#8cc665", "#44a340", "#44a340"], - border: { - radius: 2, - hover_color: "#999", - }, - click: null, - start_date: null, - //List of name months - month_names: [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ], - h_days: ["M", "W", "F"], - //Default is empty, it can be overrided - data: [], - }, - options - ); - - var _this = $(this); - - start(); - }; -})(jQuery); From 6710e800909dc6f066c39db6e2be9ba5d9ecaebe Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Thu, 20 Oct 2022 06:41:10 +0800 Subject: [PATCH 05/12] fix: b433a907e538222440a05d65a94908d686809473 --- db/app_uoj233.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/app_uoj233.sql b/db/app_uoj233.sql index 7983cdf..1b30ada 100644 --- a/db/app_uoj233.sql +++ b/db/app_uoj233.sql @@ -817,6 +817,7 @@ CREATE TABLE `user_info` ( `last_visited` timestamp NOT NULL DEFAULT 0, `images_size_limit` int(11) UNSIGNED NOT NULL DEFAULT 104857600, /* 100 MiB */ `codeforces_handle` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `github` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', PRIMARY KEY (`username`), KEY `ac_num` (`ac_num`,`username`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; From 1eb342120ea0264f839c60a8f6dd073af978329c Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Thu, 20 Oct 2022 08:44:55 +0800 Subject: [PATCH 06/12] feat(web/user): show codeforces rating --- web/app/locale/basic/en.php | 10 --- web/app/locale/basic/zh-cn.php | 10 --- web/app/locale/user/en.php | 13 ++++ web/app/locale/user/zh-cn.php | 13 ++++ web/app/models/UOJLocale.php | 2 +- web/app/views/user-info.php | 112 ++++++++++++++++++++++++++------- 6 files changed, 115 insertions(+), 45 deletions(-) create mode 100644 web/app/locale/user/en.php create mode 100644 web/app/locale/user/zh-cn.php diff --git a/web/app/locale/basic/en.php b/web/app/locale/basic/en.php index 18ac3e4..4142075 100644 --- a/web/app/locale/basic/en.php +++ b/web/app/locale/basic/en.php @@ -98,16 +98,6 @@ return [ 'friend links' => 'Frequently Used Links', 'server time' => 'Server Time', 'opensource project' => 'OpenSource Project, modified by S2OJ', - 'admin' => 'Admin', - 'student' => 'Student', - 'teacher' => 'Teacher', - 'problem uploader' => 'Problem Uploader', - 'problem manager' => 'Problem Manager', - 'contest judger' => 'Contest Judger', - 'contest only' => 'Contest Only', - 'last active at' => 'Last active at', - 'online' => 'Online', - 'offline' => 'Offline', 'apps' => 'Apps', 'image hosting' => 'Image Hosting', 'html to markdown' => 'HTML to Markdown', diff --git a/web/app/locale/basic/zh-cn.php b/web/app/locale/basic/zh-cn.php index b33496a..bbc1c5d 100644 --- a/web/app/locale/basic/zh-cn.php +++ b/web/app/locale/basic/zh-cn.php @@ -98,16 +98,6 @@ return [ 'friend links' => '常用链接', 'server time' => '服务器时间', 'opensource project' => '开源项目,S2OJ 魔改版', - 'admin' => '管理员', - 'student' => '学生', - 'teacher' => '老师', - 'problem uploader' => '题目上传者', - 'problem manager' => '题目管理员', - 'contest judger' => '比赛评测员', - 'contest only' => '仅比赛用户', - 'online' => '在线', - 'offline' => '离线', - 'last active at' => '最后活动于', 'apps' => '应用', 'image hosting' => '图床', 'html to markdown' => 'HTML 转 Markdown', diff --git a/web/app/locale/user/en.php b/web/app/locale/user/en.php new file mode 100644 index 0000000..d4e3f0d --- /dev/null +++ b/web/app/locale/user/en.php @@ -0,0 +1,13 @@ + 'Admin', + 'student' => 'Student', + 'teacher' => 'Teacher', + 'problem uploader' => 'Problem Uploader', + 'problem manager' => 'Problem Manager', + 'contest judger' => 'Contest Judger', + 'contest only' => 'Contest Only', + 'last active at' => 'Last active at', + 'online' => 'Online', + 'offline' => 'Offline', +]; diff --git a/web/app/locale/user/zh-cn.php b/web/app/locale/user/zh-cn.php new file mode 100644 index 0000000..f7fe5c5 --- /dev/null +++ b/web/app/locale/user/zh-cn.php @@ -0,0 +1,13 @@ + '管理员', + 'student' => '学生', + 'teacher' => '老师', + 'problem uploader' => '题目上传者', + 'problem manager' => '题目管理员', + 'contest judger' => '比赛评测员', + 'contest only' => '仅比赛用户', + 'online' => '在线', + 'offline' => '离线', + 'last active at' => '最后活动于', +]; diff --git a/web/app/models/UOJLocale.php b/web/app/models/UOJLocale.php index 4c5509f..a986ef3 100644 --- a/web/app/models/UOJLocale.php +++ b/web/app/models/UOJLocale.php @@ -2,7 +2,7 @@ class UOJLocale { public static $supported_locales = array('zh-cn', 'en'); - public static $supported_modules = array('basic', 'contests', 'problems', 'time'); + public static $supported_modules = array('basic', 'contests', 'problems', 'time', 'user'); public static $data = array(); public static $required = array(); diff --git a/web/app/views/user-info.php b/web/app/views/user-info.php index bc22b8f..3caf4f4 100644 --- a/web/app/views/user-info.php +++ b/web/app/views/user-info.php @@ -68,7 +68,7 @@ function fTime($time, $gran = -1) {
- +

@@ -102,35 +102,99 @@ function fTime($time, $gran = -1) {
  • $type): ?> - , - - - - - - - - - - - - - - - + , +
  • +
  • +
  • - + + + +
  • + + +
  • + + + + +
  • + + +
  • +
    Codeforces 
    +
    + + + +
    +
    +
  • @@ -139,16 +203,16 @@ function fTime($time, $gran = -1) { - + - + 0): ?> - , + , @@ -182,7 +246,7 @@ function fTime($time, $gran = -1) { - 赛后总结 +
    @@ -215,7 +279,7 @@ while ($row = DB::fetch($_result)) {

    -
    +

    @@ -233,7 +297,7 @@ while ($row = DB::fetch($_result)) { -

    +
    From 4e9b2a748a8b5719da3654e60152915576768311 Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Thu, 20 Oct 2022 08:45:23 +0800 Subject: [PATCH 07/12] feat(web/user): website --- db/app_uoj233.sql | 1 + web/app/controllers/user_info_edit.php | 13 ++++++++++++- web/app/locale/user/en.php | 1 + web/app/locale/user/zh-cn.php | 1 + web/app/upgrade/6_user_info_v2/up.sql | 1 + web/app/views/user-info.php | 8 ++++++++ 6 files changed, 24 insertions(+), 1 deletion(-) diff --git a/db/app_uoj233.sql b/db/app_uoj233.sql index 1b30ada..fce837f 100644 --- a/db/app_uoj233.sql +++ b/db/app_uoj233.sql @@ -818,6 +818,7 @@ CREATE TABLE `user_info` ( `images_size_limit` int(11) UNSIGNED NOT NULL DEFAULT 104857600, /* 100 MiB */ `codeforces_handle` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `github` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `website` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', PRIMARY KEY (`username`), KEY `ac_num` (`ac_num`,`username`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; diff --git a/web/app/controllers/user_info_edit.php b/web/app/controllers/user_info_edit.php index 38a663d..e4a2f4d 100644 --- a/web/app/controllers/user_info_edit.php +++ b/web/app/controllers/user_info_edit.php @@ -122,6 +122,16 @@ EOD); $vdata['codeforces_handle'] = $codeforces_handle; + return ''; + }, null); + $update_profile_form->addVInput('website', 'text', UOJLocale::get('user::website'), $user['website'], + function($url, &$vdata) { + if ($url && !validateURL($url)) { + return '链接格式不合法。'; + } + + $vdata['website'] = $url; + return ''; }, null); $update_profile_form->handle = function(&$vdata) use ($user, $myUser) { @@ -131,6 +141,7 @@ EOD); $esc_sex = DB::escape($_POST['sex']); $esc_motto = DB::escape($vdata['motto']); $esc_codeforces_handle = DB::escape($vdata['codeforces_handle']); + $esc_website = DB::escape($vdata['website']); if (isSuperUser($myUser)) { $esc_school = DB::escape($vdata['school']); @@ -138,7 +149,7 @@ EOD); DB::update("UPDATE user_info SET school = '$esc_school' WHERE username = '{$user['username']}'"); } - DB::update("UPDATE user_info SET email = '$esc_email', qq = '$esc_qq', sex = '$esc_sex', motto = '$esc_motto', codeforces_handle = '$esc_codeforces_handle', github = '$esc_github' WHERE username = '{$user['username']}'"); + DB::update("UPDATE user_info SET email = '$esc_email', qq = '$esc_qq', sex = '$esc_sex', motto = '$esc_motto', codeforces_handle = '$esc_codeforces_handle', github = '$esc_github', website = '$esc_website' WHERE username = '{$user['username']}'"); }; $update_profile_form->submit_button_config['margin_class'] = 'mt-3'; $update_profile_form->submit_button_config['text'] = '更新'; diff --git a/web/app/locale/user/en.php b/web/app/locale/user/en.php index d4e3f0d..5e72ddd 100644 --- a/web/app/locale/user/en.php +++ b/web/app/locale/user/en.php @@ -1,5 +1,6 @@ 'Website', 'admin' => 'Admin', 'student' => 'Student', 'teacher' => 'Teacher', diff --git a/web/app/locale/user/zh-cn.php b/web/app/locale/user/zh-cn.php index f7fe5c5..c4528f4 100644 --- a/web/app/locale/user/zh-cn.php +++ b/web/app/locale/user/zh-cn.php @@ -1,5 +1,6 @@ '网址', 'admin' => '管理员', 'student' => '学生', 'teacher' => '老师', diff --git a/web/app/upgrade/6_user_info_v2/up.sql b/web/app/upgrade/6_user_info_v2/up.sql index 0892e4e..416ffbf 100644 --- a/web/app/upgrade/6_user_info_v2/up.sql +++ b/web/app/upgrade/6_user_info_v2/up.sql @@ -1,2 +1,3 @@ ALTER TABLE `user_info` ADD COLUMN `codeforces_handle` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; ALTER TABLE `user_info` ADD COLUMN `github` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; +ALTER TABLE `user_info` ADD COLUMN `website` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; diff --git a/web/app/views/user-info.php b/web/app/views/user-info.php index 3caf4f4..6b55c43 100644 --- a/web/app/views/user-info.php +++ b/web/app/views/user-info.php @@ -197,6 +197,14 @@ function fTime($time, $gran = -1) { + +
  • + + + + +
  • + +
    @@ -309,6 +347,99 @@ EOD); return false; }); + +
    +
    + +
    + +
    + +
    + +
    + +
    + > + +
    +
    + > + +
    +
    + +
    + > + +
    + +
    + > + +
    + +
    + > + +
    + +
    + > + +
    +
    + + +
    + +
    + + + +
    +
    diff --git a/web/app/libs/uoj-utility-lib.php b/web/app/libs/uoj-utility-lib.php index 89c649a..8954e89 100644 --- a/web/app/libs/uoj-utility-lib.php +++ b/web/app/libs/uoj-utility-lib.php @@ -129,7 +129,7 @@ function blog_name_decode($name) { return $name; } -function addUserType($user, $type) { +function addUserType(&$user, $type) { $usertype = explode(',', $user['usertype']); if (!in_array($type, $usertype)) { $usertype[] = $type; @@ -137,7 +137,7 @@ function addUserType($user, $type) { $user['usertype'] = implode(',', $usertype); return $user; } -function removeUserType($user, $type) { +function removeUserType(&$user, $type) { $usertype = explode(',', $user['usertype']); if (in_array($type, $usertype)) { $usertype = array_diff($usertype, array($type)); diff --git a/web/app/locale/user/en.php b/web/app/locale/user/en.php index 5e72ddd..281cb57 100644 --- a/web/app/locale/user/en.php +++ b/web/app/locale/user/en.php @@ -1,6 +1,7 @@ 'Website', + 'user type' => 'User type', 'admin' => 'Admin', 'student' => 'Student', 'teacher' => 'Teacher', diff --git a/web/app/locale/user/zh-cn.php b/web/app/locale/user/zh-cn.php index c4528f4..449014c 100644 --- a/web/app/locale/user/zh-cn.php +++ b/web/app/locale/user/zh-cn.php @@ -1,6 +1,7 @@ '网址', + 'user type' => '用户类型', 'admin' => '管理员', 'student' => '学生', 'teacher' => '老师', From 3985b97f2e8d62717de855e53c9270e06be22742 Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Thu, 20 Oct 2022 10:02:53 +0800 Subject: [PATCH 09/12] feat(web/user): qq avatar --- db/app_uoj233.sql | 1 + web/app/controllers/user_info_edit.php | 20 ++++++++++----- web/app/libs/uoj-form-lib.php | 34 +++++++++++++++++++++++++ web/app/locale/user/en.php | 1 + web/app/locale/user/zh-cn.php | 1 + web/app/models/HTML.php | 14 ++++++++++ web/app/upgrade/6_user_info_v2/down.sql | 2 ++ web/app/upgrade/6_user_info_v2/up.sql | 1 + 8 files changed, 67 insertions(+), 7 deletions(-) diff --git a/db/app_uoj233.sql b/db/app_uoj233.sql index fce837f..aa59101 100644 --- a/db/app_uoj233.sql +++ b/db/app_uoj233.sql @@ -819,6 +819,7 @@ CREATE TABLE `user_info` ( `codeforces_handle` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `github` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `website` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `avatar_source` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'gravatar', PRIMARY KEY (`username`), KEY `ac_num` (`ac_num`,`username`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; diff --git a/web/app/controllers/user_info_edit.php b/web/app/controllers/user_info_edit.php index b1354b9..1ab650e 100644 --- a/web/app/controllers/user_info_edit.php +++ b/web/app/controllers/user_info_edit.php @@ -44,17 +44,22 @@ $update_profile_form = new UOJForm('update_profile'); $username = UOJLocale::get('username'); $avatar = UOJLocale::get('avatar'); - $change_avatar_help = UOJLocale::get('change avatar help'); $update_profile_form->appendHTML(<<
    用户名不能被修改。
    -
    -
    $avatar
    -
    $change_avatar_help
    -
    +EOD); + $update_profile_form->addVCheckboxes('avatar_source', [ + 'gravatar' => 'Gravatar', + 'qq' => 'QQ', + ], UOJLocale::get('user::avatar source'), $user['avatar_source']); + $change_avatar_help = UOJLocale::get('change avatar help'); + $update_profile_form->appendHTML(<< + $change_avatar_help +
    EOD); $update_profile_form->addVInput('email', 'email', UOJLocale::get('email'), $user['email'], function($email, &$vdata) { @@ -103,7 +108,7 @@ EOD);
    EOD); } - $update_profile_form->addVSelect('sex', [ + $update_profile_form->addVCheckboxes('sex', [ 'U' => UOJLocale::get('refuse to answer'), 'M' => UOJLocale::get('male'), 'F' => UOJLocale::get('female'), @@ -146,6 +151,7 @@ EOD); $esc_motto = DB::escape($vdata['motto']); $esc_codeforces_handle = DB::escape($vdata['codeforces_handle']); $esc_website = DB::escape($vdata['website']); + $esc_avatar_source = DB::escape($_POST['avatar_source']); if (isSuperUser($myUser)) { $esc_school = DB::escape($vdata['school']); @@ -153,7 +159,7 @@ EOD); DB::update("UPDATE user_info SET school = '$esc_school' WHERE username = '{$user['username']}'"); } - DB::update("UPDATE user_info SET email = '$esc_email', qq = '$esc_qq', sex = '$esc_sex', motto = '$esc_motto', codeforces_handle = '$esc_codeforces_handle', github = '$esc_github', website = '$esc_website' WHERE username = '{$user['username']}'"); + DB::update("UPDATE user_info SET email = '$esc_email', qq = '$esc_qq', sex = '$esc_sex', motto = '$esc_motto', codeforces_handle = '$esc_codeforces_handle', github = '$esc_github', website = '$esc_website', avatar_source = '$esc_avatar_source' WHERE username = '{$user['username']}'"); }; $update_profile_form->submit_button_config['margin_class'] = 'mt-3'; $update_profile_form->submit_button_config['text'] = '更新'; diff --git a/web/app/libs/uoj-form-lib.php b/web/app/libs/uoj-form-lib.php index 16d272a..897111a 100644 --- a/web/app/libs/uoj-form-lib.php +++ b/web/app/libs/uoj-form-lib.php @@ -225,6 +225,40 @@ EOD; EOD; $this->addNoVal($name, $html); } + public function addVCheckboxes($name, $options, $label_text, $default_value) { + $default_value = htmlspecialchars($default_value); + $html = << + +EOD; + foreach ($options as $opt_name => $opt_label) { + $html .= << +EOD; + if ($opt_name != $default_value) { + $html .= << +EOD; + } else { + $html .= << +EOD; + } + $html .= <<$opt_label + +EOD; + } + $html .= << +EOD; + $this->add($name, $html, + function($opt) use ($options) { + return isset($options[$opt]) ? '' : "无效选项"; + }, + null + ); + } public function addCKEditor($name, $label_text, $default_value, $validator_php, $validator_js) { $default_value = htmlspecialchars($default_value); global $REQUIRE_LIB; diff --git a/web/app/locale/user/en.php b/web/app/locale/user/en.php index 281cb57..0d00af9 100644 --- a/web/app/locale/user/en.php +++ b/web/app/locale/user/en.php @@ -1,5 +1,6 @@ 'Avatar source', 'website' => 'Website', 'user type' => 'User type', 'admin' => 'Admin', diff --git a/web/app/locale/user/zh-cn.php b/web/app/locale/user/zh-cn.php index 449014c..0a6da0d 100644 --- a/web/app/locale/user/zh-cn.php +++ b/web/app/locale/user/zh-cn.php @@ -1,5 +1,6 @@ '头像来源', 'website' => '网址', 'user type' => '用户类型', 'admin' => '管理员', diff --git a/web/app/models/HTML.php b/web/app/models/HTML.php index 6bc9981..547e678 100644 --- a/web/app/models/HTML.php +++ b/web/app/models/HTML.php @@ -8,6 +8,20 @@ class HTML { return strip_tags($str); } public static function avatar_addr($user, $size) { + if ($user['avatar_source'] == 'qq' && $user['qq']) { + $s = '5'; + + if ($size <= 40) { + $s = '2'; + } elseif ($size <= 100) { + $s = '3'; + } elseif ($size <= 140) { + $s = '4'; + } + + return "https://q1.qlogo.cn/g?b=qq&nk={$user['qq']}&s=$s"; + } + return '//gravatar.loli.net/avatar/' . md5(strtolower(trim($user['email']))) . "?d=mm&s=$size"; } diff --git a/web/app/upgrade/6_user_info_v2/down.sql b/web/app/upgrade/6_user_info_v2/down.sql index c6767c4..ea11898 100644 --- a/web/app/upgrade/6_user_info_v2/down.sql +++ b/web/app/upgrade/6_user_info_v2/down.sql @@ -1,2 +1,4 @@ ALTER TABLE `user_info` DROP COLUMN IF EXISTS `codeforces_handle`; ALTER TABLE `user_info` DROP COLUMN IF EXISTS `github`; +ALTER TABLE `user_info` DROP COLUMN IF EXISTS `website`; +ALTER TABLE `user_info` DROP COLUMN IF EXISTS `avatar_source`; diff --git a/web/app/upgrade/6_user_info_v2/up.sql b/web/app/upgrade/6_user_info_v2/up.sql index 416ffbf..830ca6f 100644 --- a/web/app/upgrade/6_user_info_v2/up.sql +++ b/web/app/upgrade/6_user_info_v2/up.sql @@ -1,3 +1,4 @@ ALTER TABLE `user_info` ADD COLUMN `codeforces_handle` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; ALTER TABLE `user_info` ADD COLUMN `github` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; ALTER TABLE `user_info` ADD COLUMN `website` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; +ALTER TABLE `user_info` ADD COLUMN `avatar_source` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'gravatar'; From 8977eb263d9312ca20316a20e0651aa09fc80ce7 Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Thu, 20 Oct 2022 10:21:07 +0800 Subject: [PATCH 10/12] feat(web/user/edit): set ajax submit --- web/app/controllers/user_info_edit.php | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/web/app/controllers/user_info_edit.php b/web/app/controllers/user_info_edit.php index 1ab650e..aed14b2 100644 --- a/web/app/controllers/user_info_edit.php +++ b/web/app/controllers/user_info_edit.php @@ -160,9 +160,31 @@ EOD); } DB::update("UPDATE user_info SET email = '$esc_email', qq = '$esc_qq', sex = '$esc_sex', motto = '$esc_motto', codeforces_handle = '$esc_codeforces_handle', github = '$esc_github', website = '$esc_website', avatar_source = '$esc_avatar_source' WHERE username = '{$user['username']}'"); + + header('Content-Type: application/json'); + die(json_encode(['status' => 'success'])); }; $update_profile_form->submit_button_config['margin_class'] = 'mt-3'; $update_profile_form->submit_button_config['text'] = '更新'; + $update_profile_form->setAjaxSubmit(<<runAtServer(); } elseif ($cur_tab == 'password') { if (isset($_POST['submit-change_password']) && $_POST['submit-change_password'] == 'change_password') { @@ -269,6 +291,7 @@ EOD);
    + printHTML() ?>
    @@ -314,6 +337,8 @@ EOD); $('#form-change_password').submit(function() { var ok = true; + $('#result-alert').hide(); + ok &= getFormErrorAndShowHelp('current_password', validatePassword); ok &= getFormErrorAndShowHelp('new_password', validateSettingPassword); @@ -339,6 +364,8 @@ EOD); .addClass('alert-danger') .show(); } + + $(window).scrollTop(0); }, error: function() { $('#result-alert') @@ -346,6 +373,8 @@ EOD); .removeClass('alert-success') .addClass('alert-danger') .show(); + + $(window).scrollTop(0); } }); } @@ -418,6 +447,8 @@ EOD); -
    +