diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..8665c43 --- /dev/null +++ b/.babelrc @@ -0,0 +1,8 @@ +{ + "presets" : ["es2015", "react"], + "env": { + "development": { + "plugins": ["react-hot-loader/babel", "transform-runtime"] + } + } +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0611608 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true + +# Matches multiple files with brace expansion notation +# Set default charset +[*.{js,json,jsx,css}] +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..553fbf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,254 @@ + +# Created by https://www.gitignore.io/api/osx,windows,linux,webstorm,sublimetext,vim,emacs,node + +### OSX ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon +# Thumbnails +._* +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +### Windows ### +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + + +### WebStorm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/workspace.xml +.idea/tasks.xml + +# Sensitive or high-churn files: +.idea/dataSources.ids +.idea/dataSources.xml +.idea/dataSources.local.xml +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml + +# Gradle: +.idea/gradle.xml +.idea/libraries + +# Mongo Explorer plugin: +.idea/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### WebStorm Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + + +### SublimeText ### +# cache files for sublime text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# workspace files are user-specific +*.sublime-workspace + +# project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using SublimeText +# *.sublime-project + +# sftp configuration file +sftp-config.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + + +### Vim ### +# swap +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +# session +Session.vim +# temporary +.netrwhist +# auto-generated tag files +tags + + +### Emacs ### +# -*- mode: gitignore; -*- +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +### Node ### +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +### Others ### +dist +build +yarn.lock +temp +tmp diff --git a/README.md b/README.md deleted file mode 100644 index 020c3f3..0000000 --- a/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Comunidade NodeBR - -Este repositório engloba o frontend e o backend do site oficial da comunidade -https://nodebr.org. - -Todos estão convidados a participar, basta escolher em qual parte do projeto -você deseja contribuir. - -### Backend - -O nosso backend é uma aplicação simples rodando Node.js e conectada a um banco -de dados. Pessoas sem muita experiência não terão problemas em entender o código -e pode *botar a mão na massa* em pouco tempo. - -Envie PR para a branch: [backend](https://github.com/nodebr/nodebr/tree/backend) - -### Frontend - -Nosso frontend é um pouco mais complicado pois os interessados terão que entender -um pouco de React, Redux e WebPack. Caso você seja familiar com estas tecnologias, -mesmo que ha pouco tempo, está convidado a enviar sua PR. - -Envie PR para a branch: [frontend](https://github.com/nodebr/nodebr/tree/frontend) - -### Canais de ajuda - -Antes de iniciar sua contribuição é recomendável que você acesse nosso canal no -Slack, nossa lista de e-mails ou até mesmo as issues desde repositório para -saber melhor por onde começar e evitar trabalhar na mesma coisa que outra pessoa -já está trabalhando. - -* [Canal no Slack](https://slack.nodebr.org) -* [Lista de E-mails](https://groups.google.com/d/forum/nodebr) -* [Issues](https://github.com/nodebr/nodebr/issues) - -### Licença - -Todo o código produzido neste repositório é livre para a utilização por qualquer -pessoa ou empresa dentro das normas da [Licença ISC](LICENSE) diff --git a/config/webpack.config.js b/config/webpack.config.js new file mode 100644 index 0000000..acab8c4 --- /dev/null +++ b/config/webpack.config.js @@ -0,0 +1,75 @@ +const path = require('path') +const webpack = require('webpack') +const HtmlWebpackPlugin = require('html-webpack-plugin') +const CleanWebpackPlugin = require('clean-webpack-plugin') +const ExtractTextPlugin = require('extract-text-webpack-plugin') + +const root = path.resolve(__dirname, '../') + +const config = { + entry: { + app: path.resolve(root, './src/main.js'), + vendors: path.resolve(root, './src/vendors.js') + }, + output: { + path: path.resolve(root, './dist'), + filename: '/static/js/[name]-[hash].js' + }, + resolve: {}, + module: { + loaders: [ + { + test: /\.js?/, + exclude: /node_modules/, + loader: 'babel' + }, + { + test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, + loader: 'url', + query: { + limit: 10000, + name: '/static/img/[name].[hash].[ext]' + } + }, + { + test: /\.json$/, + loader: 'json' + }, + { + test: /\.css$/, + loader: ExtractTextPlugin.extract('style-loader', 'css-loader') + }, + { + test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, + loader: 'url', + query: { + limit: 10000, + name: '/static/fonts/[name].[hash].[ext]' + } + } + ] + }, + plugins: [ + new CleanWebpackPlugin(['dist', 'build'], { root }), + new HtmlWebpackPlugin({ + template: path.resolve(root, './src/index.html'), + inject: 'body' + }), + new webpack.DefinePlugin({ + 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV) } + }), + new webpack.ProvidePlugin({ + $: 'jquery', + jQuery: 'jquery' + }), + new ExtractTextPlugin('/static/css/[name].[hash].css') + ] +} + +if (process.env.NODE_ENV === 'production') { + require('./webpack.prod')(config, root) +} else if (process.env.NODE_ENV === 'development') { + require('./webpack.dev')(config, root) +} + +module.exports = config diff --git a/config/webpack.dev.js b/config/webpack.dev.js new file mode 100644 index 0000000..aac25e7 --- /dev/null +++ b/config/webpack.dev.js @@ -0,0 +1,10 @@ +const path = require('path') + +module.exports = (config, root) => { + config.entry.app = [ + 'react-hot-loader/patch', + path.resolve(root, './src/main.js') + ] + + config.devtool = 'eval' +} diff --git a/config/webpack.prod.js b/config/webpack.prod.js new file mode 100644 index 0000000..0b130cf --- /dev/null +++ b/config/webpack.prod.js @@ -0,0 +1,22 @@ +const webpack = require('webpack') +const { set } = require('lodash') +const AppcacheWebpackPlugin = require('appcache-webpack-plugin') + +module.exports = config => { + config.plugins.push( + new webpack.optimize.OccurrenceOrderPlugin(true), + new webpack.optimize.LimitChunkCountPlugin(), + new webpack.optimize.DedupePlugin(), + new webpack.optimize.UglifyJsPlugin({ + compress: { warnings: false } + }), + new AppcacheWebpackPlugin({ + settings: ['prefer-online'], + output: 'web.appcache' + }) + ) + + set(config, 'resolve.alias.react', 'react-lite') + set(config, 'resolve.alias.react-dom', 'react-lite') + config.devtool = 'source-map' +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..986c843 --- /dev/null +++ b/package.json @@ -0,0 +1,47 @@ +{ + "name": "nodebr", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "NODE_ENV=production webpack --progress --colors --config ./config/webpack.config.js", + "dev": "NODE_ENV=development webpack-dev-server --content-base ./src --history-api-fallback --hot --inline --config ./config/webpack.config.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "standard": { + "parser": "babel-eslint" + }, + "dependencies": { + "appcache-webpack-plugin": "^1.3.0", + "axios": "^0.15.2", + "babel-core": "^6.18.0", + "babel-eslint": "^7.1.0", + "babel-loader": "^6.2.5", + "babel-plugin-transform-runtime": "^6.15.0", + "babel-preset-es2015": "^6.18.0", + "babel-preset-react": "^6.16.0", + "bootstrap": "^3.3.7", + "clean-webpack-plugin": "^0.1.13", + "css-loader": "^0.25.0", + "extract-text-webpack-plugin": "^1.0.1", + "file-loader": "^0.9.0", + "font-awesome": "^4.7.0", + "html-webpack-plugin": "^2.24.0", + "jquery": "^3.1.1", + "json-loader": "^0.5.4", + "lodash": "^4.16.6", + "react": "^15.3.2", + "react-dom": "^15.3.2", + "react-hot-loader": "3.0.0-beta.6", + "react-lite": "^0.15.26", + "react-router": "^3.0.0", + "standard": "^8.5.0", + "style-loader": "^0.13.1", + "url-loader": "^0.5.7", + "webpack": "^1.13.3", + "webpack-dev-server": "^1.16.2" + } +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..edf6cc0 --- /dev/null +++ b/readme.md @@ -0,0 +1,17 @@ +# Projeto NodeBR + +Para instalar e rodar o projeto localmente siga os seguintes passos: + +```bash +git clone https://github.com/nodebr/nodebr.git +cd nodebr && git checkout frontend +npm install +npm run dev +``` + +### Comandos + +* `npm run dev` roda um servidor local pronto para o desenvolvimento. O site +ficará disponível no endereço `http://localhost:8080` +* `npm run build` compila o projeto pronto para fazer deploy. Todos os arquivos +necessários estarão na pasta `dist/` diff --git a/src/assets/logo.png b/src/assets/logo.png new file mode 100644 index 0000000..d34197c Binary files /dev/null and b/src/assets/logo.png differ diff --git a/src/assets/nodebr.svg b/src/assets/nodebr.svg new file mode 100644 index 0000000..e198bfc --- /dev/null +++ b/src/assets/nodebr.svg @@ -0,0 +1,75 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/components/images/logo.js b/src/components/images/logo.js new file mode 100644 index 0000000..2803552 --- /dev/null +++ b/src/components/images/logo.js @@ -0,0 +1,11 @@ +import React from 'react' +import logo from '../../assets/logo.png' + +export default class LogoImage extends React.Component { + render () { + return + } +} diff --git a/src/components/layouts/default.js b/src/components/layouts/default.js new file mode 100644 index 0000000..f6a1a86 --- /dev/null +++ b/src/components/layouts/default.js @@ -0,0 +1,13 @@ +import React from 'react' +import Header from '../widgets/header' + +export default class DefaultLayout extends React.Component { + render () { + return
+
+
+ {this.props.children} +
+
+ } +} diff --git a/src/components/widgets/header.js b/src/components/widgets/header.js new file mode 100644 index 0000000..d0cd6d3 --- /dev/null +++ b/src/components/widgets/header.js @@ -0,0 +1,50 @@ +import React from 'react' +import { Link } from 'react-router' + +import logo from '../../assets/logo.png' + +const styles = { + nav: { + backgroundColor: '#333', + borderRadius: 0, + border: 0 + }, + logo: { + height: '100%' + }, + link: { + padding: '10px 15px' + }, + menu: { + color: 'white' + } +} + +export default class HeaderWidget extends React.Component { + render () { + return + } +} diff --git a/src/components/widgets/news-panel.js b/src/components/widgets/news-panel.js new file mode 100644 index 0000000..50d514d --- /dev/null +++ b/src/components/widgets/news-panel.js @@ -0,0 +1,75 @@ +import React from 'react' +import { merge } from 'lodash' + +const styles = { + warn: { + color: 'red' + }, + small: { + color: '#828282' + }, + preview: { + height: '50px', + width: '50px', + backgroundSize: 'cover' + } +} + +export default class NewsPanelWidget extends React.Component { + static get propTypes () { + return { + url: React.PropTypes.string.isRequired, + rank: React.PropTypes.number.isRequired, + title: React.PropTypes.string.isRequired, + domain: React.PropTypes.string.isRequired, + points: React.PropTypes.number.isRequired, + previewUrl: React.PropTypes.string, + onThumbsUp: React.PropTypes.func.isRequired, + onThumbsDown: React.PropTypes.func.isRequired, + username: React.PropTypes.string.isRequired, + onUsernameClick: React.PropTypes.func.isRequired, + comments: React.PropTypes.number.isRequired, + onCommentsClick: React.PropTypes.func.isRequired, + onReport: React.PropTypes.func.isRequired + } + } + + render () { + // Seta a thumb de preview correta + const previewStyle = this.props.previewUrl && merge(styles.preview, { + backgroundImage: `url("${this.props.previewUrl}")` + }) + + return ( +
+
+ {previewStyle &&
} +

+ + {this.props.rank}. {title} + + {this.props.domain && ({this.props.domain})} +

+
+ {this.props.points} + e.preventDefault() && this.props.onThumbsUp(e)}> + + + e.preventDefault() && this.props.onThumbsDown(e)}> + + + e.preventDefault() && this.props.onUsernameClick(e)}> + {this.props.username} + + e.preventDefault() && this.props.onCommentsClick(e)}> + {this.props.comments} + + e.preventDefault() && this.props.onReport(e)}> + Reportar + +
+
+
+ ) + } +} diff --git a/src/containers/enviar-noticia.js b/src/containers/enviar-noticia.js new file mode 100644 index 0000000..3376501 --- /dev/null +++ b/src/containers/enviar-noticia.js @@ -0,0 +1,22 @@ +import React from 'react' +import { Link } from 'react-router' + +import Layout from '../components/layouts/default' +import Panel from '../components/widgets/panel' + +const styles = { + header: { + border: 'none' + } +} + +export default class EnviarNoticiaContainer extends React.Component { + render () { + return +
+

Enviar Notícia

+
+ +
+ } +} diff --git a/src/containers/main.js b/src/containers/main.js new file mode 100644 index 0000000..f6b9823 --- /dev/null +++ b/src/containers/main.js @@ -0,0 +1,33 @@ +import React from 'react' +import { Link } from 'react-router' + +import Layout from '../components/layouts/default' +import Panel from '../components/widgets/panel' + +const styles = { + header: { + border: 'none' + } +} + +export default class Main extends React.Component { + render () { + return +
+

Notícias + + Enviar + +

+
+ + + + + + + + +
+ } +} diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..2b9beb0 --- /dev/null +++ b/src/index.html @@ -0,0 +1,12 @@ + + + + + + + NodeBR + + +
+ + diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..f4a7009 --- /dev/null +++ b/src/main.js @@ -0,0 +1,22 @@ +import ReactDOM from 'react-dom' +import React from 'react' +import { AppContainer } from 'react-hot-loader' + +import routes from './routes' + +ReactDOM.render( + {routes} +, document.getElementById('app')) + +// Se o HMR estiver ligado faz o patch do container principal habilitado +// para o desenvolvimento +if (module.hot) { + module.hot.accept('./routes.js', () => { + const { AppContainer } = require('react-hot-loader') + const nextRoutes = require('./routes').default + + ReactDOM.render( + {nextRoutes} + , document.getElementById('app')) + }) +} diff --git a/src/routes.js b/src/routes.js new file mode 100644 index 0000000..2e985a1 --- /dev/null +++ b/src/routes.js @@ -0,0 +1,13 @@ +import React from 'react' +import { Route, Router, browserHistory } from 'react-router' + +import Main from './containers/main' +import EnviarNoticia from './containers/enviar-noticia' + +// Mapeia os containers para as rotas +const routes = + + + + +export default routes diff --git a/src/vendors.js b/src/vendors.js new file mode 100644 index 0000000..23c6056 --- /dev/null +++ b/src/vendors.js @@ -0,0 +1,4 @@ +import 'jquery' +import 'bootstrap/dist/js/bootstrap' +import 'bootstrap/dist/css/bootstrap.css' +import 'font-awesome/css/font-awesome.css'