Commit a9f7623a authored by Tan Bui's avatar Tan Bui

Init

parents
Pipeline #852 failed with stages
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# testing
/coverage
# production
/build
/dist
/.next
# misc
.DS_Store
.env
npm-debug.log*
yarn-debug.log*
yarn-error.log*
/tags
image:
name: docker/compose:1.23.2
entrypoint: [""]
stages:
- build
- deploy
- test
test:
stage: test
script: echo "Running tests"
only:
- master
build:
stage: build
script:
- echo "Building the app"
- docker build . -t next-react-base:development
only:
- master
deploy_production:
stage: deploy
script:
- echo "Deploy to production server"
- docker-compose down
- docker-compose -f docker-compose.yml up -d
environment:
name: production
only:
- master
FROM node:8.14.0-jessie
LABEL maintainer "tanbm.hut@gmail.com"
RUN npm install -g yarn
WORKDIR /app
COPY ./package.json /app/package.json
COPY ./yarn.lock /app/yarn.lock
RUN yarn install
COPY . /app
RUN yarn build
CMD ["yarn", "start"]
build:
docker-compose build app
app:
yarn dev
up:
docker-compose -f docker-compose.yml up -d
down:
docker-compose -f docker-compose.yml down
logs:
docker-compose logs -ft --tail 50 app
hbash:
docker-compose run --rm app bash
bash:
docker-compose exec -it app bash
This project was bootstrapped with [Create Next App](https://github.com/zeit/next.js).
Find the most recent version of this guide at [here](https://github.com/zeit/next.js/blob/master/lib/templates/default/README.md). And check out [Next.js repo](https://github.com/zeit/next.js) for the most up-to-date info.
## Table of Contents
- [Questions? Feedback?](#questions-feedback)
- [Folder Structure](#folder-structure)
- [Available Scripts](#available-scripts)
- [npm run dev](#npm-run-dev)
- [npm run build](#npm-run-build)
- [npm run start](#npm-run-start)
- [Using CSS](#using-css)
- [Adding Components](#adding-components)
- [Fetching Data](#fetching-data)
- [Custom Server](#custom-server)
- [Syntax Highlighting](#syntax-highlighting)
- [Using the `static` Folder](#using-the-static-folder)
- [Deploy to Now](#deploy-to-now)
- [Something Missing?](#something-missing)
## Questions? Feedback?
Check out [Next.js FAQ & docs](https://github.com/zeit/next.js#faq) or [let us know](https://github.com/zeit/next.js/issues) your feedback.
## Folder Structure
After creating an app, it should look something like:
```
.
├── README.md
├── components
│ ├── head.js
│ └── nav.js
├── next.config.js
├── node_modules
│ ├── [...]
├── package.json
├── pages
│ └── index.js
├── static
│ └── favicon.ico
└── yarn.lock
```
Routing in Next.js is based on the file system, so `./pages/index.js` maps to the `/` route and
`./pages/about.js` would map to `/about`.
The `./static` directory maps to `/static` in the `next` server, so you can put all your
other static resources like images or compiled CSS in there.
Out of the box, we get:
- Automatic transpilation and bundling (with webpack and babel)
- Hot code reloading
- Server rendering and indexing of `./pages`
- Static file serving. `./static/` is mapped to `/static/`
Read more about [Next's Routing](https://github.com/zeit/next.js#routing)
## Available Scripts
In the project directory, you can run:
### `npm run dev`
Runs the app in the development mode.<br>
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.<br>
You will also see any errors in the console.
### `npm run build`
Builds the app for production to the `.next` folder.<br>
It correctly bundles React in production mode and optimizes the build for the best performance.
### `npm run start`
Starts the application in production mode.
The application should be compiled with \`next build\` first.
See the section in Next docs about [deployment](https://github.com/zeit/next.js/wiki/Deployment) for more information.
## Using CSS
[`styled-jsx`](https://github.com/zeit/styled-jsx) is bundled with next to provide support for isolated scoped CSS. The aim is to support "shadow CSS" resembling of Web Components, which unfortunately [do not support server-rendering and are JS-only](https://github.com/w3c/webcomponents/issues/71).
```jsx
export default () => (
<div>
Hello world
<p>scoped!</p>
<style jsx>{`
p {
color: blue;
}
div {
background: red;
}
@media (max-width: 600px) {
div {
background: blue;
}
}
`}</style>
</div>
)
```
Read more about [Next's CSS features](https://github.com/zeit/next.js#css).
## Adding Components
We recommend keeping React components in `./components` and they should look like:
### `./components/simple.js`
```jsx
const Simple = () => <div>Simple Component</div>
export default Simple // don't forget to export default!
```
### `./components/complex.js`
```jsx
import { Component } from 'react'
class Complex extends Component {
state = {
text: 'World'
}
render() {
const { text } = this.state
return <div>Hello {text}</div>
}
}
export default Complex // don't forget to export default!
```
## Fetching Data
You can fetch data in `pages` components using `getInitialProps` like this:
### `./pages/stars.js`
```jsx
const Page = props => <div>Next stars: {props.stars}</div>
Page.getInitialProps = async ({ req }) => {
const res = await fetch('https://api.github.com/repos/zeit/next.js')
const json = await res.json()
const stars = json.stargazers_count
return { stars }
}
export default Page
```
For the initial page load, `getInitialProps` will execute on the server only. `getInitialProps` will only be executed on the client when navigating to a different route via the `Link` component or using the routing APIs.
_Note: `getInitialProps` can **not** be used in children components. Only in `pages`._
Read more about [fetching data and the component lifecycle](https://github.com/zeit/next.js#fetching-data-and-component-lifecycle)
## Custom Server
Want to start a new app with a custom server? Run `create-next-app --example custom-server custom-app`
Typically you start your next server with `next start`. It's possible, however, to start a server 100% programmatically in order to customize routes, use route patterns, etc
This example makes `/a` resolve to `./pages/b`, and `/b` resolve to `./pages/a`:
```jsx
const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
createServer((req, res) => {
// Be sure to pass `true` as the second argument to `url.parse`.
// This tells it to parse the query portion of the URL.
const parsedUrl = parse(req.url, true)
const { pathname, query } = parsedUrl
if (pathname === '/a') {
app.render(req, res, '/b', query)
} else if (pathname === '/b') {
app.render(req, res, '/a', query)
} else {
handle(req, res, parsedUrl)
}
}).listen(3000, err => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
```
Then, change your `start` script to `NODE_ENV=production node server.js`.
Read more about [custom server and routing](https://github.com/zeit/next.js#custom-server-and-routing)
## Syntax Highlighting
To configure the syntax highlighting in your favorite text editor, head to the [relevant Babel documentation page](https://babeljs.io/docs/editors) and follow the instructions. Some of the most popular editors are covered.
## Deploy to Now
[now](https://zeit.co/now) offers a zero-configuration single-command deployment.
1. Install the `now` command-line tool either via the recommended [desktop tool](https://zeit.co/download) or via node with `npm install -g now`.
2. Run `now` from your project directory. You will see a **now.sh** URL in your output like this:
```
> Ready! https://your-project-dirname-tpspyhtdtk.now.sh (copied to clipboard)
```
Paste that URL into your browser when the build is complete, and you will see your deployed app.
You can find more details about [`now` here](https://zeit.co/now).
## Something Missing?
If you have ideas for how we could improve this readme or the project in general, [let us know](https://github.com/zeit/next.js/issues) or [contribute some!](https://github.com/zeit/next.js/edit/master/lib/templates/default/README.md)
const config = require("./config."+(process.env.NODE_ENV || "dev")+".js");
module.exports = {
presets: [
"next/babel",
],
plugins: [
["@babel/plugin-proposal-optional-chaining"],
["transform-define", config],
["module-resolver", {
root: ["."],
alias: {
styles: "./styles"
},
cwd: "babelrc",
}],
["@babel/plugin-proposal-decorators", { "legacy": true }],
["lodash"],
["import", {
libraryName: "antd"
}]
]
}
export * from "./pin";
import React, {PureComponent} from 'react';
const ICON = `M20.2,15.7L20.2,15.7c1.1-1.6,1.8-3.6,1.8-5.7c0-5.6-4.5-10-10-10S2,4.5,2,10c0,2,0.6,3.9,1.6,5.4c0,0.1,0.1,0.2,0.2,0.3
c0,0,0.1,0.1,0.1,0.2c0.2,0.3,0.4,0.6,0.7,0.9c2.6,3.1,7.4,7.6,7.4,7.6s4.8-4.5,7.4-7.5c0.2-0.3,0.5-0.6,0.7-0.9
C20.1,15.8,20.2,15.8,20.2,15.7z`;
const pinStyle = {
cursor: 'pointer',
fill: '#d00',
stroke: 'none'
};
export const Pin = class CustomPin extends PureComponent {
render() {
const {size = 20, onClick} = this.props;
return (
<svg
height={size}
viewBox="0 0 24 24"
style={{
...pinStyle
}}
onClick={onClick}
>
<path d={ICON} />
</svg>
);
}
}
module.exports = {
DEFAULT_VIEWPORT: {
latitude: 21.026745,
longitude: 105.801982,
zoom: 16,
bearing: 0,
pitch: 0
}
}
module.exports = {
DEFAULT_VIEWPORT: {
latitude: 21.026745,
longitude: 105.801982,
zoom: 16,
bearing: 0,
pitch: 0
}
}
version: "2.1"
services:
app:
build: .
image: 'next-react-base:development'
environment:
NODE_ENV: production
command: sh -c 'yarn start'
working_dir: /app
ports:
- '8600:3000'
import React from 'react';
import MainLayout from '../layouts';
/*
* Higher order component that passes `getInitialProps` through
* to the child component
*/
export const Main = Child => {
return class Higher extends React.Component {
static getInitialProps = async (ctx) => {
const pageProps = Child.getInitialProps ? await Child.getInitialProps(ctx) : {};
return {
...pageProps
}
}
render() {
return (
<MainLayout>
<Child {...this.props} />
</MainLayout>
);
}
}
}
import React from "react";
import { Layout, Menu, Breadcrumb } from 'antd';
const { Header, Content, Footer } = Layout;
import { withRouter } from 'next/router';
import Link from 'next/link';
@withRouter
export default class MainLayout extends React.Component {
constructor(props){
super(props);
this.state = this.state ? {
...this.state,
path: props.router.pathname,
collapsed: false
}:{
path: props.router.pathname,
collapsed: false
}
}
render(){
return(
<Layout className="layout">
<Header>
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={[this.state.path]}
onSelect={this.onSelect}
style={{ lineHeight: '64px' }}
>
<Menu.Item key="/"><Link href="/"><a className="nav-text">Dashboard</a></Link></Menu.Item>
</Menu>
</Header>
<Content style={{ padding: '0 0' }}>
<div style={{ background: '#fff', padding: 0, minHeight: 'calc(100vh - 69px - 64px)', margin: 0 }}>
{ this.props.children }
</div>
</Content>
<Footer style={{ textAlign: 'center' }}>Goong copyright 2019 - Created by Goong Team</Footer>
</Layout>
);
}
}
const withSass = require('@zeit/next-sass')
const webpack = require('webpack')
module.exports = withSass({
webpack: config => {
config.node = {
fs: 'empty'
}
config.module.rules.push(
{
test: /.mjs$/,
include: /node_modules/,
type: "javascript/auto"
}
);
return config
}
});
import React from 'react';
import Head from 'next/head';
import { ConfigProvider } from 'antd';
import App, { Container } from 'next/app';
import vi_VN from 'antd/lib/locale-provider/vi_VN';
export default class MainApp extends App {
render() {
const { Component, pageProps, store, router } = this.props;
return (
<Container>
<Head>
<meta charSet="UTF-8" />
<title>Mext React App Base</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/antd/3.14.1/antd.min.css" />
</Head>
<ConfigProvider locale={vi_VN}>
<Component {...pageProps} />
</ConfigProvider>
</Container>
)
}
}
import Document, { Head, Main, NextScript } from 'next/document';
class MyDocument extends Document {
render() {
return (
<html>
<Head>
<link href="/static/favicon.ico" rel="shortcut icon" />
</Head>
<body className="order-body">
<Main />
<NextScript />
</body>
</html>
);
}
}
export default MyDocument;
import React from 'react';
import Head from 'next/head';
import Link from 'next/link';
import { Tag, Button } from 'antd';
export default class Error extends React.Component {
static getInitialProps({ res, err }) {
const statusCode = res ? res.statusCode : err ? err.statusCode : null;
const errorMsg = res ? res.message : err ? err.message : null;
return { statusCode, errorMsg };
}
render() {
return (
<div style={{ display: 'flex', height: '100vh', alignItems: 'center', justifyContent: 'center' }}>
<Head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/antd/3.13.2/antd.min.css" />
<title>Oops page</title>
</Head>
{this.props.statusCode ? (<div style={{textAlign: "center"}}>
<div style={{display: "flex", alignItems: "center", justifyContent: "center"}}>
<Tag color="#f50" style={{fontSize: 35, lineHeight: "50px", height: 50}}>{this.props.statusCode}</Tag>
<div style={{borderRight: "1px", borderColor: "#888", textAlign: "left"}}>
{this.props.errorMsg || "An error occurred on server!"}
</div>
</div>
</div>) : (
<div>
<Tag color="#f50">Unknown</Tag>
<span> | {this.props.errorMsg || "An error occurred!"}</span>
</div>
)}
</div>
);
}
}
import React from 'react';
import { Main } from "../hocs";
@Main
class Home extends React.Component {
static async getInitialProps({ req, query, params }) {
return { query }
}
constructor(props) {
super(props);
this.state = {
...props.query,
};
}
render(){
return <React.Fragment>
Next React Base Project
</React.Fragment>
}
}
export default Home
const nextRoutes = require('next-routes')
const routes = (module.exports = nextRoutes())
//routes.add('index', '/:id')
const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const routes = require('./routes');
const handle = routes.getRequestHandler(app);
app.prepare().then(() => {
createServer((req, res) => {
const parsedUrl = parse(req.url, true)
const { pathname, query } = parsedUrl
handle(req, res, parsedUrl)
}).listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
import axios from "axios";
const { CancelToken } = axios;
export const GET = (url, params, options = {}) => {
let cancel;
let promise = new Promise((resolve, reject) => {
axios.get(`${options.host_name || HOST_NAME}${url}`, {
params: {
...params,
api_key: options.api_key || API_KEY
},
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
})
.then(res => {
resolve(res);
})
.catch(err => {
reject(err);
});
});
promise.cancel = cancel;
return promise;
}
export const DecodeGeometry = (t, e) => {
for (var n, r, i = 0, o = 0, s = 0, a = [], u = 0, c = 0, l = null, f = Math.pow(10, e || 5); i < t.length;) {
l = null, u = 0, c = 0;
do l = t.charCodeAt(i++) - 63, c |= (31 & l) << u, u += 5; while (l >= 32);
n = 1 & c ? ~(c >> 1) : c >> 1, u = c = 0;
do l = t.charCodeAt(i++) - 63, c |= (31 & l) << u, u += 5; while (l >= 32);
r = 1 & c ? ~(c >> 1) : c >> 1, o += n, s += r, a.push([s / f, o / f])
}
return a;
}
/**
* IndexOf function for object with key, default by :id, return -1 -> is not found!
* @param {Object} obj description
* @param {string} key = "id" description
* @return {number} description
*/
Array.prototype.oIndexOf = function(obj, key = "id") {
return this.map(function(e) {
return e[key];
}).indexOf(obj[key]);
};
String.prototype.cNormalize = function() {
return this
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/đ/g, "d")
.replace(/Đ/g, "D")
.toLowerCase();
}
Array.prototype.oContains = function(obj, oKey = null) {
return this.map(function(e) {
return oKey ? JSON.stringify(e[oKey]) : JSON.stringify(e);
}).indexOf(oKey ? JSON.stringify(obj[oKey]) : JSON.stringify(obj)) > -1;
};
/**
* Number.prototype.format(n, x, s, c)
*
* @param integer n: length of decimal
* @param integer x: length of whole part
* @param mixed s: sections delimiter
* @param mixed c: decimal delimiter
*/
Number.prototype.format = function(n, x, s, c) {
var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
num = this.toFixed(Math.max(0, ~~n));
return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
};
/**
* Convert character first to uper case
*/
String.prototype.capitalize = function () {
return this.charAt(0).toUpperCase() + this.slice(1);
}
/**
* Conver field name to real string
*/
String.prototype.toFieldName = function () {
const texts = this.split(/[.,\-_/ "'/+:/$]|(?=[A-Z])/)
return texts.reduce(function (accumulator, currentValue) {
return accumulator + ( currentValue && " " + currentValue.capitalize())
}).capitalize()
}
export const RemoveById = (mapView, id) => {
if(mapView.getLayer(id)) mapView.removeLayer(id);
if(mapView.getSource(id)) mapView.removeSource(id);
}
export const DrawLine = (mapView, id, coordinates, options) => {
if(!options) options = {};
RemoveById(mapView, id);
mapView.addSource(id, {
"type": "geojson",
"data": {
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": coordinates
}
}
});
mapView.addLayer({
id: id,
"type": "line",
"source": id,
"layout": {
'visibility': 'visible',
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': options.colorLine || '#080',
'line-opacity': options.opacity || 0.8,
'line-width': options.width || 6
}
})
}
export const EnabledBuilding = (mapView, enable, fieldName, layer_id) => {
if(enable){
mapView.addLayer({
'id': layer_id || '3d-buildings',
'source': 'composite',
'source-layer': fieldName || 'VN_Building',
'filter': ['==', 'extrude', 'true'],
'type': 'fill-extrusion',
'minzoom': 15,
'paint': {
'fill-extrusion-color': '#aaa',
'fill-extrusion-height': {
'type': 'identity',
'property': 'height'
},
'fill-extrusion-base': {
'type': 'identity',
'property': 'min_height'
},
'fill-extrusion-opacity': .4
}
});
}
else{
if(mapView.getLayer(layer_id || '3d-buildings')) mapView.removeLayer(layer_id || '3d-buildings');
}
}
import axios from "axios";
import { GET } from "./base_request";
import { API_URL } from "../consts";
export default {
}
This diff is collapsed.
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