Commit 861e9909 authored by 神楽坂玲奈's avatar 神楽坂玲奈

reformat code

parent ad3f621b
......@@ -2,15 +2,19 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = lf
[*.md]
max_line_length = 0
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
# Indentation override
#[lib/**.js]
#[{package.json,.travis.yml}]
#[**/**.js]
......@@ -23,11 +23,16 @@
"no-bitwise": [0],
"no-cond-assign": [0],
"import/no-unresolved": [0],
"require-yield": [1]
"require-yield": [1],
"react/react-in-jsx-scope": [0],
"no-extra-semi": [0]
},
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
},
"env": {
"browser": true
}
}
......@@ -18,7 +18,9 @@ class EmailForm extends React.Component {
onSubmit = (e) => {
const { form, dispatch, user: { id } } = this.props;
e && e.preventDefault();
if (e) {
e.preventDefault();
}
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
......
......@@ -18,6 +18,24 @@ class EmailForm extends React.Component {
static contextTypes = {
intl: PropTypes.object.isRequired,
};
onSubmit = (e) => {
const { form, dispatch, user: { id } } = this.props;
if (e) {
e.preventDefault();
}
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
const { new_password, password } = values;
dispatch({ type: 'user/updateAccount', payload: { new_password, password, user_id: id } });
}
});
};
checkPassword = (rule, value, callback) => {
const form = this.props.form;
const { intl: { messages } } = this.context;
......@@ -36,20 +54,6 @@ class EmailForm extends React.Component {
callback();
};
onSubmit = (e) => {
const { form, dispatch, user: { id } } = this.props;
e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
const { new_password, password } = values;
dispatch({ type: 'user/updateAccount', payload: { new_password, password, user_id: id } });
}
});
};
render() {
const { form } = this.props;
......@@ -131,7 +135,7 @@ class EmailForm extends React.Component {
}
function mapStateToProps(state, props) {
function mapStateToProps(state) {
const {
user: { user },
} = state;
......
......@@ -18,7 +18,9 @@ class EmailForm extends React.Component {
onSubmit = (e) => {
const { form, dispatch, user: { id } } = this.props;
e && e.preventDefault();
if (e) {
e.preventDefault();
}
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
......@@ -59,7 +61,8 @@ class EmailForm extends React.Component {
{getFieldDecorator('email', { ...emailProps.decorator })(
<Input
{...emailProps.input}
onBlur={() => dispatch({ type: 'auth/checkEmail', payload: { ...form.getFieldsValue(), id } })}/>,
onBlur={() => dispatch({ type: 'auth/checkEmail', payload: { ...form.getFieldsValue(), id } })}
/>,
)}
</FormItem>
......
......@@ -18,7 +18,9 @@ class EmailForm extends React.Component {
onSubmit = (e) => {
const { form, dispatch, user: { id } } = this.props;
e && e.preventDefault();
if (e) {
e.preventDefault();
}
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
......
/* global apiRoot */
export default {
apiRoot: apiRoot
apiRoot,
};
......@@ -11,7 +11,7 @@ import './index.less';
// 1. Initialize
const app = dva({
onError: (error, dispatch) => {
onError: (error) => {
message.destroy();
message.error(error.message);
},
......
html, body, :global(#root) {
height: 100%;
min-height: 100%;
}
:global {
......@@ -21,4 +21,4 @@ html, body, :global(#root) {
opacity: 0.01;
transition: opacity 300ms ease-in;
}
}
\ No newline at end of file
}
......@@ -21,7 +21,7 @@ export default {
register: {},
},
reducers: {
signOut(state){
signOut(state) {
console.log('sign out');
localStorage.removeItem('token');
localStorage.removeItem('user');
......
import { Redirect, Route, Router } from 'dva/router';
import { Route, Router } from 'dva/router';
import React from 'react';
import Active from './routes/Activate.js';
......
......@@ -14,9 +14,11 @@ class Login extends React.Component {
};
onSubmitLogin = (e) => {
const { form, dispatch, params: { id } } = this.props;
const { form, dispatch } = this.props;
e && e.preventDefault();
if (e) {
e.preventDefault();
}
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
......@@ -33,7 +35,7 @@ class Login extends React.Component {
const { loading } = this.props;
const { intl: { messages } } = this.context;
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%'}}>
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
<Spin spinning={loading} delay={100}>
<Form onSubmit={this.onSubmitLogin} className="login-form">
......@@ -46,7 +48,10 @@ class Login extends React.Component {
{getFieldDecorator('email', {
rules: [{ required: true, message: 'Please input your username or email!' }],
})(
<Input prefix={<Icon type="user" style={{ fontSize: 13 }}/>} placeholder={messages['email-address-or-username']}/>,
<Input
prefix={<Icon type="user" style={{ fontSize: 13 }}/>}
placeholder={messages['email-address-or-username']}
/>,
)}
</FormItem>
......
......@@ -124,12 +124,12 @@ const particleConfig = {
function Index({ children, messages, dispatch }) {
return (
<div style={{ height: '100%'}}>
<DocumentTitle title={messages.title || 'Moe Cube'} />
<div style={{ display: 'flex', flexDirection: 'column', minHeight: '100%' }}>
<DocumentTitle title={messages.title || 'Moe Cube'}/>
<Header style={{ display: 'flex', alignItems: 'center' }}>
<Link to="/" style={{ marginTop: '20px' }}>
<img src={logo} style={{ width: '140px', height: '44px' }}/>
<img src={logo} style={{ width: '140px', height: '44px' }} alt="logo"/>
</Link>
<Menu
......@@ -152,10 +152,14 @@ function Index({ children, messages, dispatch }) {
style={{ lineHeight: '64px', position: 'absolute', right: '50px' }}
>
{localStorage.getItem('user') ? (<Menu.Item key="1">
<div onClick={() => { dispatch({ type : 'auth/signOut' }) }}>
<div
onClick={() => {
dispatch({ type: 'auth/signOut' });
}}
>
<Format id="sign-out"/>
</div>
</Menu.Item>):(<div></div>)
</Menu.Item>) : (<div/>)
}
</Menu>
</Header>
......@@ -168,7 +172,7 @@ function Index({ children, messages, dispatch }) {
/>
{children}
<Footer style={{ position: 'absolute', width: '100%'}}>
<Footer style={{ position: 'absolute', width: '100%' }}>
<div>© MoeCube 2017 all right reserved.</div>
</Footer>
</div>
......
.particles {
position: fixed;
top: 0;
left: 0;
z-index: 1;
width: 100%;
height: 100%;
}
\ No newline at end of file
.particles {
position: fixed;
top: 0;
left: 0;
z-index: 1;
width: 100%;
height: 100%;
}
......@@ -35,7 +35,7 @@ class Login extends React.Component {
const { intl: { messages } } = this.context;
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
<div style={{ display: 'flex', flexGrow: 1, justifyContent: 'center', alignItems: 'center', height: '100%' }}>
<Spin spinning={loading} delay={100}>
<Form onSubmit={this.onSubmitLogin} className="login-form">
......@@ -43,14 +43,20 @@ class Login extends React.Component {
{getFieldDecorator('account', {
rules: [{ required: true, message: messages['Please input your account!'] }],
})(
<Input prefix={<Icon type="user" style={{ fontSize: 13 }}/>} placeholder={messages['email-address-or-username']}/>,
<Input
prefix={<Icon type="user" style={{ fontSize: 13 }}/>}
placeholder={messages['email-address-or-username']}
/>,
)}
</FormItem>
<FormItem>
{getFieldDecorator('password', {
rules: [{ required: true, message: messages['Please-input-your-Password!'] }],
})(
<Input prefix={<Icon type="lock" style={{ fontSize: 13 }}/>} type="password" placeholder={messages.password}/>,
<Input
prefix={<Icon type="lock" style={{ fontSize: 13 }}/>} type="password"
placeholder={messages.password}
/>,
)}
</FormItem>
<FormItem>
......
......@@ -19,11 +19,11 @@ const formItemLayout = {
wrapperCol: { span: 15 },
};
function getBase64(img, callback) {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
reader.readAsDataURL(img);
}
// function getBase64(img, callback) {
// const reader = new FileReader();
// reader.addEventListener('load', () => callback(reader.result));
// reader.readAsDataURL(img);
// }
class Profiles extends React.Component {
......@@ -31,15 +31,20 @@ class Profiles extends React.Component {
intl: PropTypes.object.isRequired,
};
handleUpload = () => {
if (typeof this.cropper.getCroppedCanvas() === 'undefined') {
return;
onUpdateSubmit = (e) => {
const { form, dispatch, user: { id } } = this.props;
if (e) {
e.preventDefault();
}
const { user: { id } } = this.props;
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
this.cropper.getCroppedCanvas().toBlob(blob => {
console.log(blob);
this.props.dispatch({ type: 'upload/upload', payload: { image: blob, user_id: id } });
const { username, name, password } = values;
dispatch({ type: 'user/updateProfile', payload: { username, name, password, user_id: id } });
}
});
};
......@@ -57,18 +62,15 @@ class Profiles extends React.Component {
reader.readAsDataURL(files[0]);
};
onUpdateSubmit = (e) => {
const { form, dispatch, user: { id }, } = this.props;
e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
const { username, name, password } = values;
handleUpload = () => {
if (typeof this.cropper.getCroppedCanvas() === 'undefined') {
return;
}
const { user: { id } } = this.props;
dispatch({ type: 'user/updateProfile', payload: { username, name, password, user_id: id } });
}
this.cropper.getCroppedCanvas().toBlob((blob) => {
console.log(blob);
this.props.dispatch({ type: 'upload/upload', payload: { image: blob, user_id: id } });
});
};
......@@ -91,7 +93,7 @@ class Profiles extends React.Component {
},
};
/* eslint-disable jsx-a11y/label-has-for */
return (
<Spin spinning={loading} delay={100}>
<Tabs defaultActiveKey="1" className="app-detail-nav">
......@@ -103,20 +105,25 @@ class Profiles extends React.Component {
isUpload ?
<div>
<Cropper
ref={cropper => {
ref={(cropper) => {
this.cropper = cropper;
}}
src={ imageUrl || defaultAvatar}
src={imageUrl || defaultAvatar}
style={{ height: '20vw', width: '20vw' }}
aspectRatio={1 / 1}
guides={true}
guides
/>
<Button>
<label >
<label>
<Icon type="plus"/> add file
<input type="file" onChange={this.onGetFile} ref={file => {
this.file = file;
}} style={{ display: 'none' }}/>
<input
type="file"
onChange={this.onGetFile}
ref={(file) => {
this.file = file;
}}
style={{ display: 'none' }}
/>
</label>
</Button>
<Button type="primary" onClick={this.handleUpload}>
......@@ -124,9 +131,11 @@ class Profiles extends React.Component {
</Button>
</div>
:
<img src={avatar || imageUrl || defaultAvatar}
style={{ height: '256px', width: '256px' }}
onClick={() => dispatch({ type: 'upload/start' })}
<img
alt="avatar"
src={avatar || imageUrl || defaultAvatar}
style={{ height: '256px', width: '256px' }}
onClick={() => dispatch({ type: 'upload/start' })}
/>
}
......
import { Button, Form, Icon, Input, Select, Spin, Steps } from 'antd';
import { Button, Form, Icon, Input, Spin, Steps } from 'antd';
import { connect } from 'dva';
import { Link } from 'dva/router';
import React, { PropTypes } from 'react';
import { FormattedMessage as Format } from 'react-intl';
const FormItem = Form.Item;
const Option = Select.Option;
const Step = Steps.Step;
......@@ -16,14 +15,16 @@ class Register extends React.Component {
};
onSubmitLogin = (e) => {
const { form, dispatch, params: { id } } = this.props;
const { form, dispatch } = this.props;
e && e.preventDefault();
if (e) {
e.preventDefault();
}
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
const { email, username, password, } = values;
const { email, username, password } = values;
dispatch({ type: 'auth/register', payload: { email, username, password } });
}
......@@ -49,15 +50,17 @@ class Register extends React.Component {
};
render() {
const { dispatch, register, form, checkEmail, checkUsername, isEmailExists, isUserNameExists, isRegisterSubmit, loading } = this.props;
const { getFieldDecorator, } = form;
const { email, username, password } = register;
const {
dispatch, form, checkEmail, checkUsername,
isEmailExists, isUserNameExists, loading,
} = this.props;
const { getFieldDecorator } = form;
const { intl: { messages } } = this.context;
const emailProps = {
hasFeedback: true,
validateStatus: checkEmail,
help: isEmailExists ? messages['i_email_exists'] : '',
help: isEmailExists ? messages.i_email_exists : '',
};
const emailInputProps = {
......@@ -77,7 +80,7 @@ class Register extends React.Component {
};
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%'}}>
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
<Spin spinning={loading} delay={100}>
<Steps size="large" current={0}>
......@@ -86,7 +89,7 @@ class Register extends React.Component {
</Steps>
<Form onSubmit={this.onSubmitLogin} className="login-form" style={{ marginTop: '24px' }}>
<FormItem {...emailProps} >
<FormItem {...emailProps} >
{getFieldDecorator('email', {
rules: [{
required: true,
......@@ -123,7 +126,8 @@ class Register extends React.Component {
<Input
prefix={<Icon type="lock" style={{ fontSize: 13 }}/>}
type="password"
placeholder={messages.password}/>,
placeholder={messages.password}
/>,
)}
</FormItem>
......@@ -141,7 +145,8 @@ class Register extends React.Component {
prefix={<Icon type="lock" style={{ fontSize: 13 }}/>}
type="password"
onBlur={this.handleConfirmBlur}
placeholder={messages['password-again']}/>,
placeholder={messages['password-again']}
/>,
)}
</FormItem>
......@@ -163,7 +168,10 @@ class Register extends React.Component {
function mapStateToProps(state) {
const {
auth: { register, checkEmail, checkUsername, isEmailExists, isUserNameExists, isRegisterSubmit },
auth: {
register, checkEmail, checkUsername, isEmailExists,
isUserNameExists, isRegisterSubmit,
},
} = state;
const loading = state.loading.global || false;
......
......@@ -20,7 +20,6 @@
}
}
.action {
margin-top: 24px;
}
\ No newline at end of file
}
import { Button, Form, Icon, Input, Select, Spin } from 'antd';
import { Button, Form, Icon, Input, Spin } from 'antd';
import { connect } from 'dva';
import React, { PropTypes } from 'react';
import { FormattedMessage as Format } from 'react-intl';
const FormItem = Form.Item;
const Option = Select.Option;
class Reset extends React.Component {
......@@ -16,7 +14,9 @@ class Reset extends React.Component {
onSubmitReset = (e) => {
const { form, dispatch, location: { query: { key, user_id } } } = this.props;
e && e.preventDefault();
if (e) {
e.preventDefault();
}
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
......@@ -55,7 +55,7 @@ class Reset extends React.Component {
<Spin spinning={isResetSubmit} delay={100}>
<Form onSubmit={this.onSubmitReset} className="login-form">
<FormItem>
<h1><Format id='reset-password2'/></h1>
<h1><Format id="reset-password2"/></h1>
</FormItem>
<FormItem>
{getFieldDecorator('password', {
......@@ -63,8 +63,10 @@ class Reset extends React.Component {
}, {
validator: this.checkConfirm,
})(
<Input prefix={<Icon type="lock" style={{ fontSize: 13 }}/>} type="password"
placeholder={messages.password}/>,
<Input
prefix={<Icon type="lock" style={{ fontSize: 13 }}/>} type="password"
placeholder={messages.password}
/>,
)}
</FormItem>
......@@ -81,7 +83,7 @@ class Reset extends React.Component {
</FormItem>
<Button type="primary" htmlType="submit" className="login-form-button">
<Format id='reset-password2'/>
<Format id="reset-password2"/>
</Button>
</Form>
</Spin>
......@@ -90,7 +92,7 @@ class Reset extends React.Component {
}
}
function mapStateToProps(state, props) {
function mapStateToProps(state) {
const {
auth: { isResetSubmit },
} = state;
......
......@@ -4,6 +4,7 @@ import { routerRedux } from 'dva/router';
import React, { PropTypes } from 'react';
import { FormattedMessage as Format } from 'react-intl';
import SubmitButton from '../components/SubmitButton';
const FormItem = Form.Item;
const Step = Steps.Step;
......@@ -20,7 +21,9 @@ class Verify extends React.Component {
onSubmit = (e) => {
const { form, dispatch, input: { password }, user: { id } } = this.props;
e && e.preventDefault();
if (e) {
e.preventDefault();
}
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
......@@ -35,12 +38,14 @@ class Verify extends React.Component {
onReSend = (e) => {
const { dispatch, input: { password }, user: { id, email } } = this.props;
e && e.preventDefault();
if (e) {
e.preventDefault();
}
dispatch({ type: 'user/updateEmail', payload: { email, password, user_id: id } });
};
render(select) {
render() {
const { form, dispatch, user, checkEmail, isEmailExists, loading, input } = this.props;
const { getFieldDecorator } = form;
const { id, email } = user;
......@@ -64,7 +69,8 @@ class Verify extends React.Component {
return (
<div
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', flex: 1 }}>
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', flex: 1 }}
>
<Spin spinning={loading} delay={100}>
<Steps size="large" current={1}>
......@@ -72,7 +78,7 @@ class Verify extends React.Component {
<Step title={messages['verify-email']} icon={<Icon type="mail"/>}/>
</Steps>
{id && input['password'] ?
{id && input.password ?
<Alert
style={{ marginTop: '24px' }}
message={
......@@ -93,8 +99,9 @@ class Verify extends React.Component {
message={
<div>
<span style={{ marginRight: '10px' }}><Format id={'Please-sign-in'}/></span>
<Tag color="blue" onClick={ () => dispatch(routerRedux.replace('/signin'))}><Format
id={'sign-in'}/></Tag>
<Tag color="blue" onClick={() => dispatch(routerRedux.replace('/signin'))}><Format
id={'sign-in'}
/></Tag>
</div>
}
type="warning"
......@@ -109,7 +116,8 @@ class Verify extends React.Component {
{getFieldDecorator('email', { ...emailProps.decorator })(
<Input
{...emailProps.input}
onBlur={() => dispatch({ type: 'auth/checkEmail', payload: { ...form.getFieldsValue(), id } })}/>,
onBlur={() => dispatch({ type: 'auth/checkEmail', payload: { ...form.getFieldsValue(), id } })}
/>,
)}
</FormItem>
......@@ -125,7 +133,7 @@ class Verify extends React.Component {
}
}
function mapStateToProps(state, props) {
function mapStateToProps(state) {
const {
user: { user },
auth: { input, isEmailExists, checkEmail },
......
import request from '../utils/request';
export async function login(params) {
return request(`/signin`, {
return request('/signin', {
method: 'POST',
body: JSON.stringify(params),
});
}
export async function forgot(params) {
return request(`/forgot`, {
return request('/forgot', {
method: 'POST',
body: JSON.stringify(params),
});
}
export async function register(params) {
return request(`/signup`, {
return request('/signup', {
method: 'POST',
body: JSON.stringify(params),
});
}
export async function reset(params) {
return request(`/reset`, {
return request('/reset', {
method: 'PATCH',
body: JSON.stringify(params),
});
}
export async function activate(params) {
return request(`/activate`, {
return request('/activate', {
method: 'POST',
body: JSON.stringify(params),
});
......@@ -50,7 +50,7 @@ export async function getUserByUsername(params) {
}
export async function checkUserExists(params) {
return request(`/user/exists`, {
return request('/user/exists', {
method: 'POST',
body: JSON.stringify(params),
});
......@@ -58,7 +58,7 @@ export async function checkUserExists(params) {
export async function getAuthUser(params) {
return request(`/authUser`, {
return request('/authUser', {
method: 'GET',
headers: {
Authorization: `Bearer ${params.token}`,
......
import request from '../utils/request';
export async function uploadImage(params) {
console.log(params);
let data = new FormData();
data.append('file', params['image']);
const data = new FormData();
data.append('file', params.image);
return request('/upload/image', {
method: 'POST',
......
......@@ -10,11 +10,11 @@ async function checkStatus(response) {
return response;
}
let message
let message;
try {
message = (await response.json())["message"]
message = (await response.json()).message;
} catch (error) {
message = response.statusText
message = response.statusText;
}
const error = new Error(message);
......@@ -29,17 +29,19 @@ async function checkStatus(response) {
* @param {object} [options] The options we want to pass to "fetch"
* @return {object} An object containing either "data" or "err"
*/
export default function request(url, options) {
url = `${config.apiRoot}${url}`
if(options && !options.headers) {
options.headers = {
"content-type": "application/json"
}
export default function request(relativeUrl, options) {
const url = `${config.apiRoot}${relativeUrl}`;
if (options && !options.headers) {
Object.assign(options, {
headers: {
'content-type': 'application/json',
},
});
}
console.log(options)
console.log(options);
return fetch(url, options)
.then(checkStatus)
.then(parseJSON)
.then(data => ({ data }))
// .catch(err => ({ err }));
}
.then(data => ({ data }));
// .catch(err => ({ err }));
};
import crypto from 'crypto'
import "url-api-polyfill";
import crypto from 'crypto';
import 'url-api-polyfill';
const url = new URL(window.location)
let sso
let ssoString = url.searchParams.get('sso')
let sso;
const ssoString = new URL(window.location).searchParams.get('sso');
if (ssoString) {
sso = new URLSearchParams(Buffer.from(ssoString, 'base64').toString())
sso = new URLSearchParams(Buffer.from(ssoString, 'base64').toString());
}
export const handleSSO = (user) => {
if(sso) {
let params = new URLSearchParams()
let url = new URL(sso.get("return_sso_url"));
if (sso) {
const params = new URLSearchParams();
const url = new URL(sso.get('return_sso_url'));
for (let [key, value] of Object.entries(user)) {
params.set(key, value)
for (const [key, value] of Object.entries(user)) {
params.set(key, value);
}
params.set("return_sso_url", sso.get("return_sso_url"))
params.set("nonce", sso.get("nonce"))
params.set("external_id", user.id)
let payload = Buffer.from(params.toString()).toString('base64')
url.searchParams.set("sso", payload)
url.searchParams.set('sig', crypto.createHmac('sha256', 'zsZv6LXHDwwtUAGa').update(payload).digest('hex'))
window.location.href = url
return true
}else {
return false
params.set('return_sso_url', sso.get('return_sso_url'));
params.set('nonce', sso.get('nonce'));
params.set('external_id', user.id);
const payload = Buffer.from(params.toString()).toString('base64');
url.searchParams.set('sso', payload);
url.searchParams.set('sig', crypto.createHmac('sha256', 'zsZv6LXHDwwtUAGa').update(payload).digest('hex'));
window.location.href = url;
return true;
} else {
return false;
}
}
\ No newline at end of file
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment