Commit e92aa55c authored by Nacim Goura's avatar Nacim Goura

modif notif WP

parent 87a03dc3
...@@ -17,7 +17,7 @@ standard-minifier-css@1.3.4 # CSS minifier run for production mode ...@@ -17,7 +17,7 @@ standard-minifier-css@1.3.4 # CSS minifier run for production mode
standard-minifier-js@2.1.0 # JS minifier run for production mode standard-minifier-js@2.1.0 # JS minifier run for production mode
es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers. es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers.
ecmascript@0.8.0 # Enable ECMAScript2015+ syntax in app code ecmascript@0.8.0 # Enable ECMAScript2015+ syntax in app code
fourseven:scss # Compile scss to css fourseven:scss@4.5.0 # Compile scss to css
fortawesome:fontawesome # pretty icon fortawesome:fontawesome # pretty icon
# package for view # package for view
...@@ -47,3 +47,4 @@ dynamic-import ...@@ -47,3 +47,4 @@ dynamic-import
aldeed:tabular aldeed:tabular
ajduke:bootstrap-tagsinput ajduke:bootstrap-tagsinput
percolate:synced-cron percolate:synced-cron
matb33:collection-hooks
...@@ -55,6 +55,7 @@ launch-screen@1.1.1 ...@@ -55,6 +55,7 @@ launch-screen@1.1.1
livedata@1.0.18 livedata@1.0.18
localstorage@1.1.0 localstorage@1.1.0
logging@1.1.17 logging@1.1.17
matb33:collection-hooks@0.8.4
meteor@1.6.1 meteor@1.6.1
meteor-base@1.1.0 meteor-base@1.1.0
minifier-css@1.2.16 minifier-css@1.2.16
......
import { AutoForm } from 'meteor/aldeed:autoform'; import { AutoForm } from 'meteor/aldeed:autoform';
import displayNotif from '/imports/api/notif/notif.js'; import { displayNotif } from '/imports/api/notif/notif.js';
const hooksFormApiCrawl = { const hooksFormApiCrawl = {
onSuccess(formType, result) { onSuccess(formType, result) {
displayNotif({ Meteor.call('addNotif', {
type: 'success', type: 'info',
title: 'Indexation : ', title: 'Indexation API : ',
message: `Indexation de ${result.api.idPage} pour l\'api ${result.api.type} fini avec succès avec ${result.index.items.length} urls indexées!`, message: `Début de l\'indexation pour ${result.idPage}!`,
save: true, save: true,
}); });
}, },
onError(formType, error) { onError(formType, error) {
displayNotif({ Meteor.call('addNotif', {
type: 'error', type: 'error',
title: 'Indexation : ', title: 'Indexation API : ',
message: error.reason ? error.reason : error, message: error.reason ? error.reason : error,
save: true, save: true,
}); });
......
...@@ -2,17 +2,18 @@ ...@@ -2,17 +2,18 @@
import CrawlFacebook from './crawlFacebook'; import CrawlFacebook from './crawlFacebook';
import CrawlTwitter from './crawlTwitter'; import CrawlTwitter from './crawlTwitter';
export default class crawlWebsite { export default class crawlApi {
constructor(config) { constructor() {
console.log('init crawl api!');
}
init(config) {
switch (config.type) { switch (config.type) {
case 'facebook': case 'facebook':
return new CrawlFacebook(config); return new CrawlFacebook(config);
case 'twitter': case 'twitter':
return new CrawlTwitter(config); return new CrawlTwitter(config);
case 'instagram':
break;
default: default:
throw new Meteor.Error('Error', 'Aucun type pour l\'API indiqué'); throw new Meteor.Error('Error', 'Aucun type pour l\'API indiqué');
} }
......
import { AutoForm } from 'meteor/aldeed:autoform'; import { AutoForm } from 'meteor/aldeed:autoform';
import displayNotif from '/imports/api/notif/notif.js'; import { displayNotif } from '/imports/api/notif/notif.js';
const hooksFormWebsiteCrawl = { const hooksFormWebsiteCrawl = {
onSuccess(formType, result) { onSuccess(formType, result) {
displayNotif({ Meteor.call('addNotif', {
type: 'success', type: 'success',
title: 'Indexation : ', title: 'Indexation : ',
message: `Indexation fini avec succès avec ${result.index.items.length} urls indexées!`, message: `Indexation fini avec succès avec ${result.index.items.length} urls indexées!`,
...@@ -12,7 +12,7 @@ const hooksFormWebsiteCrawl = { ...@@ -12,7 +12,7 @@ const hooksFormWebsiteCrawl = {
}); });
}, },
onError(formType, error) { onError(formType, error) {
displayNotif({ Meteor.call('addNotif', {
type: 'error', type: 'error',
title: 'Indexation : ', title: 'Indexation : ',
message: error.reason ? error.reason : error, message: error.reason ? error.reason : error,
......
...@@ -19,15 +19,14 @@ Meteor.methods({ ...@@ -19,15 +19,14 @@ Meteor.methods({
}, },
indexWebsite(url) { indexWebsite(url) {
check(url, String); check(url, String);
this.unblock();
const index = new IndexWebsite(); const index = new IndexWebsite();
return index.indexationWebsite(url); return index.indexationWebsite(url);
}, },
indexApi(data) { indexApi(data) {
check(data, Object); check(data, Object);
formApiCrawlSchema.validate(data); formApiCrawlSchema.validate(data);
this.unblock();
const index = new IndexApi(); const index = new IndexApi();
return index.indexationApi(data); index.indexationApi(data);
return data;
}, },
}); });
...@@ -9,15 +9,13 @@ export default class IndexApi extends IndexGeneric { ...@@ -9,15 +9,13 @@ export default class IndexApi extends IndexGeneric {
* @param data * @param data
* @returns Promise * @returns Promise
*/ */
async indexationApi(data) { indexationApi(data) {
return new CrawlApi(data) const crawlApi = new CrawlApi();
.then(dataToIndex => new Promise(async resolve => resolve({ crawlApi.init(data)
index: await this.indexByBulk(dataToIndex), .then((dataToIndex) => {
dataForm: { this.indexByBulk(dataToIndex)
api: data, .then(result => this.notifyUser(result));
}, }).catch((error) => {
})))
.catch((error) => {
throw error; throw error;
}); });
} }
......
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import indexationElastic from '/imports/libs/elasticsearch/elasticsearch'; import indexationElastic from '/imports/libs/elasticsearch/elasticsearch';
import configElastic from './elasticSearchConfig'; import configElastic from '/imports/libs/elasticsearch/elasticSearchConfig';
import { addNotif } from '/imports/api/notif/methods';
const esIndex = Meteor.settings.private.elasticsearch.esIndex; const esIndex = Meteor.settings.private.elasticsearch.esIndex;
const esType = Meteor.settings.private.elasticsearch.esType; const esType = Meteor.settings.private.elasticsearch.esType;
...@@ -37,87 +38,9 @@ export default class IndexGeneric { ...@@ -37,87 +38,9 @@ export default class IndexGeneric {
} }
/** /**
* search * Add element on collection to warn the user of the end
* @param term
* @returns {promise}
*/ */
search(term) { notifyUser(result) {
const params = { addNotif(result);
from: 0,
size: 10,
};
if (term) {
/**
*
* common ( sépare les tokens les plus présents dans l’index des autres, et ne les utilise que pour améliorer la pertinence )
* fuzziness (permet une recherche même avec des fautes)
*/
params.query = {
bool: {
must: [
{
multi_match: {
query: term,
fuzziness: 'AUTO',
fields: [
'description',
'description.stemmed',
'body',
'body.stemmed',
'urlText',
'urlText.stemmed',
'url',
],
},
},
],
should: [
{
multi_match: {
query: term,
fuzziness: 'AUTO',
fields: [
'title',
'title.stemmed',
'url',
'breadcrumb',
'h1',
'h2',
'html',
],
},
},
],
minimum_should_match: 1,
boost: 2.0,
},
};
}
return indexationElastic.search(esIndex, esType, params);
}
/**
* autocompletion
* @param term
* @returns {promise}
*/
autoComplete(term) {
let params = {};
if (term) {
params = {
suggest: {
prefix: term,
completion: {
field: 'title_suggest',
size: 25,
},
},
};
}
return indexationElastic.suggest(esIndex, params);
} }
} }
...@@ -3,7 +3,7 @@ import { AutoForm } from 'meteor/aldeed:autoform'; ...@@ -3,7 +3,7 @@ import { AutoForm } from 'meteor/aldeed:autoform';
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import { Session } from 'meteor/session'; import { Session } from 'meteor/session';
import { FlowRouter } from 'meteor/kadira:flow-router'; import { FlowRouter } from 'meteor/kadira:flow-router';
import displayNotif from '/imports/api/notif/notif.js'; import { displayNotif } from '/imports/api/notif/notif.js';
const hooksFormLogin = { const hooksFormLogin = {
onSubmit: (insertDoc, updateDoc, currentDoc) => { onSubmit: (insertDoc, updateDoc, currentDoc) => {
......
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import notifsCollection from './notifsCollection'; import notifsCollection from '/imports/api/notif/notifsCollection';
export function addNotif(notif) { export function addNotif(notif) {
notif.userId = this.userId; notif.userId = this.userId;
......
...@@ -2,7 +2,11 @@ ...@@ -2,7 +2,11 @@
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import iziToast from 'izitoast'; import iziToast from 'izitoast';
export default function (options) { /**
* display notif for user
* @param options
*/
export function displayNotif(options) {
this.options = { this.options = {
position: 'topCenter', position: 'topCenter',
}; };
...@@ -13,13 +17,5 @@ export default function (options) { ...@@ -13,13 +17,5 @@ export default function (options) {
Object.assign(this.options, options); Object.assign(this.options, options);
iziToast[options.type](this.options); iziToast[this.options.type](this.options);
if (this.options.type === 'error') {
this.options.type = 'danger';
}
if (this.options.save === true) {
Meteor.call('addNotif', this.options);
}
} }
import SimpleSchema from 'simpl-schema'; import SimpleSchema from 'simpl-schema';
import { Mongo } from 'meteor/mongo'; import { Mongo } from 'meteor/mongo';
import moment from 'moment';
/** /**
* this collection keep tracks of all notification of this application * this collection keep tracks of all notification of this application
...@@ -12,7 +11,7 @@ const notifsCollection = new Mongo.Collection('notifs'); ...@@ -12,7 +11,7 @@ const notifsCollection = new Mongo.Collection('notifs');
SimpleSchema.notifsCollection = new SimpleSchema({ SimpleSchema.notifsCollection = new SimpleSchema({
type: { type: {
type: String, type: String,
allowedValues: ['info', 'success', 'warning', 'danger'], allowedValues: ['info', 'success', 'warning', 'danger', 'error'],
}, },
title: { title: {
type: String, type: String,
...@@ -22,7 +21,7 @@ SimpleSchema.notifsCollection = new SimpleSchema({ ...@@ -22,7 +21,7 @@ SimpleSchema.notifsCollection = new SimpleSchema({
}, },
createdAt: { createdAt: {
type: Date, type: Date,
defaultValue: moment().toDate(), defaultValue: new Date(),
}, },
userId: { userId: {
type: String, type: String,
......
import { Meteor } from 'meteor/meteor';
import moment from 'moment';
import notifsCollection from '/imports/api/notif/notifsCollection';
console.log(moment().subtract(5, 'm').toISOString(), moment().add(5, 'm').toISOString());
Meteor.publish('notif', function () {
return notifsCollection.find({
userId: this.userId,
createdAt: {
$gte: moment().subtract(5, 'm').toISOString(),
$lt: moment().add(5, 'm').toISOString(),
},
});
});
...@@ -8,10 +8,8 @@ export default new SimpleSchema({ ...@@ -8,10 +8,8 @@ export default new SimpleSchema({
type: String, type: String,
required: false, required: false,
}, },
term: { searchTerm: {
label: false,
type: String, type: String,
}, },
afterDate: {
type: Date,
},
}, { tracker: Tracker }); }, { tracker: Tracker });
...@@ -2,13 +2,15 @@ ...@@ -2,13 +2,15 @@
import { check } from 'meteor/check'; import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import _ from 'lodash'; import _ from 'lodash';
import IndexGeneric from '/imports/api/indexation/server/indexGeneric'; import Search from '/imports/api/search/server/search';
import formSearchSchema from '/imports/api/search/formSearchSchema';
Meteor.methods({ Meteor.methods({
searchByTerm(term) { searchByTerm(data) {
check(term, String); check(data, Object);
const index = new IndexGeneric(); formSearchSchema.validate(data);
return index.search(term) const search = new Search();
return search.search(data.searchTerm)
.then(result => ({ .then(result => ({
total: result.hits.total, total: result.hits.total,
list: _.map(result.hits.hits, '_source'), list: _.map(result.hits.hits, '_source'),
...@@ -20,8 +22,8 @@ Meteor.methods({ ...@@ -20,8 +22,8 @@ Meteor.methods({
}, },
autoCompletion(term) { autoCompletion(term) {
check(term, String); check(term, String);
const index = new IndexGeneric(); const search = new Search();
return index.autoComplete(term) return search.autoComplete(term)
.then((result) => { .then((result) => {
if (result.suggest) { if (result.suggest) {
return _.take(_.map(result.suggest[0].options, 'text'), 5); return _.take(_.map(result.suggest[0].options, 'text'), 5);
......
import indexationElastic from '/imports/libs/elasticsearch/elasticsearch';
const esIndex = Meteor.settings.private.elasticsearch.esIndex;
const esType = Meteor.settings.private.elasticsearch.esType;
export default class Search {
constructor() {
console.log('search');
}
/**
* search
* @param term
* @returns {promise}
*/
search(term) {
const params = {
from: 0,
size: 10,
};
if (term) {
/**
*
* common ( sépare les tokens les plus présents dans l’index des autres, et ne les utilise que pour améliorer la pertinence )
* fuzziness (permet une recherche même avec des fautes)
*/
params.query = {
bool: {
must: [
{
multi_match: {
query: term,
fuzziness: 'AUTO',
fields: [
'description',
'description.stemmed',
'body',
'body.stemmed',
'urlText',
'urlText.stemmed',
'url',
],
},
},
],
should: [
{
multi_match: {
query: term,
fuzziness: 'AUTO',
fields: [
'title',
'title.stemmed',
'url',
'breadcrumb',
'h1',
'h2',
'html',
],
},
},
],
minimum_should_match: 1,
boost: 2.0,
},
};
}
return indexationElastic.search(esIndex, esType, params);
}
/**
* autocompletion
* @param term
* @returns {promise}
*/
autoComplete(term) {
let params = {};
if (term) {
params = {
suggest: {
prefix: term,
completion: {
field: 'title_suggest',
size: 25,
},
},
};
}
return indexationElastic.suggest(esIndex, params);
}
}
import SimpleSchema from 'simpl-schema'; import SimpleSchema from 'simpl-schema';
import { Mongo } from 'meteor/mongo'; import { Mongo } from 'meteor/mongo';
import moment from 'moment';
/** /**
* this local collection keep tracks of all tabs of this application * this local collection keep tracks of all tabs of this application
...@@ -38,7 +37,7 @@ SimpleSchema.TabsCollection = new SimpleSchema({ ...@@ -38,7 +37,7 @@ SimpleSchema.TabsCollection = new SimpleSchema({
}, },
createdAt: { createdAt: {
type: Date, type: Date,
defaultValue: moment().toDate(), defaultValue: new Date(),
}, },
}); });
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check'; import { check } from 'meteor/check';
import _ from 'lodash'; import _ from 'lodash';
import moment from 'moment';
import testSearchCollection from '/imports/api/testSearch/testSearchCollection'; import testSearchCollection from '/imports/api/testSearch/testSearchCollection';
export function addTest(test) { export function addTest(test) {
...@@ -29,7 +28,7 @@ export function addTest(test) { ...@@ -29,7 +28,7 @@ export function addTest(test) {
testSearchCollection.update(oldTest[0]._id, { testSearchCollection.update(oldTest[0]._id, {
$set: { $set: {
urlPosition: test.urlPosition, urlPosition: test.urlPosition,
createdAt: moment().toDate(), createdAt: new Date().toISOString(),
}, },
}); });
} else { } else {
......
import SimpleSchema from 'simpl-schema'; import SimpleSchema from 'simpl-schema';
import { Mongo } from 'meteor/mongo'; import { Mongo } from 'meteor/mongo';
import moment from 'moment';
/** /**
* this collection is temporaire for testsearch * this collection is temporaire for testsearch
...@@ -26,7 +25,7 @@ SimpleSchema.testSearchCollection = new SimpleSchema({ ...@@ -26,7 +25,7 @@ SimpleSchema.testSearchCollection = new SimpleSchema({
}, },
createdAt: { createdAt: {
type: Date, type: Date,
defaultValue: moment().toDate(), defaultValue: new Date(),
}, },
}); });
......
...@@ -5,3 +5,4 @@ import 'bootstrap-sass'; ...@@ -5,3 +5,4 @@ import 'bootstrap-sass';
import './routes'; import './routes';
moment.locale('fr'); moment.locale('fr');
...@@ -17,7 +17,7 @@ import '/imports/ui/pages/not-found/not-found'; ...@@ -17,7 +17,7 @@ import '/imports/ui/pages/not-found/not-found';
import '/imports/ui/pages/admin/indexation/indexation'; import '/imports/ui/pages/admin/indexation/indexation';
import '/imports/ui/pages/admin/account/account'; import '/imports/ui/pages/admin/account/account';
import '/imports/ui/pages/admin/statistique/statistique'; import '/imports/ui/pages/admin/statistique/statistique';
import '/imports/ui/pages/admin/notif/notif'; import '/imports/ui/pages/notif/notif';
// Set up all routes in the app // Set up all routes in the app
import './adminRoutes'; import './adminRoutes';
......
...@@ -4,6 +4,7 @@ import '/imports/api/indexation/methods'; ...@@ -4,6 +4,7 @@ import '/imports/api/indexation/methods';
import '/imports/api/account/methods'; import '/imports/api/account/methods';
import '/imports/api/config/methods'; import '/imports/api/config/methods';
import '/imports/api/notif/methods'; import '/imports/api/notif/methods';
import '/imports/api/notif/publications';
import '/imports/api/testSearch/methods'; import '/imports/api/testSearch/methods';
import '/imports/api/search/methods'; import '/imports/api/search/methods';
import '/imports/tabular/tabularUser'; import '/imports/tabular/tabularUser';
......
...@@ -3,10 +3,9 @@ ...@@ -3,10 +3,9 @@
<!-- Template searchTpl --> <!-- Template searchTpl -->
<div class="autocomplete-holder"> <div class="autocomplete-holder">
<form role="search" class="form-horizontal" id="formSearch"> {{#autoForm id="formSearch" schema=formSearchSchema type="method" meteormethod="searchByTerm" resetOnSuccess=false}}
<div class="input-group"> <div class="input-group">
<input id="searchResult" type="search" class="form-control" placeholder="Effectuer votre recherche..." {{> afQuickField name='searchTerm' placeholder="Recherche..."}}
name="searchTerm">
<span class="input-group-btn"> <span class="input-group-btn">
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">
<i class="fa fa-search"></i>