feat: jqValidateForm에 Values Type 지정
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { activeFlip, mb_strwidth, isBrightColor, getIconPath, errUnknown, errUnknownToast, quickReject, initTooltip } from "./common_legacy";
|
||||
import { activeFlip, isBrightColor, getIconPath, errUnknown, errUnknownToast, quickReject, initTooltip } from "./common_legacy";
|
||||
import { mb_strwidth } from "./util/mb_strwidth";
|
||||
import { TemplateEngine } from "./util/TemplateEngine";
|
||||
import { escapeHtml } from "./legacy/escapeHtml";
|
||||
import { nl2br } from "./util/nl2br";
|
||||
|
||||
@@ -8,66 +8,6 @@ import 'bootstrap';
|
||||
import axios from "axios";
|
||||
|
||||
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
//TODO: X-Requested-With 믿지 말자.
|
||||
|
||||
|
||||
|
||||
//https://gist.github.com/demouth/3217440
|
||||
/**
|
||||
* mb_strwidth
|
||||
* @see http://php.net/manual/function.mb-strwidth.php
|
||||
*/
|
||||
export function mb_strwidth(str: string): number {
|
||||
const l = str.length;
|
||||
let length = 0;
|
||||
for (let i = 0; i < l; i++) {
|
||||
const c = str.charCodeAt(i);
|
||||
if (0x0000 <= c && c <= 0x0019) {
|
||||
length += 0;
|
||||
} else if (0x0020 <= c && c <= 0x1FFF) {
|
||||
length += 1;
|
||||
} else if (0x2000 <= c && c <= 0xFF60) {
|
||||
length += 2;
|
||||
} else if (0xFF61 <= c && c <= 0xFF9F) {
|
||||
length += 1;
|
||||
} else if (0xFFA0 <= c) {
|
||||
length += 2;
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mb_strimwidth
|
||||
* @param String
|
||||
* @param int
|
||||
* @param int
|
||||
* @param String
|
||||
* @return String
|
||||
* @see http://www.php.net/manual/function.mb-strimwidth.php
|
||||
*/
|
||||
export function mb_strimwidth(str: string, start: number, width: number, trimmarker = ''): string {
|
||||
const trimmakerWidth = mb_strwidth(trimmarker);
|
||||
const l = str.length;
|
||||
let trimmedLength = 0;
|
||||
const trimmedStr: string[] = [];
|
||||
for (let i = start; i < l; i++) {
|
||||
const c = str.charAt(i);
|
||||
const charWidth = mb_strwidth(c);
|
||||
const next = str.charAt(i + 1);
|
||||
const nextWidth = mb_strwidth(next);
|
||||
|
||||
trimmedLength += charWidth;
|
||||
trimmedStr.push(c);
|
||||
if (trimmedLength + trimmakerWidth + nextWidth > width) {
|
||||
trimmedStr.push(trimmarker);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return trimmedStr.join('');
|
||||
}
|
||||
|
||||
/**
|
||||
* object의 array를 id를 key로 삼는 object로 재 변환
|
||||
*/
|
||||
|
||||
+17
-3
@@ -5,8 +5,7 @@ import 'bootstrap';
|
||||
import { setAxiosXMLHttpRequest } from "./util/setAxiosXMLHttpRequest";
|
||||
import axios from "axios";
|
||||
import { InvalidResponse } from "./defs";
|
||||
import { Rules } from "async-validator";
|
||||
import { JQValidateForm } from "./util/jqValidateForm";
|
||||
import { JQValidateForm, NamedRules } from "./util/jqValidateForm";
|
||||
import { convertFormData } from "./util/convertFormData";
|
||||
|
||||
type ResponseScenarioItem = {
|
||||
@@ -130,7 +129,22 @@ function scenarioPreview() {
|
||||
});
|
||||
}
|
||||
|
||||
const descriptor: Rules = {
|
||||
type InstallFormType = {
|
||||
turnterm: number,
|
||||
sync: 1|0,
|
||||
scenario: number,
|
||||
fiction: number,
|
||||
extend: number,
|
||||
npcmode: number,
|
||||
show_img_level: number,
|
||||
tournament_trig: number,
|
||||
join_mode: number,
|
||||
autorun_user: string[],
|
||||
autorun_user_minutes: number,
|
||||
reserve_open?: string,
|
||||
pre_reserve_open?: string,
|
||||
}
|
||||
const descriptor: NamedRules<InstallFormType> = {
|
||||
turnterm: {
|
||||
required: true,
|
||||
type: "enum",
|
||||
|
||||
+10
-3
@@ -1,8 +1,7 @@
|
||||
|
||||
import axios from 'axios';
|
||||
import jQuery from 'jquery';
|
||||
import { Rules } from 'async-validator';
|
||||
import { JQValidateForm } from './util/jqValidateForm';
|
||||
import { JQValidateForm, NamedRules } from './util/jqValidateForm';
|
||||
import { convertFormData } from './util/convertFormData';
|
||||
import { InvalidResponse } from './defs';
|
||||
import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest';
|
||||
@@ -10,7 +9,15 @@ import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest';
|
||||
jQuery(async function ($) {
|
||||
setAxiosXMLHttpRequest();
|
||||
|
||||
const descriptor: Rules = {
|
||||
type FormValue = {
|
||||
full_reset: string,
|
||||
db_host: string,
|
||||
db_port: number,
|
||||
db_id: string,
|
||||
db_pw: string,
|
||||
db_name: string,
|
||||
}
|
||||
const descriptor: NamedRules<FormValue> = {
|
||||
full_reset: {
|
||||
required: true,
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@ import { isArray, isString, isNumber, isBoolean } from "lodash";
|
||||
export function convertFormData(values: Record<string, null|number[]|string[]|boolean[]|number|string|boolean>): FormData{
|
||||
const formData = new FormData();
|
||||
|
||||
const simpleConv = (v: unknown):string=>{
|
||||
const simpleConv = (v: unknown, key: string):string=>{
|
||||
if(isString(v)){
|
||||
return v;
|
||||
}
|
||||
@@ -16,19 +16,19 @@ export function convertFormData(values: Record<string, null|number[]|string[]|bo
|
||||
if(v===null){
|
||||
return '';
|
||||
}
|
||||
throw new TypeError('지원하지 않는 formData Type');
|
||||
throw new TypeError(`지원하지 않는 formData Type: ${key}`);
|
||||
}
|
||||
|
||||
for(const [key, value] of Object.entries(values)){
|
||||
if(isArray(value)){
|
||||
const arrKey = `${key}[]`;
|
||||
for(const subValue of value){
|
||||
formData.append(arrKey, simpleConv(subValue));
|
||||
formData.append(arrKey, simpleConv(subValue, key));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
formData.append(key, simpleConv(value));
|
||||
formData.append(key, simpleConv(value, key));
|
||||
}
|
||||
|
||||
return formData;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Schema, { Rules, Values } from "async-validator";
|
||||
import Schema, { Rule, Values } from "async-validator";
|
||||
import { isArray } from "lodash";
|
||||
import { mergeKVArray } from "./mergeKVArray";
|
||||
import $ from 'jquery';
|
||||
@@ -8,10 +8,17 @@ type Option = {
|
||||
postParse?: (values:Record<string, string | string[]>, $target?: JQuery<HTMLElement>)=>[Record<string, string | string[]>, Map<string, string>]
|
||||
}
|
||||
|
||||
export class JQValidateForm {
|
||||
type DefaultFormDataType = Record<string, null|number[]|string[]|boolean[]|number|string|boolean>;
|
||||
|
||||
export type NamedRules<T extends Record<string, unknown>> = {
|
||||
[v in keyof T]: Rule
|
||||
}
|
||||
|
||||
export class JQValidateForm<TypedValue extends Values = DefaultFormDataType> {
|
||||
|
||||
public readonly validator: Schema;
|
||||
public readonly inputs: JQuery<HTMLElement>;
|
||||
constructor(public readonly target: JQuery<HTMLElement>, public readonly rule: Rules, public readonly option?:Option) {
|
||||
constructor(public readonly target: JQuery<HTMLElement>, public readonly rule: NamedRules<TypedValue>, public readonly option?:Option) {
|
||||
this.validator = new Schema(rule);
|
||||
this.inputs = target.find(':input');
|
||||
}
|
||||
@@ -29,7 +36,7 @@ export class JQValidateForm {
|
||||
return this;
|
||||
}
|
||||
|
||||
public async validate(): Promise<undefined | Values> {
|
||||
public async validate(): Promise<undefined | TypedValue> {
|
||||
if(this.option?.preParse !== undefined){
|
||||
this.option.preParse(this.target);
|
||||
}
|
||||
@@ -106,6 +113,6 @@ export class JQValidateForm {
|
||||
}
|
||||
this.clearErrMsg();
|
||||
this.inputs.addClass('is-valid');
|
||||
return validateResult;
|
||||
return validateResult as TypedValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { mb_strwidth } from "./mb_strwidth";
|
||||
|
||||
/**
|
||||
* mb_strimwidth
|
||||
* @param String
|
||||
* @param int
|
||||
* @param int
|
||||
* @param String
|
||||
* @return String
|
||||
* @see http://www.php.net/manual/function.mb-strimwidth.php
|
||||
*/
|
||||
export function mb_strimwidth(str: string, start: number, width: number, trimmarker = ''): string {
|
||||
const trimmakerWidth = mb_strwidth(trimmarker);
|
||||
const l = str.length;
|
||||
let trimmedLength = 0;
|
||||
const trimmedStr: string[] = [];
|
||||
for (let i = start; i < l; i++) {
|
||||
const c = str.charAt(i);
|
||||
const charWidth = mb_strwidth(c);
|
||||
const next = str.charAt(i + 1);
|
||||
const nextWidth = mb_strwidth(next);
|
||||
|
||||
trimmedLength += charWidth;
|
||||
trimmedStr.push(c);
|
||||
if (trimmedLength + trimmakerWidth + nextWidth > width) {
|
||||
trimmedStr.push(trimmarker);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return trimmedStr.join('');
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//TODO: X-Requested-With 믿지 말자.
|
||||
//https://gist.github.com/demouth/3217440
|
||||
/**
|
||||
* mb_strwidth
|
||||
* @see http://php.net/manual/function.mb-strwidth.php
|
||||
*/
|
||||
export function mb_strwidth(str: string): number {
|
||||
const l = str.length;
|
||||
let length = 0;
|
||||
for (let i = 0; i < l; i++) {
|
||||
const c = str.charCodeAt(i);
|
||||
if (0x0000 <= c && c <= 0x0019) {
|
||||
length += 0;
|
||||
} else if (0x0020 <= c && c <= 0x1FFF) {
|
||||
length += 1;
|
||||
} else if (0x2000 <= c && c <= 0xFF60) {
|
||||
length += 2;
|
||||
} else if (0xFF61 <= c && c <= 0xFF9F) {
|
||||
length += 1;
|
||||
} else if (0xFFA0 <= c) {
|
||||
length += 2;
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
-113
@@ -1,113 +0,0 @@
|
||||
$(document).ready(function () {
|
||||
$("#main_form").validate({
|
||||
rules: {
|
||||
username: {
|
||||
required: true
|
||||
},
|
||||
password: {
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
username: {
|
||||
required: "유저명을 입력해주세요"
|
||||
},
|
||||
password: {
|
||||
required: "비밀번호를 입력해주세요"
|
||||
}
|
||||
},
|
||||
errorElement: "div",
|
||||
errorPlacement: function (error, element) {
|
||||
// Add the `help-block` class to the error element
|
||||
error.addClass("invalid-feedback");
|
||||
|
||||
if (element.prop("type") === "checkbox") {
|
||||
error.insertAfter(element.parent("label"));
|
||||
} else {
|
||||
error.insertAfter(element);
|
||||
}
|
||||
},
|
||||
highlight: function (element, errorClass, validClass) {
|
||||
$(element).addClass("is-invalid").removeClass("is-valid");
|
||||
},
|
||||
unhighlight: function (element, errorClass, validClass) {
|
||||
$(element).addClass("is-valid").removeClass("is-invalid");
|
||||
}
|
||||
});
|
||||
|
||||
$("#main_form").submit(function () {
|
||||
var raw_password = $('#password').val();
|
||||
var salt = $('#global_salt').val();
|
||||
var hash_pw = sha512(salt + raw_password + salt);
|
||||
|
||||
$.post({
|
||||
url: 'j_login.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
'username': $('#username').val(),
|
||||
'password': hash_pw
|
||||
}
|
||||
}).then(function (obj) {
|
||||
if (obj.result) {
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
if (!obj.reqOTP) {
|
||||
alert(obj.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
var $modal = $('#modalOTP').modal();
|
||||
$modal.on('shown.bs.modal', function () {
|
||||
$('#otp_code').focus();
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#otp_form').submit(function () {
|
||||
$.post({
|
||||
url: 'oauth_kakao/j_check_OTP.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
'otp': $('#otp_code').val(),
|
||||
}
|
||||
}).then(function (obj) {
|
||||
if (obj.result) {
|
||||
alert(obj.reason);
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
|
||||
alert(obj.reason);
|
||||
|
||||
if (obj.reset) {
|
||||
$('#modalOTP').modal('hide')
|
||||
return;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
if (document.body.clientWidth < 700) {
|
||||
var targetWidth = document.body.clientWidth * 0.9;
|
||||
var scale = targetWidth / 700;
|
||||
var $map = $('#running_map');
|
||||
$map.find('.col').css('max-width', targetWidth);
|
||||
$map.find('.card').css('width', targetWidth);
|
||||
$map.find('.map-container').css({
|
||||
'transform-origin': 'top left',
|
||||
'transform': 'scale({0}, {0})'.format(scale),
|
||||
'height': 500 * scale,
|
||||
});
|
||||
$map.find('.map_body').data('scale', scale);
|
||||
}
|
||||
});
|
||||
|
||||
window.fitIframe = function () {
|
||||
var iframe = document.querySelector('#running_map');
|
||||
iframe.style.height = iframe.contentWindow.document.body.scrollHeight + 'px';
|
||||
}
|
||||
+15
-7
@@ -1,13 +1,13 @@
|
||||
import $ from 'jquery';
|
||||
import axios from 'axios';
|
||||
import { Rules } from 'async-validator';
|
||||
import { JQValidateForm } from '../hwe/ts/util/jqValidateForm';
|
||||
import { JQValidateForm, NamedRules } from '../hwe/ts/util/jqValidateForm';
|
||||
import { convertFormData } from '../hwe/ts/util/convertFormData';
|
||||
import { InvalidResponse } from '../hwe/ts/defs';
|
||||
import { setAxiosXMLHttpRequest } from '../hwe/ts/util/setAxiosXMLHttpRequest';
|
||||
import { unwrap_any } from '../hwe/ts/util//unwrap_any';
|
||||
import { sha512 } from 'js-sha512';
|
||||
import { isString } from 'lodash';
|
||||
import { mb_strwidth } from '../hwe/ts/util/mb_strwidth';
|
||||
|
||||
$(async function () {
|
||||
setAxiosXMLHttpRequest();
|
||||
@@ -15,7 +15,16 @@ $(async function () {
|
||||
const terms1P = axios('../terms.1.html');
|
||||
const terms2P = axios('../terms.2.html');
|
||||
|
||||
const descriptor: Rules = {
|
||||
type JoinFormType = {
|
||||
secret_agree: boolean,
|
||||
secret_agree2: boolean,
|
||||
third_use: boolean,
|
||||
username: string,
|
||||
password: string,
|
||||
confirm_password: string,
|
||||
nickname: string,
|
||||
}
|
||||
const descriptor: NamedRules<JoinFormType> = {
|
||||
username: {
|
||||
required: true,
|
||||
min: 4,
|
||||
@@ -81,8 +90,10 @@ $(async function () {
|
||||
},
|
||||
nickname: {
|
||||
required: true,
|
||||
max: 9,
|
||||
asyncValidator: async (rule, value: string) => {
|
||||
if (!value || !isString(value) || mb_strwidth(value) > 18) {
|
||||
throw new Error(`글자 너비가 알파벳 ${18}자보다 길지 않아야합니다`);
|
||||
}
|
||||
const response = await axios({
|
||||
url: 'j_check_dup.php',
|
||||
method: 'post',
|
||||
@@ -100,9 +111,6 @@ $(async function () {
|
||||
options: {
|
||||
messages: {
|
||||
required: "유저명을 입력해주세요",
|
||||
string: {
|
||||
max: (v, l) => `닉네임은 ${l}자를 넘을 수 없습니다`,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+6
-3
@@ -3,9 +3,8 @@ import 'popper.js';
|
||||
import Popper from 'popper.js';
|
||||
(window as unknown as {Popper:unknown}).Popper = Popper;
|
||||
import 'bootstrap';
|
||||
import { JQValidateForm } from '../hwe/ts/util/jqValidateForm';
|
||||
import { JQValidateForm, NamedRules } from '../hwe/ts/util/jqValidateForm';
|
||||
import axios from 'axios';
|
||||
import { Rules } from 'async-validator';
|
||||
import { convertFormData } from '../hwe/ts/util/convertFormData';
|
||||
import { setAxiosXMLHttpRequest } from '../hwe/ts/util/setAxiosXMLHttpRequest';
|
||||
import { unwrap_any } from '../hwe/ts/util/unwrap_any';
|
||||
@@ -161,7 +160,11 @@ window.postOAuthResult = postOAuthResult;
|
||||
$(function ($) {
|
||||
setAxiosXMLHttpRequest();
|
||||
|
||||
const descriptor: Rules = {
|
||||
type LoginFormType = {
|
||||
username: string,
|
||||
password: string,
|
||||
};
|
||||
const descriptor: NamedRules<LoginFormType> = {
|
||||
username: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
|
||||
Reference in New Issue
Block a user