Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

some more stuffs

  • Loading branch information...
commit 58f27a0f34b5771e797a95374acc2bd15f9cfcde 1 parent ff8f62b
t8g authored
42 app.js
View
@@ -8,6 +8,22 @@
* Module dependencies
*/
+// var cluster = require('cluster')
+// , http = require('http')
+// , numCPUs = require('os').cpus().length
+// ;
+
+// if (cluster.isMaster) {
+// // Fork workers.
+// for (var i = 0; i < numCPUs; i++) {
+// cluster.fork();
+// }
+
+// cluster.on('death', function(worker) {
+// console.log('worker ' + worker.pid + ' died');
+// });
+// } else {
+
var express = require('express')
, mongoose = require('mongoose')
, models = require('./models')
@@ -150,7 +166,8 @@ app.get('/documents', function(req, res) {
app.get('/documents/:id', function(req, res) {
Document.findById(req.params.id, function(err, doc) {
- res.respond(err || doc, err ? 500 : ( doc ? 200 : 404 ));
+ //console.log(doc.toJSON2());
+ res.respond(err || doc.toJSON2(), err ? 500 : ( doc ? 200 : 404 ));
});
});
@@ -206,6 +223,19 @@ app.del('/documents/:id', function(req, res) {
app.put('/documents/:id', function(req, res) {
Document.findById(req.params.id, function(err, doc) {
+ if (err) return res.respond(err, 500);
+
+ // @TODO upload pj + regeneration thumb (option)
+ // @TODO upload thumb
+
+ doc.set(req.body);
+ doc.save(function(err) {
+ res.respond(err || doc, err ? 500 : 200);
+ });
+
+ });
+
+/*
// T'es en train de bosser ici !!!
@@ -234,7 +264,7 @@ app.put('/documents/:id', function(req, res) {
})
}
});
-
+*/
});
/**
@@ -321,8 +351,8 @@ app.post('/documents/batch/tags', function(req, res) {
docs,
function(doc, fn) {
var tags = doc.tags;
- tags = _.difference(tags, req.body.todelete);
- tags = _.union(tags, req.body.toadd);
+ if (req.body.todelete) tags = _.difference(tags, req.body.todelete);
+ if (req.body.toadd) tags = _.union(tags, req.body.toadd);
doc.tags = tags;
doc.save(fn);
},
@@ -475,6 +505,6 @@ app.get('/*', function(req, res, next) {
else next();
});
-
app.listen(nconf.get('application:port'));
-console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
+//}
+//console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
3  conf.json
View
@@ -20,7 +20,8 @@
"title": "like",
"resource.size": "exact",
"resource.name": "like"
- }
+ },
+ "index": ["title", "description"]
},
"thumbnails": {
8 extrafields.js
View
@@ -0,0 +1,8 @@
+module.exports = {
+ 'extra': {
+ type: String,
+ get: function(v) {
+ return v ? v + ' PLOP' : '';
+ }
+ }
+}
55 models.js
View
@@ -4,6 +4,7 @@ var fs = require('fs')
, im = require('imagemagick')
, _ = require('underscore')
, nconf = require('nconf')
+ , extrafields = require('./extrafields')
;
@@ -104,7 +105,8 @@ function define(mongoose, fn) {
'updated_at': {
type: Date,
default: Date.now
- }
+ },
+ '_keywords': [String]
})
.pre('save', function(next) { // A tester
if (!this.created_at) {
@@ -112,6 +114,8 @@ function define(mongoose, fn) {
} else {
this.updated_at = new Date;
}
+ // indexation
+ this._keywords = this.index();
next();
})
.pre('remove', function(next) {
@@ -130,8 +134,40 @@ function define(mongoose, fn) {
// sinon passe à null (retour fonc sur mime)
});
+ // Extra fields (from extrafields.js file)
+ Document_Schema.add(extrafields);
+
+ // Indexation
+ Document_Schema.methods.index = function() {
+ var indexables = nconf.get('documents:index')
+ , index = []
+ , _this = this
+ ;
+
+ indexables.forEach(function(indexable) {
+ index = index.concat((_this[indexable]) ? _this[indexable].split(' ') : []);
+ });
+
+ return index;
+ };
+
+ // toJSON with getters
+ // https://gist.github.com/1584121
+ // https://github.com/LearnBoost/mongoose/issues/412
+ Document_Schema.methods.toJSON2 = function() {
+ var json = this.toJSON()
+ , _this = this
+ ;
+
+ Document_Schema.eachPath(function(path) {
+ json[path] = _this.get(path);
+ });
+ return json;
+ }
+
+
// thumbnail maker with imagemagick
- Document_Schema.methods.createThumbnail = function createThumbnail(callback) {
+ Document_Schema.methods.createThumbnail = function(callback) {
var options = nconf.get('thumbnails:options');
if (nconf.get('thumbnails:thumbables').indexOf(this.resource.mime) !== -1) {
@@ -165,7 +201,7 @@ function define(mongoose, fn) {
}
};
- Document_Schema.statics.getSome = function getSome(req, callback) {
+ Document_Schema.statics.getSome = function(req, callback) {
var query = {}
,blackhole = nconf.get('documents:blackhole')
,tags
@@ -193,6 +229,7 @@ function define(mongoose, fn) {
if (filter = _.find(nconf.get('documents:filters'), function(v, k) { return k == key; })) {
// Tranforme valeur si Number
+ // @TODO regarder eachPath sur http://mongoosejs.com/docs/api.html
var path = Document_Schema.path(key);
if (!(type = (path ? path.instance : false))) {
var subpaths = key.split('.');
@@ -202,7 +239,15 @@ function define(mongoose, fn) {
if (type == 'Number') value = parseFloat(value);
if (filter == 'exact') _this.where(key, value);
- if (filter == 'like') _this.regex(key, new RegExp(value, 'i'));
+ if (filter == 'like') _this.regex(key, new RegExp(value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i'));
+ }
+
+ if (key == 'search') {
+ var values = value.split(' ');
+ values.forEach(function(value){
+ value = value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
+ _this.regex('_keywords', new RegExp(value, 'i'));
+ });
}
});
@@ -234,7 +279,7 @@ function define(mongoose, fn) {
}}
});
- Tag_Schema.statics.getSome = function getSome(req, callback) {
+ Tag_Schema.statics.getSome = function(req, callback) {
var query = {}
,subdirsof
;
30 public/css/bootstrap.css
View
@@ -2866,7 +2866,7 @@ header {
-webkit-user-select: none;
user-select: none;
}
-#filters, #sub_directory {
+#filters, #sub_directory, #search_informations ul {
list-style: none;
margin: 0 0 18px;
padding: 7px 14px;
@@ -2981,6 +2981,34 @@ header {
margin-bottom: 0;
color: rgba(0, 0, 0, 0.8);
}
+/* @TODO A optimiser (en particulier le li (.inline)) */
+#search_informations button span {
+ font-size: 1em;
+ margin-right: 5px;
+}
+#search_informations form {
+ margin-bottom: 0;
+}
+#search_informations form .iconic {
+ font-size: 2.2em;
+ padding: 2px 4px;
+ height: 28px;
+ margin-top: -2px;
+}
+#search_informations ul.inline li {
+ float: left;
+ display: inline;
+}
+#search_informations ul.inline li.right {
+ float: right;
+}
+ul.dir_select li {
+ float: left;
+ list-style-type: none;
+}
+ul.dir_select li ul li {
+ float: none;
+}
/* Usefull stuff */
#uploader {
position: relative;
41 public/css/main.less
View
@@ -28,7 +28,7 @@ header {
cursor: pointer;
.user-select;
}
-#filters, #sub_directory {
+#filters, #sub_directory, #search_informations ul {
list-style: none;
.greybackgrounds;
}
@@ -60,10 +60,10 @@ header {
i {
padding-right: 5px;
font-size: 1.4em;
- padding-left: 5px;
+ padding-left: 5px;
}
&:last-child {
- border-bottom: none;
+ border-bottom: none;
}
&:hover {
background-color: @linkColor;
@@ -79,7 +79,7 @@ header {
a {
color: inherit;
}
- }
+ }
}
}
a {
@@ -88,7 +88,7 @@ header {
text-decoration: none;
span {
text-decoration: none;
- }
+ }
}
}
}
@@ -116,7 +116,7 @@ header {
.optioncheckbox {
margin-left: 10px;
float: left;
- padding-top: 6px;
+ padding-top: 6px;
}
#editfiles {
.actions {
@@ -134,4 +134,33 @@ header {
color: rgba(0,0,0,.8)
}
+/* @TODO A optimiser (en particulier le li (.inline)) */
+#search_informations button span {
+ font-size: 1em;
+ margin-right: 5px;
+}
+#search_informations form {
+ margin-bottom: 0;
+}
+#search_informations form .iconic {
+ font-size: 2.2em;
+ padding: 2px 4px;
+ height: 28px;
+ margin-top: -2px;
+}
+#search_informations ul.inline li {
+ float: left;
+ display: inline;
+}
+#search_informations ul.inline li.right {
+ float: right;
+}
+
+ul.dir_select li {
+ float: left;
+ list-style-type: none;
+}
+ul.dir_select li ul li {
+ float: none;
+}
55 public/js/dir-selector.js
View
@@ -0,0 +1,55 @@
+;(function($) {
+
+ $.dirSelector = function(el, options) {
+
+ var defaults = {
+ dir: '/'
+ //propertyName: 'value',
+ //onSomeEvent: function() {}
+ }
+
+ var plugin = this;
+ plugin.settings = {}
+
+ var init = function() {
+ plugin.settings = $.extend({}, defaults, options);
+ plugin.el = el;
+ addSelect(plugin.settings.dir);
+ }
+
+ var addSelect = function(dir, dirname) {
+ var li = $('<li class="dropdown" data-dropdown="dropdown"><a class="dropdown-toggle">' + (dirname || '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;') + '</a><ul class="dropdown-menu"></lu></li>')
+ , dirs = dir.split('/')
+ , fulldirname = dir + (dirname || '/')
+ ;
+
+ plugin.el.prepend(li);
+
+ $.get('/tags', { subdirsof: dir || '/'}, function(data) {
+ var ul = li.find('ul');
+ data.forEach(function(item) {
+ //ul.append()
+ if (fulldirname !== item.label)
+ ul.append($('<li><a href="#' + item.label + '">' + item.label.replace(dir, '') + '</a></li>')).find('a').on('click', function(ev) {
+ ev.preventDefault();
+ plugin.el.empty();
+ addSelect(this.hash.substr(1));
+ });
+ });
+ });
+
+ // réccurence
+ dirname = dirs.pop();
+ if (dir.length) addSelect(dirs.join('/'), '/' + dirname);
+ }
+
+/*
+ plugin.foo_public_method = function() {
+ // code goes here
+ }
+*/
+ init();
+
+ }
+
+})(jQuery);
137 public/js/main.js
View
@@ -10,7 +10,11 @@ $(function() {
, $documentCheckboxes = $documents.find('tbody input')
, $filterToggle = $('#filter_toggle')
, $filters = $('#filters')
- , $filterMime = $('#filter_mime');
+ , $filterMime = $('#filter_mime')
+ , $searchForms = $('.search_form')
+ , $searchInfos = $('#search_informations')
+ , $navigationInfos = $('#navigation_docs')
+ ;
/********/
/* Misc */
@@ -236,14 +240,14 @@ $(function() {
// Create the tags
$editTags.on('click', function(e) {
e.preventDefault();
-
+
$globalTagsTags.tagit('removeAll').data({
ids: ids
, some: []
, toadd: []
, todelete: []
});
-
+
$overlayRightbar.overlayToggle(false)
$globalTags.overlayToggle(true);
});
@@ -269,25 +273,25 @@ $(function() {
/************/
/* Filters */
/************/
-
+
$filters.on('submit', function(e) {
e.preventDefault();
var form = {}
, url = $.url(location.href)
, query = url.data.param.query;
-
+
$.map($(this).serializeArray(), function(n, i){
form[n['name']] = n['value'];
});
-
+
$.extend(query, form);
-
+
url = url.attr('path') + '?' + $.map(query, function(v, k) { return v ? k + '=' + v : null; }).join('&');
-
+
history.pushState({}, 'guacamole', url);
changeContent();
});
-
+
// Toggle the filters
$filterToggle.on('click', function(e) {
$filterToggle.find('.iconic').toggleClass('plus-alt minus-alt')
@@ -309,6 +313,24 @@ $(function() {
});
});
+ /*************/
+ /* Search */
+ /*************/
+
+ $searchForms.on('submit', function(ev) {
+ ev.preventDefault();
+ var $this = $(this)
+ , query = $this.find('input:text').val()
+ , url = query ? '/?search=' + query : '/';
+ history.pushState({}, 'guacamole', url);
+ changeContent();
+ });
+
+ $searchInfos.find('button.danger').on('click', function(ev) {
+ ev.preventDefault();
+ history.pushState({}, 'guacamole', '/');
+ changeContent();
+ });
/*************/
/* Documents */
@@ -330,6 +352,7 @@ $(function() {
var template = Hogan.compile(templates.editForm)
, render = template.render({
title: doc.title,
+ description: doc.description || '',
created_at: doc.created_at.split('T')[0].split('-').reverse().join('/'),
// Size from o to ko
size: Math.ceil(doc.resource.size / 1024),
@@ -344,10 +367,46 @@ $(function() {
// The one which start with a /
repertoire: doc.tags.filter(function(tag) {
return tag[0] === '/';
- })[0]
+ })[0],
+ extra: doc.extra || ''
});
$documentEditContent.html(render);
+ var myplugin = new $.dirSelector($documentEditContent.find('ul.dir_select'), {
+ dir: '/rep1/rep1_1'
+ });
+
+//$documentEditContent.find('.dir_select').dirSelector();
+//console.log($documentEditContent.find('.dir_select'));
+/*
+ <li class="dropdown" data-dropdown="dropdown" >\
+ <a href="#" class="dropdown-toggle">Dropdown</a>\
+ <ul class="dropdown-menu">\
+ <li><a href="#">Secondary link</a></li>\
+ <li><a href="#">Something else here</a></li>\
+ <li class="divider"></li>\
+ <li><a href="#">Another link</a></li>\
+ </ul>\
+ </li>\
+ <li class="dropdown" data-dropdown="dropdown" >\
+ <a href="#" class="dropdown-toggle">Dropdown</a>\
+ <ul class="dropdown-menu">\
+ <li><a href="#">Secondary link</a></li>\
+ <li><a href="#">Something else here</a></li>\
+ <li class="divider"></li>\
+ <li><a href="#">Another link</a></li>\
+ </ul>\
+ </li>\
+ <li class="dropdown" data-dropdown="dropdown" >\
+ <a href="#" class="dropdown-toggle">Dropdown</a>\
+ <ul class="dropdown-menu">\
+ <li><a href="#">Secondary link</a></li>\
+ <li><a href="#">Something else here</a></li>\
+ <li class="divider"></li>\
+ <li><a href="#">Another link</a></li>\
+ </ul>\
+ </li>\
+*/
$documentEditContent.find('button.delete').on('click', function(e) {
e.preventDefault();
@@ -514,7 +573,7 @@ $(function() {
, path = url.attr('path').replace(/\/$/, '')
, tags = url.param('tags') ? url.param('tags').split(',') : []
, parameters = url.param();
-
+
// Add tags from url
if (isPopstate || !$tags.data('run')) {
$tags.data('run', false).tagit('removeAll');
@@ -560,7 +619,7 @@ $(function() {
});
var realTags = tags;
- realTags.push(path || '/');
+ if (!parameters.search) realTags.push(path || '/');
parameters.tags = realTags.join(',');
// Show the documents
$.get('/documents', parameters, function(data) {
@@ -584,7 +643,7 @@ $(function() {
});
}).join('') :
template.render({ empty: true });
-
+
// Uncheck the $masterCheckbox
$masterCheckbox.prop('checked', false);
// Render the documents
@@ -592,7 +651,7 @@ $(function() {
// Hide the form
$documentsForm.css({ opacity: 0 });
infoFooter.html(data.length + ' documents trouvés');
-
+
// Get the mime type filters
var types = []
, definedTypes = {}
@@ -608,13 +667,13 @@ $(function() {
}
});
$filterMime.html(template.render({ types: types }));
-
+
// Get the defaults filters
// parameters is the filters + tags
delete parameters.tags;
var filters = Object.keys(parameters);
// If it contains filters
- if (filters.length) {
+ if (filters.length || parameters.search) {
// If the form is closed, open it
$filters.hasClass('filters_close') && $filterToggle.click();
// Add the values to the fields
@@ -623,6 +682,18 @@ $(function() {
});
}
+if (!parameters.search) {
+ if ($subDirectory.is(':hidden')) {
+ $subDirectory.show().prev('h3').show();
+ }
+ $searchInfos.hide();
+ $navigationInfos.show();
+} else {
+ $subDirectory.hide().prev('h3').hide();
+ $searchInfos.show().find('input:text').val(parameters.search);
+ $navigationInfos.hide();
+}
+
// The first time, initialize tablesorter, afterwards, update it
if (!$documents.data('sorted')) {
$documents.tablesorter({
@@ -672,20 +743,12 @@ var templates = {
{{#types}}\
<option value="{{mime}}">{{label}}\
{{/types}}'
- , editForm: ' <form>\
- <fieldset>\
- <label for="apercu">Aperçu : </label>\
- <div class="input">\
- <img src="{{thumbnail}}">\
- <input class="input-file xlarge" id="fileInput" name="fileInput" type="file">\
- </div>\
- </fieldset>\
- </form>\
- <form>\
+ , editForm: '<form method="post" action="/documents/{{id}}">\
+ <input type="hidden" name="_method" value="PUT">\
<fieldset>\
<label for="title">Titre : </label>\
<div class="input">\
- <input class="xlarge" type="text" name="title" id="title" value={{title}}>\
+ <input class="xlarge" type="text" name="title" id="title" value="{{title}}">\
</div>\
</fieldset>\
<fieldset>\
@@ -720,15 +783,31 @@ var templates = {
<fieldset>\
<label for="repertoire">Répertoire : </label>\
<div class="input">\
- <input class="xlarge" type="text" name="repertoire" id="repertoire" value={{repertoire}} />\
+ <ul class="dir_select"></ul>\
+ <input type="hidden" name="repertoire" id="repertoire" value="{{repertoire}}" />\
</div>\
</fieldset>\
- <fieldset>\
+ <fieldset>\
+ <label for="extra">Extra : </label>\
+ <div class="input">\
+ <input class="xlarge" type="text" name="extra" id="extra" value="{{extra}}" />\
+ </div>\
+ </fieldset>\
+ <fieldset>\
<div class="actions">\
<button class="btn danger delete"><span class="iconic trash"></span>Supprimer</button>&nbsp;<button class="btn danger hide"><span class="iconic x"></span>Annuler</button>&nbsp;<button class="btn success"><span class="iconic check"></span>Sauvegarder</button>\
</div>\
</fieldset>\
</form>\
+ <form>\
+ <fieldset>\
+ <label for="apercu">Aperçu : </label>\
+ <div class="input">\
+ <img src="{{thumbnail}}">\
+ <input class="input-file xlarge" id="fileInput" name="fileInput" type="file">\
+ </div>\
+ </fieldset>\
+ </form>\
<form id="editfiles">\
<div class="actions">\
<fieldset>\
15 views/index.html
View
@@ -74,8 +74,8 @@
</ul>
</li>
</ul>-->
- <form class="pull-left" action="">
- <input type="text" placeholder="Search" />
+ <form class="pull-left search_form" action="/?" method="get">
+ <input type="text" placeholder="Search" name="search" />
<button type="submit" class="btn primary iconic magnifying-glass"></button>
</form>
<ul class="nav secondary-nav">
@@ -102,12 +102,19 @@
<div id="uploader" class="btn large primary" data-placement="below" data-twipsy title='Cliquer ou glisser/déposer des documents'>
<span class='iconic box'></span>
<label>Uploads</label>
- <input type=file id="file" multiple>
+ <input type="file" id="file" multiple>
</div>
</form>
</li>
</ul>
</section>
+ <section id="search_informations" class="grid_12">
+ <h3>Recherche<span class="iconic magnifying-glass"></span></h3>
+ <ul class="inline">
+ <li class="right"><button class="btn danger"><span class="iconic x"></span>Annuler la recherche</button></li>
+ <li><form class="search_form">Votre recherche : <input class="xxlarge" /> <button type="submit" class="btn primary iconic magnifying-glass"></button></form></li>
+ </ul>
+ </section>
<section class="grid_4">
<h3 id="filter_toggle">Filtrez les documents<span class="iconic plus-alt"></span></h3>
@@ -273,6 +280,7 @@ <h3 id="filter_toggle">Filtrez les documents<span class="iconic plus-alt"></span
<script src="/js/bootstrap/bootstrap-scrollspy.js"></script>
<script src="/js/bootstrap/bootstrap-buttons.js"></script>
<script src="/js/bootstrap/bootstrap-tabs.js"></script>
+<script src="/js/dir-selector.js"></script>
<script src="/js/application.js"></script>
<script src="/js/main.js"></script>
@@ -283,5 +291,6 @@ <h3 id="filter_toggle">Filtrez les documents<span class="iconic plus-alt"></span
<script>window.attachEvent('onload',function(){CFInstall.check({mode:'overlay'})})</script>
<![endif]-->
+
</body>
</html>
Please sign in to comment.
Something went wrong with that request. Please try again.