Compare commits
12 Commits
master
...
5569c4444b
| Author | SHA1 | Date | |
|---|---|---|---|
| 5569c4444b | |||
| d901943758 | |||
| 91765d2c84 | |||
| b0eefe8de3 | |||
| 2f526632fe | |||
| ea64b0a6c5 | |||
| 78acb0a1c7 | |||
| 17c2f18193 | |||
| e6e1f6d6b3 | |||
| c86e06fe23 | |||
| e98765fbdb | |||
| 924ea137b9 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -32,3 +32,4 @@ tmp/
|
|||||||
bower_components
|
bower_components
|
||||||
node_modules
|
node_modules
|
||||||
/webapp/index.html
|
/webapp/index.html
|
||||||
|
dist/
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ COPY . /satbd
|
|||||||
RUN go get $(go list -e -f "{{.Imports}} {{.TestImports}}" . | tr "[" " " | tr "]" " " | xargs go list -e -f "{{if not .Standard}}{{.ImportPath}}{{end}}")
|
RUN go get $(go list -e -f "{{.Imports}} {{.TestImports}}" . | tr "[" " " | tr "]" " " | xargs go list -e -f "{{if not .Standard}}{{.ImportPath}}{{end}}")
|
||||||
RUN go build
|
RUN go build
|
||||||
RUN go test
|
RUN go test
|
||||||
RUN gulp build
|
RUN gulp
|
||||||
|
|
||||||
EXPOSE 33276
|
EXPOSE 33276
|
||||||
|
|
||||||
|
|||||||
13
album.go
13
album.go
@@ -5,6 +5,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -65,6 +66,7 @@ type Album struct {
|
|||||||
Designers []string `json:"dessins"`
|
Designers []string `json:"dessins"`
|
||||||
Colorists []string `json:"couleurs"`
|
Colorists []string `json:"couleurs"`
|
||||||
|
|
||||||
|
mx sync.Mutex
|
||||||
Links map[string]string
|
Links map[string]string
|
||||||
|
|
||||||
FetchDate time.Time
|
FetchDate time.Time
|
||||||
@@ -114,3 +116,14 @@ func AlbumCoverExt(URL string) string {
|
|||||||
}
|
}
|
||||||
return strings.ToLower(ext)
|
return strings.ToLower(ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Album) addLink(title string, value string) {
|
||||||
|
a.mx.Lock()
|
||||||
|
defer a.mx.Unlock()
|
||||||
|
|
||||||
|
if a.Links == nil {
|
||||||
|
a.Links = make(map[string]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Links[title] = value
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
@@ -43,14 +44,19 @@ func (s *AlbumDatabaseSuite) TestCanGet(c *C) {
|
|||||||
|
|
||||||
func (s *AlbumDatabaseSuite) TestCanSort(c *C) {
|
func (s *AlbumDatabaseSuite) TestCanSort(c *C) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
data := []AlbumID{160366, 58595, 15875, 9935, 84448, 46005, 19762, 164, 52100, 8179, 44989, 32043, 22737, 754}
|
|
||||||
sorted, err := s.db.ByPurchaseDate()
|
sorted, err := s.db.ByPurchaseDate()
|
||||||
|
|
||||||
log.Printf("sorting took %s", time.Since(start))
|
log.Printf("sorting took %s", time.Since(start))
|
||||||
|
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(len(sorted), Equals, len(data))
|
c.Assert(len(sorted) > 0, Equals, true)
|
||||||
for i, a := range sorted {
|
last := time.Now()
|
||||||
c.Check(a, Equals, data[i], Commentf("expected %d", a))
|
for _, a := range sorted {
|
||||||
|
al, err := s.db.get(fmt.Sprintf("%d", a))
|
||||||
|
if c.Check(err, IsNil) == false {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c.Check(last.After(al.PurchaseDate), Equals, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -29,11 +30,13 @@ func linkFromSelection(s *goquery.Selection) Link {
|
|||||||
// Get fetches data from www.bedetheque.com and parses it to a
|
// Get fetches data from www.bedetheque.com and parses it to a
|
||||||
func (g *AlbumDescriptionGetter) Get(a *Album) error {
|
func (g *AlbumDescriptionGetter) Get(a *Album) error {
|
||||||
URL := path.Join("www.bedetheque.com", fmt.Sprintf("BD--%d.html", a.ID))
|
URL := path.Join("www.bedetheque.com", fmt.Sprintf("BD--%d.html", a.ID))
|
||||||
resp, err := g.getter.Get("http://" + URL)
|
resp, err := g.getter.Get("https://" + URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer closeOrPanic(resp.Body, "GET:http://"+URL)
|
defer closeOrPanic(resp.Body, "GET:https://"+URL)
|
||||||
|
|
||||||
|
log.Printf("Fetched %s", URL)
|
||||||
|
|
||||||
doc, err := goquery.NewDocumentFromReader(resp.Body)
|
doc, err := goquery.NewDocumentFromReader(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -100,7 +103,6 @@ func (g *AlbumDescriptionGetter) Get(a *Album) error {
|
|||||||
|
|
||||||
details := map[string][]*goquery.Selection{}
|
details := map[string][]*goquery.Selection{}
|
||||||
previous := ""
|
previous := ""
|
||||||
a.Links = map[string]string{}
|
|
||||||
doc.Find("div.detail-album ul.infos-albums li").Each(func(i int, s *goquery.Selection) {
|
doc.Find("div.detail-album ul.infos-albums li").Each(func(i int, s *goquery.Selection) {
|
||||||
labelSelection := s.Find("label")
|
labelSelection := s.Find("label")
|
||||||
if labelSelection.Size() != 1 {
|
if labelSelection.Size() != 1 {
|
||||||
@@ -124,7 +126,7 @@ func (g *AlbumDescriptionGetter) Get(a *Album) error {
|
|||||||
l := linkFromSelection(s.Find("a"))
|
l := linkFromSelection(s.Find("a"))
|
||||||
if len(l.Title) > 0 {
|
if len(l.Title) > 0 {
|
||||||
a.Scenarists = append(a.Scenarists, l.Title)
|
a.Scenarists = append(a.Scenarists, l.Title)
|
||||||
a.Links[l.Title] = l.Target
|
a.addLink(l.Title, l.Target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errors <- nil
|
errors <- nil
|
||||||
@@ -141,7 +143,7 @@ func (g *AlbumDescriptionGetter) Get(a *Album) error {
|
|||||||
l := linkFromSelection(s.Find("a"))
|
l := linkFromSelection(s.Find("a"))
|
||||||
if len(l.Title) > 0 {
|
if len(l.Title) > 0 {
|
||||||
a.Designers = append(a.Designers, l.Title)
|
a.Designers = append(a.Designers, l.Title)
|
||||||
a.Links[l.Title] = l.Target
|
a.addLink(l.Title, l.Target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errors <- nil
|
errors <- nil
|
||||||
@@ -158,7 +160,7 @@ func (g *AlbumDescriptionGetter) Get(a *Album) error {
|
|||||||
l := linkFromSelection(s.Find("a"))
|
l := linkFromSelection(s.Find("a"))
|
||||||
if len(l.Title) > 0 {
|
if len(l.Title) > 0 {
|
||||||
a.Colorists = append(a.Colorists, l.Title)
|
a.Colorists = append(a.Colorists, l.Title)
|
||||||
a.Links[l.Title] = l.Target
|
a.addLink(l.Title, l.Target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errors <- nil
|
errors <- nil
|
||||||
@@ -173,9 +175,11 @@ func (g *AlbumDescriptionGetter) Get(a *Album) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(errorList) != 0 {
|
if len(errorList) != 0 {
|
||||||
return fmt.Errorf("Could not parse description from http://%s:%s",
|
return fmt.Errorf("Could not parse description from https://%s:%s\n%s",
|
||||||
URL,
|
URL,
|
||||||
strings.Join(append([]string{""}, errorList...), "\n * "))
|
strings.Join(append([]string{""}, errorList...), "\n * "),
|
||||||
|
resp.Body)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a.FetchDate = time.Now()
|
a.FetchDate = time.Now()
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ func (s *AlbumDescriptionGetterSuite) TestGet(c *C) {
|
|||||||
if c.Check(s.g.Get(&aStripped), IsNil) == true {
|
if c.Check(s.g.Get(&aStripped), IsNil) == true {
|
||||||
//we skip the fetch date, for sure it will always expire
|
//we skip the fetch date, for sure it will always expire
|
||||||
aStripped.FetchDate = a.FetchDate
|
aStripped.FetchDate = a.FetchDate
|
||||||
|
//we skip the note as it is a dynamic value, and may change over time
|
||||||
|
aStripped.Note = a.Note
|
||||||
c.Check(aStripped, DeepEquals, a)
|
c.Check(aStripped, DeepEquals, a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
158
gulpfile.js
158
gulpfile.js
@@ -1,6 +1,137 @@
|
|||||||
var gulp = require('gulp');
|
var gulp = require('gulp');
|
||||||
var plugins = require('gulp-load-plugins')({});
|
var plugins = require('gulp-load-plugins')({});
|
||||||
var karma = require('karma');
|
var karma = require('karma');
|
||||||
|
var es = require('event-stream');
|
||||||
|
var mainBowerFiles = require('main-bower-files');
|
||||||
|
var exists = require('path-exists').sync
|
||||||
|
var Q = require('q');
|
||||||
|
var del = require('del');
|
||||||
|
|
||||||
|
var pipes = {};
|
||||||
|
|
||||||
|
var paths = {
|
||||||
|
appFiles: 'webapp/js/**/*.js',
|
||||||
|
cssFiles: 'webapp/css/**/*.css',
|
||||||
|
partials: 'webapp/js/**/*.html',
|
||||||
|
pages : ['webapp/html/**/*.html', '!webapp/html/index.html'],
|
||||||
|
index : 'webapp/html/index.html',
|
||||||
|
distDev : 'dist/dev',
|
||||||
|
distProd: 'dist/prod'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pipes.bowerFiles = function() {
|
||||||
|
return gulp.src(mainBowerFiles({
|
||||||
|
overrides : {
|
||||||
|
jquery : {
|
||||||
|
main: []
|
||||||
|
},
|
||||||
|
bootstrap : {
|
||||||
|
main: [
|
||||||
|
"dist/**/*.min.css",
|
||||||
|
'./dist/fonts/*.*'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),{base: 'webapp/bower_components'});
|
||||||
|
}
|
||||||
|
|
||||||
|
pipes.bowerFilesMinified = function() {
|
||||||
|
return pipes.bowerFiles()
|
||||||
|
.pipe(plugins.rename(function (path) {
|
||||||
|
testpath = 'webapp/bower_components/' + path.dirname + '/' + path.basename + '.min' + path.extname;
|
||||||
|
if (exists(testpath)) {
|
||||||
|
path.extname = '.min' + path.extname;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
pipes.validatedAppScripts = function() {
|
||||||
|
return gulp.src(paths.appFiles)
|
||||||
|
.pipe(plugins.jshint())
|
||||||
|
.pipe(plugins.jshint.reporter('jshint-stylish'));
|
||||||
|
}
|
||||||
|
|
||||||
|
pipes.validatedIndex = function() {
|
||||||
|
return gulp.src(paths.index)
|
||||||
|
.pipe(plugins.htmlhint())
|
||||||
|
.pipe(plugins.htmlhint.reporter());
|
||||||
|
}
|
||||||
|
|
||||||
|
pipes.validatedPartials = function() {
|
||||||
|
return gulp.src(paths.partials)
|
||||||
|
.pipe(plugins.htmlhint({'doctype-first': false}))
|
||||||
|
.pipe(plugins.htmlhint.reporter());
|
||||||
|
}
|
||||||
|
|
||||||
|
pipes.validatedPages = function() {
|
||||||
|
return gulp.src(paths.pages)
|
||||||
|
.pipe(plugins.htmlhint({'doctype-first': false}))
|
||||||
|
.pipe(plugins.htmlhint.reporter());
|
||||||
|
}
|
||||||
|
|
||||||
|
pipes.builtIndexDev = function() {
|
||||||
|
var vendorFiles = pipes.bowerFilesMinified()
|
||||||
|
.pipe(gulp.dest(paths.distDev + '/vendor'));
|
||||||
|
var appScript = pipes.validatedAppScripts()
|
||||||
|
.pipe(plugins.angularFilesort())
|
||||||
|
.pipe(gulp.dest(paths.distDev + '/js'))
|
||||||
|
var appStyle = gulp.src(paths.cssFiles)
|
||||||
|
.pipe(gulp.dest(paths.distDev + '/css'))
|
||||||
|
|
||||||
|
var partials = pipes.validatedPartials()
|
||||||
|
.pipe(gulp.dest(paths.distDev + '/js'))
|
||||||
|
|
||||||
|
var pages = pipes.validatedPages()
|
||||||
|
.pipe(gulp.dest(paths.distDev + '/html'))
|
||||||
|
|
||||||
|
return pipes.validatedIndex()
|
||||||
|
.pipe(plugins.inject(vendorFiles, {ignorePath: '/'+ paths.distDev, name:'bower'}))
|
||||||
|
.pipe(plugins.inject(es.merge(appStyle,partials,pages), {ignorePath: '/'+ paths.distDev}))
|
||||||
|
.pipe(plugins.inject(appScript, {ignorePath: '/'+ paths.distDev}))
|
||||||
|
.pipe(gulp.dest(paths.distDev));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pipes.builtIndexProd = function() {
|
||||||
|
var filterJS = plugins.filter('**/*.js',{restore: true});
|
||||||
|
var vendorFiles = pipes.bowerFiles()
|
||||||
|
.pipe(filterJS)
|
||||||
|
.pipe(plugins.concat('vendor.min.js'))
|
||||||
|
.pipe(plugins.uglify())
|
||||||
|
.pipe(filterJS.restore)
|
||||||
|
.pipe(gulp.dest(paths.distProd + '/vendor'));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var appScript = pipes.validatedAppScripts()
|
||||||
|
.pipe(plugins.angularFilesort())
|
||||||
|
.pipe(plugins.ngAnnotate())
|
||||||
|
.pipe(plugins.concat('app.min.js'))
|
||||||
|
.pipe(plugins.uglify())
|
||||||
|
.pipe(gulp.dest(paths.distProd + '/js'));
|
||||||
|
|
||||||
|
var appStyle = gulp.src(paths.cssFiles)
|
||||||
|
.pipe(plugins.minifyCss())
|
||||||
|
.pipe(plugins.rename(function (path) {
|
||||||
|
path.extname = '.min'+ path.extname;
|
||||||
|
}))
|
||||||
|
.pipe(gulp.dest(paths.distProd + '/css'))
|
||||||
|
|
||||||
|
var partials = pipes.validatedPartials()
|
||||||
|
.pipe(gulp.dest(paths.distProd + '/js'))
|
||||||
|
|
||||||
|
var pages = pipes.validatedPages()
|
||||||
|
.pipe(gulp.dest(paths.distProd + '/html'))
|
||||||
|
|
||||||
|
return pipes.validatedIndex()
|
||||||
|
.pipe(plugins.inject(vendorFiles, {ignorePath: '/' + paths.distProd, name : 'bower'}))
|
||||||
|
.pipe(plugins.inject(es.merge(appStyle,partials,pages), {ignorePath: '/' + paths.distProd}))
|
||||||
|
.pipe(plugins.inject(appScript, {ignorePath: '/' + paths.distProd}))
|
||||||
|
.pipe(gulp.dest(paths.distProd));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gulp.task('test', function(done) {
|
gulp.task('test', function(done) {
|
||||||
server = new karma.Server({
|
server = new karma.Server({
|
||||||
@@ -15,19 +146,24 @@ gulp.task('test', function(done) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
gulp.task('build-dev', pipes.builtIndexDev);
|
||||||
|
|
||||||
|
gulp.task('build-prod', pipes.builtIndexProd);
|
||||||
|
|
||||||
gulp.task('build', function() {
|
pipes.cleanDir = function(dir) {
|
||||||
return gulp.src('./webapp/html/index.html')
|
}
|
||||||
.pipe(plugins.inject(
|
|
||||||
gulp.src(['./webapp/js/**/*.js']).pipe(plugins.angularFilesort()),
|
gulp.task('clean-dev', function() {
|
||||||
{
|
return del([paths.distDev]);
|
||||||
ignorePath: '/webapp'
|
|
||||||
}
|
|
||||||
))
|
|
||||||
.pipe(gulp.dest('./webapp'));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('autobuild', function() {
|
gulp.task('clean-prod', function() {
|
||||||
return gulp.watch(['webapp/js/**/*.js','webapp/html/index.html'], ['build']);
|
return del([paths.distProd]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
gulp.task('clean-build-dev', ['clean-dev'], pipes.builtIndexDev);
|
||||||
|
|
||||||
|
gulp.task('clean-build-prod', ['clean-prod'] , pipes.builtIndexProd);
|
||||||
|
|
||||||
|
gulp.task('default',['clean-build-prod'])
|
||||||
|
|||||||
5
main.go
5
main.go
@@ -27,6 +27,7 @@ type Options struct {
|
|||||||
RequestWindow time.Duration `long:"request-window" description:"Window over which no more --max-request are done"`
|
RequestWindow time.Duration `long:"request-window" description:"Window over which no more --max-request are done"`
|
||||||
CacheTTL time.Duration `long:"chache-ttl" description:"TTL of the cached data" `
|
CacheTTL time.Duration `long:"chache-ttl" description:"TTL of the cached data" `
|
||||||
BatchSize int `long:"batch-size" description:"Sizes of the batch for indexing" default:"1000"`
|
BatchSize int `long:"batch-size" description:"Sizes of the batch for indexing" default:"1000"`
|
||||||
|
BasePath string `long:"basepath" short:"b" description:"basepath of the webapp" default:"dist/prod"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type appData struct {
|
type appData struct {
|
||||||
@@ -77,7 +78,7 @@ func newAppData(opts Options) (*appData, error) {
|
|||||||
|
|
||||||
res.db = OpenAlbumDatabase(filepath.Join(basepath, "db"))
|
res.db = OpenAlbumDatabase(filepath.Join(basepath, "db"))
|
||||||
res.getter = &AlbumDescriptionGetter{
|
res.getter = &AlbumDescriptionGetter{
|
||||||
getter: NewRateLimitedGetter(10, 10),
|
getter: NewRateLimitedGetter(opts.MaxRequests, opts.RequestWindow),
|
||||||
}
|
}
|
||||||
|
|
||||||
res.cover = NewAlbumCoverCache(filepath.Join(basepath, "covers"), opts.MaxRequests, opts.RequestWindow)
|
res.cover = NewAlbumCoverCache(filepath.Join(basepath, "covers"), opts.MaxRequests, opts.RequestWindow)
|
||||||
@@ -378,7 +379,7 @@ func Execute() error {
|
|||||||
|
|
||||||
log.Printf("Listening on %s", opts.Listen)
|
log.Printf("Listening on %s", opts.Listen)
|
||||||
a.start(srv.StopChan())
|
a.start(srv.StopChan())
|
||||||
srv.Server.Handler = a.buildRouter()
|
srv.Server.Handler = a.buildRouter(opts.BasePath)
|
||||||
if err := srv.ListenAndServe(); err != nil {
|
if err := srv.ListenAndServe(); err != nil {
|
||||||
if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
|
if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
|
||||||
return err
|
return err
|
||||||
|
|||||||
15
package.json
15
package.json
@@ -4,20 +4,35 @@
|
|||||||
"description": "Small website for exploring privately satellite.bar bedetheque",
|
"description": "Small website for exploring privately satellite.bar bedetheque",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"bower": "^1.7.7",
|
"bower": "^1.7.7",
|
||||||
|
"del": "^2.2.0",
|
||||||
"gulp": "^3.9.1",
|
"gulp": "^3.9.1",
|
||||||
"gulp-angular-filesort": "^1.1.1",
|
"gulp-angular-filesort": "^1.1.1",
|
||||||
|
"gulp-concat": "^2.6.0",
|
||||||
|
"gulp-debug": "^2.1.2",
|
||||||
|
"gulp-filter": "^3.0.1",
|
||||||
|
"gulp-htmlhint": "^0.3.1",
|
||||||
|
"gulp-htmlmin": "^1.3.0",
|
||||||
"gulp-inject": "^3.0.0",
|
"gulp-inject": "^3.0.0",
|
||||||
"gulp-jasmine": "^2.2.1",
|
"gulp-jasmine": "^2.2.1",
|
||||||
|
"gulp-jshint": "^2.0.0",
|
||||||
"gulp-karma": "0.0.5",
|
"gulp-karma": "0.0.5",
|
||||||
"gulp-load-plugins": "^1.2.0",
|
"gulp-load-plugins": "^1.2.0",
|
||||||
|
"gulp-minify-css": "^1.2.3",
|
||||||
|
"gulp-ng-annotate": "^1.1.0",
|
||||||
|
"gulp-rename": "^1.2.2",
|
||||||
|
"gulp-uglify": "^1.5.3",
|
||||||
"gulp-util": "^3.0.7",
|
"gulp-util": "^3.0.7",
|
||||||
"jasmine-core": "^2.4.1",
|
"jasmine-core": "^2.4.1",
|
||||||
|
"jshint": "^2.9.1",
|
||||||
|
"jshint-stylish": "^2.1.0",
|
||||||
"karma": "^0.13.19",
|
"karma": "^0.13.19",
|
||||||
"karma-chrome-launcher": "^0.2.2",
|
"karma-chrome-launcher": "^0.2.2",
|
||||||
"karma-firefox-launcher": "^0.1.7",
|
"karma-firefox-launcher": "^0.1.7",
|
||||||
"karma-jasmine": "^0.3.7",
|
"karma-jasmine": "^0.3.7",
|
||||||
"karma-junit-reporter": "^0.3.8",
|
"karma-junit-reporter": "^0.3.8",
|
||||||
"karma-safari-launcher": "^0.1.1",
|
"karma-safari-launcher": "^0.1.1",
|
||||||
|
"main-bower-files": "^2.11.1",
|
||||||
|
"path-exists": "^2.1.0",
|
||||||
"protractor": "^3.1.1"
|
"protractor": "^3.1.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
10
router.go
10
router.go
@@ -19,7 +19,7 @@ import (
|
|||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *appData) buildRouter() http.Handler {
|
func (a *appData) buildRouter(basepath string) http.Handler {
|
||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
|
|
||||||
logger := narco.NewLogger()
|
logger := narco.NewLogger()
|
||||||
@@ -126,19 +126,19 @@ func (a *appData) buildRouter() http.Handler {
|
|||||||
|
|
||||||
})))
|
})))
|
||||||
|
|
||||||
dirs := []string{"css", "js", "img", "bower_components", "html"}
|
dirs := []string{"css", "js", "vendor", "html"}
|
||||||
for _, d := range dirs {
|
for _, d := range dirs {
|
||||||
router.ServeFiles(path.Join("/", d, "/*filepath"), http.Dir(filepath.Join("webapp", d)))
|
router.ServeFiles(path.Join("/", d, "/*filepath"), http.Dir(filepath.Join(basepath, d)))
|
||||||
}
|
}
|
||||||
|
|
||||||
router.GET("/", narco.EndChain(ch, narco.HandlerFunc(
|
router.GET("/", narco.EndChain(ch, narco.HandlerFunc(
|
||||||
func(ctx context.Context, w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
|
func(ctx context.Context, w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
|
||||||
f, err := os.Open(filepath.Join("webapp", "index.html"))
|
f, err := os.Open(filepath.Join(basepath, "index.html"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
narco.Error(ctx, w, err, http.StatusInternalServerError)
|
narco.Error(ctx, w, err, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer closeOrPanic(f, filepath.Join("webapp", "index.html"))
|
defer closeOrPanic(f, filepath.Join(basepath, "index.html"))
|
||||||
|
|
||||||
_, err = io.Copy(w, f)
|
_, err = io.Copy(w, f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"ID": 8179,
|
"ID": 8179,
|
||||||
"ISBN": "2-8001-1161-5",
|
"ISBN": "2-8001-1161-5",
|
||||||
"série": "Mortes saisons",
|
"série": "Mortes saisons",
|
||||||
@@ -12,8 +12,8 @@
|
|||||||
"ref": "BERT-9",
|
"ref": "BERT-9",
|
||||||
"LegalDeposit": "1985-10-01T00:00:00Z",
|
"LegalDeposit": "1985-10-01T00:00:00Z",
|
||||||
"PrintDate": "0001-01-01T00:00:00Z",
|
"PrintDate": "0001-01-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-09-04T00:00:00Z",
|
"PurchaseDate": "2013-09-02T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/Couv_8179.jpg",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/Couv_8179.jpg",
|
||||||
"description": "",
|
"description": "",
|
||||||
"Note": 3.4,
|
"Note": 3.4,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -26,9 +26,9 @@
|
|||||||
"Berthet, Philippe"
|
"Berthet, Philippe"
|
||||||
],
|
],
|
||||||
"Links": {
|
"Links": {
|
||||||
"Andreas":"http://www.bedetheque.com/auteur-267-BD-Andreas.html",
|
"Andreas":"https://www.bedetheque.com/auteur-267-BD-Andreas.html",
|
||||||
"Berthet, Philippe": "http://www.bedetheque.com/auteur-13-BD-Berthet-Philippe.html"
|
"Berthet, Philippe": "https://www.bedetheque.com/auteur-13-BD-Berthet-Philippe.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -45,8 +45,8 @@
|
|||||||
"ref": "ZCO-35",
|
"ref": "ZCO-35",
|
||||||
"LegalDeposit": "1979-01-01T00:00:00Z",
|
"LegalDeposit": "1979-01-01T00:00:00Z",
|
||||||
"PrintDate": "0001-01-01T00:00:00Z",
|
"PrintDate": "0001-01-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-09-04T00:00:00Z",
|
"PurchaseDate": "2013-09-01T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/abeldopeulapeul02.JPG",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/Couv_44989.jpg",
|
||||||
"description": "",
|
"description": "",
|
||||||
"Note": 4,
|
"Note": 4,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -55,8 +55,12 @@
|
|||||||
"dessins": [
|
"dessins": [
|
||||||
"Loro"
|
"Loro"
|
||||||
],
|
],
|
||||||
|
"couleurs": [
|
||||||
|
"<Quadrichromie>"
|
||||||
|
],
|
||||||
"Links": {
|
"Links": {
|
||||||
"Loro": "http://www.bedetheque.com/auteur-839-BD-Loro.html"
|
"Loro": "https://www.bedetheque.com/auteur-839-BD-Loro.html",
|
||||||
|
"<Quadrichromie>" : "https://www.bedetheque.com/auteur-7691-BD-Quadrichromie.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
@@ -75,7 +79,7 @@
|
|||||||
"LegalDeposit": "0001-01-01T00:00:00Z",
|
"LegalDeposit": "0001-01-01T00:00:00Z",
|
||||||
"PrintDate": "0001-01-01T00:00:00Z",
|
"PrintDate": "0001-01-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-12-07T00:00:00Z",
|
"PurchaseDate": "2013-12-07T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/plantufourmicouverture.JPG",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/plantufourmicouverture.JPG",
|
||||||
"description": "",
|
"description": "",
|
||||||
"Note": 3,
|
"Note": 3,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -88,8 +92,8 @@
|
|||||||
"\u003cN\u0026B\u003e"
|
"\u003cN\u0026B\u003e"
|
||||||
],
|
],
|
||||||
"Links" : {
|
"Links" : {
|
||||||
"Plantu": "http://www.bedetheque.com/auteur-5996-BD-Plantu.html",
|
"Plantu": "https://www.bedetheque.com/auteur-5996-BD-Plantu.html",
|
||||||
"\u003cN\u0026B\u003e": "http://www.bedetheque.com/auteur-477-BD-NB.html"
|
"\u003cN\u0026B\u003e": "https://www.bedetheque.com/auteur-477-BD-NB.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
@@ -107,8 +111,8 @@
|
|||||||
"ref": "DARK-2",
|
"ref": "DARK-2",
|
||||||
"LegalDeposit": "2002-09-01T00:00:00Z",
|
"LegalDeposit": "2002-09-01T00:00:00Z",
|
||||||
"PrintDate": "2002-09-01T00:00:00Z",
|
"PrintDate": "2002-09-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-09-06T00:00:00Z",
|
"PurchaseDate": "2013-08-31T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/Darken02_22102002.jpg",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/Darken02_22102002.jpg",
|
||||||
"description": "Kelmar le Darken a retrouvé Lorik, son frère, engagé dans la résistance au Nouvel Ordre Humain. Celui-ci aurait découvert l'endroit où leur mère est tenue prisonnière : le Mangeforêt, un monstre mécanique qui défriche la forêt héossienne et sert de bagne aux autochtones récalcitrants. Mais pour les chefs de la résistance, ce n'est pas un objectif prioritaire. Alors Kelmar part à l'assaut de la machine avec Langue Agile la voleuse feling, Doonda la Woon, et une poignée d'enfants-soldats. Et s'il avait été prévu dès le début... Lire la suite",
|
"description": "Kelmar le Darken a retrouvé Lorik, son frère, engagé dans la résistance au Nouvel Ordre Humain. Celui-ci aurait découvert l'endroit où leur mère est tenue prisonnière : le Mangeforêt, un monstre mécanique qui défriche la forêt héossienne et sert de bagne aux autochtones récalcitrants. Mais pour les chefs de la résistance, ce n'est pas un objectif prioritaire. Alors Kelmar part à l'assaut de la machine avec Langue Agile la voleuse feling, Doonda la Woon, et une poignée d'enfants-soldats. Et s'il avait été prévu dès le début... Lire la suite",
|
||||||
"Note": 5,
|
"Note": 5,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -116,16 +120,16 @@
|
|||||||
"Rastoin, Bernard"
|
"Rastoin, Bernard"
|
||||||
],
|
],
|
||||||
"dessins": [
|
"dessins": [
|
||||||
"Swal, Christophe"
|
"Swal, Christophe"
|
||||||
],
|
],
|
||||||
"couleurs": [
|
"couleurs": [
|
||||||
"Robert, Jacky"
|
"Robert, Jacky"
|
||||||
],
|
],
|
||||||
"Links": {
|
"Links": {
|
||||||
"Polouchine, Igor": "http://www.bedetheque.com/auteur-2556-BD-Polouchine-Igor.html",
|
"Polouchine, Igor": "https://www.bedetheque.com/auteur-2556-BD-Polouchine-Igor.html",
|
||||||
"Rastoin, Bernard": "http://www.bedetheque.com/auteur-31834-BD-Rastoin-Bernard.html",
|
"Rastoin, Bernard": "https://www.bedetheque.com/auteur-31834-BD-Rastoin-Bernard.html",
|
||||||
"Swal, Christophe": "http://www.bedetheque.com/auteur-2557-BD-Swal-Christophe.html",
|
"Swal, Christophe": "https://www.bedetheque.com/auteur-2557-BD-Swal-Christophe.html",
|
||||||
"Robert, Jacky": "http://www.bedetheque.com/auteur-820-BD-Robert-Jacky.html"
|
"Robert, Jacky": "https://www.bedetheque.com/auteur-820-BD-Robert-Jacky.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
@@ -144,7 +148,7 @@
|
|||||||
"LegalDeposit": "1992-10-01T00:00:00Z",
|
"LegalDeposit": "1992-10-01T00:00:00Z",
|
||||||
"PrintDate": "0001-01-01T00:00:00Z",
|
"PrintDate": "0001-01-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-10-31T00:00:00Z",
|
"PurchaseDate": "2013-10-31T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/bizu05.jpg",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/bizu05.jpg",
|
||||||
"description": "",
|
"description": "",
|
||||||
"Note": 3,
|
"Note": 3,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -157,8 +161,8 @@
|
|||||||
"D'Authenay, Anne-Marie"
|
"D'Authenay, Anne-Marie"
|
||||||
],
|
],
|
||||||
"Links": {
|
"Links": {
|
||||||
"Fournier, Jean-Claude": "http://www.bedetheque.com/auteur-755-BD-Fournier-Jean-Claude.html",
|
"Fournier, Jean-Claude": "https://www.bedetheque.com/auteur-755-BD-Fournier-Jean-Claude.html",
|
||||||
"D'Authenay, Anne-Marie":"http://www.bedetheque.com/auteur-550-BD-D-Authenay-Anne-Marie.html"
|
"D'Authenay, Anne-Marie":"https://www.bedetheque.com/auteur-550-BD-D-Authenay-Anne-Marie.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
@@ -176,8 +180,8 @@
|
|||||||
"ref": "EAU-5",
|
"ref": "EAU-5",
|
||||||
"LegalDeposit": "1992-02-01T00:00:00Z",
|
"LegalDeposit": "1992-02-01T00:00:00Z",
|
||||||
"PrintDate": "0001-01-01T00:00:00Z",
|
"PrintDate": "0001-01-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-09-06T00:00:00Z",
|
"PurchaseDate": "2013-08-30T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/Couv_164.jpg",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/Couv_164.jpg",
|
||||||
"description": "",
|
"description": "",
|
||||||
"Note": 3.9,
|
"Note": 3.9,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -190,8 +194,8 @@
|
|||||||
"Adamov, Philippe"
|
"Adamov, Philippe"
|
||||||
],
|
],
|
||||||
"Links": {
|
"Links": {
|
||||||
"Cothias, Patrick": "http://www.bedetheque.com/auteur-36-BD-Cothias-Patrick.html",
|
"Cothias, Patrick": "https://www.bedetheque.com/auteur-36-BD-Cothias-Patrick.html",
|
||||||
"Adamov, Philippe": "http://www.bedetheque.com/auteur-471-BD-Adamov-Philippe.html"
|
"Adamov, Philippe": "https://www.bedetheque.com/auteur-471-BD-Adamov-Philippe.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
@@ -209,8 +213,8 @@
|
|||||||
"ref": "KEN-2",
|
"ref": "KEN-2",
|
||||||
"LegalDeposit": "2003-01-01T00:00:00Z",
|
"LegalDeposit": "2003-01-01T00:00:00Z",
|
||||||
"PrintDate": "0001-01-01T00:00:00Z",
|
"PrintDate": "0001-01-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-09-03T00:00:00Z",
|
"PurchaseDate": "2013-08-29T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/kenyaco02.jpg",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/kenyaco02.jpg",
|
||||||
"description": "",
|
"description": "",
|
||||||
"Note": 4,
|
"Note": 4,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -224,9 +228,9 @@
|
|||||||
"Scarlett"
|
"Scarlett"
|
||||||
],
|
],
|
||||||
"Links": {
|
"Links": {
|
||||||
"Leo": "http://www.bedetheque.com/auteur-97-BD-Leo.html",
|
"Leo": "https://www.bedetheque.com/auteur-97-BD-Leo.html",
|
||||||
"Rodolphe": "http://www.bedetheque.com/auteur-128-BD-Rodolphe.html",
|
"Rodolphe": "https://www.bedetheque.com/auteur-128-BD-Rodolphe.html",
|
||||||
"Scarlett": "http://www.bedetheque.com/auteur-1296-BD-Scarlett.html"
|
"Scarlett": "https://www.bedetheque.com/auteur-1296-BD-Scarlett.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
@@ -244,8 +248,8 @@
|
|||||||
"ref": "ACC-2",
|
"ref": "ACC-2",
|
||||||
"LegalDeposit": "2003-12-01T00:00:00Z",
|
"LegalDeposit": "2003-12-01T00:00:00Z",
|
||||||
"PrintDate": "0001-01-01T00:00:00Z",
|
"PrintDate": "0001-01-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-09-04T00:00:00Z",
|
"PurchaseDate": "2013-08-28T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/accrocderap.jpg",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/accrocderap.jpg",
|
||||||
"description": "",
|
"description": "",
|
||||||
"Note": -1,
|
"Note": -1,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -258,9 +262,9 @@
|
|||||||
"Ptiluc"
|
"Ptiluc"
|
||||||
],
|
],
|
||||||
"Links": {
|
"Links": {
|
||||||
"Harty": "http://www.bedetheque.com/auteur-6505-BD-Harty.html",
|
"Harty": "https://www.bedetheque.com/auteur-6505-BD-Harty.html",
|
||||||
"Joan": "http://www.bedetheque.com/auteur-4285-BD-Joan.html",
|
"Joan": "https://www.bedetheque.com/auteur-4285-BD-Joan.html",
|
||||||
"Ptiluc": "http://www.bedetheque.com/auteur-125-BD-Ptiluc.html"
|
"Ptiluc": "https://www.bedetheque.com/auteur-125-BD-Ptiluc.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
@@ -278,8 +282,8 @@
|
|||||||
"ref": "CHI-23",
|
"ref": "CHI-23",
|
||||||
"LegalDeposit": "1978-03-01T00:00:00Z",
|
"LegalDeposit": "1978-03-01T00:00:00Z",
|
||||||
"PrintDate": "0001-01-01T00:00:00Z",
|
"PrintDate": "0001-01-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-09-06T00:00:00Z",
|
"PurchaseDate": "2013-08-27T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/Couv_46005.jpg",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/Couv_46005.jpg",
|
||||||
"description": "",
|
"description": "",
|
||||||
"Note": 3,
|
"Note": 3,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -292,7 +296,7 @@
|
|||||||
"Tibet"
|
"Tibet"
|
||||||
],
|
],
|
||||||
"Links": {
|
"Links": {
|
||||||
"Tibet": "http://www.bedetheque.com/auteur-1791-BD-Tibet.html"
|
"Tibet": "https://www.bedetheque.com/auteur-1791-BD-Tibet.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
@@ -311,7 +315,7 @@
|
|||||||
"LegalDeposit": "1990-10-01T00:00:00Z",
|
"LegalDeposit": "1990-10-01T00:00:00Z",
|
||||||
"PrintDate": "0001-01-01T00:00:00Z",
|
"PrintDate": "0001-01-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-12-02T00:00:00Z",
|
"PurchaseDate": "2013-12-02T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/Couv_15875.jpg",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/Couv_15875.jpg",
|
||||||
"description": "",
|
"description": "",
|
||||||
"Note": 4,
|
"Note": 4,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -324,8 +328,8 @@
|
|||||||
"\u003cBichromie\u003e"
|
"\u003cBichromie\u003e"
|
||||||
],
|
],
|
||||||
"Links": {
|
"Links": {
|
||||||
"Veyron, Martin": "http://www.bedetheque.com/auteur-1491-BD-Veyron-Martin.html",
|
"Veyron, Martin": "https://www.bedetheque.com/auteur-1491-BD-Veyron-Martin.html",
|
||||||
"\u003cBichromie\u003e": "http://www.bedetheque.com/auteur-6563-BD-Bichromie.html"
|
"\u003cBichromie\u003e": "https://www.bedetheque.com/auteur-6563-BD-Bichromie.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
@@ -344,7 +348,7 @@
|
|||||||
"LegalDeposit": "2009-02-01T00:00:00Z",
|
"LegalDeposit": "2009-02-01T00:00:00Z",
|
||||||
"PrintDate": "2009-03-01T00:00:00Z",
|
"PrintDate": "2009-03-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-10-14T00:00:00Z",
|
"PurchaseDate": "2013-10-14T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/84448_c.jpg",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/84448_c.jpg",
|
||||||
"description": "À travers l’histoire d’une frégate, devenez le témoin de l’indépendance du peuple américain au siècle des lumières. En 1778, dans l'arsenal de Rochefort la frégate L’Hermione est mise en chantier d’après les plans de l’ingénieur Chevillard Aîné. Pendant près d’un an, charpentiers, perceurs, calfats, forgerons et bagnards se relaient pour construire ce navire de près de 45 mètres, doté d’une voilure de 1500 m2, de 26 canons pouvant tirer des boulets de 12 livres. En 1779, Gilbert Motier, marquis de La Fayette, cherche... Lire la suite",
|
"description": "À travers l’histoire d’une frégate, devenez le témoin de l’indépendance du peuple américain au siècle des lumières. En 1778, dans l'arsenal de Rochefort la frégate L’Hermione est mise en chantier d’après les plans de l’ingénieur Chevillard Aîné. Pendant près d’un an, charpentiers, perceurs, calfats, forgerons et bagnards se relaient pour construire ce navire de près de 45 mètres, doté d’une voilure de 1500 m2, de 26 canons pouvant tirer des boulets de 12 livres. En 1779, Gilbert Motier, marquis de La Fayette, cherche... Lire la suite",
|
||||||
"Note": 3.7,
|
"Note": 3.7,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -357,7 +361,7 @@
|
|||||||
"Delitte, Jean-Yves"
|
"Delitte, Jean-Yves"
|
||||||
],
|
],
|
||||||
"Links": {
|
"Links": {
|
||||||
"Delitte, Jean-Yves":"http://www.bedetheque.com/auteur-808-BD-Delitte-Jean-Yves.html"
|
"Delitte, Jean-Yves":"https://www.bedetheque.com/auteur-808-BD-Delitte-Jean-Yves.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
@@ -376,7 +380,7 @@
|
|||||||
"LegalDeposit": "2012-04-01T00:00:00Z",
|
"LegalDeposit": "2012-04-01T00:00:00Z",
|
||||||
"PrintDate": "0001-01-01T00:00:00Z",
|
"PrintDate": "0001-01-01T00:00:00Z",
|
||||||
"PurchaseDate": "2014-03-31T00:00:00Z",
|
"PurchaseDate": "2014-03-31T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/Couv_160366.jpg",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/Couv_160366.jpg",
|
||||||
"description": "Ralph, toujours accompagné par les magiciens Yassou et maître Migachi, a décidé de voler la couronne de Tanghor, dont le pouvoir pourrait rendre la mémoire à sa soeur. Il s'associe à trois voleurs rencontrés sur le bord de la route et se rend à Onophalae, où la couronne magique est conservée en haut d'un pic particulièrement bien protégé. Du moins pour le commun des mortels, car rien ne résiste aux méthodes non- conventionnelles de Ralph. De son côté, le père de Ralph, qui a survécu à l'effondrement du barrage, s'installe à... Lire la suite",
|
"description": "Ralph, toujours accompagné par les magiciens Yassou et maître Migachi, a décidé de voler la couronne de Tanghor, dont le pouvoir pourrait rendre la mémoire à sa soeur. Il s'associe à trois voleurs rencontrés sur le bord de la route et se rend à Onophalae, où la couronne magique est conservée en haut d'un pic particulièrement bien protégé. Du moins pour le commun des mortels, car rien ne résiste aux méthodes non- conventionnelles de Ralph. De son côté, le père de Ralph, qui a survécu à l'effondrement du barrage, s'installe à... Lire la suite",
|
||||||
"Note": 4.1,
|
"Note": 4.1,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -389,8 +393,8 @@
|
|||||||
"Findakly, Brigitte"
|
"Findakly, Brigitte"
|
||||||
],
|
],
|
||||||
"Links": {
|
"Links": {
|
||||||
"Trondheim, Lewis": "http://www.bedetheque.com/auteur-145-BD-Trondheim-Lewis.html",
|
"Trondheim, Lewis": "https://www.bedetheque.com/auteur-145-BD-Trondheim-Lewis.html",
|
||||||
"Findakly, Brigitte": "http://www.bedetheque.com/auteur-1382-BD-Findakly-Brigitte.html"
|
"Findakly, Brigitte": "https://www.bedetheque.com/auteur-1382-BD-Findakly-Brigitte.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
@@ -408,8 +412,8 @@
|
|||||||
"ref": "MAX-2",
|
"ref": "MAX-2",
|
||||||
"LegalDeposit": "1993-05-01T00:00:00Z",
|
"LegalDeposit": "1993-05-01T00:00:00Z",
|
||||||
"PrintDate": "0001-01-01T00:00:00Z",
|
"PrintDate": "0001-01-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-09-03T00:00:00Z",
|
"PurchaseDate": "2013-08-26T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/Couv_754.jpg",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/Couv_754.jpg",
|
||||||
"description": "",
|
"description": "",
|
||||||
"Note": -1,
|
"Note": -1,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -419,7 +423,7 @@
|
|||||||
"Bruyninx, Marc"
|
"Bruyninx, Marc"
|
||||||
],
|
],
|
||||||
"Links": {
|
"Links": {
|
||||||
"Bruyninx, Marc": "http://www.bedetheque.com/auteur-17-BD-Bruyninx-Marc.html"
|
"Bruyninx, Marc": "https://www.bedetheque.com/auteur-17-BD-Bruyninx-Marc.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
},
|
},
|
||||||
@@ -437,8 +441,8 @@
|
|||||||
"ref": "YIU-5",
|
"ref": "YIU-5",
|
||||||
"LegalDeposit": "2005-11-01T00:00:00Z",
|
"LegalDeposit": "2005-11-01T00:00:00Z",
|
||||||
"PrintDate": "0001-01-01T00:00:00Z",
|
"PrintDate": "0001-01-01T00:00:00Z",
|
||||||
"PurchaseDate": "2013-09-04T00:00:00Z",
|
"PurchaseDate": "2013-08-25T00:00:00Z",
|
||||||
"CoverURL": "http://www.bedetheque.com/media/Couvertures/Couv_52100.jpg",
|
"CoverURL": "https://www.bedetheque.com/media/Couvertures/Couv_52100.jpg",
|
||||||
"description": "",
|
"description": "",
|
||||||
"Note": 4.4,
|
"Note": 4.4,
|
||||||
"scenario": [
|
"scenario": [
|
||||||
@@ -452,9 +456,9 @@
|
|||||||
"Guénet, Nicolas"
|
"Guénet, Nicolas"
|
||||||
],
|
],
|
||||||
"Links" : {
|
"Links" : {
|
||||||
"Téhy": "http://www.bedetheque.com/auteur-205-BD-Tehy.html",
|
"Téhy": "https://www.bedetheque.com/auteur-205-BD-Tehy.html",
|
||||||
"Vee, J.M.": "http://www.bedetheque.com/auteur-8231-BD-Vee-JM.html",
|
"Vee, J.M.": "https://www.bedetheque.com/auteur-8231-BD-Vee-JM.html",
|
||||||
"Guénet, Nicolas": "http://www.bedetheque.com/auteur-2601-BD-Guenet-Nicolas.html"
|
"Guénet, Nicolas": "https://www.bedetheque.com/auteur-2601-BD-Guenet-Nicolas.html"
|
||||||
},
|
},
|
||||||
"FetchDate": "0001-01-01T00:00:00Z"
|
"FetchDate": "0001-01-01T00:00:00Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,12 @@
|
|||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link href="/bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
|
|
||||||
<link rel="icon" href="https://satellite.bar/images/sat.ico" />
|
<link rel="icon" href="https://satellite.bar/images/sat.ico" />
|
||||||
<link href="/css/satbd.sateliite.bar.css" rel="stylesheet" />
|
|
||||||
<title>satbd: explorez la betheque de sat</title>
|
<title>satbd: explorez la betheque de sat</title>
|
||||||
|
<!-- bower:css -->
|
||||||
|
<!-- endinject -->
|
||||||
|
<!-- inject:css -->
|
||||||
|
<!-- endinject -->
|
||||||
</head>
|
</head>
|
||||||
<body ng-app="satbd.satellite.bar">
|
<body ng-app="satbd.satellite.bar">
|
||||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||||
@@ -46,12 +48,8 @@
|
|||||||
<div class="container-fluid" ng-view>
|
<div class="container-fluid" ng-view>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/bower_components/angular/angular.min.js"></script>
|
<!-- bower:js -->
|
||||||
<script src="/bower_components/angular-animate/angular-animate.min.js"></script>
|
<!-- endinject -->
|
||||||
<script src="/bower_components/angular-route/angular-route.min.js"></script>
|
|
||||||
<script src="/bower_components/angular-sanitize/angular-sanitize.min.js"></script>
|
|
||||||
<script src="/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
|
|
||||||
<script src="/bower_components/angular-inview/angular-inview.js"></script>
|
|
||||||
<!-- inject:js -->
|
<!-- inject:js -->
|
||||||
<!-- endinject -->
|
<!-- endinject -->
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ album.component('album', {
|
|||||||
id: '<albumId',
|
id: '<albumId',
|
||||||
ratio: '<'
|
ratio: '<'
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
album.controller('AlbumModalInstanceCtrl', function($scope,$uibModalInstance,album) {
|
album.controller('AlbumModalInstanceCtrl', function($scope,$uibModalInstance,album) {
|
||||||
$scope.album = album;
|
$scope.album = album;
|
||||||
@@ -47,5 +47,5 @@ album.controller('AlbumModalInstanceCtrl', function($scope,$uibModalInstance,alb
|
|||||||
};
|
};
|
||||||
$scope.getLink = function(n) {
|
$scope.getLink = function(n) {
|
||||||
return $scope.album[n];
|
return $scope.album[n];
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
var controllers = angular.module('satbd.satellite.bar.controllers',[
|
var controllers = angular.module('satbd.satellite.bar.controllers',[
|
||||||
'ui.bootstrap',
|
'ui.bootstrap',
|
||||||
'ngAnimate'
|
'ngAnimate'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
controllers.controller('NavBarCtrl',function($scope,$location,$uibModal) {
|
controllers.controller('NavBarCtrl',function($scope,$location,$uibModal) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
$scope.isCollapsed = true;
|
$scope.isCollapsed = true;
|
||||||
$scope.isActive = function(loc) {
|
$scope.isActive = function(loc) {
|
||||||
return loc === $location.path();
|
return loc === $location.path();
|
||||||
@@ -15,7 +15,7 @@ controllers.controller('NavBarCtrl',function($scope,$location,$uibModal) {
|
|||||||
if (searchTerms) {
|
if (searchTerms) {
|
||||||
$location.url('/search?q='+ encodeURIComponent(searchTerms));
|
$location.url('/search?q='+ encodeURIComponent(searchTerms));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
$scope.openHelpModal = function () {
|
$scope.openHelpModal = function () {
|
||||||
var modalInstance = $uibModal.open({
|
var modalInstance = $uibModal.open({
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('satbd.satellite.bar',[
|
angular.module('satbd.satellite.bar',[
|
||||||
'ngRoute',
|
'ngRoute',
|
||||||
'satbd.satellite.bar.controllers',
|
'satbd.satellite.bar.controllers',
|
||||||
@@ -9,5 +7,7 @@ angular.module('satbd.satellite.bar',[
|
|||||||
'satbd.satellite.bar.views.authors',
|
'satbd.satellite.bar.views.authors',
|
||||||
'satbd.satellite.bar.views.search'
|
'satbd.satellite.bar.views.search'
|
||||||
]).config(function($routeProvider) {
|
]).config(function($routeProvider) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
$routeProvider.otherwise({redirectTo: '/recents'});
|
$routeProvider.otherwise({redirectTo: '/recents'});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
var services = angular.module('satbd.satellite.bar.services',[])
|
var services = angular.module('satbd.satellite.bar.services',[]);
|
||||||
|
|
||||||
services.factory('albumService',['$http','$log','$q', function($http,$log,$q) {
|
services.factory('albumService',['$http','$log','$q', function($http,$log,$q) {
|
||||||
var determinantRegexp = /^(.*) \(([Ll][eas']+)\)$/;
|
var determinantRegexp = /^(.*) \(([Ll][eas']+)\)$/;
|
||||||
@@ -6,8 +6,8 @@ services.factory('albumService',['$http','$log','$q', function($http,$log,$q) {
|
|||||||
var removeSerie = /^\(.*\) .*$/;
|
var removeSerie = /^\(.*\) .*$/;
|
||||||
|
|
||||||
function cleanupName(name) {
|
function cleanupName(name) {
|
||||||
matches = name.match(determinantRegexp);
|
var matches = name.match(determinantRegexp);
|
||||||
if (matches == null) {
|
if (matches === null) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
return matches[2] + ' ' + matches[1];
|
return matches[2] + ' ' + matches[1];
|
||||||
@@ -18,7 +18,7 @@ services.factory('albumService',['$http','$log','$q', function($http,$log,$q) {
|
|||||||
album.série = undefined;
|
album.série = undefined;
|
||||||
album.editeur = album.éditeur;
|
album.editeur = album.éditeur;
|
||||||
album.éditeur = undefined;
|
album.éditeur = undefined;
|
||||||
if (removeSerie.test(album.serie) == true) {
|
if (removeSerie.test(album.serie) === true) {
|
||||||
album.serieDisplay = '';
|
album.serieDisplay = '';
|
||||||
} else {
|
} else {
|
||||||
album.serieDisplay = cleanupName(album.serie);
|
album.serieDisplay = cleanupName(album.serie);
|
||||||
@@ -64,7 +64,7 @@ services.factory('albumService',['$http','$log','$q', function($http,$log,$q) {
|
|||||||
"query": terms
|
"query": terms
|
||||||
}
|
}
|
||||||
}).then(function(response) {
|
}).then(function(response) {
|
||||||
if ( fuzzify == true && response.data.total_hits == 0) {
|
if ( fuzzify === true && response.data.total_hits === 0) {
|
||||||
return search(fuzzifyTerms(terms),from,false,response.data.took);
|
return search(fuzzifyTerms(terms),from,false,response.data.took);
|
||||||
}
|
}
|
||||||
return processResult(response.data,previousTime);
|
return processResult(response.data,previousTime);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('satbd.satellite.bar.views.authors',[
|
angular.module('satbd.satellite.bar.views.authors',[
|
||||||
'ngRoute'
|
'ngRoute'
|
||||||
]).config(function($routeProvider) {
|
]).config(function($routeProvider) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
$routeProvider.when('/authors', {
|
$routeProvider.when('/authors', {
|
||||||
templateUrl: 'js/views/authors/authors.html',
|
templateUrl: 'js/views/authors/authors.html',
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('satbd.satellite.bar.views.recents',[
|
angular.module('satbd.satellite.bar.views.recents',[
|
||||||
'ngRoute',
|
'ngRoute',
|
||||||
'satbd.satellite.bar.components.album',
|
'satbd.satellite.bar.components.album',
|
||||||
'angular-inview'
|
'angular-inview'
|
||||||
]).config(function($routeProvider) {
|
]).config(function($routeProvider) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
$routeProvider.when('/recents', {
|
$routeProvider.when('/recents', {
|
||||||
templateUrl: 'js/views/recents/recents.html',
|
templateUrl: 'js/views/recents/recents.html',
|
||||||
controller: 'RecentsCtrl'
|
controller: 'RecentsCtrl'
|
||||||
});
|
});
|
||||||
}).controller('RecentsCtrl', function( $scope, $http, $log) {
|
}).controller('RecentsCtrl', function( $scope, $http, $log) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
$scope.albumIDs = [];
|
$scope.albumIDs = [];
|
||||||
$scope.allAlbums = [];
|
$scope.allAlbums = [];
|
||||||
$scope.scrollMore = false;
|
$scope.scrollMore = false;
|
||||||
@@ -29,13 +31,12 @@ angular.module('satbd.satellite.bar.views.recents',[
|
|||||||
$log.info('Loading more components');
|
$log.info('Loading more components');
|
||||||
if (!$scope.scrollMore || $scope.albumIDs.length >= $scope.allAlbums.length) {
|
if (!$scope.scrollMore || $scope.albumIDs.length >= $scope.allAlbums.length) {
|
||||||
$scope.scrollMore = false;
|
$scope.scrollMore = false;
|
||||||
$log.info('reached the end of albums')
|
$log.info('reached the end of albums');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var newSize = Math.min($scope.albumIDs.length + batchSize, $scope.allAlbums.length);
|
var newSize = Math.min($scope.albumIDs.length + batchSize, $scope.allAlbums.length);
|
||||||
for( var i = $scope.albumIDs.length; i < newSize; i++) {
|
for( var i = $scope.albumIDs.length; i < newSize; i++) {
|
||||||
$scope.albumIDs.push($scope.allAlbums[i]);
|
$scope.albumIDs.push($scope.allAlbums[i]);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('satbd.satellite.bar.views.search',[
|
angular.module('satbd.satellite.bar.views.search',[
|
||||||
'ngRoute',
|
'ngRoute',
|
||||||
'ngSanitize',
|
'ngSanitize',
|
||||||
@@ -7,11 +5,15 @@ angular.module('satbd.satellite.bar.views.search',[
|
|||||||
'satbd.satellite.bar.components.album',
|
'satbd.satellite.bar.components.album',
|
||||||
'angular-inview'
|
'angular-inview'
|
||||||
]).config(function($routeProvider) {
|
]).config(function($routeProvider) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
$routeProvider.when('/search', {
|
$routeProvider.when('/search', {
|
||||||
templateUrl: 'js/views/search/search.html',
|
templateUrl: 'js/views/search/search.html',
|
||||||
controller: 'SearchCtrl'
|
controller: 'SearchCtrl'
|
||||||
});
|
});
|
||||||
}).controller('SearchCtrl', function($scope,$routeParams,$log,$sce,albumService) {
|
}).controller('SearchCtrl', function($scope,$routeParams,$log,$sce,albumService) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
$scope.terms=$routeParams.q;
|
$scope.terms=$routeParams.q;
|
||||||
$scope.scrollMore = false;
|
$scope.scrollMore = false;
|
||||||
$scope.allHits = [];
|
$scope.allHits = [];
|
||||||
@@ -43,14 +45,14 @@ angular.module('satbd.satellite.bar.views.search',[
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.inSecond= function(bleveValue) {
|
$scope.inSecond= function(bleveValue) {
|
||||||
return bleveValue / 1e9;
|
return bleveValue / 1e6;
|
||||||
}
|
};
|
||||||
|
|
||||||
$scope.trustedFragment = function(f) {
|
$scope.trustedFragment = function(f) {
|
||||||
return $sce.trustAsHtml(f);
|
return $sce.trustAsHtml(f);
|
||||||
}
|
};
|
||||||
|
|
||||||
$scope.round4Dec = function(value) {
|
$scope.round4Dec = function(value) {
|
||||||
return Math.round(value * 10000) / 10000;
|
return Math.round(value * 10000) / 10000;
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('satbd.satellite.bar.views.series',[
|
angular.module('satbd.satellite.bar.views.series',[
|
||||||
'ngRoute',
|
'ngRoute',
|
||||||
'satbd.satellite.bar.directives.responsive-ratio'
|
'satbd.satellite.bar.directives.responsive-ratio'
|
||||||
]).config(function($routeProvider) {
|
]).config(function($routeProvider) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
$routeProvider.when('/series', {
|
$routeProvider.when('/series', {
|
||||||
templateUrl: 'js/views/series/series.html'
|
templateUrl: 'js/views/series/series.html'
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user