const {h, render, Component} = preact;
const html = htm.bind(h);
class Login extends Component {
state = {user: '', pass: ''};
onclick = (app) => {
const authhdr = 'Basic ' + btoa(this.state.user + ':' + this.state.pass);
const headers = {Authorization: authhdr};
return axios.get('/api/login', {headers})
.then(res => app.setUser(res.data.token))
.catch(err => alert('Login failed'));
};
onpassinput = (ev) => this.setState({pass: ev.target.value});
onuserinput = (ev) => this.setState({user: ev.target.value});
render({app}, {user, pass, signup}) {
return html`
`
}
};
class Dropdown extends Component {
state = {show: false};
render(props, state) {
const onclick = x => this.setState({show: x});
const show = state.show ? 'show' : '';
return html`
onclick(!state.show)}
class="dropdown-toggle my-0 ${props.bcls}"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
${props.title}
onclick(false)} style=${props.dstyle}
class="dropdown-menu ${props.dcls} ${show}">
${props.children}
`;
}
};
const NavLink = ({href, title, url}) => html`${title}`;
class Header extends Component {
state = {expanded: false};
ontoggle = () => this.setState({expanded: !this.state.expanded});
render(props, state) {
const u = props.app.state.user || {};
return html`
`
}
};
class AdminDashboard extends Component {
state = {udata: '', adata: ''};
componentDidMount() {
axios.get('/api/user/data').then(r => this.setState({udata: r.data}));
axios.get('/api/admin/data').then(r => this.setState({adata: r.data}));
}
render(props, state) {
console.log('-->', state);
return html`
this is admin page
admin data, returned by server:
${JSON.stringify(state.adata)}
user data, returned by server:
${JSON.stringify(state.udata)}
`
}
}
class UserDashboard extends Component {
state = {udata: ''};
componentDidMount() {
axios.get('/api/user/data').then(r => this.setState({udata: r.data}));
axios.get('/api/admin/data').then(r => this.setState({adata: r.data}));
}
render(props, state) {
return html`
admin data, returned by server (must be empty and dev tools should show 403):
${JSON.stringify(state.adata)}
user data, returned by server:
${JSON.stringify(state.udata)}
`
}
}
class Settings extends Component {
state = {};
render(props, state) {
return html`settings page
`
}
}
class App extends Component {
state = {user: null, url: '/'};
setUser(token) {
const maxAge = token ? 86400 : 0;
document.cookie = `access_token=${token};path=/;max-age=${maxAge}`;
// this.setState({token});
return axios.get('/api/login')
.then(res => this.setState({user: res.data}))
.catch(err => this.setState({user: {}}));
}
componentDidMount() {
const getCookie = name => {
var v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
return v ? v[2] : '';
};
this.setUser(getCookie('access_token')); // Move from state1 to 2 or 3
}
render(props, state) {
// We have three states:
// 1. Beginning. We don't know if we have a valid auth token or not
// 2. We sent an /api/login request, and failed to login
// 3. We sent an /api/login request, and succeeded to login
if (!state.user) return ''; // State 1
if (!state.user.user) return h(Login, {app: this}); // State 2
return h( // State 3
'div', {}, h(Header, {url: state.url, app: this}),
h(preactRouter.Router, {
history: History.createHashHistory(),
onChange: ev => this.setState({url: ev.url}),
},
h(state.user.user == 'admin' ? AdminDashboard : UserDashboard,
{default: true, app: this}),
h(Settings, {path: 'settings', app: this})));
}
};
window.onload = () => render(h(App), document.body);