├── README.md ├── babel ├── .babelrc ├── .gitignore ├── dist │ ├── crud.html │ ├── css │ │ └── bootstrap.min.css │ ├── index.html │ ├── index.js │ ├── js │ │ ├── bootstrap.min.js │ │ ├── jquery-3.3.1.min.js │ │ ├── js.js │ │ └── popper.min.js │ └── listagem-table.html ├── package-lock.json ├── package.json └── src │ └── index.js ├── bootstrap-index ├── crud.html ├── css │ └── bootstrap.min.css ├── index.html ├── js │ ├── bootstrap.min.js │ ├── jquery-3.3.1.min.js │ ├── js.js │ └── popper.min.js └── listagem-table.html ├── projeto-piloto ├── rest-api │ ├── .gitignore │ ├── api.js │ ├── banco │ │ ├── banco.xml │ │ ├── dbconexao.js │ │ └── script-popular.sql │ ├── model │ │ ├── PortfolioModel.js │ │ └── RespostaClass.js │ ├── package-lock.json │ ├── package.json │ └── router │ │ └── portfolioRouter.js ├── roteiro.js └── web-app │ ├── .babelrc │ ├── .gitignore │ ├── dist │ ├── bundle │ │ ├── babelpolyfill.bundle.js │ │ ├── css.css │ │ ├── index.bundle.js │ │ ├── indexController.bundle.js │ │ └── portfolioController.bundle.js │ ├── index.html │ └── view │ │ └── portfolio │ │ └── crud.html │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── ConfigClass.js │ ├── controllers │ │ ├── IndexController.js │ │ └── PortfolioController.js │ ├── css │ │ └── base.css │ ├── index.js │ ├── models │ │ └── portfolio │ │ │ ├── PortfolioClass.js │ │ │ └── PortfolioModel.js │ └── scss │ │ ├── _variaveis.scss │ │ └── base.scss │ └── webpack.config.js ├── projeto-portfolio ├── rest-api │ ├── .gitignore │ ├── api.js │ ├── banco │ │ ├── banco.xml │ │ ├── dbConexao.js │ │ ├── script-popular.sql │ │ └── script_tab.sql │ ├── model │ │ ├── RespostaClass.js │ │ └── portfolio │ │ │ └── PortfolioModel.js │ ├── package-lock.json │ ├── package.json │ └── router │ │ └── portfolioRouter.js └── web-app │ ├── .babelrc │ ├── .gitignore │ ├── dist │ ├── bundle │ │ ├── babelpolyfill.bundle.js │ │ ├── css.css │ │ ├── index.bundle.js │ │ ├── indexController.bundle.js │ │ └── portfolioController.bundle.js │ ├── index.html │ └── view │ │ └── portfolio │ │ └── crud.html │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── ConfigClass.js │ ├── controllers │ │ ├── IndexController.js │ │ └── PortfolioController.js │ ├── css │ │ └── base.css │ ├── index.js │ ├── models │ │ └── portfolio │ │ │ ├── PortfolioClass.js │ │ │ └── PortfolioModel.js │ └── scss │ │ ├── _variaveis.scss │ │ └── base.scss │ └── webpack.config.js ├── template-html ├── crud.html ├── css │ └── bootstrap.min.css ├── index.html ├── js │ ├── bootstrap.min.js │ ├── jquery-3.3.1.min.js │ ├── js.js │ └── popper.min.js └── listagem-table.html └── webpack ├── .babelrc ├── .gitignore ├── dist ├── bundle.js ├── bundle │ ├── babelpolyfill.bundle.js │ ├── css.css │ ├── index.bundle.js │ ├── vendors~babelpolyfill.bundle.js │ └── vendors~index.bundle.js ├── crud.html ├── css │ └── bootstrap.min.css ├── index.html ├── js │ ├── bootstrap.min.js │ ├── jquery-3.3.1.min.js │ ├── js.js │ └── popper.min.js └── listagem-table.html ├── package-lock.json ├── package.json ├── src ├── cliente-class.js ├── css │ └── base.css ├── index.js ├── instancia-cliente.js ├── promise.js └── scss │ ├── _variaveis.scss │ └── base.scss └── webpack.config.js /README.md: -------------------------------------------------------------------------------- 1 | # Projeto RESTFul CRUD + JavaScript + NodeJs + Express + MySQL 2 | 3 | Criei um projeto Web completo com Home Page e CRUD com Bootstrap, JavaScript ES6, Node, Express, MySQL, Webpack, Babel.. 4 | 5 | O desenvolvimento Web tem crescido a passos largos com surgimento de diversas tecnologias baseadas em JavaScript, sendo de grande importância o surgimento do NodeJs, no qual esta se popularizando no mercado e nos possibilita desenvolver com JavaScript no lado servidor Back-end. 6 | 7 | Com a gama de frameworks JavaScript front-end e back-end o desenvolvedor deve aprimorar seus conhecimentos em JavaScript moderno ES6 e ESNext, podendo desenvolver aplicações Web sofisticadas e escaláveis através do uso do NodeJs e SPA (Single Page Application) no Front-end com requisições Ajax. 8 | 9 | Com a popularidade do NodeJs, o Express Middleware, que trata requisições e repostas em servidores Node, mostrou-se eficiente para criação de aplicações Web e API RESTFul, no qual fazemos uso neste curso. -------------------------------------------------------------------------------- /babel/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "env", 5 | { 6 | "targets": { 7 | "browsers": [ 8 | "last 3 versions", 9 | "ie >= 8" 10 | ] 11 | } 12 | } 13 | ] 14 | ] 15 | } -------------------------------------------------------------------------------- /babel/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /babel/dist/crud.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Template com HTML5 e Bootstrap 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |
61 | 62 |
63 |

Form com HTML Simples

64 |

Cadastro de Cliente

65 | 66 |
67 |
68 | 69 | 70 |
71 |
72 | 73 | 74 |
75 |
76 | 77 | 78 | 79 |
80 |
81 | 82 | 83 | 84 | 85 |
86 |
87 | 93 |
94 | 95 |
96 | 97 |
98 |
99 |
100 | 101 |
102 |

Form com Bootstrap

103 |

Cadastro de Cliente

104 |
105 | 106 |
107 | 108 | 109 |
110 | 111 |
112 | 113 | 114 |
115 | 116 |
117 | 118 | 119 |
120 |
121 | 122 |
123 | 124 | 125 |
126 |
127 | 128 | 129 |
130 |
131 | 132 | 133 | 139 |
140 |
141 | 142 |
143 | 144 |
145 |
146 | 147 |
148 |
149 | 150 |
151 | 152 |
153 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /babel/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Template com HTML5 e Bootstrap 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |

Template com HTML5 e Bootstrap

61 | 62 |
63 |
64 |
65 | 66 | 67 | We'll never share your email with anyone else. 68 |
69 |
70 | 71 | 72 |
73 |
74 | 75 | 76 |
77 | 78 |
79 |
80 | 81 |
82 | 83 |
84 | 85 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /babel/dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var nome = "teste"; 4 | console.log(nome); 5 | var a = 1; 6 | var b = 3; 7 | console.log(a, b); 8 | var _ref = [a, b]; 9 | b = _ref[0]; 10 | a = _ref[1]; 11 | 12 | console.log(a, b); -------------------------------------------------------------------------------- /babel/dist/js/js.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/madsonar/Projeto-Site-Portfolio-RESTFul-CRUD-JavaScript-NodeJs-Express-MySQL/f6d324ac6ff74972cc7693c530981e466ee06f34/babel/dist/js/js.js -------------------------------------------------------------------------------- /babel/dist/js/popper.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) Federico Zivolo 2018 3 | Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT). 4 | */(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(e){return e&&'[object Function]'==={}.toString.call(e)}function t(e,t){if(1!==e.nodeType)return[];var o=getComputedStyle(e,null);return t?o[t]:o}function o(e){return'HTML'===e.nodeName?e:e.parentNode||e.host}function n(e){if(!e)return document.body;switch(e.nodeName){case'HTML':case'BODY':return e.ownerDocument.body;case'#document':return e.body;}var i=t(e),r=i.overflow,p=i.overflowX,s=i.overflowY;return /(auto|scroll|overlay)/.test(r+s+p)?e:n(o(e))}function r(e){return 11===e?re:10===e?pe:re||pe}function p(e){if(!e)return document.documentElement;for(var o=r(10)?document.body:null,n=e.offsetParent;n===o&&e.nextElementSibling;)n=(e=e.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&'BODY'!==i&&'HTML'!==i?-1!==['TD','TABLE'].indexOf(n.nodeName)&&'static'===t(n,'position')?p(n):n:e?e.ownerDocument.documentElement:document.documentElement}function s(e){var t=e.nodeName;return'BODY'!==t&&('HTML'===t||p(e.firstElementChild)===e)}function d(e){return null===e.parentNode?e:d(e.parentNode)}function a(e,t){if(!e||!e.nodeType||!t||!t.nodeType)return document.documentElement;var o=e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING,n=o?e:t,i=o?t:e,r=document.createRange();r.setStart(n,0),r.setEnd(i,0);var l=r.commonAncestorContainer;if(e!==l&&t!==l||n.contains(i))return s(l)?l:p(l);var f=d(e);return f.host?a(f.host,t):a(e,d(t).host)}function l(e){var t=1=o.clientWidth&&n>=o.clientHeight}),l=0a[e]&&!t.escapeWithReference&&(n=J(f[o],a[e]-('right'===e?f.width:f.height))),ae({},o,n)}};return l.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';f=le({},f,m[t](e))}),e.offsets.popper=f,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,n=t.reference,i=e.placement.split('-')[0],r=Z,p=-1!==['top','bottom'].indexOf(i),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]r(n[s])&&(e.offsets.popper[d]=r(n[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,o){var n;if(!q(e.instance.modifiers,'arrow','keepTogether'))return e;var i=o.element;if('string'==typeof i){if(i=e.instance.popper.querySelector(i),!i)return e;}else if(!e.instance.popper.contains(i))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var r=e.placement.split('-')[0],p=e.offsets,s=p.popper,d=p.reference,a=-1!==['left','right'].indexOf(r),l=a?'height':'width',f=a?'Top':'Left',m=f.toLowerCase(),h=a?'left':'top',c=a?'bottom':'right',u=S(i)[l];d[c]-us[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,y=t(e.instance.popper),w=parseFloat(y['margin'+f],10),E=parseFloat(y['border'+f+'Width'],10),v=b-e.offsets.popper[m]-w-E;return v=$(J(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},ae(n,m,Q(v)),ae(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case he.FLIP:p=[n,i];break;case he.CLOCKWISE:p=z(n);break;case he.COUNTERCLOCKWISE:p=z(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)f(l.top)||'bottom'===n&&f(a.top)f(o.right),g=f(a.top)f(o.bottom),b='left'===n&&h||'right'===n&&c||'top'===n&&g||'bottom'===n&&u,y=-1!==['top','bottom'].indexOf(n),w=!!t.flipVariations&&(y&&'start'===r&&h||y&&'end'===r&&c||!y&&'start'===r&&g||!y&&'end'===r&&u);(m||b||w)&&(e.flipped=!0,(m||b)&&(n=p[d+1]),w&&(r=G(r)),e.placement=n+(r?'-'+r:''),e.offsets.popper=le({},e.offsets.popper,C(e.instance.popper,e.offsets.reference,e.placement)),e=P(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport'},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],n=e.offsets,i=n.popper,r=n.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return i[p?'left':'top']=r[o]-(s?i[p?'width':'height']:0),e.placement=T(t),e.offsets.popper=g(i),e}},hide:{order:800,enabled:!0,fn:function(e){if(!q(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=D(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottomo.right||t.top>o.bottom||t.right 2 | 3 | 4 | 5 | 6 | 7 | 8 | Template com HTML5 e Bootstrap 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |
61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 |
Listagem de Clientes
IdNomeRuaIdNomeRuaIdNomeRua
10PedroRua A10PedroRua A10PedroRua A
11MariaRua B11MariaRua B11MariaRua B
13JoãoRua C13JoãoRua C13JoãoRua C
14FranciscoRua A14FranciscoRua A14FranciscoRua A
130 |
131 |
132 | 133 |
134 |
135 |
136 | Featured 137 |
138 |
139 |
Special title treatment
140 |

With supporting text below as a natural lead-in to additional content.

141 | Go somewhere 142 |
143 |
144 |
145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /babel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-babel", 3 | "version": "1.0.0", 4 | "description": "teste com babel", 5 | "main": "index.js", 6 | "scripts": { 7 | "build":"babel src -d dist" 8 | }, 9 | "author": "Prof. Madson Aguiar", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "babel-cli": "^6.26.0", 13 | "babel-preset-env": "^1.7.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /babel/src/index.js: -------------------------------------------------------------------------------- 1 | let nome = "teste"; 2 | console.log(nome); 3 | let a = 1; 4 | let b = 3; 5 | console.log(a, b); 6 | [b, a] = [a, b]; 7 | console.log(a, b); -------------------------------------------------------------------------------- /bootstrap-index/crud.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Template com HTML5 e Bootstrap 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |
61 | 62 |
63 |

Form com HTML Simples

64 |

Cadastro de Cliente

65 | 66 |
67 |
68 | 69 | 70 |
71 |
72 | 73 | 74 |
75 |
76 | 77 | 78 | 79 |
80 |
81 | 82 | 83 | 84 | 85 |
86 |
87 | 93 |
94 | 95 |
96 | 97 |
98 |
99 |
100 | 101 |
102 |

Form com Bootstrap

103 |

Cadastro de Cliente

104 |
105 | 106 |
107 | 108 | 109 |
110 | 111 |
112 | 113 | 114 |
115 | 116 |
117 | 118 | 119 |
120 |
121 | 122 |
123 | 124 | 125 |
126 |
127 | 128 | 129 |
130 |
131 | 132 | 133 | 139 |
140 |
141 | 142 |
143 | 144 |
145 |
146 | 147 |
148 |
149 | 150 |
151 | 152 |
153 |
154 |
155 |
156 | Featured 157 |
158 |
159 |
Special title treatment
160 |

With supporting text below as a natural lead-in to additional content.

161 | Go somewhere 162 |
163 |
164 |
165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /bootstrap-index/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Template com HTML5 e Bootstrap 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |

Template com HTML5 e Bootstrap

61 | 62 |
63 |
64 |
65 | 66 | 67 | We'll never share your email with anyone else. 68 |
69 |
70 | 71 | 72 |
73 |
74 | 75 | 76 |
77 | 78 |
79 |
80 | 81 |
82 | 83 |
84 | 85 |
86 |
87 |
88 | Featured 89 |
90 |
91 |
Special title treatment
92 |

With supporting text below as a natural lead-in to additional content.

93 | Go somewhere 94 |
95 |
96 |
97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /bootstrap-index/js/js.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/madsonar/Projeto-Site-Portfolio-RESTFul-CRUD-JavaScript-NodeJs-Express-MySQL/f6d324ac6ff74972cc7693c530981e466ee06f34/bootstrap-index/js/js.js -------------------------------------------------------------------------------- /bootstrap-index/listagem-table.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Template com HTML5 e Bootstrap 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |
61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 |
Listagem de Clientes
IdNomeRuaIdNomeRuaIdNomeRua
10PedroRua A10PedroRua A10PedroRua A
11MariaRua B11MariaRua B11MariaRua B
13JoãoRua C13JoãoRua C13JoãoRua C
14FranciscoRua A14FranciscoRua A14FranciscoRua A
130 |
131 |
132 | 133 |
134 |
135 |
136 | Featured 137 |
138 |
139 |
Special title treatment
140 |

With supporting text below as a natural lead-in to additional content.

141 | Go somewhere 142 |
143 |
144 |
145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /projeto-piloto/rest-api/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /projeto-piloto/rest-api/api.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const bodyParser = require('body-parser'); 3 | var cors = require('cors'); 4 | /**/const routePortfolio = require('./router/portfolioRouter'); 5 | const api = express(); 6 | const port = 3000 //porta padrão 7 | const router = express.Router() 8 | 9 | api.use(cors()); 10 | 11 | api.use(bodyParser.urlencoded({ extended: true })); 12 | api.use(bodyParser.json()); 13 | 14 | router.get('/', (req, res) => res.json({ 15 | mensagem: 'API online!' })) 16 | 17 | api.use('/', router) 18 | api.use('/portfolio',routePortfolio); 19 | 20 | api.listen(port) 21 | console.log('Run API...') 22 | -------------------------------------------------------------------------------- /projeto-piloto/rest-api/banco/dbconexao.js: -------------------------------------------------------------------------------- 1 | var mysql = require('mysql'); 2 | 3 | var conexao = mysql.createPool({ 4 | host: 'localhost', 5 | user: 'root', 6 | password: '', 7 | database: 'db_portfolio' 8 | }); 9 | 10 | module.exports = conexao; 11 | -------------------------------------------------------------------------------- /projeto-piloto/rest-api/banco/script-popular.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO portfolio(descricao, detalhes) 2 | VALUES('Desenvolvimento de Websites', 'Tecnologias JavaScript, NodeJs, Express e MySQL'); 3 | INSERT INTO portfolio(descricao, detalhes) 4 | VALUES('Desenvolvimento de APIs', 'Tecnologias JavaScript, NodeJs, Express e MySQL'); -------------------------------------------------------------------------------- /projeto-piloto/rest-api/model/PortfolioModel.js: -------------------------------------------------------------------------------- 1 | var db = require('../banco/dbconexao'); 2 | 3 | module.exports = class PortfolioModel{ 4 | 5 | static getTodos(callback){ 6 | return db.query("SELECT * FROM portfolio", callback); 7 | } 8 | 9 | static getId(id, callback) { 10 | return db.query("SELECT * FROM portfolio WHERE id_portfolio=?", [id], callback); 11 | } 12 | 13 | static adicionar(portfolio, callback) { 14 | 15 | return db.query("INSERT INTO portfolio (descricao, detalhes) VALUES(?,?)", 16 | [portfolio.descricao, portfolio.detalhes], callback); 17 | } 18 | 19 | static deletar(id, callback) { 20 | return db.query("DELETE FROM portfolio WHERE id_portfolio=?", [id], callback); 21 | } 22 | 23 | static editar(portfolio, callback) { 24 | return db.query("UPDATE portfolio SET descricao=?, detalhes=? WHERE id_portfolio=?", 25 | [portfolio.descricao, portfolio.detalhes, portfolio.id_portfolio], callback); 26 | } 27 | 28 | }; 29 | //module.exports = portfolio; -------------------------------------------------------------------------------- /projeto-piloto/rest-api/model/RespostaClass.js: -------------------------------------------------------------------------------- 1 | module.exports = class RespostaClass{ 2 | constructor(){ 3 | this.erro = false; 4 | this.msg = null; 5 | this.dados = null; 6 | } 7 | } -------------------------------------------------------------------------------- /projeto-piloto/rest-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rest-api", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "api.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Prof. Madson Aguiar", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "body-parser": "^1.18.3", 13 | "cors": "^2.8.4", 14 | "express": "^4.16.3", 15 | "mysql": "^2.16.0", 16 | "nodemon": "^1.18.4" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /projeto-piloto/rest-api/router/portfolioRouter.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var PortfolioModel = require('../model/PortfolioModel'); 4 | var RespostaClass = require('../model/RespostaClass'); 5 | 6 | router.get('/', function (req, res, next) { 7 | 8 | PortfolioModel.getTodos(function (erro, retorno) { 9 | 10 | let resposta = new RespostaClass(); 11 | if (erro) { 12 | resposta.erro = true; 13 | resposta.msg = "Ocorreu um erro."; 14 | console.log("erro", erro); 15 | } 16 | else resposta.dados = retorno; 17 | res.json(resposta); 18 | }); 19 | }); 20 | 21 | 22 | router.get('/:id?', function (req, res, next) { 23 | 24 | PortfolioModel.getId(req.params.id, function (erro, retorno) { 25 | 26 | let resposta = new RespostaClass(); 27 | 28 | if (erro) { 29 | resposta.erro = true; 30 | resposta.msg = "Ocorreu um erro."; 31 | console.log("erro", erro); 32 | } 33 | else 34 | resposta.dados = retorno; 35 | res.json(resposta); 36 | }); 37 | }); 38 | 39 | router.post('/', function (req, res, next) { 40 | 41 | PortfolioModel.adicionar(req.body, function (erro, retorno) { 42 | 43 | let resposta = new RespostaClass(); 44 | 45 | if (erro) { 46 | resposta.erro = true; 47 | resposta.msg = "Ocorreu um erro."; 48 | console.log("erro", erro); 49 | } 50 | else { 51 | if (retorno.affectedRows > 0) { 52 | resposta.msg = "cadastro realizado com sucesso"; 53 | } else { 54 | resposta.erro = true; 55 | resposta.msg = "Não foi realziar o cadastro"; 56 | } 57 | } 58 | console.log('resp cadastrar', resposta); 59 | res.json(resposta); 60 | }); 61 | }); 62 | 63 | 64 | 65 | router.delete('/:id', function (req, res, next) { 66 | 67 | PortfolioModel.deletar(req.params.id, function (erro, retorno) { 68 | 69 | let resposta = new RespostaClass(); 70 | 71 | if (erro) { 72 | resposta.erro = true; 73 | resposta.msg = "Ocorreu um erro."; 74 | console.log("erro", erro); 75 | } 76 | else { 77 | if (retorno.affectedRows > 0) { 78 | resposta.msg = "registro excluído com sucesso"; 79 | } else { 80 | resposta.erro = true; 81 | resposta.msg = "Não foi possível excluir o registro"; 82 | } 83 | } 84 | res.json(resposta); 85 | }); 86 | }); 87 | 88 | router.put('/', function (req, res, next) { 89 | 90 | PortfolioModel.editar(req.body, function (erro, retorno) { 91 | 92 | let resposta = new RespostaClass(); 93 | 94 | if (erro) { 95 | resposta.erro = true; 96 | resposta.msg = "Ocorreu um erro."; 97 | console.log("erro", erro); 98 | } 99 | else { 100 | if (retorno.affectedRows > 0) { 101 | resposta.msg = "registro alterado com sucesso"; 102 | } else { 103 | resposta.erro = true; 104 | resposta.msg = "Não foi possível alterar o registro"; 105 | } 106 | } 107 | res.json(resposta); 108 | }); 109 | 110 | }); 111 | 112 | module.exports = router; -------------------------------------------------------------------------------- /projeto-piloto/roteiro.js: -------------------------------------------------------------------------------- 1 | /* 2 | - instalar visual studio code 3 | 4 | 5 | - instalar o node 6 | 7 | 8 | - lançar aulas babel e webpack 9 | 10 | 11 | OK - inslatar o xamp OBS: Vai instalar o MySQL e PHPAdmin para acessar o banco de dados 12 | https://www.apachefriends.org/pt_br/download.html 13 | 14 | 15 | - Criar uma pasta chamda: 'projeto-portfolio' 16 | - Criar a API, criar uma pasta chamda rest-api 17 | - npm init -y 18 | - npm install --save-dev express body-parser cors 19 | - criar o arquivo 'api.js' para rodar o servidor, implementar o código 'foto' e 20 | testar o via o server via http://localhost:3000/ 21 | 22 | 23 | - Criar a pasta 'banco' 24 | - Criar a pasta 'banco' e Pegar o script pronto no DBDesigner e salvar na pasta 'banco' 25 | para mostrar o, aluno como criar o bando no phpmyadmin e rodar script de criar tabela 26 | e popular dados. 27 | 28 | 29 | - npm install --save-dev mysql 30 | - dentro uma pasta cria arquivo 'dbConexao' na pasta banco 31 | - criar a pasta Model e dentro o arquivo PortfolioModel.js 32 | - implementar o métodos 'getTodos' 33 | 34 | 35 | - Criar classe resposta padrão "RespostaClass.js" dentro de model 36 | - Criar pasta 'router' e dentro o arquivo 'portfolioRouter.js' 37 | - Implementar apenas métodos 'getTodos' 38 | 39 | 40 | - Configurar portfolioRouter.js dentro de api.js 41 | - Testar getTodos com PostMan 42 | - instar nodemon: npm install nodemon -g 43 | npm config get prefix 44 | set PATH=%PATH%;C:\Users\madson\AppData\Roaming\npm 45 | 46 | 47 | - Implementação operação por get por id em 'PortfolioModel.js' 48 | - Implementação operação por get por id em 'portfolioRouter.js' 49 | - Testar com postman 50 | 51 | 52 | - Implementação operação adicionar em 'PortfolioModel.js' 53 | - Implementação operação adicionar em 'portfolioRouter.js' 54 | - Testar com postman 55 | 56 | 57 | - Implementação operação deletar em 'PortfolioModel.js' 58 | - Implementação operação deletar em 'portfolioRouter.js' 59 | - Testar com postman 60 | 61 | 62 | - Implementação operação editar em 'PortfolioModel.js' 63 | - Implementação operação editar em 'portfolioRouter.js' 64 | - Testar com postman 65 | 66 | 67 | /////WEB/////////////////////////////////////////////////////////// 68 | 69 | --Criar estrutura do projeto 70 | - Cria uma pasta chamada 'web-api', 71 | - Copiar o conteúdo da pasta 'webpack'para dentro da pasta do projeto 'web-app' 72 | - Rodar o comando: npm init e renomear o projeto para 'web-app' 73 | - Instalar os módulos via npm: npm i 74 | - Deletar alguns arquivos de dentro da pasta 'dis': 75 | Pasta 'css', 'js', 76 | Arquivo: listagem-table.html, bundle.js 77 | Limpar a pasta bundle 78 | - Dentro de 'dist' criar uma pasta 'view->portfolio' 79 | - Mover o arquivo CRUD.html para dentro de 'view->portfolio' 80 | 81 | 82 | --Preparar index.html 83 | - Deletar alguns arquivos de dentro da pasta 'src': 84 | Arquivos: cliente-class.js, instancia-cliente.js, promise.js 85 | - Deletar o conteúdo da div content de index.html e deixar o código abaixo 86 |
87 |

Portfólio de Serviços

88 |
89 |
90 |
91 | OBS: Colocar o mesmo tídulo no title head 92 | Obs; navbar: Home 93 | OBS: navbar:Cadastro Portfólio 94 | -Deletar entradas css e js substituir pelos bundles via npm build 95 | Obs: Antes delatar imports index.js: 96 | import {} from './instancia-cliente'; 97 | import {} from './promise'; 98 | Obs 2; retirar formatação sass e css referente cor de plano de fundo 99 | Obs 3: comentar a duplicação de código do webpack.config 100 | 101 | 102 | --preparar página crud 103 | -Cópiar index.html e renomear de crud crud.html (renomear o velho para não conflitar) 104 | -Alterar link index para Home 105 | -apagar dados do container div e por: 106 | OBS: pode copiar parte de crud velho 107 |

Cadastro de Portfólio

108 |
109 | 110 |
111 | 112 |
113 |
114 |
115 |
116 |
117 | 118 | 119 |
120 |
121 |
122 |
123 | 124 |
125 | 126 | 127 |
128 | 129 |
130 | 131 | 132 |
133 | 134 |
135 | 136 | 137 |
138 | 139 |
140 | 141 | 142 |
143 |
144 | 145 |
146 |
147 |
148 | 149 |
150 | 151 | -alterar tilte para: Cadastro de Portfólio 152 | -voltar níveis css e js ../../ 153 | -deletar crud.html velho 154 | 155 | 156 | --Criando classe 'ConfigClass' na raiz junto com index.js(foto) 157 | 158 | 159 | --Criando pasta 'Models->portfolio' 160 | -Criar classe 'PortfolioClass.js'(foto) 161 | -Criar classe 'PortfolioModel.js'(foto) 162 | 163 | 164 | --Criando estrutura pasta 'controllers' 165 | -Criar classe 'IndexController.js' (foto) 166 | 167 | 168 | --Imoplementar lista portfolio index 169 | -implementar 'getTodos' em model (foto) 170 | -implementar getTodos em 'IndexController'(Foto) 171 | -informar IndexController no webpack e index.html 172 | -Testar (rodar API) 173 | 174 | 175 | --Criar classe 'PortfolioController.js'(Foto) 176 | -informar IndexController no webpack e crud.html 177 | -Testar (rodar API) 178 | 179 | 180 | --ocultar form no CRUD portfolio 181 | -Criar métodos ocultarElemento e exibirElemento e chamar no main(Foto) 182 | -Criar métodos 'limparCamposForm()'(Foto) 183 | -Criar método 'registrarEvents()'(Foto) 184 | -Testar 185 | 186 | 187 | --Implementar método para alerts do bootstrap(foto) OBS: e o limpar 188 | 189 | 190 | --Implementar a listagem no CRUD portfolio 191 | -criar método getTodosTable e por no main(Foto) 192 | 193 | 194 | --Implementar o registros de eventos dos botões e por no main(Foto) 195 | 196 | 197 | --Implementar função adicionar 198 | -primeiro o método do model(Foto) 199 | -segundo o método no controller(Foto) 200 | -testar 201 | 202 | 203 | --Implementar método editar 204 | -primeiro getid e editar no model(Foto) 205 | -segundo prepararEditar no controler(Foto) 206 | -terceiro editar no controler(Foto) 207 | -testar 208 | 209 | 210 | --Implementar ecluir 211 | -primeiro no model 212 | 213 | 214 | */ 215 | 216 | -------------------------------------------------------------------------------- /projeto-piloto/web-app/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env" 4 | ] 5 | } -------------------------------------------------------------------------------- /projeto-piloto/web-app/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /projeto-piloto/web-app/dist/bundle/indexController.bundle.js: -------------------------------------------------------------------------------- 1 | !function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=337)}({337:function(e,n,t){"use strict";var r=function(){function e(e,n){for(var t=0;t\n
\n
'+c.descricao+'
\n
\n
\n

'+c.detalhes+"

\n
\n
"}}catch(e){o=!0,i=e}finally{try{!r&&a.return&&a.return()}finally{if(o)throw i}}e.innerHTML=t}).catch(function(e){console.log("p.catch",e)})}}]),e}();window.onload=function(){(new u).getTodosIndex(i)}},91:function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,n){for(var t=0;t=400)throw new Error("Erro server");return e.json()})}},{key:"adicionar",value:function(e){return fetch(o,{headers:{Accept:"application/json","Content-Type":"application/json"},method:"POST",body:JSON.stringify(e)}).then(function(e){if(e.status>=400)throw new Error("Erro server");return e.json()})}},{key:"getId",value:function(e){return fetch(o+"/"+e).then(function(e){if(e.status>=400)throw new Error("Erro server");return e.json()})}},{key:"editar",value:function(e){return fetch(o,{headers:{Accept:"application/json","Content-Type":"application/json"},method:"PUT",body:JSON.stringify(e)}).then(function(e){if(e.status>=400)throw new Error("Erro server");return e.json()})}},{key:"deletar",value:function(e){return fetch(o+"/"+e,{headers:{Accept:"application/json","Content-Type":"application/json"},method:"DELETE"}).then(function(e){if(e.status>=400)throw new Error("Erro server");return e.json()})}}]),e}();n.default=i},92:function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,n){for(var t=0;t\n "+s.id_portfolio+"\n "+s.descricao+'\n \n \n "}}catch(e){i=!0,a=e}finally{try{!o&&u.return&&u.return()}finally{if(i)throw a}}n+=" ",e.innerHTML=n;var d=window.document.querySelectorAll(".btn-editar"),f=window.document.querySelectorAll(".btn-excluir");d.forEach(function(e){e.addEventListener("click",function(e){c.limparMsgAlert();var t=e.target.getAttribute("data-id");c.prepararEditar(t)})}),f.forEach(function(e){e.addEventListener("click",function(e){c.limparMsgAlert();var t=e.target.getAttribute("data-id");c.deletar(t)})})}}).catch(function(e){console.log("p.catch",e)})}},{key:"adicionar",value:function(e){var t,r,n=this;if(t=form.descricao.value,r=form.detalhes.value,t||r){var a=new i.default(null,t,r);new Promise(function(e,t){o.default.adicionar(a).then(function(t){e(t)})}).then(function(e){e.erro?n.exibirMsgAlert(e.msg,"erro"):(n.getTodosTable(l),n.exibirMsgAlert(e.msg,"sucesso"),c.ocultarElemento("formulario"),c.exibirElemento("listagem"),n.limparCamposForm(form))}).catch(function(e){console.log("catch erro:",e),n.exibirMsgAlert(e,"erro")})}else this.exibirMsgAlert("Favor preencher todos os campos.","erro"),console.log("erro:",response)}},{key:"prepararEditar",value:function(e){var t=this;new Promise(function(t,r){o.default.getId(e).then(function(e){t(e)})}).then(function(e){if(e.erro)t.exibirMsgAlert(e.msg,"erro");else{var r=new i.default(e.dados[0].id_portfolio,e.dados[0].descricao,e.dados[0].detalhes);s.id.value=r.id_portfolio,s.descricao.value=r.descricao,s.detalhes.value=r.detalhes,c.ocultarElemento("listagem"),c.exibirElemento("formulario")}}).catch(function(e){console.log("catch erro:",e),t.exibirMsgAlert(e,"erro")})}},{key:"editar",value:function(e){var t,r,n,a=this;if(t=form.id.value,r=form.descricao.value,n=form.detalhes.value,t||r||n){var u=new i.default(t,r,n);new Promise(function(e,t){o.default.editar(u).then(function(t){e(t)})}).then(function(e){e.erro?a.exibirMsgAlert(e.msg,"erro"):(a.getTodosTable(l),a.exibirMsgAlert(e.msg,"sucesso"),c.ocultarElemento("formulario"),c.exibirElemento("listagem"),a.limparCamposForm(form))}).catch(function(e){console.log("catch erro:",e),a.exibirMsgAlert(e,"erro")})}else this.exibirMsgAlert("Favor preencher todos os campos.","erro"),console.log("erro:",response)}},{key:"deletar",value:function(e){var t=this;new Promise(function(t,r){o.default.deletar(e).then(function(e){t(e)})}).then(function(e){e.erro?t.exibirMsgAlert(e.msg,"erro"):(t.getTodosTable(l),t.exibirMsgAlert(e.msg,"sucesso"))}).catch(function(e){console.log("catch erro:",e),t.exibirMsgAlert(e,"erro")})}},{key:"ocultarElemento",value:function(e){document.getElementById(e).style.display="none"}},{key:"exibirElemento",value:function(e){document.getElementById(e).style.display="block"}},{key:"limparCamposForm",value:function(e){form.id.value="",form.descricao.value="",form.detalhes.value=""}},{key:"exibirElemento",value:function(e){document.getElementById(e).style.display="block"}},{key:"exibirMsgAlert",value:function(e,t){var r="";"sucesso"==t?r='':"erro"==t&&(r=''),u.innerHTML=r}},{key:"limparMsgAlert",value:function(){u.innerHTML=""}},{key:"registrarEvents",value:function(){document.getElementById("btn-exibir-formulario").addEventListener("click",function(){c.limparMsgAlert(),c.ocultarElemento("listagem"),c.exibirElemento("formulario")}),document.getElementById("btn-cadastrar-portfolio").addEventListener("click",function(e){e.preventDefault(),c.limparMsgAlert(),s.id.value?c.editar(s):c.adicionar(s)}),document.getElementById("btn-cancelar-operacao").addEventListener("click",function(){c.limparMsgAlert(),c.limparCamposForm(),c.ocultarElemento("formulario"),c.exibirElemento("listagem")})}}]),e}();window.onload=function(){(c=new d).ocultarElemento("formulario"),c.getTodosTable(l),c.registrarEvents()}},339:function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.default=function e(t,r,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),null!=t&&(this.id_portfolio=t),this.descricao=r,this.detalhes=n}},91:function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=function(){function e(e,t){for(var r=0;r=400)throw new Error("Erro server");return e.json()})}},{key:"adicionar",value:function(e){return fetch(o,{headers:{Accept:"application/json","Content-Type":"application/json"},method:"POST",body:JSON.stringify(e)}).then(function(e){if(e.status>=400)throw new Error("Erro server");return e.json()})}},{key:"getId",value:function(e){return fetch(o+"/"+e).then(function(e){if(e.status>=400)throw new Error("Erro server");return e.json()})}},{key:"editar",value:function(e){return fetch(o,{headers:{Accept:"application/json","Content-Type":"application/json"},method:"PUT",body:JSON.stringify(e)}).then(function(e){if(e.status>=400)throw new Error("Erro server");return e.json()})}},{key:"deletar",value:function(e){return fetch(o+"/"+e,{headers:{Accept:"application/json","Content-Type":"application/json"},method:"DELETE"}).then(function(e){if(e.status>=400)throw new Error("Erro server");return e.json()})}}]),e}();t.default=i},92:function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=function(){function e(e,t){for(var r=0;r 2 | 3 | 4 | 5 | 6 | 7 | 8 | Portfólio de Serviços 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |
61 |

Portfólio de Serviços

62 |
63 |
64 |
65 | 66 |
67 | 68 |
69 |
70 |
71 | Featured 72 |
73 |
74 |
Special title treatment
75 |

With supporting text below as a natural lead-in to additional content.

76 | Go somewhere 77 |
78 |
79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /projeto-piloto/web-app/dist/view/portfolio/crud.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Cadastro de Portfólio 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |

Cadastro de Portfólio

61 |
62 | 63 |
64 | 65 |
66 |
67 |
68 |
69 |
70 | 71 | 72 |
73 |
74 |
75 |
76 | 77 |
78 | 79 | 80 |
81 | 82 |
83 | 84 | 85 |
86 | 87 |
88 | 89 | 90 |
91 | 92 |
93 | 94 | 95 |
96 |
97 | 98 |
99 |
100 |
101 | 102 |
103 | 104 |
105 | 106 |
107 |
108 |
109 | Featured 110 |
111 |
112 |
Special title treatment
113 |

With supporting text below as a natural lead-in to additional content.

114 | Go somewhere 115 |
116 |
117 |
118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /projeto-piloto/web-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-app", 3 | "version": "1.0.0", 4 | "description": "test com webpack", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "webpack --mode development", 8 | "build": "webpack --mode production", 9 | "start": "webpack-dev-server --mode production --open" 10 | }, 11 | "author": "Prof. Madson Aguiar", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "autoprefixer": "^9.1.3", 15 | "babel-core": "^6.26.3", 16 | "babel-loader": "^7.1.5", 17 | "babel-preset-env": "^1.7.0", 18 | "css-loader": "^1.0.0", 19 | "file-loader": "^2.0.0", 20 | "mini-css-extract-plugin": "^0.4.2", 21 | "node-sass": "^4.9.3", 22 | "optimize-css-assets-webpack-plugin": "^5.0.0", 23 | "postcss-loader": "^3.0.0", 24 | "precss": "^3.1.2", 25 | "sass-loader": "^7.1.0", 26 | "style-loader": "^0.22.1", 27 | "uglifyjs-webpack-plugin": "^1.3.0", 28 | "webpack": "^4.17.1", 29 | "webpack-cli": "^3.1.0", 30 | "webpack-dev-server": "^3.1.5" 31 | }, 32 | "dependencies": { 33 | "babel-polyfill": "^6.26.0", 34 | "bootstrap": "^4.1.3", 35 | "jquery": "^3.3.1", 36 | "popper.js": "^1.14.4" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /projeto-piloto/web-app/src/ConfigClass.js: -------------------------------------------------------------------------------- 1 | export default class ConfigClass{ 2 | constructor(){ 3 | } 4 | 5 | static getUrlApi(){ 6 | this.urlApi = "http://localhost:3000"; 7 | return this.urlApi; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /projeto-piloto/web-app/src/controllers/IndexController.js: -------------------------------------------------------------------------------- 1 | import PortfolioModel from "../models/portfolio/PortfolioModel"; 2 | 3 | let divPortfolios = window.document.getElementById("portfolios") 4 | let objIndexController; 5 | 6 | class IndexController { 7 | 8 | /**/ getTodosIndex(divPortfolios) { 9 | 10 | let promise = new Promise(function (resolve, reject) { 11 | let promiseFetch = PortfolioModel.getTodos() 12 | promiseFetch.then(response => { 13 | resolve(response) 14 | //return response; 15 | }) 16 | }); 17 | 18 | promise.then(response => { 19 | 20 | let dados = ""; 21 | 22 | for (const servico of response.dados) { 23 | 24 | dados += `
25 |
26 |
${servico.descricao}
27 |
28 |
29 |

${servico.detalhes}

30 |
31 |

`; 32 | 33 | } 34 | 35 | divPortfolios.innerHTML = dados; 36 | 37 | }).catch(response => { 38 | console.log('p.catch', response); 39 | }); 40 | /**/ } 41 | 42 | } 43 | 44 | function main() { 45 | objIndexController = new IndexController(); 46 | /**/objIndexController.getTodosIndex(divPortfolios); 47 | } 48 | 49 | window.onload = main; 50 | 51 | 52 | -------------------------------------------------------------------------------- /projeto-piloto/web-app/src/controllers/PortfolioController.js: -------------------------------------------------------------------------------- 1 | import PortfolioModel from "../models/portfolio/PortfolioModel"; 2 | import PortfolioClass from "../models/portfolio/PortfolioClass"; 3 | 4 | let divPortfolios = window.document.getElementById("portfolios"); 5 | let divMsg = window.document.getElementById("msg"); 6 | let formulario = window.document.getElementById("form"); 7 | 8 | let objPortfolioController; 9 | 10 | class PortfolioController { 11 | 12 | getTodosTable(divPortfolios) { 13 | 14 | let promise = new Promise(function (resolve, reject) { 15 | let promiseFetch = PortfolioModel.getTodos() 16 | promiseFetch.then(response => { 17 | resolve(response) 18 | }) 19 | }); 20 | 21 | promise.then(response => { 22 | 23 | if (response.erro) { 24 | this.exibirMsgAlert(response.msg, 'erro'); 25 | } else { 26 | 27 | let dados = `
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | `; 38 | 39 | for (const servico of response.dados) { 40 | dados += ` 41 | 42 | 43 | 46 | 49 | ` 50 | } 51 | 52 | dados += `
IdDescrição
${servico.id_portfolio}${servico.descricao}
` 53 | divPortfolios.innerHTML = dados; 54 | 55 | let btnsEditar = window.document.querySelectorAll(".btn-editar"); 56 | let btnsExcuir = window.document.querySelectorAll(".btn-excluir"); 57 | 58 | btnsEditar.forEach(function (item) { 59 | item.addEventListener("click", event => { 60 | objPortfolioController.limparMsgAlert(); 61 | let id = event.target.getAttribute('data-id') 62 | objPortfolioController.prepararEditar(id); 63 | }); 64 | }); 65 | 66 | btnsExcuir.forEach(function (item) { 67 | item.addEventListener("click", event => { 68 | objPortfolioController.limparMsgAlert(); 69 | let id = event.target.getAttribute('data-id') 70 | objPortfolioController.deletar(id); 71 | }); 72 | }); 73 | } 74 | 75 | }).catch(response => { 76 | console.log('p.catch', response); 77 | }); 78 | } 79 | 80 | 81 | adicionar(from) { 82 | 83 | let descricao, detalhes; 84 | descricao = form.descricao.value; 85 | detalhes = form.detalhes.value; 86 | 87 | if (descricao || detalhes) { 88 | let objPortfolioClass = new PortfolioClass( 89 | null, descricao, detalhes); 90 | 91 | let promise = new Promise(function (resolve, reject) { 92 | let promiseFetch = PortfolioModel.adicionar(objPortfolioClass) 93 | promiseFetch.then(response => { 94 | resolve(response) 95 | }) 96 | }); 97 | 98 | promise.then(response => { 99 | 100 | if (response.erro) { 101 | this.exibirMsgAlert(response.msg, 'erro'); 102 | } else { 103 | this.getTodosTable(divPortfolios); 104 | this.exibirMsgAlert(response.msg, 'sucesso'); 105 | objPortfolioController.ocultarElemento("formulario"); 106 | objPortfolioController.exibirElemento("listagem"); 107 | this.limparCamposForm(form); 108 | } 109 | 110 | }).catch(response => { 111 | console.log('catch erro:', response); 112 | this.exibirMsgAlert(response, 'erro'); 113 | }); 114 | 115 | } else { 116 | this.exibirMsgAlert('Favor preencher todos os campos.', 'erro'); 117 | console.log('erro:', response); 118 | } 119 | 120 | } 121 | 122 | prepararEditar(id) { 123 | 124 | let promise = new Promise(function (resolve, reject) { 125 | let promiseFetch = PortfolioModel.getId(id) 126 | promiseFetch.then(response => { 127 | resolve(response) 128 | }) 129 | }); 130 | 131 | promise.then(response => { 132 | 133 | if (response.erro) { 134 | this.exibirMsgAlert(response.msg, 'erro'); 135 | } else { 136 | const portfolio = new PortfolioClass( 137 | response.dados[0].id_portfolio, 138 | response.dados[0].descricao, 139 | response.dados[0].detalhes) 140 | 141 | formulario.id.value = portfolio.id_portfolio; 142 | formulario.descricao.value = portfolio.descricao; 143 | formulario.detalhes.value = portfolio.detalhes; 144 | 145 | objPortfolioController.ocultarElemento("listagem"); 146 | objPortfolioController.exibirElemento("formulario"); 147 | } 148 | }).catch(response => { 149 | console.log('catch erro:', response); 150 | this.exibirMsgAlert(response, 'erro'); 151 | }); 152 | 153 | } 154 | 155 | 156 | editar(from) { 157 | 158 | let id, descricao, detalhes; 159 | id = form.id.value; 160 | descricao = form.descricao.value; 161 | detalhes = form.detalhes.value; 162 | 163 | if (id || descricao || detalhes) { 164 | let objPortfolioClass = new PortfolioClass( 165 | id, descricao, detalhes); 166 | 167 | let promise = new Promise(function (resolve, reject) { 168 | let promiseFetch = PortfolioModel.editar(objPortfolioClass) 169 | promiseFetch.then(response => { 170 | resolve(response) 171 | }) 172 | }); 173 | 174 | promise.then(response => { 175 | 176 | if (response.erro) { 177 | this.exibirMsgAlert(response.msg, 'erro'); 178 | } else { 179 | this.getTodosTable(divPortfolios); 180 | this.exibirMsgAlert(response.msg, 'sucesso'); 181 | objPortfolioController.ocultarElemento("formulario"); 182 | objPortfolioController.exibirElemento("listagem"); 183 | this.limparCamposForm(form); 184 | } 185 | 186 | }).catch(response => { 187 | console.log('catch erro:', response); 188 | this.exibirMsgAlert(response, 'erro'); 189 | }); 190 | 191 | 192 | } else { 193 | this.exibirMsgAlert('Favor preencher todos os campos.', 'erro'); 194 | console.log('erro:', response); 195 | } 196 | 197 | } 198 | 199 | deletar(id) { 200 | 201 | let promise = new Promise(function (resolve, reject) { 202 | let promiseFetch = PortfolioModel.deletar(id) 203 | promiseFetch.then(response => { 204 | resolve(response) 205 | }) 206 | }); 207 | 208 | promise.then(response => { 209 | 210 | if (response.erro) { 211 | this.exibirMsgAlert(response.msg, 'erro'); 212 | } else { 213 | this.getTodosTable(divPortfolios); 214 | this.exibirMsgAlert(response.msg, 'sucesso'); 215 | } 216 | 217 | }).catch(response => { 218 | console.log('catch erro:', response); 219 | this.exibirMsgAlert(response, 'erro'); 220 | }); 221 | } 222 | 223 | 224 | ocultarElemento(elemento) { 225 | document.getElementById(elemento).style.display = "none"; 226 | } 227 | 228 | exibirElemento(elemento) { 229 | document.getElementById(elemento).style.display = "block"; 230 | } 231 | 232 | limparCamposForm(from) { 233 | form.id.value = ""; 234 | form.descricao.value = ""; 235 | form.detalhes.value = ""; 236 | } 237 | 238 | exibirElemento(elemento) { 239 | document.getElementById(elemento).style.display = "block"; 240 | } 241 | 242 | exibirMsgAlert(msg, tipo) {//tipo = 'erro' ou 'sucesso' 243 | let dados = ""; 244 | if (tipo == 'sucesso') { 245 | dados = `` 251 | } else if (tipo == 'erro') { 252 | dados = `` 258 | } 259 | 260 | divMsg.innerHTML = dados; 261 | } 262 | 263 | limparMsgAlert() { 264 | divMsg.innerHTML = ""; 265 | } 266 | 267 | registrarEvents() { 268 | document.getElementById("btn-exibir-formulario").addEventListener("click", function () { 269 | objPortfolioController.limparMsgAlert(); 270 | objPortfolioController.ocultarElemento("listagem"); 271 | objPortfolioController.exibirElemento("formulario"); 272 | }); 273 | 274 | document.getElementById("btn-cadastrar-portfolio").addEventListener("click", function (event) { 275 | event.preventDefault(); 276 | //let form = document.getElementById("form"); 277 | objPortfolioController.limparMsgAlert(); 278 | if (formulario.id.value) 279 | objPortfolioController.editar(formulario); 280 | else 281 | objPortfolioController.adicionar(formulario); 282 | }); 283 | 284 | document.getElementById("btn-cancelar-operacao").addEventListener("click", function () { 285 | objPortfolioController.limparMsgAlert(); 286 | objPortfolioController.limparCamposForm(); 287 | objPortfolioController.ocultarElemento("formulario"); 288 | objPortfolioController.exibirElemento("listagem"); 289 | }); 290 | } 291 | } 292 | 293 | function main() { 294 | objPortfolioController = new PortfolioController(); 295 | objPortfolioController.ocultarElemento("formulario"); 296 | objPortfolioController.getTodosTable(divPortfolios); 297 | /**/objPortfolioController.registrarEvents(); 298 | } 299 | 300 | window.onload = main; 301 | -------------------------------------------------------------------------------- /projeto-piloto/web-app/src/css/base.css: -------------------------------------------------------------------------------- 1 | /*body{ 2 | background-color: beige ; 3 | }*/ -------------------------------------------------------------------------------- /projeto-piloto/web-app/src/index.js: -------------------------------------------------------------------------------- 1 | import 'bootstrap'; 2 | import base from './css/base.css' 3 | import scss from './scss/base.scss' 4 | -------------------------------------------------------------------------------- /projeto-piloto/web-app/src/models/portfolio/PortfolioClass.js: -------------------------------------------------------------------------------- 1 | export default class PortfolioClass{ 2 | constructor(id, descricao, detalhes){ 3 | if(id!=null) this.id_portfolio = id; 4 | this.descricao = descricao; 5 | this.detalhes = detalhes; 6 | } 7 | } -------------------------------------------------------------------------------- /projeto-piloto/web-app/src/models/portfolio/PortfolioModel.js: -------------------------------------------------------------------------------- 1 | import ConfigClass from "../../ConfigClass"; 2 | 3 | let caminho = `${ConfigClass.getUrlApi().toString()}/portfolio/`; 4 | 5 | export default class PortfolioModel { 6 | constructor() { 7 | } 8 | 9 | static getTodos() { 10 | return fetch(caminho).then(response => { 11 | if (response.status >= 400) { 12 | throw new Error("Erro server"); 13 | } 14 | return response.json(); 15 | }) 16 | 17 | } 18 | 19 | 20 | static adicionar(portfolioClass) { 21 | 22 | return fetch(caminho, 23 | { 24 | headers: { 25 | 'Accept': 'application/json', 26 | 'Content-Type': 'application/json' 27 | }, 28 | method: "POST", 29 | body: JSON.stringify(portfolioClass) 30 | } 31 | ).then(response => { 32 | if (response.status >= 400) { 33 | throw new Error("Erro server"); 34 | } 35 | 36 | return response.json(); 37 | }); 38 | } 39 | 40 | 41 | static getId(id) { 42 | return fetch(`${caminho}/${id}`).then(response => { 43 | if (response.status >= 400) { 44 | throw new Error("Erro server"); 45 | } 46 | return response.json(); 47 | }) 48 | } 49 | 50 | static editar(portfolioClass) { 51 | 52 | return fetch(caminho, 53 | { 54 | headers: { 55 | 'Accept': 'application/json', 56 | 'Content-Type': 'application/json' 57 | }, 58 | method: "PUT", 59 | body: JSON.stringify(portfolioClass) 60 | } 61 | ).then(response => { 62 | if (response.status >= 400) { 63 | throw new Error("Erro server"); 64 | } 65 | 66 | return response.json(); 67 | }); 68 | } 69 | 70 | static deletar(id) { 71 | return fetch(`${caminho}/${id}`, 72 | { 73 | headers: { 74 | 'Accept': 'application/json', 75 | 'Content-Type': 'application/json' 76 | }, 77 | method: "DELETE" 78 | }).then(response => { 79 | if (response.status >= 400) { 80 | throw new Error("Erro server"); 81 | } 82 | return response.json(); 83 | }) 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /projeto-piloto/web-app/src/scss/_variaveis.scss: -------------------------------------------------------------------------------- 1 | $cor-fundo: blue; -------------------------------------------------------------------------------- /projeto-piloto/web-app/src/scss/base.scss: -------------------------------------------------------------------------------- 1 | @import '_variaveis.scss'; 2 | @import "~bootstrap/scss/bootstrap"; 3 | 4 | /*body{ 5 | background-color: $cor-fundo; 6 | }*/ -------------------------------------------------------------------------------- /projeto-piloto/web-app/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 3 | const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); 4 | const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); 5 | 6 | /* 7 | entry: ["babel-polyfill", "./src/index.js"],//irá empacotar em um único arquivo 8 | output: { 9 | path: path.resolve(__dirname, 'dist'), 10 | filename: 'bundle.js' 11 | }, 12 | */ 13 | 14 | module.exports = { 15 | entry: { 16 | babelpolyfill: 'babel-polyfill', 17 | index: './src/index.js', 18 | indexController: './src/controllers/IndexController.js', 19 | portfolioController: './src/controllers/PortfolioController.js', 20 | }, 21 | output: { 22 | path: path.resolve(__dirname, 'dist/bundle'), 23 | filename: '[name].bundle.js' 24 | }, 25 | optimization: { 26 | /*splitChunks: { 27 | chunks: 'all' 28 | },*/ 29 | minimizer: [ 30 | new UglifyJsPlugin({ 31 | uglifyOptions: { 32 | output: { 33 | comments: false 34 | } 35 | } 36 | }), 37 | new OptimizeCSSAssetsPlugin({}) 38 | ] 39 | }, 40 | plugins: [ 41 | new MiniCssExtractPlugin({ 42 | filename: "css.css" 43 | }) 44 | ], 45 | module: { 46 | rules: [ 47 | { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }, 48 | { 49 | test: /\.css$/, 50 | use: [ 51 | { loader: MiniCssExtractPlugin.loader },//style-loader 52 | { loader: "css-loader" } 53 | ] 54 | }, 55 | /*{ 56 | test: /\.css$/, 57 | use: [ 58 | { loader: "style-loader" }, 59 | { loader: "css-loader" } 60 | ] 61 | } { 62 | test: /\.css$/, 63 | use: [ 64 | { loader: "style-loader/url" }, 65 | { loader: "file-loader" } 66 | ] 67 | }, 68 | { 69 | test: /\.scss$/, 70 | use: [ 71 | "style-loader", // creates style nodes from JS strings 72 | "css-loader", // translates CSS into CommonJS 73 | "sass-loader" // compiles Sass to CSS, using Node Sass by default 74 | ] 75 | }*/ 76 | { 77 | test: /\.(scss)$/, 78 | use: [{ 79 | loader: MiniCssExtractPlugin.loader, // inject CSS to page 'style-loader' 80 | }, { 81 | loader: 'css-loader', // translates CSS into CommonJS modules 82 | }, { 83 | loader: 'postcss-loader', // Run post css actions 84 | options: { 85 | plugins: function () { // post css plugins, can be exported to postcss.config.js 86 | return [ 87 | require('precss'), 88 | require('autoprefixer') 89 | ]; 90 | } 91 | } 92 | }, { 93 | loader: 'sass-loader' // compiles Sass to CSS 94 | }] 95 | } 96 | ] 97 | }, 98 | devServer: { 99 | contentBase: './dist', 100 | port: 9000 101 | } 102 | }; -------------------------------------------------------------------------------- /projeto-portfolio/rest-api/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /projeto-portfolio/rest-api/api.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const bodyparser = require('body-parser'); 3 | const cors = require('cors'); 4 | const api = express(); 5 | const port = 3000; 6 | const router = express.Router(); 7 | 8 | const portfolioRouter = require('./router/portfolioRouter'); 9 | 10 | api.use(cors()); 11 | 12 | api.use(bodyparser.urlencoded({extended: true})); 13 | api.use(bodyparser.json()); 14 | 15 | router.get("/", (req, res) => res.json({ 16 | mensagem: 'API online...!' 17 | })); 18 | 19 | api.use('/', router); 20 | api.use('/portfolio', portfolioRouter); 21 | 22 | api.listen(port); 23 | console.log('Run API Express...'); 24 | -------------------------------------------------------------------------------- /projeto-portfolio/rest-api/banco/dbConexao.js: -------------------------------------------------------------------------------- 1 | const mysql = require('mysql'); 2 | 3 | const conexao = mysql.createPool({ 4 | host: 'localhost', 5 | user: 'root', 6 | password: '', 7 | database: 'db_portfolio' 8 | }); 9 | 10 | module.exports = conexao; -------------------------------------------------------------------------------- /projeto-portfolio/rest-api/banco/script-popular.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO portfolio(descricao, detalhes) 2 | VALUES('Desenvolvimento de Websites', 'Tecnologias JavaScript, NodeJs, Express e MySQL'); 3 | INSERT INTO portfolio(descricao, detalhes) 4 | VALUES('Desenvolvimento de APIs', 'Tecnologias JavaScript, NodeJs, Express e MySQL'); -------------------------------------------------------------------------------- /projeto-portfolio/rest-api/banco/script_tab.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE portfolio ( 2 | id_portfolio INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, 3 | descricao VARCHAR(255) NULL , 4 | detalhes TEXT NULL , 5 | PRIMARY KEY(id_portfolio)); 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /projeto-portfolio/rest-api/model/RespostaClass.js: -------------------------------------------------------------------------------- 1 | module.exports = class RespostaClass{ 2 | constructor(){ 3 | this.erro = false; 4 | this.msg = null; 5 | this.dados = null; 6 | } 7 | } -------------------------------------------------------------------------------- /projeto-portfolio/rest-api/model/portfolio/PortfolioModel.js: -------------------------------------------------------------------------------- 1 | const db = require('../../banco/dbConexao'); 2 | 3 | module.exports = class PortfolioModel { 4 | 5 | static getTodos(callback) { 6 | return db.query("SELECT * FROM portfolio", callback); 7 | } 8 | 9 | static getId(id, callback) { 10 | return db.query("SELECT * FROM portfolio WHERE id_portfolio = ?", [id], callback) 11 | } 12 | 13 | static adicionar(portfolio, callback) { 14 | return db.query("INSERT INTO portfolio (descricao, detalhes) VALUES(?, ?)", 15 | [portfolio.descricao, portfolio.detalhes], callback); 16 | } 17 | 18 | static deletar(id, callback) { 19 | return db.query("DELETE FROM portfolio WHERE id_portfolio = ?", 20 | [id], callback) 21 | } 22 | 23 | static editar(portfolio, callback) { 24 | return db.query("UPDATE portfolio SET descricao = ?, detalhes = ? WHERE id_portfolio = ?", 25 | [portfolio.descricao, portfolio.detalhes, portfolio.id_portfolio], callback) 26 | } 27 | 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /projeto-portfolio/rest-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rest-api", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "api.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Prof. Madson Aguiar", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "body-parser": "^1.18.3", 13 | "cors": "^2.8.4", 14 | "express": "^4.16.3" 15 | }, 16 | "dependencies": { 17 | "mysql": "^2.16.0", 18 | "nodemon": "^1.18.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /projeto-portfolio/rest-api/router/portfolioRouter.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var PortfolioModel = require('../model/portfolio/PortfolioModel'); 4 | var RespostaClass = require('../model/RespostaClass'); 5 | 6 | router.get("/", function(req, res, next){ 7 | 8 | PortfolioModel.getTodos(function(erro, retorno){ 9 | let resposta = new RespostaClass(); 10 | 11 | if(erro){ 12 | resposta.erro = true; 13 | resposta.msg = 'Ocorreu um erro'; 14 | console.log('erro:', erro); 15 | }else{ 16 | resposta.dados = retorno; 17 | } 18 | res.json(resposta); 19 | }) 20 | }); 21 | 22 | router.get("/:id?", function(req, res, next){ 23 | 24 | PortfolioModel.getId(req.params.id ,function(erro, retorno){ 25 | let resposta = new RespostaClass(); 26 | 27 | if(erro){ 28 | resposta.erro = true; 29 | resposta.msg = 'Ocorreu um erro'; 30 | console.log('erro:', erro); 31 | }else{ 32 | resposta.dados = retorno; 33 | } 34 | res.json(resposta); 35 | }) 36 | }) 37 | 38 | 39 | router.post("/?", function(req, res, next){ 40 | 41 | PortfolioModel.adicionar(req.body, function(erro, retorno){ 42 | let resposta = new RespostaClass(); 43 | 44 | if(erro){ 45 | resposta.erro = true; 46 | resposta.msg = 'Ocorreu um erro'; 47 | console.log('erro:', erro); 48 | }else{ 49 | if(retorno.affectedRows > 0){ 50 | resposta.msg = "cadastro realizado com sucesso."; 51 | }else{ 52 | resposta.erro = true; 53 | resposta.msg = 'Não foi possível realizar a operação.' 54 | } 55 | } 56 | console.log('resp:', resposta); 57 | res.json(resposta); 58 | }) 59 | }) 60 | 61 | router.delete("/:id", function(req, res, next){ 62 | 63 | PortfolioModel.deletar(req.params.id, function(erro, retorno){ 64 | let resposta = new RespostaClass(); 65 | 66 | if(erro){ 67 | resposta.erro = true; 68 | resposta.msg = 'Ocorreu um erro'; 69 | console.log('erro:', erro); 70 | }else{ 71 | if(retorno.affectedRows > 0){ 72 | resposta.msg = "Registro excluído com sucesso."; 73 | }else{ 74 | resposta.erro = true; 75 | resposta.msg = 'Não foi possível excluir o resgistro.' 76 | } 77 | } 78 | console.log('resp:', resposta); 79 | res.json(resposta); 80 | }) 81 | }) 82 | 83 | router.put("/", function(req, res, next){ 84 | 85 | PortfolioModel.editar(req.body, function(erro, retorno){ 86 | let resposta = new RespostaClass(); 87 | 88 | if(erro){ 89 | resposta.erro = true; 90 | resposta.msg = 'Ocorreu um erro'; 91 | console.log('erro:', erro); 92 | }else{ 93 | if(retorno.affectedRows > 0){ 94 | resposta.msg = "Registro editado com sucesso."; 95 | }else{ 96 | resposta.erro = true; 97 | resposta.msg = 'Não foi possível editar o resgistro.' 98 | } 99 | } 100 | console.log('resp:', resposta); 101 | res.json(resposta); 102 | }) 103 | }) 104 | 105 | module.exports = router; -------------------------------------------------------------------------------- /projeto-portfolio/web-app/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env" 4 | ] 5 | } -------------------------------------------------------------------------------- /projeto-portfolio/web-app/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /projeto-portfolio/web-app/dist/bundle/indexController.bundle.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 40 | /******/ } 41 | /******/ }; 42 | /******/ 43 | /******/ // define __esModule on exports 44 | /******/ __webpack_require__.r = function(exports) { 45 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 46 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 47 | /******/ } 48 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 49 | /******/ }; 50 | /******/ 51 | /******/ // create a fake namespace object 52 | /******/ // mode & 1: value is a module id, require it 53 | /******/ // mode & 2: merge all properties of value into the ns 54 | /******/ // mode & 4: return value when already ns object 55 | /******/ // mode & 8|1: behave like require 56 | /******/ __webpack_require__.t = function(value, mode) { 57 | /******/ if(mode & 1) value = __webpack_require__(value); 58 | /******/ if(mode & 8) return value; 59 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 60 | /******/ var ns = Object.create(null); 61 | /******/ __webpack_require__.r(ns); 62 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 63 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 64 | /******/ return ns; 65 | /******/ }; 66 | /******/ 67 | /******/ // getDefaultExport function for compatibility with non-harmony modules 68 | /******/ __webpack_require__.n = function(module) { 69 | /******/ var getter = module && module.__esModule ? 70 | /******/ function getDefault() { return module['default']; } : 71 | /******/ function getModuleExports() { return module; }; 72 | /******/ __webpack_require__.d(getter, 'a', getter); 73 | /******/ return getter; 74 | /******/ }; 75 | /******/ 76 | /******/ // Object.prototype.hasOwnProperty.call 77 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 78 | /******/ 79 | /******/ // __webpack_public_path__ 80 | /******/ __webpack_require__.p = ""; 81 | /******/ 82 | /******/ 83 | /******/ // Load entry module and return exports 84 | /******/ return __webpack_require__(__webpack_require__.s = "./src/controllers/IndexController.js"); 85 | /******/ }) 86 | /************************************************************************/ 87 | /******/ ({ 88 | 89 | /***/ "./src/ConfigClass.js": 90 | /*!****************************!*\ 91 | !*** ./src/ConfigClass.js ***! 92 | \****************************/ 93 | /*! no static exports found */ 94 | /***/ (function(module, exports, __webpack_require__) { 95 | 96 | "use strict"; 97 | eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar ConfigClass = function () {\n function ConfigClass() {\n _classCallCheck(this, ConfigClass);\n }\n\n _createClass(ConfigClass, null, [{\n key: \"getUrlApi\",\n value: function getUrlApi() {\n this.urlApi = \"http://localhost:3000\";\n return this.urlApi;\n }\n }]);\n\n return ConfigClass;\n}();\n\nexports.default = ConfigClass;\n\n//# sourceURL=webpack:///./src/ConfigClass.js?"); 98 | 99 | /***/ }), 100 | 101 | /***/ "./src/controllers/IndexController.js": 102 | /*!********************************************!*\ 103 | !*** ./src/controllers/IndexController.js ***! 104 | \********************************************/ 105 | /*! no static exports found */ 106 | /***/ (function(module, exports, __webpack_require__) { 107 | 108 | "use strict"; 109 | eval("\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _PortfolioModel = __webpack_require__(/*! ../models/portfolio/PortfolioModel */ \"./src/models/portfolio/PortfolioModel.js\");\n\nvar _PortfolioModel2 = _interopRequireDefault(_PortfolioModel);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar divPortfolios = window.document.getElementById(\"div-portfolios\");\nvar objIndexController = void 0;\n\nvar IndexController = function () {\n function IndexController() {\n _classCallCheck(this, IndexController);\n }\n\n _createClass(IndexController, [{\n key: \"getTodosIndex\",\n value: function getTodosIndex(divPortfolios) {\n var promise = new Promise(function (resolve, reject) {\n var promiseFetch = _PortfolioModel2.default.getTodos();\n\n promiseFetch.then(function (response) {\n resolve(response);\n });\n });\n\n promise.then(function (response) {\n var dados = \"\";\n\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = response.dados[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var servico = _step.value;\n\n dados += \"
\\n
\\n
\" + servico.descricao + \"
\\n
\\n
\\n

\" + servico.detalhes + \"

\\n
\\n

\";\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n\n divPortfolios.innerHTML = dados;\n }).catch(function (response) {\n return console.log(\"erro catch:\", response);\n });\n }\n }]);\n\n return IndexController;\n}();\n\nfunction main() {\n objIndexController = new IndexController();\n objIndexController.getTodosIndex(divPortfolios);\n}\n\nwindow.onload = main;\n\n//# sourceURL=webpack:///./src/controllers/IndexController.js?"); 110 | 111 | /***/ }), 112 | 113 | /***/ "./src/models/portfolio/PortfolioModel.js": 114 | /*!************************************************!*\ 115 | !*** ./src/models/portfolio/PortfolioModel.js ***! 116 | \************************************************/ 117 | /*! no static exports found */ 118 | /***/ (function(module, exports, __webpack_require__) { 119 | 120 | "use strict"; 121 | eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _ConfigClass = __webpack_require__(/*! ../../ConfigClass */ \"./src/ConfigClass.js\");\n\nvar _ConfigClass2 = _interopRequireDefault(_ConfigClass);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar caminho = _ConfigClass2.default.getUrlApi().toString() + '/portfolio';\n\nvar PortfolioModel = function () {\n function PortfolioModel() {\n _classCallCheck(this, PortfolioModel);\n }\n\n _createClass(PortfolioModel, null, [{\n key: 'getTodos',\n value: function getTodos() {\n return fetch(caminho).then(function (response) {\n if (response.status >= 400) {\n throw new Error('erro server');\n }\n return response.json();\n });\n }\n }, {\n key: 'getId',\n value: function getId(id) {\n return fetch(caminho + '/' + id).then(function (response) {\n if (response.status >= 400) {\n throw new Error('erro server');\n }\n return response.json();\n });\n }\n }, {\n key: 'adicionar',\n value: function adicionar(objPortfolioClass) {\n return fetch(caminho, {\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json'\n },\n method: \"POST\",\n body: JSON.stringify(objPortfolioClass)\n }).then(function (response) {\n if (response.status >= 400) {\n throw new Error('erro server');\n }\n return response.json();\n });\n }\n }, {\n key: 'editar',\n value: function editar(objPortfolioClass) {\n return fetch(caminho, {\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json'\n },\n method: \"PUT\",\n body: JSON.stringify(objPortfolioClass)\n }).then(function (response) {\n if (response.status >= 400) {\n throw new Error('erro server');\n }\n return response.json();\n });\n }\n }, {\n key: 'deletar',\n value: function deletar(id) {\n return fetch(caminho + '/' + id, {\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json'\n },\n method: \"DELETE\"\n }).then(function (response) {\n if (response.status >= 400) {\n throw new Error('erro server');\n }\n return response.json();\n });\n }\n }]);\n\n return PortfolioModel;\n}();\n\nexports.default = PortfolioModel;\n\n//# sourceURL=webpack:///./src/models/portfolio/PortfolioModel.js?"); 122 | 123 | /***/ }) 124 | 125 | /******/ }); -------------------------------------------------------------------------------- /projeto-portfolio/web-app/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Portfólio de Serviços 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |

Portfólio de Serviços

61 |
62 | 63 |
64 | 65 |
66 | 67 |
68 |
69 |
70 | Featured 71 |
72 |
73 |
Special title treatment
74 |

With supporting text below as a natural lead-in to additional content.

75 | Go somewhere 76 |
77 |
78 |
79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /projeto-portfolio/web-app/dist/view/portfolio/crud.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Cadastro Portfólio de Serviços 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |

Cadastro de Portfólio de Serviços

61 |
62 | 63 |
64 | 65 |
66 |
67 |
68 |
69 | 70 |
71 |
72 |
73 |
74 |
75 | 76 | 77 |
78 |
79 | 80 | 81 |
82 | 83 |
84 | 85 | 86 |
87 | 88 |
89 | 90 | 91 |
92 |
93 |
94 |
95 |
96 | 97 | 98 |
99 | 100 |
101 | 102 |
103 |
104 |
105 | Featured 106 |
107 |
108 |
Special title treatment
109 |

With supporting text below as a natural lead-in to additional content.

110 | Go somewhere 111 |
112 |
113 |
114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /projeto-portfolio/web-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-app", 3 | "version": "1.0.0", 4 | "description": "test com webpack", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "webpack --mode development", 8 | "build": "webpack --mode development", 9 | "start": "webpack-dev-server --mode production --open" 10 | }, 11 | "author": "Prof. Madson Aguiar", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "autoprefixer": "^9.1.3", 15 | "babel-core": "^6.26.3", 16 | "babel-loader": "^7.1.5", 17 | "babel-preset-env": "^1.7.0", 18 | "css-loader": "^1.0.0", 19 | "file-loader": "^2.0.0", 20 | "mini-css-extract-plugin": "^0.4.2", 21 | "node-sass": "^4.9.3", 22 | "optimize-css-assets-webpack-plugin": "^5.0.0", 23 | "postcss-loader": "^3.0.0", 24 | "precss": "^3.1.2", 25 | "sass-loader": "^7.1.0", 26 | "style-loader": "^0.22.1", 27 | "uglifyjs-webpack-plugin": "^1.3.0", 28 | "webpack": "^4.17.1", 29 | "webpack-cli": "^3.1.0", 30 | "webpack-dev-server": "^3.1.5" 31 | }, 32 | "dependencies": { 33 | "babel-polyfill": "^6.26.0", 34 | "bootstrap": "^4.1.3", 35 | "jquery": "^3.3.1", 36 | "popper.js": "^1.14.4" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /projeto-portfolio/web-app/src/ConfigClass.js: -------------------------------------------------------------------------------- 1 | export default class ConfigClass{ 2 | constructor(){ 3 | 4 | } 5 | 6 | static getUrlApi(){ 7 | this.urlApi = "http://localhost:3000"; 8 | return this.urlApi; 9 | } 10 | } -------------------------------------------------------------------------------- /projeto-portfolio/web-app/src/controllers/IndexController.js: -------------------------------------------------------------------------------- 1 | import PortfolioModel from "../models/portfolio/PortfolioModel"; 2 | 3 | let divPortfolios = window.document.getElementById("div-portfolios"); 4 | let objIndexController; 5 | 6 | class IndexController{ 7 | 8 | getTodosIndex(divPortfolios){ 9 | let promise = new Promise(function(resolve, reject){ 10 | let promiseFetch = PortfolioModel.getTodos(); 11 | 12 | promiseFetch.then(response =>{ 13 | resolve(response); 14 | }); 15 | }) 16 | 17 | promise.then(response =>{ 18 | let dados = ""; 19 | 20 | for(const servico of response.dados){ 21 | dados += `
22 |
23 |
${servico.descricao}
24 |
25 |
26 |

${servico.detalhes}

27 |
28 |

`; 29 | } 30 | 31 | divPortfolios.innerHTML = dados; 32 | }).catch(response => console.log("erro catch:", response)); 33 | } 34 | } 35 | 36 | function main(){ 37 | objIndexController = new IndexController(); 38 | objIndexController.getTodosIndex(divPortfolios); 39 | } 40 | 41 | window.onload = main; -------------------------------------------------------------------------------- /projeto-portfolio/web-app/src/controllers/PortfolioController.js: -------------------------------------------------------------------------------- 1 | import PortfolioModel from "../models/portfolio/PortfolioModel"; 2 | import PortfolioClass from "../models/portfolio/PortfolioClass"; 3 | 4 | let divMsg = window.document.getElementById("msg"); 5 | let divPortfolios = window.document.getElementById("portfolios"); 6 | let formulario = window.document.getElementById("form"); 7 | 8 | let objPortfolioController; 9 | 10 | class PortfolioController{ 11 | 12 | getTodosTable(divPortfolios){ 13 | let promise = new Promise(function(resolve, reject){ 14 | let promiseFetch = PortfolioModel.getTodos(); 15 | 16 | promiseFetch.then(response =>{ 17 | resolve(response); 18 | }); 19 | }) 20 | 21 | promise.then(response =>{ 22 | let dados = ""; 23 | 24 | if(response.erro){ 25 | this.exibirMsgAlert(response.msg, 'erro'); 26 | }else{ 27 | dados += `
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | `; 38 | 39 | for(const servico of response.dados){ 40 | dados += ` 41 | 42 | 43 | 44 | 45 | `; 46 | 47 | } 48 | 49 | dados += "
CódigoDescrição
${servico.id_portfolio}${servico.descricao}
"; 50 | divPortfolios.innerHTML = dados; 51 | 52 | let btnsEditar = document.querySelectorAll(".btn-editar"); 53 | let btnsExcluir= document.querySelectorAll(".btn-excluir"); 54 | 55 | btnsEditar.forEach(function(item){ 56 | item.addEventListener("click", event =>{ 57 | objPortfolioController.limparMsgAlert(); 58 | let id = event.target.getAttribute('data-id'); 59 | objPortfolioController.prepararEditar(id); 60 | } ); 61 | }); 62 | 63 | btnsExcluir.forEach(function(item){ 64 | item.addEventListener("click", event =>{ 65 | objPortfolioController.limparMsgAlert(); 66 | let id = event.target.getAttribute('data-id'); 67 | objPortfolioController.deletar(id); 68 | } ); 69 | }); 70 | } 71 | }).catch(response => console.log("erro catch:", response)); 72 | } 73 | 74 | prepararEditar(id){ 75 | 76 | let promise = new Promise(function(resolve, reject){ 77 | let promiseFetch = PortfolioModel.getId(id); 78 | 79 | promiseFetch.then(response =>{ 80 | resolve(response); 81 | }); 82 | }) 83 | 84 | promise.then(response =>{ 85 | if(response.erro){ 86 | this.exibirMsgAlert(response.msg,"erro"); 87 | }else{ 88 | 89 | let objPortfolioClass = new PortfolioClass( 90 | response.dados[0].id_portfolio, 91 | response.dados[0].descricao, 92 | response.dados[0].detalhes); 93 | 94 | formulario.id.value = objPortfolioClass.id_portfolio; 95 | formulario.descricao.value = objPortfolioClass.descricao; 96 | formulario.detalhes.value = objPortfolioClass.detalhes; 97 | 98 | objPortfolioController.ocultarElemento("listagem"); 99 | objPortfolioController.exibirElemento("formulario"); 100 | } 101 | }).catch(response => { 102 | console.log("erro catch:", response); 103 | }); 104 | }; 105 | 106 | editar(formulario){ 107 | let id, descricao, detalhes; 108 | id = formulario.id.value; 109 | descricao = formulario.descricao.value; 110 | detalhes = formulario.detalhes.value; 111 | 112 | if(id && descricao && detalhes){ 113 | let objPortfolioClass = new PortfolioClass(id, descricao, detalhes); 114 | 115 | let promise = new Promise(function(resolve, reject){ 116 | let promiseFetch = PortfolioModel.editar(objPortfolioClass); 117 | 118 | promiseFetch.then(response =>{ 119 | resolve(response); 120 | }); 121 | }) 122 | 123 | promise.then(response =>{ 124 | if(response.erro){ 125 | this.exibirMsgAlert(response.msg,"erro"); 126 | }else{ 127 | objPortfolioController.getTodosTable(divPortfolios); 128 | objPortfolioController.exibirMsgAlert(response.msg,"sucesso"); 129 | objPortfolioController.ocultarElemento("formulario"); 130 | objPortfolioController.exibirElemento("listagem"); 131 | objPortfolioController.limparCamposForm(formulario); 132 | } 133 | }).catch(response => { 134 | console.log("erro catch:", response); 135 | }); 136 | 137 | }else{ 138 | this.exibirMsgAlert("Por favor preencher todos os campos.","erro"); 139 | } 140 | } 141 | 142 | adicionar(formulario){ 143 | let descricao, detalhes; 144 | descricao = formulario.descricao.value; 145 | detalhes = formulario.detalhes.value; 146 | 147 | if(descricao && detalhes){ 148 | let objPortfolioClass = new PortfolioClass(null, descricao, detalhes); 149 | 150 | let promise = new Promise(function(resolve, reject){ 151 | let promiseFetch = PortfolioModel.adicionar(objPortfolioClass); 152 | 153 | promiseFetch.then(response =>{ 154 | resolve(response); 155 | }); 156 | }) 157 | 158 | promise.then(response =>{ 159 | if(response.erro){ 160 | this.exibirMsgAlert(response.msg,"erro"); 161 | }else{ 162 | objPortfolioController.getTodosTable(divPortfolios); 163 | objPortfolioController.exibirMsgAlert(response.msg,"sucesso"); 164 | objPortfolioController.ocultarElemento("formulario"); 165 | objPortfolioController.exibirElemento("listagem"); 166 | objPortfolioController.limparCamposForm(formulario); 167 | } 168 | }).catch(response => { 169 | console.log("erro catch:", response); 170 | }); 171 | 172 | }else{ 173 | this.exibirMsgAlert("Por favor preencher todos os campos.","erro"); 174 | } 175 | } 176 | 177 | deletar(id){ 178 | 179 | let promise = new Promise(function(resolve, reject){ 180 | let promiseFetch = PortfolioModel.deletar(id); 181 | 182 | promiseFetch.then(response =>{ 183 | resolve(response); 184 | }); 185 | }) 186 | 187 | promise.then(response =>{ 188 | if(response.erro){ 189 | this.exibirMsgAlert(response.msg,"erro"); 190 | }else{ 191 | objPortfolioController.getTodosTable(divPortfolios); 192 | objPortfolioController.exibirMsgAlert(response.msg,"sucesso"); 193 | } 194 | }).catch(response => { 195 | console.log("erro catch:", response); 196 | }); 197 | }; 198 | 199 | ocultarElemento(elemento){ 200 | document.getElementById(elemento).style.display = "none"; 201 | 202 | } 203 | 204 | exibirElemento(elemento){ 205 | document.getElementById(elemento).style.display = "block"; 206 | } 207 | 208 | limparCamposForm(form){ 209 | form.id.value = ""; 210 | form.descricao.value = ""; 211 | form.detalhes.value = ""; 212 | } 213 | 214 | exibirMsgAlert(msg, tipo){ 215 | let dados = ""; 216 | if(tipo == "sucesso"){ 217 | dados = `` 223 | }else if(tipo == "erro"){ 224 | dados = `` 230 | } 231 | 232 | divMsg.innerHTML = dados; 233 | } 234 | 235 | limparMsgAlert(){ 236 | divMsg.innerHTML = ""; 237 | } 238 | 239 | registrarEvents(){ 240 | document.getElementById('btn-exibir-formulario').addEventListener("click",function(){ 241 | objPortfolioController.limparMsgAlert(); 242 | objPortfolioController.ocultarElemento("listagem"); 243 | objPortfolioController.exibirElemento("formulario"); 244 | }); 245 | 246 | document.getElementById('btn-cadastrar-portfolio').addEventListener("click",function(){ 247 | event.preventDefault(); 248 | objPortfolioController.limparMsgAlert(); 249 | if(formulario.id.value){ 250 | objPortfolioController.editar(formulario); 251 | }else{ 252 | objPortfolioController.adicionar(formulario); 253 | } 254 | }); 255 | 256 | document.getElementById('btn-cancelar-operacao').addEventListener("click",function(){ 257 | objPortfolioController.limparMsgAlert(); 258 | objPortfolioController.limparCamposForm(formulario); 259 | objPortfolioController.ocultarElemento("formulario"); 260 | objPortfolioController.exibirElemento("listagem"); 261 | }); 262 | } 263 | 264 | 265 | 266 | } 267 | 268 | function main(){ 269 | objPortfolioController = new PortfolioController(); 270 | objPortfolioController.ocultarElemento("formulario"); 271 | objPortfolioController.getTodosTable(divPortfolios); 272 | objPortfolioController.registrarEvents(); 273 | } 274 | 275 | window.onload = main; -------------------------------------------------------------------------------- /projeto-portfolio/web-app/src/css/base.css: -------------------------------------------------------------------------------- 1 | /*body{ 2 | background-color: beige ; 3 | }*/ -------------------------------------------------------------------------------- /projeto-portfolio/web-app/src/index.js: -------------------------------------------------------------------------------- 1 | import 'bootstrap'; 2 | import base from './css/base.css' 3 | import scss from './scss/base.scss' 4 | 5 | -------------------------------------------------------------------------------- /projeto-portfolio/web-app/src/models/portfolio/PortfolioClass.js: -------------------------------------------------------------------------------- 1 | export default class PortfolioClass{ 2 | constructor(id, descricao, detalhes){ 3 | if(id!=null) this.id_portfolio = id; 4 | this.descricao = descricao; 5 | this.detalhes = detalhes; 6 | } 7 | } -------------------------------------------------------------------------------- /projeto-portfolio/web-app/src/models/portfolio/PortfolioModel.js: -------------------------------------------------------------------------------- 1 | import ConfigClass from "../../ConfigClass" 2 | 3 | const caminho = `${ConfigClass.getUrlApi().toString()}/portfolio`; 4 | 5 | export default class PortfolioModel{ 6 | constructor(){ 7 | } 8 | 9 | static getTodos(){ 10 | return fetch(caminho).then(response =>{ 11 | if(response.status >= 400){ 12 | throw new Error('erro server'); 13 | } 14 | return response.json(); 15 | }) 16 | } 17 | 18 | static getId(id){ 19 | return fetch(`${caminho}/${id}`).then(response =>{ 20 | if(response.status >= 400){ 21 | throw new Error('erro server'); 22 | } 23 | return response.json(); 24 | }) 25 | } 26 | 27 | static adicionar(objPortfolioClass){ 28 | return fetch(caminho, 29 | { 30 | headers:{ 31 | 'Accept': 'application/json', 32 | 'Content-Type':'application/json' 33 | }, 34 | method: "POST", 35 | body: JSON.stringify(objPortfolioClass) 36 | } 37 | ).then(response =>{ 38 | if(response.status >= 400){ 39 | throw new Error('erro server'); 40 | } 41 | return response.json(); 42 | }) 43 | } 44 | 45 | static editar(objPortfolioClass){ 46 | return fetch(caminho, 47 | { 48 | headers:{ 49 | 'Accept': 'application/json', 50 | 'Content-Type':'application/json' 51 | }, 52 | method: "PUT", 53 | body: JSON.stringify(objPortfolioClass) 54 | } 55 | ).then(response =>{ 56 | if(response.status >= 400){ 57 | throw new Error('erro server'); 58 | } 59 | return response.json(); 60 | }) 61 | } 62 | 63 | static deletar(id){ 64 | return fetch(`${caminho}/${id}`, 65 | { 66 | headers:{ 67 | 'Accept': 'application/json', 68 | 'Content-Type':'application/json' 69 | }, 70 | method: "DELETE", 71 | } 72 | ).then(response =>{ 73 | if(response.status >= 400){ 74 | throw new Error('erro server'); 75 | } 76 | return response.json(); 77 | }) 78 | } 79 | } -------------------------------------------------------------------------------- /projeto-portfolio/web-app/src/scss/_variaveis.scss: -------------------------------------------------------------------------------- 1 | $cor-fundo: blue; -------------------------------------------------------------------------------- /projeto-portfolio/web-app/src/scss/base.scss: -------------------------------------------------------------------------------- 1 | @import '_variaveis.scss'; 2 | @import "~bootstrap/scss/bootstrap"; 3 | 4 | /*body{ 5 | background-color: $cor-fundo; 6 | }*/ -------------------------------------------------------------------------------- /projeto-portfolio/web-app/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 3 | const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); 4 | const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); 5 | 6 | /* 7 | entry: ["babel-polyfill", "./src/index.js"],//irá empacotar em um único arquivo 8 | output: { 9 | path: path.resolve(__dirname, 'dist'), 10 | filename: 'bundle.js' 11 | }, 12 | */ 13 | 14 | module.exports = { 15 | entry: { 16 | babelpolyfill: 'babel-polyfill', 17 | index: './src/index.js', 18 | indexController: './src/controllers/IndexController.js', 19 | portfolioController: './src/controllers/PortfolioController.js' 20 | }, 21 | output: { 22 | path: path.resolve(__dirname, 'dist/bundle'), 23 | filename: '[name].bundle.js' 24 | }, 25 | optimization: { 26 | /*splitChunks: { 27 | chunks: 'all' 28 | },*/ 29 | minimizer: [ 30 | new UglifyJsPlugin({ 31 | uglifyOptions: { 32 | output: { 33 | comments: false 34 | } 35 | } 36 | }), 37 | new OptimizeCSSAssetsPlugin({}) 38 | ] 39 | }, 40 | plugins: [ 41 | new MiniCssExtractPlugin({ 42 | filename: "css.css" 43 | }) 44 | ], 45 | module: { 46 | rules: [ 47 | { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }, 48 | { 49 | test: /\.css$/, 50 | use: [ 51 | { loader: MiniCssExtractPlugin.loader },//style-loader 52 | { loader: "css-loader" } 53 | ] 54 | }, 55 | /*{ 56 | test: /\.css$/, 57 | use: [ 58 | { loader: "style-loader" }, 59 | { loader: "css-loader" } 60 | ] 61 | } { 62 | test: /\.css$/, 63 | use: [ 64 | { loader: "style-loader/url" }, 65 | { loader: "file-loader" } 66 | ] 67 | }, 68 | { 69 | test: /\.scss$/, 70 | use: [ 71 | "style-loader", // creates style nodes from JS strings 72 | "css-loader", // translates CSS into CommonJS 73 | "sass-loader" // compiles Sass to CSS, using Node Sass by default 74 | ] 75 | }*/ 76 | { 77 | test: /\.(scss)$/, 78 | use: [{ 79 | loader: MiniCssExtractPlugin.loader, // inject CSS to page 'style-loader' 80 | }, { 81 | loader: 'css-loader', // translates CSS into CommonJS modules 82 | }, { 83 | loader: 'postcss-loader', // Run post css actions 84 | options: { 85 | plugins: function () { // post css plugins, can be exported to postcss.config.js 86 | return [ 87 | require('precss'), 88 | require('autoprefixer') 89 | ]; 90 | } 91 | } 92 | }, { 93 | loader: 'sass-loader' // compiles Sass to CSS 94 | }] 95 | } 96 | ] 97 | }, 98 | devServer: { 99 | contentBase: './dist', 100 | port: 9000 101 | } 102 | }; -------------------------------------------------------------------------------- /template-html/crud.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Template com HTML5 e Bootstrap 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |
61 | 62 |
63 |

Form com HTML Simples

64 |

Cadastro de Cliente

65 | 66 |
67 |
68 | 69 | 70 |
71 |
72 | 73 | 74 |
75 |
76 | 77 | 78 | 79 |
80 |
81 | 82 | 83 | 84 | 85 |
86 |
87 | 93 |
94 | 95 |
96 | 97 |
98 |
99 |
100 | 101 |
102 |

Form com Bootstrap

103 |

Cadastro de Cliente

104 |
105 | 106 |
107 | 108 | 109 |
110 | 111 |
112 | 113 | 114 |
115 | 116 |
117 | 118 | 119 |
120 |
121 | 122 |
123 | 124 | 125 |
126 |
127 | 128 | 129 |
130 |
131 | 132 | 133 | 139 |
140 |
141 | 142 |
143 | 144 |
145 |
146 | 147 |
148 |
149 | 150 |
151 | 152 |
153 |
154 |
155 |
156 | Featured 157 |
158 |
159 |
Special title treatment
160 |

With supporting text below as a natural lead-in to additional content.

161 | Go somewhere 162 |
163 |
164 |
165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /template-html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Template com HTML5 e Bootstrap 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |

Template com HTML5 e Bootstrap

61 | 62 |
63 |
64 |
65 | 66 | 67 | We'll never share your email with anyone else. 68 |
69 |
70 | 71 | 72 |
73 |
74 | 75 | 76 |
77 | 78 |
79 |
80 | 81 |
82 | 83 |
84 | 85 |
86 |
87 |
88 | Featured 89 |
90 |
91 |
Special title treatment
92 |

With supporting text below as a natural lead-in to additional content.

93 | Go somewhere 94 |
95 |
96 |
97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /template-html/js/js.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/madsonar/Projeto-Site-Portfolio-RESTFul-CRUD-JavaScript-NodeJs-Express-MySQL/f6d324ac6ff74972cc7693c530981e466ee06f34/template-html/js/js.js -------------------------------------------------------------------------------- /template-html/listagem-table.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Template com HTML5 e Bootstrap 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |
61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 |
Listagem de Clientes
IdNomeRuaIdNomeRuaIdNomeRua
10PedroRua A10PedroRua A10PedroRua A
11MariaRua B11MariaRua B11MariaRua B
13JoãoRua C13JoãoRua C13JoãoRua C
14FranciscoRua A14FranciscoRua A14FranciscoRua A
130 |
131 |
132 | 133 |
134 |
135 |
136 | Featured 137 |
138 |
139 |
Special title treatment
140 |

With supporting text below as a natural lead-in to additional content.

141 | Go somewhere 142 |
143 |
144 |
145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /webpack/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env" 4 | ] 5 | } -------------------------------------------------------------------------------- /webpack/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /webpack/dist/bundle/babelpolyfill.bundle.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,f,i=r[0],l=r[1],a=r[2],c=0,s=[];c 2 | 3 | 4 | 5 | 6 | 7 | 8 | Template com HTML5 e Bootstrap 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |
61 | 62 |
63 |

Form com HTML Simples

64 |

Cadastro de Cliente

65 | 66 |
67 |
68 | 69 | 70 |
71 |
72 | 73 | 74 |
75 |
76 | 77 | 78 | 79 |
80 |
81 | 82 | 83 | 84 | 85 |
86 |
87 | 93 |
94 | 95 |
96 | 97 |
98 |
99 |
100 | 101 |
102 |

Form com Bootstrap

103 |

Cadastro de Cliente

104 |
105 | 106 |
107 | 108 | 109 |
110 | 111 |
112 | 113 | 114 |
115 | 116 |
117 | 118 | 119 |
120 |
121 | 122 |
123 | 124 | 125 |
126 |
127 | 128 | 129 |
130 |
131 | 132 | 133 | 139 |
140 |
141 | 142 |
143 | 144 |
145 |
146 | 147 |
148 |
149 | 150 |
151 | 152 |
153 |
154 |
155 |
156 | Featured 157 |
158 |
159 |
Special title treatment
160 |

With supporting text below as a natural lead-in to additional content.

161 | Go somewhere 162 |
163 |
164 |
165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /webpack/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Template com HTML5 e Bootstrap 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 55 |
56 | 57 |
58 | 59 |
60 | 61 |

Template com HTML5 e Bootstrap

62 | 63 |
64 |
65 |
66 | 67 | 68 | We'll never share your email with anyone else. 69 |
70 |
71 | 72 | 73 |
74 |
75 | 76 | 77 |
78 | 79 |
80 |
81 | 82 |
83 | 84 |
85 | 86 |
87 |
88 |
89 | Featured 90 |
91 |
92 |
Special title treatment
93 |

With supporting text below as a natural lead-in to additional content.

94 | Go somewhere 95 |
96 |
97 |
98 | 99 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /webpack/dist/js/js.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/madsonar/Projeto-Site-Portfolio-RESTFul-CRUD-JavaScript-NodeJs-Express-MySQL/f6d324ac6ff74972cc7693c530981e466ee06f34/webpack/dist/js/js.js -------------------------------------------------------------------------------- /webpack/dist/listagem-table.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Template com HTML5 e Bootstrap 9 | 10 | 11 | 12 | 13 | 14 |
15 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |
61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 |
Listagem de Clientes
IdNomeRuaIdNomeRuaIdNomeRua
10PedroRua A10PedroRua A10PedroRua A
11MariaRua B11MariaRua B11MariaRua B
13JoãoRua C13JoãoRua C13JoãoRua C
14FranciscoRua A14FranciscoRua A14FranciscoRua A
130 |
131 |
132 | 133 |
134 |
135 |
136 | Featured 137 |
138 |
139 |
Special title treatment
140 |

With supporting text below as a natural lead-in to additional content.

141 | Go somewhere 142 |
143 |
144 |
145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-webpack", 3 | "version": "1.0.0", 4 | "description": "test com webpack", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "webpack --mode development", 8 | "build": "webpack --mode production", 9 | "start": "webpack-dev-server --mode production --open" 10 | }, 11 | "author": "Prof. Madson Aguiar", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "autoprefixer": "^9.1.3", 15 | "babel-core": "^6.26.3", 16 | "babel-loader": "^7.1.5", 17 | "babel-preset-env": "^1.7.0", 18 | "css-loader": "^1.0.0", 19 | "file-loader": "^2.0.0", 20 | "mini-css-extract-plugin": "^0.4.2", 21 | "node-sass": "^4.9.3", 22 | "optimize-css-assets-webpack-plugin": "^5.0.0", 23 | "postcss-loader": "^3.0.0", 24 | "precss": "^3.1.2", 25 | "sass-loader": "^7.1.0", 26 | "style-loader": "^0.22.1", 27 | "uglifyjs-webpack-plugin": "^1.3.0", 28 | "webpack": "^4.17.1", 29 | "webpack-cli": "^3.1.0", 30 | "webpack-dev-server": "^3.1.5" 31 | }, 32 | "dependencies": { 33 | "babel-polyfill": "^6.26.0", 34 | "bootstrap": "^4.1.3", 35 | "jquery": "^3.3.1", 36 | "popper.js": "^1.14.4" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /webpack/src/cliente-class.js: -------------------------------------------------------------------------------- 1 | export default class Cliente{ 2 | constructor(nome){ 3 | this.nome = nome; 4 | } 5 | 6 | falar(){ 7 | console.log(`Olá tudo bem, meu nome é ${this.nome}!`); 8 | } 9 | } -------------------------------------------------------------------------------- /webpack/src/css/base.css: -------------------------------------------------------------------------------- 1 | body{ 2 | background-color: beige ; 3 | } -------------------------------------------------------------------------------- /webpack/src/index.js: -------------------------------------------------------------------------------- 1 | import {} from './instancia-cliente'; 2 | import {} from './promise'; 3 | import 'bootstrap'; 4 | import base from './css/base.css' 5 | import scss from './scss/base.scss' 6 | 7 | 8 | const es = "ES2015-const"; 9 | console.log(es); -------------------------------------------------------------------------------- /webpack/src/instancia-cliente.js: -------------------------------------------------------------------------------- 1 | import Cliente from './cliente-class'; 2 | 3 | const objCliente = new Cliente('João'); 4 | objCliente.falar(); 5 | -------------------------------------------------------------------------------- /webpack/src/promise.js: -------------------------------------------------------------------------------- 1 | let p = new Promise(function(resolve, reject){ 2 | 3 | let teste = false; 4 | 5 | if(teste){ 6 | resolve('tudo ok'); 7 | }else{ 8 | reject('deu um erro'); 9 | } 10 | 11 | }); 12 | 13 | p.then(retorno=>{ 14 | console.log(retorno); 15 | }).catch(retorno=>{ 16 | console.log(retorno); 17 | }); -------------------------------------------------------------------------------- /webpack/src/scss/_variaveis.scss: -------------------------------------------------------------------------------- 1 | $cor-fundo: blue; -------------------------------------------------------------------------------- /webpack/src/scss/base.scss: -------------------------------------------------------------------------------- 1 | @import '_variaveis.scss'; 2 | @import "~bootstrap/scss/bootstrap"; 3 | 4 | body{ 5 | background-color: $cor-fundo; 6 | } -------------------------------------------------------------------------------- /webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 3 | const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); 4 | const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); 5 | 6 | /* 7 | entry: ["babel-polyfill", "./src/index.js"],//irá empacotar em um único arquivo 8 | output: { 9 | path: path.resolve(__dirname, 'dist'), 10 | filename: 'bundle.js' 11 | }, 12 | */ 13 | 14 | module.exports = { 15 | entry: { 16 | babelpolyfill: 'babel-polyfill', 17 | index: './src/index.js' 18 | }, 19 | output: { 20 | path: path.resolve(__dirname, 'dist/bundle'), 21 | filename: '[name].bundle.js' 22 | }, 23 | optimization: { 24 | splitChunks: { 25 | chunks: 'all' 26 | }, 27 | minimizer: [ 28 | new UglifyJsPlugin({ 29 | uglifyOptions: { 30 | output: { 31 | comments: false 32 | } 33 | } 34 | }), 35 | new OptimizeCSSAssetsPlugin({}) 36 | ] 37 | }, 38 | plugins: [ 39 | new MiniCssExtractPlugin({ 40 | filename: "css.css" 41 | }) 42 | ], 43 | module: { 44 | rules: [ 45 | { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }, 46 | { 47 | test: /\.css$/, 48 | use: [ 49 | { loader: MiniCssExtractPlugin.loader },//style-loader 50 | { loader: "css-loader" } 51 | ] 52 | }, 53 | /*{ 54 | test: /\.css$/, 55 | use: [ 56 | { loader: "style-loader" }, 57 | { loader: "css-loader" } 58 | ] 59 | } { 60 | test: /\.css$/, 61 | use: [ 62 | { loader: "style-loader/url" }, 63 | { loader: "file-loader" } 64 | ] 65 | }, 66 | { 67 | test: /\.scss$/, 68 | use: [ 69 | "style-loader", // creates style nodes from JS strings 70 | "css-loader", // translates CSS into CommonJS 71 | "sass-loader" // compiles Sass to CSS, using Node Sass by default 72 | ] 73 | }*/ 74 | { 75 | test: /\.(scss)$/, 76 | use: [{ 77 | loader: MiniCssExtractPlugin.loader, // inject CSS to page 'style-loader' 78 | }, { 79 | loader: 'css-loader', // translates CSS into CommonJS modules 80 | }, { 81 | loader: 'postcss-loader', // Run post css actions 82 | options: { 83 | plugins: function () { // post css plugins, can be exported to postcss.config.js 84 | return [ 85 | require('precss'), 86 | require('autoprefixer') 87 | ]; 88 | } 89 | } 90 | }, { 91 | loader: 'sass-loader' // compiles Sass to CSS 92 | }] 93 | } 94 | ] 95 | }, 96 | devServer: { 97 | contentBase: './dist', 98 | port: 9000 99 | } 100 | }; --------------------------------------------------------------------------------