Added bootstrap v4.0.0-beta.6 and more scaffolding
parent
0559058dc2
commit
826e5d99bf
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"bootstrapVersion": 4,
|
||||||
|
"useFlexbox": true,
|
||||||
|
"preBootstrapCustomizations": "app/assets/_bs-variables.scss"
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
{"rules": {"indent": ["error", "tab"], "no-tabs": "off", "react/jsx-indent": ["error", "tab"]}, "extends": "airbnb", "env": {"browser": true, "node": true}}
|
{"rules": {"indent": ["error", "tab"], "no-tabs": "off", "react/jsx-indent": ["error", "tab"], "react/jsx-indent-props": ["error", "tab"]}, "extends": "airbnb", "env": {"browser": true, "node": true}}
|
||||||
|
|
33
Gruntfile.js
33
Gruntfile.js
|
@ -9,6 +9,9 @@ module.exports = function (grunt) {
|
||||||
filename: 'bundle.js',
|
filename: 'bundle.js',
|
||||||
path: './dist/app/'
|
path: './dist/app/'
|
||||||
},
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.jsx'],
|
||||||
|
},
|
||||||
module: {
|
module: {
|
||||||
loaders: [
|
loaders: [
|
||||||
{
|
{
|
||||||
|
@ -38,6 +41,12 @@ module.exports = function (grunt) {
|
||||||
cwd: './app/',
|
cwd: './app/',
|
||||||
src: ['assets/**'],
|
src: ['assets/**'],
|
||||||
dest: './dist/app/assets/'
|
dest: './dist/app/assets/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expand: true,
|
||||||
|
cwd: './node_modules/bootstrap/',
|
||||||
|
src: ['dist/**'],
|
||||||
|
dest: './dist/app/assets/bootstrap/'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -58,15 +67,33 @@ module.exports = function (grunt) {
|
||||||
{
|
{
|
||||||
expand: true,
|
expand: true,
|
||||||
cwd: './server/',
|
cwd: './server/',
|
||||||
src: ['*.js'],
|
src: ['**/*.js'],
|
||||||
dest: './dist/server/'
|
dest: './dist/server/'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
eslint: {
|
eslint: {
|
||||||
app: ['./app/*.js*'],
|
app: {
|
||||||
server: ['./server/*.js']
|
files: [
|
||||||
|
{
|
||||||
|
expand: true,
|
||||||
|
cwd: './app/',
|
||||||
|
src: ['**/*.js*'],
|
||||||
|
dest: './dist/app/'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
expand: true,
|
||||||
|
cwd: './server/',
|
||||||
|
src: ['**/*.js'],
|
||||||
|
dest: './dist/server/'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/prefer-stateless-function
|
||||||
|
export default class Button extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<button className={`btn btn-${this.props.color}`} onClick={this.props.onClick}>
|
||||||
|
{ this.props.children }
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button.propTypes = {
|
||||||
|
children: React.PropTypes.node.isRequired,
|
||||||
|
onClick: React.PropTypes.func,
|
||||||
|
color: React.PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
Button.defaultProps = {
|
||||||
|
onClick: () => {},
|
||||||
|
color: 'primary',
|
||||||
|
};
|
|
@ -0,0 +1,38 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/prefer-stateless-function
|
||||||
|
export default class Column extends React.Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.className = this.className.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
className() {
|
||||||
|
if (this.props.width) {
|
||||||
|
if (this.props.breakpoint) {
|
||||||
|
return `col-${this.props.breakpoint}-${this.props.width}`;
|
||||||
|
}
|
||||||
|
return `col-${this.props.width}`;
|
||||||
|
}
|
||||||
|
return 'col';
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className={this.className()}>
|
||||||
|
{ this.props.children }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column.propTypes = {
|
||||||
|
children: React.PropTypes.node.isRequired,
|
||||||
|
width: React.PropTypes.number,
|
||||||
|
breakpoint: React.PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
Column.defaultProps = {
|
||||||
|
width: null,
|
||||||
|
breakpoint: null,
|
||||||
|
};
|
|
@ -0,0 +1,16 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/prefer-stateless-function
|
||||||
|
export default class Container extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="container">
|
||||||
|
{ this.props.children }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Container.propTypes = {
|
||||||
|
children: React.PropTypes.node.isRequired,
|
||||||
|
};
|
|
@ -0,0 +1,17 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/prefer-stateless-function
|
||||||
|
export default class Row extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="row">
|
||||||
|
{ this.props.children }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row.propTypes = {
|
||||||
|
children: React.PropTypes.node.isRequired,
|
||||||
|
};
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Chronos</title>
|
<title>Chronos</title>
|
||||||
|
<link rel="stylesheet" href="assets/bootstrap/dist/css/bootstrap.min.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root">
|
<div id="root">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<script src="bundle.js"></script>
|
<script src="bundle.js"></script>
|
||||||
|
<script src="assets/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,7 +1,18 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
import { BrowserRouter as Router, Route } from 'react-router-dom';
|
||||||
|
|
||||||
|
import Navigation from './navigation';
|
||||||
|
import PageLogin from './pages/login';
|
||||||
|
import PageMain from './pages/main';
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<h1>Hello, world!</h1>,
|
<Router>
|
||||||
|
<div>
|
||||||
|
<Navigation />
|
||||||
|
<Route exact path="/" component={PageMain} />
|
||||||
|
<Route path="/login" component={PageLogin} />
|
||||||
|
</div>
|
||||||
|
</Router>,
|
||||||
document.getElementById('root'),
|
document.getElementById('root'),
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import Container from './components/layouts/container';
|
||||||
|
import Button from './components/button';
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/prefer-stateless-function
|
||||||
|
export default class Navigation extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<nav className="navbar navbar-inverse bg-inverse sticky-top">
|
||||||
|
<Container>
|
||||||
|
<div className="d-flex flex-row">
|
||||||
|
<span className="navbar-brand">Chronos</span>
|
||||||
|
<ul className="navbar-nav mr-auto">
|
||||||
|
<li className="nav-item">
|
||||||
|
<Link className="nav-link" to="/login">Login</Link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div className="form-inline">
|
||||||
|
<Button color="secondary" onClick={() => alert('test')}>Logout</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Container from '../components/layouts/container';
|
||||||
|
import Button from '../components/button';
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/prefer-stateless-function
|
||||||
|
export default class PageLogin extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Button>
|
||||||
|
Login
|
||||||
|
</Button>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Container from '../components/layouts/container';
|
||||||
|
import Row from '../components/layouts/row';
|
||||||
|
import Column from '../components/layouts/column';
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/prefer-stateless-function
|
||||||
|
export default class PageMain extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Row>
|
||||||
|
<Column width="3" breakpoint="lg">
|
||||||
|
<h1>Hello, world! </h1>
|
||||||
|
</Column>
|
||||||
|
<Column>
|
||||||
|
<h1>Hello, world! </h1>
|
||||||
|
</Column>
|
||||||
|
</Row>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,9 +34,12 @@
|
||||||
"webpack": "^2.2.1"
|
"webpack": "^2.2.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"bootstrap": "^4.0.0-alpha.6",
|
||||||
"express": "^4.14.1",
|
"express": "^4.14.1",
|
||||||
"mysql": "^2.13.0",
|
"mysql": "^2.13.0",
|
||||||
"react": "^15.4.2",
|
"react": "^15.4.2",
|
||||||
"react-dom": "^15.4.2"
|
"react-dom": "^15.4.2",
|
||||||
|
"react-router-dom": "^4.0.0-beta.6",
|
||||||
|
"semver": "^5.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,5 +9,12 @@ export default class API {
|
||||||
this.router.get('/', (req, res) => {
|
this.router.get('/', (req, res) => {
|
||||||
res.end('API v1');
|
res.end('API v1');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.router.all('/*', this.constructor.auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
static auth(req, res, next) {
|
||||||
|
res.end('not implemented');
|
||||||
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import mysql from 'mysql';
|
import mysql from 'mysql';
|
||||||
|
import semver from 'semver';
|
||||||
import { fatal, getVersion } from './utils';
|
import { fatal, getVersion } from './utils';
|
||||||
|
|
||||||
const DATABASE = 'chronos';
|
const DATABASE = 'chronos';
|
||||||
|
@ -12,7 +13,7 @@ export default class Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
query(query, values) {
|
query(query, values) {
|
||||||
console.log('QUERY:', query);
|
console.log('QUERY:', query.replace(/[\n\t]+/g, ' ').replace(/^ /g, '').replace(/ $/g, ''));
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.connection.query(query, values, (err, results, fields) => {
|
this.connection.query(query, values, (err, results, fields) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -23,134 +24,141 @@ export default class Database {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAndMigrate() {
|
async checkAndMigrate() {
|
||||||
this.query(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`, [])
|
return this.query(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`)
|
||||||
.then(() => this.query(`USE ${DATABASE}`, []))
|
.then(() => this.query(`USE ${DATABASE}`))
|
||||||
.then(() => this.query('SELECT value FROM options WHERE option = "version"', (err, result) => {
|
.then(() => this.query('SELECT * FROM options WHERE option = ?', ['VERSION'])
|
||||||
if (err || result === undefined || getVersion() !== result[0].value) {
|
.then(result => this.migrate(result[0] ? result[0].value : null))
|
||||||
return this.migrate(result).catch(e => fatal(e));
|
.catch(() => this.migrate()))
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}))
|
|
||||||
.catch(err => fatal(err));
|
.catch(err => fatal(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
async migrate(oldVersion) {
|
async migrate(oldVersion) {
|
||||||
if (!oldVersion) {
|
if (semver.satisfies(oldVersion, '~1')) {
|
||||||
// create tables
|
// database is up-to-date
|
||||||
const tables = [
|
|
||||||
`CREATE TABLE options (
|
|
||||||
option VARCHAR(12) NOT NULL,
|
|
||||||
value VARCHAR(64) NOT NULL,
|
|
||||||
PRIMARY KEY (option)
|
|
||||||
)`,
|
|
||||||
`CREATE TABLE school (
|
|
||||||
id INT NOT NULL AUTO_INCREMENT,
|
|
||||||
name VARCHAR(64) NOT NULL,
|
|
||||||
domain VARCHAR(32),
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
)`,
|
|
||||||
`CREATE TABLE auth (
|
|
||||||
school INT NOT NULL,
|
|
||||||
id INT NOT NULL,
|
|
||||||
type CHAR(3) NOT NULL,
|
|
||||||
oid_meta VARCHAR(128),
|
|
||||||
oid_cid VARCHAR(64),
|
|
||||||
oid_csecret VARCHAR(64),
|
|
||||||
PRIMARY KEY (school, id),
|
|
||||||
FOREIGN KEY (school) REFERENCES school(id) ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
)`,
|
|
||||||
`CREATE TABLE holiday (
|
|
||||||
id INT NOT NULL AUTO_INCREMENT,
|
|
||||||
name VARCHAR(64) NOT NULL,
|
|
||||||
start DATETIME NOT NULL,
|
|
||||||
end DATETIME NOT NULL,
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
)`,
|
|
||||||
`CREATE TABLE observes (
|
|
||||||
school INT NOT NULL,
|
|
||||||
holiday INT NOT NULL,
|
|
||||||
FOREIGN KEY (school) REFERENCES school(id) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
FOREIGN KEY (holiday) REFERENCES holiday(id) ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
)`,
|
|
||||||
`CREATE TABLE user (
|
|
||||||
school INT NOT NULL,
|
|
||||||
id INT AUTO_INCREMENT NOT NULL,
|
|
||||||
name VARCHAR(64),
|
|
||||||
email VARCHAR(64),
|
|
||||||
oid_id VARCHAR(64),
|
|
||||||
pwd_hash VARCHAR(64),
|
|
||||||
role CHAR(3),
|
|
||||||
PRIMARY KEY (id),
|
|
||||||
FOREIGN KEY (school) REFERENCES school(id) ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
)`,
|
|
||||||
`CREATE TABLE group_ (
|
|
||||||
id INT AUTO_INCREMENT NOT NULL,
|
|
||||||
name VARCHAR(64) NOT NULL,
|
|
||||||
type CHAR(3),
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
)`,
|
|
||||||
`CREATE TABLE group_mentor (
|
|
||||||
id INT NOT NULL,
|
|
||||||
level TINYINT NOT NULL,
|
|
||||||
year YEAR NOT NULL,
|
|
||||||
PRIMARY KEY (id),
|
|
||||||
FOREIGN KEY (id) REFERENCES group_(id) ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
)`,
|
|
||||||
`CREATE TABLE member (
|
|
||||||
user INT NOT NULL,
|
|
||||||
group_ INT NOT NULL,
|
|
||||||
FOREIGN KEY (user) REFERENCES user(id) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
FOREIGN KEY (group_) REFERENCES group_(id) ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
)`,
|
|
||||||
`CREATE TABLE event_once (
|
|
||||||
group_ INT NOT NULL,
|
|
||||||
id INT AUTO_INCREMENT NOT NULL,
|
|
||||||
name VARCHAR(64) NOT NULL,
|
|
||||||
start DATETIME NOT NULL,
|
|
||||||
end DATETIME NOT NULL,
|
|
||||||
PRIMARY KEY (id),
|
|
||||||
FOREIGN KEY (group_) REFERENCES group_(id) ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
)`,
|
|
||||||
`CREATE TABLE attachment (
|
|
||||||
event_once INT NOT NULL,
|
|
||||||
id INT NOT NULL,
|
|
||||||
PRIMARY KEY (event_once, id),
|
|
||||||
FOREIGN KEY (event_once) REFERENCES event_once(id) ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
)`,
|
|
||||||
`CREATE TABLE event_weekly (
|
|
||||||
group_ INT NOT NULL,
|
|
||||||
id INT AUTO_INCREMENT NOT NULL,
|
|
||||||
name VARCHAR(64) NOT NULL,
|
|
||||||
day TINYINT NOT NULL,
|
|
||||||
starttime TIME NOT NULL,
|
|
||||||
endtime TIME NOT NULL,
|
|
||||||
PRIMARY KEY (id),
|
|
||||||
FOREIGN KEY (group_) REFERENCES group_(id) ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
)`,
|
|
||||||
`CREATE TABLE ignored (
|
|
||||||
user INT NOT NULL,
|
|
||||||
event_weekly INT NOT NULL,
|
|
||||||
FOREIGN KEY (user) REFERENCES user(id) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
FOREIGN KEY (event_weekly) REFERENCES event_weekly(id) ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
)`,
|
|
||||||
];
|
|
||||||
|
|
||||||
for (let i = 0; i < tables.length; i += 1) {
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
await this.query(tables[i], []);
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.query(`
|
|
||||||
INSERT INTO options (option, value)
|
|
||||||
VALUES ('version', '${getVersion()}')
|
|
||||||
`);
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
} else if (semver.satisfies(oldVersion, '~0')) { // lmao forces database migration
|
||||||
|
// database needs to be updated
|
||||||
|
return this.query(`DROP DATABASE ${DATABASE}`)
|
||||||
|
.then(() => this.checkAndMigrate());
|
||||||
}
|
}
|
||||||
// for now
|
// database does not exist
|
||||||
return this.query(`DROP DATABASE ${DATABASE}`, [])
|
|
||||||
.then(() => this.checkAndMigrate());
|
// create tables
|
||||||
|
const tables = [
|
||||||
|
`CREATE TABLE options (
|
||||||
|
option VARCHAR(12) NOT NULL,
|
||||||
|
value VARCHAR(64) NOT NULL,
|
||||||
|
PRIMARY KEY (option)
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE school (
|
||||||
|
id INT NOT NULL AUTO_INCREMENT,
|
||||||
|
name VARCHAR(64) NOT NULL,
|
||||||
|
domain VARCHAR(32),
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE auth (
|
||||||
|
school INT NOT NULL,
|
||||||
|
id INT NOT NULL,
|
||||||
|
type CHAR(3) NOT NULL,
|
||||||
|
oid_meta VARCHAR(128),
|
||||||
|
oid_cid VARCHAR(64),
|
||||||
|
oid_csecret VARCHAR(64),
|
||||||
|
PRIMARY KEY (school, id),
|
||||||
|
FOREIGN KEY (school) REFERENCES school(id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE holiday (
|
||||||
|
id INT NOT NULL AUTO_INCREMENT,
|
||||||
|
name VARCHAR(64) NOT NULL,
|
||||||
|
start DATETIME NOT NULL,
|
||||||
|
end DATETIME NOT NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE observes (
|
||||||
|
school INT NOT NULL,
|
||||||
|
holiday INT NOT NULL,
|
||||||
|
FOREIGN KEY (school) REFERENCES school(id) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
FOREIGN KEY (holiday) REFERENCES holiday(id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE user (
|
||||||
|
school INT NOT NULL,
|
||||||
|
id INT AUTO_INCREMENT NOT NULL,
|
||||||
|
name VARCHAR(64),
|
||||||
|
email VARCHAR(64),
|
||||||
|
oid_id VARCHAR(64),
|
||||||
|
pwd_hash VARCHAR(64),
|
||||||
|
role CHAR(3),
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
FOREIGN KEY (school) REFERENCES school(id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE group_ (
|
||||||
|
id INT AUTO_INCREMENT NOT NULL,
|
||||||
|
name VARCHAR(64) NOT NULL,
|
||||||
|
type CHAR(3),
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE group_mentor (
|
||||||
|
id INT NOT NULL,
|
||||||
|
level TINYINT NOT NULL,
|
||||||
|
year YEAR NOT NULL,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
FOREIGN KEY (id) REFERENCES group_(id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE member (
|
||||||
|
user INT NOT NULL,
|
||||||
|
group_ INT NOT NULL,
|
||||||
|
FOREIGN KEY (user) REFERENCES user(id) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
FOREIGN KEY (group_) REFERENCES group_(id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE event_once (
|
||||||
|
group_ INT NOT NULL,
|
||||||
|
id INT AUTO_INCREMENT NOT NULL,
|
||||||
|
name VARCHAR(64) NOT NULL,
|
||||||
|
start DATETIME NOT NULL,
|
||||||
|
end DATETIME NOT NULL,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
FOREIGN KEY (group_) REFERENCES group_(id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE attachment (
|
||||||
|
event_once INT NOT NULL,
|
||||||
|
id INT NOT NULL,
|
||||||
|
PRIMARY KEY (event_once, id),
|
||||||
|
FOREIGN KEY (event_once) REFERENCES event_once(id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE event_weekly (
|
||||||
|
group_ INT NOT NULL,
|
||||||
|
id INT AUTO_INCREMENT NOT NULL,
|
||||||
|
name VARCHAR(64) NOT NULL,
|
||||||
|
day TINYINT NOT NULL,
|
||||||
|
starttime TIME NOT NULL,
|
||||||
|
endtime TIME NOT NULL,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
FOREIGN KEY (group_) REFERENCES group_(id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE ignored (
|
||||||
|
user INT NOT NULL,
|
||||||
|
event_weekly INT NOT NULL,
|
||||||
|
FOREIGN KEY (user) REFERENCES user(id) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
FOREIGN KEY (event_weekly) REFERENCES event_weekly(id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
)`,
|
||||||
|
];
|
||||||
|
for (let i = 0; i < tables.length; i += 1) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await this.query(tables[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set version number
|
||||||
|
await this.query(`
|
||||||
|
INSERT INTO options (option, value)
|
||||||
|
VALUES ('version', '${getVersion()}')
|
||||||
|
`);
|
||||||
|
|
||||||
|
// add first school
|
||||||
|
await this.query(`
|
||||||
|
INSERT INTO school (name, domain)
|
||||||
|
VALUES (?, ?)
|
||||||
|
`, ['NUS High School', 'nushigh.edu.sg']);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue