Commit bb2c2c4e authored by Nacim Goura's avatar Nacim Goura

add meteor

parent 2592736e
{
"directory": "public/bower_components"
}
\ No newline at end of file
node_modules
npm-debug.log
public/bower_components
# http://editorconfig.org
root = true
[*]
indent_style = tab
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
/node_modules/* /node_modules/*
/public/bower_components/* /.meteor/*
\ No newline at end of file \ No newline at end of file
{ {
"extends": "eslint:recommended", "env": {
"env": { "meteor": true,
"browser": true, "es6": true,
"node": true, "shared-node-browser": true
"es6": true },
}, "parser": "babel-eslint",
"rules": { "parserOptions": {
"no-unused-vars": "warn", "allowImportExportEverywhere": true
"indent": ["error", 4, { "SwitchCase": 1 }], },
"linebreak-style": ["error", "unix"], "plugins": [
"semi": ["error", "always"], "meteor"
"no-console": "off", ],
"curly": "error", "extends": [
"eqeqeq": "error" "eslint:recommended",
} "plugin:meteor/recommended"
} ],
\ No newline at end of file "settings": {
"import/resolver": "meteor"
},
"rules": {
"import/no-extraneous-dependencies": 0,
"import/extensions": ["off", "never"],
"no-unused-vars": "warn",
"indent": ["error", "tab", { "SwitchCase": 1 }],
"linebreak-style": ["error", "unix"],
"semi": ["error", "always"],
"no-console": "off"
}
}
/node_modules node_modules/*
.idea .meteor/*
yarn.lock .idea/*
/public/bower_components
*.log
\ No newline at end of file
FROM node:boron
# Create app directory
RUN mkdir -p /usr/src/idsearch
WORKDIR /usr/src/idsearch
# Install all dependencies
COPY * /usr/src/idsearch/
RUN npm install
# Bundle app source
COPY . /usr/src/idsearch
EXPOSE 3000
CMD ["npm", "start"]
"use strict";
const express = require('express');
const path = require('path');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const exphbs = require('express-handlebars');
let app = express();
let urlPublic = path.join(__dirname, 'public');
app.engine('html', exphbs({
defaultLayout : 'main',
extname : '.html'
}));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('node-sass-middleware')({
src: urlPublic,
dest: urlPublic,
outputStyle: 'compressed',
sourceMap: true
}));
app.use(express.static(urlPublic));
require('./routes/index')(app);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
let err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
#!/usr/bin/env node
/**
* Module dependencies.
*/
const app = require('../app');
const debug = require('debug')('idsearch:server');
const http = require('http');
/**
* Get port from environment and store in Express.
*/
let port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
let server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
let port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
let bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
let addr = server.address();
let bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
{
"name": "public",
"version": "0.0.1",
"dependencies": {
"bootstrap-sass": "^3.3.7"
}
}
<head>
<title>meteorSearch</title>
</head>
\ No newline at end of file
import '../imports/startup/client';
@import "../imports/ui/stylesheets/_variables.scss";
@import "../node_modules/bootstrap-sass/assets/stylesheets/_bootstrap.scss";
// Global namespace
@import "../imports/ui/stylesheets/sidebar.scss";
/* CSS declarations go here */
body {
margin-top: 50px;
overflow: hidden;
}
form {
margin-bottom: 20px;
}
@media (min-width: $grid-float-breakpoint) {
.container-fluid {
margin-left: 42px;
}
}
.row {
padding-top: 5px;
}
.wrapper {
position: relative;
overflow: auto;
background-color: #ffffff;
padding-top: 15px;
}
.border-left {
border-left: 1px solid $table-border-color;
}
.navbar-inverse .navbar-brand {
font-size: 24px;
}
.two-cols {
column-count: 2;
}
.fa {
font-size: 16px;
}
.two-columns {
column-count: 2;
}
.view-group-addon .fa,
.delete-group-addon .fa {
color: #ffffff;
}
.radio-select-inline > div,
.radio-select-inline .radio {
display: inline-block;
vertical-align: bottom;
}
.radio-select-inline label:first-child {
padding-right: 10px;
}
.rc-percentage {
margin-bottom: 0;
width: 120px
}
.panel-footer {
background: transparent;
}
.input-group-addon {
color: #fff;
}
.max-height {
height: 100%;
overflow: auto;
}
.max-width {
width: 100%;
}
.half-width {
width: 50%;
}
.clear {
overflow: auto;
}
.btn-interface {
padding: 5px 2px 3px 2px;
position: absolute;
top: 0;
}
.btn-interface-caption {
position: relative;
top: 0;
margin-right: 5px;
}
.caption-title {
font-weight: bold;
color: $gray-dark;
}
.label-display {
font-weight: bold;
}
.nav-tabs {
border-bottom-width: 0;
}
.radio,
.checkbox {
margin: 0;
}
.relative {
position: relative;
}
span.link {
color: $brand-primary;
text-decoration: underline;
cursor: pointer;
}
.modal-header {
border-radius: 6px 6px 0 0;
}
.big-modal {
width: 75% !important;
height: 80vh !important;
margin: 10vh auto !important;
.modal-body {
position: absolute;
width: 100%;
top: 50px;
bottom: 0;
overflow-y: auto;
}
.tab-content {
position: absolute;
top: 65px;
bottom: 0;
overflow-y: auto;
}
.tab-pane {
padding-bottom: 60px;
}
.btn-region {
position: absolute;
bottom: 15px;
right: 15px;
left: 15px;
}
}
.movable {
cursor: move;
}
.not-movable {
cursor: no-drop;
}
.warning {
@extend .bg-warning;
}
.danger {
@extend .bg-danger;
}
"use strict";
module.exports = {
addApi() {
}
};
"use strict";
const Sitemapper = require('sitemapper');
const Crawler = require("crawler");
const chalk = require('chalk');
const Q = require('q');
const searchSite = require('../model/search.server.models');
module.exports = {
/**
* get all site in sitemap.xml
* @param urlSiteMap
* @returns array sites
*/
getSiteMap(urlSiteMap) {
let deferred = Q.defer();
let sitemap = new Sitemapper();
sitemap.fetch(urlSiteMap).then((data) => {
deferred.resolve(data.sites);
}, function(err) {
deferred.reject(err);
});
return deferred.promise;
},
/**
* crawl array sites
* @param listSite
*/
indexUrl(listSite) {
let listError = [];
let deferred = Q.defer();
let crawler = new Crawler({
maxConnections : 1000,
jQuery: {
name: 'cheerio',
options: {
normalizeWhitespace: true,
xmlMode: false,
decodeEntities: true
}
},
// This will be called for each crawled page
callback : function (error, res, done) {
if(error || res.statusCode !== 200){
listError.push({
url: res.options.uri,
error: error ? error : null,
status: res.statusCode
});
}else {
let $ = res.$;
let urlVisited = res.options.uri;
let obj = {
body : cleanHtml($),
title: $("title").text().toLowerCase(),
url: decodeURIComponent(urlVisited)
};
searchSite.index(obj)
.then(function(resp) {
console.log(resp);
}, function(err) {
console.log(err);
});
}
done();
}
});
searchSite.initElasticsearch()
.then((success) => {
console.log(chalk.green(success));
crawler.queue('http://www.hautesavoie.fr/vos-elus/christian-monteil');
crawler.queue(listSite);
crawler.on('drain', function(){
if(listError !== []) {
console.log(chalk.red("================="));
console.dir(listError, {depth: null});
console.log(chalk.red("================="));
}
deferred.resolve("indexation done");
});
}, function(err) {
deferred.reject(err);
});
return deferred.promise;
},
search(term) {
let deferred = Q.defer();
searchSite.search(term)
.then((data) => {
deferred.resolve(data.hits.hits);
}, (err) => {
deferred.reject(err);
});
return deferred.promise;
}
};
/**
* clean html
*/
function cleanHtml($) {
let bodyText = $('html > body').text().toLowerCase();
return bodyText
.replace(/\n/g, " ")
.replace(/function.*}/g, " ");
/*return sanitizeHtml(bodyText, {
allowedTags: [ 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div',
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre' ],
allowedAttributes: false,
selfClosing: [ 'img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta' ],
allowedSchemes: [ 'http', 'https', 'ftp', 'mailto' ],
allowedSchemesByTag: {},
allowProtocolRelative: true
});*/
}
/**
* search term in body
* @param data
* @param word
* @returns {boolean}
*/
function searchForWord(data, word) {
return data.indexOf(word.toLowerCase()) !== -1;
}
/**
* count occurence terms
* @param data
* @param word
* @returns {Number}
*/
function countOccurenceWord(data, word) {
let regex = new RegExp(word.toLowerCase(), 'g');
return (data.match(regex) || []).length;
}
/**
* search internal links in analyzed page
* @param $ dom jquery
*/
function getInternalLinks($) {
let allRelativeLinks = [];
let allAbsoluteLinks = [];
let relativeLinks = $("a[href^='/']");
relativeLinks.each(function() {
allRelativeLinks.push($(this).attr('href'));
});
let absoluteLinks = $("a[href^='http']");
absoluteLinks.each(function() {
allAbsoluteLinks.push($(this).attr('href'));
});
console.log("Found " + allRelativeLinks.length + " relative links");
console.log("Found " + allAbsoluteLinks.length + " absolute links");
}
\ No newline at end of file
// import dependance
import { FlowRouter } from 'meteor/kadira:flow-router';
import { BlazeLayout } from 'meteor/kadira:blaze-layout';
const adminSection = FlowRouter.group({
prefix: '/admin',
});
adminSection.route('/indexation', {
action() {
BlazeLayout.render('mainLayoutTpl', { sidebar: 'sidebarTpl', main: 'homeTpl', navbar: 'navbarTpl' });
},
});
import 'bootstrap-sass';
import './routes.js';
// import dependance
import { FlowRouter } from 'meteor/kadira:flow-router';
import { BlazeLayout } from 'meteor/kadira:blaze-layout';
import { Accounts } from 'meteor/accounts-base';
// Import template
import '../../ui/layouts/main/main.js';
import '../../ui/layouts/sidebar/sidebar.js';
import '../../ui/layouts/navbar/navbar.js';
import '../../ui/pages/login/login.js';
import '../../ui/pages/home/home.js';
// Routing
import './adminRoutes.js';
FlowRouter.route('/', {
name: 'App.home',
action() {
BlazeLayout.render('mainLayoutTpl', { main: 'loginTpl', navbar: 'navbarTpl' });
},
});
FlowRouter.route('/logout', {
name: 'logout',
action() {
Accounts.logout();
FlowRouter.go('/');
}
});
import '../../api/api';
<template name="mainLayoutTpl">
{{> Template.dynamic template=navbar}}
{{> Template.dynamic template=sidebar}}
<div class="container-fluid">
{{> Template.dynamic template=main}}
</div>
</template>
import './main.html';
\ No newline at end of file
<template name="navbarTpl">
<!-- navbarTpl -->
<nav role="navigation" class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">meteorSearch</a>
</div>
</div>
</nav>
</template>
import './navbar.html';
\ No newline at end of file
<template name="sidebarTpl">
<!-- sidebarTpl -->
<div class="collapse navbar-collapse navbar-ex1-collapse sidebar" id="navbar-ex1-collapse">
<ul class="nav navbar-nav side-nav">
<li>
<a href="/admin/indexation"><i class="fa fa-fw fa-etsy fa-20px" aria-hidden="true"></i> Indexation</a>
</li>
<!--<li>
<a href="/"><i class="fa fa-fw fa-cog fa-20px" aria-hidden="true"></i> Admin web</a>
</li>-->
<li>
<a class="" href="/logout" ><i class="fa fa-fw fa-lock fa-20px" aria-hidden="true"></i> Déconnexion</a>
</li>
</ul>
</div>
</template>
<template name="homeTpl">
<!-- homeTpl -->
<div class="panel panel-default wrapper">
<div class="panel-body">
</div>
</div>
</template>
import './home.html';
<template name="loginTpl">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form class="signin-form">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="plain huge">Connectez-vous </h3>